@tscircuit/core 0.0.1915 → 0.0.1916
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +2 -0
- package/dist/index.js +1373 -204
- package/package.json +2 -1
package/dist/index.js
CHANGED
|
@@ -6119,11 +6119,11 @@ function Trace_doInitialPcbTraceRender(trace) {
|
|
|
6119
6119
|
const closestNetBPort = getClosest(netAPort, netBPorts);
|
|
6120
6120
|
const netAPortPosition = netAPort._getGlobalPcbPositionBeforeLayout();
|
|
6121
6121
|
const netBPortPosition = closestNetBPort._getGlobalPcbPositionBeforeLayout();
|
|
6122
|
-
const
|
|
6122
|
+
const distance23 = Math.sqrt(
|
|
6123
6123
|
(netAPortPosition.x - netBPortPosition.x) ** 2 + (netAPortPosition.y - netBPortPosition.y) ** 2
|
|
6124
6124
|
);
|
|
6125
|
-
if (
|
|
6126
|
-
closestDistance =
|
|
6125
|
+
if (distance23 < closestDistance) {
|
|
6126
|
+
closestDistance = distance23;
|
|
6127
6127
|
closestPortPair = [netAPort, closestNetBPort];
|
|
6128
6128
|
}
|
|
6129
6129
|
}
|
|
@@ -7283,7 +7283,7 @@ var getMaxLengthFromConnectedComponents = (ports, { db }) => {
|
|
|
7283
7283
|
return sourceComponent.max_decoupling_trace_length;
|
|
7284
7284
|
}
|
|
7285
7285
|
return null;
|
|
7286
|
-
}).filter((
|
|
7286
|
+
}).filter((length8) => typeof length8 === "number");
|
|
7287
7287
|
if (componentMaxLengths.length === 0) return void 0;
|
|
7288
7288
|
return Math.min(...componentMaxLengths);
|
|
7289
7289
|
};
|
|
@@ -10130,11 +10130,11 @@ import { schematicPathProps } from "@tscircuit/props";
|
|
|
10130
10130
|
import SVGPathCommander from "svg-path-commander";
|
|
10131
10131
|
function sampleCurveSegment(segmentPath, samplesPerUnit) {
|
|
10132
10132
|
const commander = new SVGPathCommander(segmentPath);
|
|
10133
|
-
const
|
|
10134
|
-
const numSamples = Math.max(2, Math.ceil(
|
|
10133
|
+
const length8 = commander.getTotalLength();
|
|
10134
|
+
const numSamples = Math.max(2, Math.ceil(length8 * samplesPerUnit));
|
|
10135
10135
|
const points = [];
|
|
10136
10136
|
for (let i = 1; i <= numSamples; i++) {
|
|
10137
|
-
const t = i / numSamples *
|
|
10137
|
+
const t = i / numSamples * length8;
|
|
10138
10138
|
const point6 = commander.getPointAtLength(t);
|
|
10139
10139
|
points.push({ x: point6.x, y: point6.y });
|
|
10140
10140
|
}
|
|
@@ -12303,7 +12303,7 @@ var createComponentsFromCircuitJson = ({
|
|
|
12303
12303
|
const schematicSymbolId = schematicComponent?.schematic_symbol_id;
|
|
12304
12304
|
const parentSymbol = typeof schematicSymbolId === "string" ? schematicSymbolsByImportedId.get(schematicSymbolId) : void 0;
|
|
12305
12305
|
if (parentSymbol && schematicComponent?.is_box_with_pins === true && elm.center && elm.side_of_component) {
|
|
12306
|
-
const
|
|
12306
|
+
const distance23 = elm.distance_from_component_edge;
|
|
12307
12307
|
const facingDirection = getFacingDirectionFromSide(
|
|
12308
12308
|
elm.side_of_component
|
|
12309
12309
|
);
|
|
@@ -12311,8 +12311,8 @@ var createComponentsFromCircuitJson = ({
|
|
|
12311
12311
|
const directionVector = getUnitVectorFromDirection2(facingDirection);
|
|
12312
12312
|
const stemDirection = elm.facing_direction === facingDirection ? 1 : -1;
|
|
12313
12313
|
const portCenter = {
|
|
12314
|
-
x: elm.center.x + directionVector.x *
|
|
12315
|
-
y: elm.center.y + directionVector.y *
|
|
12314
|
+
x: elm.center.x + directionVector.x * distance23 * stemDirection,
|
|
12315
|
+
y: elm.center.y + directionVector.y * distance23 * stemDirection
|
|
12316
12316
|
};
|
|
12317
12317
|
const sourcePort = sourcePortsByImportedId.get(elm.source_port_id);
|
|
12318
12318
|
const aliases = Array.from(
|
|
@@ -13543,9 +13543,9 @@ var getLabelPlacementAlongRoute = (route) => {
|
|
|
13543
13543
|
for (let pointIndex = 1; pointIndex < route.length; pointIndex++) {
|
|
13544
13544
|
const from = route[pointIndex - 1];
|
|
13545
13545
|
const to = route[pointIndex];
|
|
13546
|
-
const
|
|
13547
|
-
if (
|
|
13548
|
-
longestSegment = { from, to, length:
|
|
13546
|
+
const length8 = Math.hypot(to.x - from.x, to.y - from.y);
|
|
13547
|
+
if (length8 > longestSegment.length) {
|
|
13548
|
+
longestSegment = { from, to, length: length8 };
|
|
13549
13549
|
}
|
|
13550
13550
|
}
|
|
13551
13551
|
const deltaX = longestSegment.to.x - longestSegment.from.x;
|
|
@@ -16770,15 +16770,15 @@ var Capacitor_addPolarityFabricationSymbols = (capacitor) => {
|
|
|
16770
16770
|
source_port_id: negatives[0].source_port_id
|
|
16771
16771
|
});
|
|
16772
16772
|
if (!positive || !negative) return;
|
|
16773
|
-
const
|
|
16774
|
-
if (
|
|
16773
|
+
const distance23 = Math.hypot(negative.x - positive.x, negative.y - positive.y);
|
|
16774
|
+
if (distance23 < 1e-6) return;
|
|
16775
16775
|
const frame = compose6(
|
|
16776
16776
|
translate4((positive.x + negative.x) / 2, (positive.y + negative.y) / 2),
|
|
16777
16777
|
rotate3(Math.atan2(negative.y - positive.y, negative.x - positive.x))
|
|
16778
16778
|
);
|
|
16779
16779
|
const point6 = (x, y) => applyToPoint25(frame, { x, y });
|
|
16780
|
-
const offset =
|
|
16781
|
-
const halfSize = Math.min(
|
|
16780
|
+
const offset = distance23 / 4;
|
|
16781
|
+
const halfSize = Math.min(distance23 * 0.12, 0.3);
|
|
16782
16782
|
const routes = [
|
|
16783
16783
|
[point6(-offset - halfSize, 0), point6(-offset + halfSize, 0)],
|
|
16784
16784
|
[point6(-offset, -halfSize), point6(-offset, halfSize)],
|
|
@@ -18270,7 +18270,7 @@ import {
|
|
|
18270
18270
|
groupProps
|
|
18271
18271
|
} from "@tscircuit/props";
|
|
18272
18272
|
import {
|
|
18273
|
-
distance as
|
|
18273
|
+
distance as distance16
|
|
18274
18274
|
} from "circuit-json";
|
|
18275
18275
|
import Debug15 from "debug";
|
|
18276
18276
|
|
|
@@ -18977,7 +18977,7 @@ function validateOriginalEndpointConnectivity(params) {
|
|
|
18977
18977
|
representativeConnection.name
|
|
18978
18978
|
)
|
|
18979
18979
|
).map((obstacle) => ({ type: "obstacle", obstacle }));
|
|
18980
|
-
const
|
|
18980
|
+
const routeCopper2 = (routedSrj.traces ?? []).filter(
|
|
18981
18981
|
(trace) => traceBelongsToNet(inputSrj, trace, representativeConnection)
|
|
18982
18982
|
).flatMap((trace) => extractTraceCopper(trace, layerNames));
|
|
18983
18983
|
const planeCopper = [
|
|
@@ -18994,7 +18994,7 @@ function validateOriginalEndpointConnectivity(params) {
|
|
|
18994
18994
|
const copper = [
|
|
18995
18995
|
...endpointCopper,
|
|
18996
18996
|
...obstacleCopper,
|
|
18997
|
-
...
|
|
18997
|
+
...routeCopper2,
|
|
18998
18998
|
...planeCopper
|
|
18999
18999
|
];
|
|
19000
19000
|
const connectedCopper = new DisjointSet(copper.length);
|
|
@@ -19469,8 +19469,8 @@ function getTerminalDirections(params) {
|
|
|
19469
19469
|
x: plan.targetPoint.x - plan.sourcePoint.x,
|
|
19470
19470
|
y: plan.targetPoint.y - plan.sourcePoint.y
|
|
19471
19471
|
};
|
|
19472
|
-
const
|
|
19473
|
-
const outward =
|
|
19472
|
+
const length8 = Math.hypot(rawOutward.x, rawOutward.y);
|
|
19473
|
+
const outward = length8 > EPSILON4 ? { x: rawOutward.x / length8, y: rawOutward.y / length8 } : { x: 1, y: 0 };
|
|
19474
19474
|
return {
|
|
19475
19475
|
outward,
|
|
19476
19476
|
perpendicular: { x: -outward.y, y: outward.x }
|
|
@@ -19759,7 +19759,7 @@ function runLocalCompletionPass(params) {
|
|
|
19759
19759
|
};
|
|
19760
19760
|
}
|
|
19761
19761
|
function traceLength(trace) {
|
|
19762
|
-
let
|
|
19762
|
+
let length8 = 0;
|
|
19763
19763
|
let previousWire;
|
|
19764
19764
|
for (const point6 of trace.route) {
|
|
19765
19765
|
if (point6.route_type !== "wire") {
|
|
@@ -19767,10 +19767,10 @@ function traceLength(trace) {
|
|
|
19767
19767
|
continue;
|
|
19768
19768
|
}
|
|
19769
19769
|
if (previousWire?.layer === point6.layer)
|
|
19770
|
-
|
|
19770
|
+
length8 += distance9(previousWire, point6);
|
|
19771
19771
|
previousWire = point6;
|
|
19772
19772
|
}
|
|
19773
|
-
return
|
|
19773
|
+
return length8;
|
|
19774
19774
|
}
|
|
19775
19775
|
function trimCompletedFanoutTails(params) {
|
|
19776
19776
|
const { fanoutSrj, completionTraces } = params;
|
|
@@ -20480,8 +20480,8 @@ function* getMultiSegmentTuningWindows(params) {
|
|
|
20480
20480
|
for (const [index, segment2] of plan.segments.entries()) {
|
|
20481
20481
|
if (segment2.layer !== plan.targetLayer || index < (plan.sourceEscapeSegmentCount ?? 1))
|
|
20482
20482
|
continue;
|
|
20483
|
-
const
|
|
20484
|
-
const steps = Math.max(1, Math.ceil(
|
|
20483
|
+
const length8 = distance9(segment2.start, segment2.end);
|
|
20484
|
+
const steps = Math.max(1, Math.ceil(length8 / (segment2.width / 2)));
|
|
20485
20485
|
for (let step = 0; step <= steps; step++) {
|
|
20486
20486
|
consumeWork();
|
|
20487
20487
|
const fraction = step / steps;
|
|
@@ -26416,7 +26416,7 @@ function hasValidTurns(segments) {
|
|
|
26416
26416
|
const segment2 = segments[i];
|
|
26417
26417
|
const dx = segment2.end.x - segment2.start.x;
|
|
26418
26418
|
const dy = segment2.end.y - segment2.start.y;
|
|
26419
|
-
const
|
|
26419
|
+
const length8 = Math.hypot(dx, dy);
|
|
26420
26420
|
if (Math.min(
|
|
26421
26421
|
Math.abs(dx),
|
|
26422
26422
|
Math.abs(dy),
|
|
@@ -26425,12 +26425,12 @@ function hasValidTurns(segments) {
|
|
|
26425
26425
|
return false;
|
|
26426
26426
|
const next = segments[i + 1];
|
|
26427
26427
|
if (next && distance9(segment2.end, next.start) > EPSILON8) return false;
|
|
26428
|
-
if (!next || next.layer !== segment2.layer ||
|
|
26428
|
+
if (!next || next.layer !== segment2.layer || length8 < EPSILON8) continue;
|
|
26429
26429
|
const nx = next.end.x - next.start.x;
|
|
26430
26430
|
const ny = next.end.y - next.start.y;
|
|
26431
26431
|
const nextLength = Math.hypot(nx, ny);
|
|
26432
26432
|
if (nextLength < EPSILON8) continue;
|
|
26433
|
-
if ((dx * nx + dy * ny) / (
|
|
26433
|
+
if ((dx * nx + dy * ny) / (length8 * nextLength) < Math.SQRT1_2 - EPSILON8)
|
|
26434
26434
|
return false;
|
|
26435
26435
|
}
|
|
26436
26436
|
return true;
|
|
@@ -26751,7 +26751,7 @@ function normalizeFanoutPlanCorners(params) {
|
|
|
26751
26751
|
0
|
|
26752
26752
|
)
|
|
26753
26753
|
);
|
|
26754
|
-
if (lengths.some((
|
|
26754
|
+
if (lengths.some((length8) => !Number.isFinite(length8)) || Math.abs(lengths[0] - lengths[1]) > pair.lengthTolerance + EPSILON8)
|
|
26755
26755
|
return null;
|
|
26756
26756
|
}
|
|
26757
26757
|
if (params.inputSrj.traces?.length && plans.length) {
|
|
@@ -26990,7 +26990,7 @@ function rebuildTraceRoute(plan, segments) {
|
|
|
26990
26990
|
function createPlanWithSegments(plan, segments, updateSourceEscapeCount = false) {
|
|
26991
26991
|
const route = rebuildTraceRoute(plan, segments);
|
|
26992
26992
|
if (!route) return null;
|
|
26993
|
-
const
|
|
26993
|
+
const length8 = [...segments, ...plan.planeEndpointSegments ?? []].reduce(
|
|
26994
26994
|
(total, segment2) => total + distance9(segment2.start, segment2.end),
|
|
26995
26995
|
0
|
|
26996
26996
|
);
|
|
@@ -27002,7 +27002,7 @@ function createPlanWithSegments(plan, segments, updateSourceEscapeCount = false)
|
|
|
27002
27002
|
...updateSourceEscapeCount && plan.sourceEscapeSegmentCount !== void 0 && sourceEscapeSegmentCount >= 0 ? { sourceEscapeSegmentCount } : {},
|
|
27003
27003
|
trace: { ...plan.trace, route },
|
|
27004
27004
|
segments,
|
|
27005
|
-
length:
|
|
27005
|
+
length: length8
|
|
27006
27006
|
};
|
|
27007
27007
|
}
|
|
27008
27008
|
function addedTuningViasAreSelfClear(plan, addedVias, clearance) {
|
|
@@ -27532,11 +27532,11 @@ function* createExtendedFoldCandidates(params) {
|
|
|
27532
27532
|
continue;
|
|
27533
27533
|
} else if (start.layer !== plan.targetLayer && (!params.allowTransitLayerMatching || !(bus.allowedLayers ?? [plan.targetLayer]).includes(start.layer) || !(bus.routableEscapeLayers ?? bus.allowedLayers ?? [plan.targetLayer]).includes(start.layer)))
|
|
27534
27534
|
continue;
|
|
27535
|
-
const
|
|
27536
|
-
if (
|
|
27535
|
+
const length8 = distance9(start.start, start.end);
|
|
27536
|
+
if (length8 <= EPSILON9) continue;
|
|
27537
27537
|
const direction = {
|
|
27538
|
-
x: (start.end.x - start.start.x) /
|
|
27539
|
-
y: (start.end.y - start.start.y) /
|
|
27538
|
+
x: (start.end.x - start.start.x) / length8,
|
|
27539
|
+
y: (start.end.y - start.start.y) / length8
|
|
27540
27540
|
};
|
|
27541
27541
|
for (let last = first + 2; last < Math.min(plan.segments.length, first + 16); last++) {
|
|
27542
27542
|
const span = plan.segments.slice(first, last + 1);
|
|
@@ -27613,19 +27613,19 @@ function* createSpreadLaneCandidates(plan, clearance, workBudget) {
|
|
|
27613
27613
|
for (const { segment: segment2, index } of plan.segments.map((segment3, index2) => ({ segment: segment3, index: index2 })).filter(({ segment: segment3 }) => segment3.layer === plan.targetLayer).toSorted(
|
|
27614
27614
|
(a, b) => distance9(b.segment.start, b.segment.end) - distance9(a.segment.start, a.segment.end)
|
|
27615
27615
|
)) {
|
|
27616
|
-
const
|
|
27617
|
-
if (
|
|
27616
|
+
const length8 = distance9(segment2.start, segment2.end);
|
|
27617
|
+
if (length8 <= EPSILON9) continue;
|
|
27618
27618
|
const dx = Math.abs(segment2.end.x - segment2.start.x);
|
|
27619
27619
|
const dy = Math.abs(segment2.end.y - segment2.start.y);
|
|
27620
27620
|
if (dx > EPSILON9 && dy > EPSILON9 && Math.abs(dx - dy) > EPSILON9) continue;
|
|
27621
27621
|
const tangent = {
|
|
27622
|
-
x: (segment2.end.x - segment2.start.x) /
|
|
27623
|
-
y: (segment2.end.y - segment2.start.y) /
|
|
27622
|
+
x: (segment2.end.x - segment2.start.x) / length8,
|
|
27623
|
+
y: (segment2.end.y - segment2.start.y) / length8
|
|
27624
27624
|
};
|
|
27625
27625
|
const pitch = segment2.width + clearance;
|
|
27626
27626
|
for (const multiple of [2, 3, 4, 6]) {
|
|
27627
27627
|
const offset = pitch * multiple;
|
|
27628
|
-
if (
|
|
27628
|
+
if (length8 < 2 * offset + pitch) continue;
|
|
27629
27629
|
for (const sign of [1, -1]) {
|
|
27630
27630
|
consumeMatchingWork(workBudget);
|
|
27631
27631
|
const normal = { x: -tangent.y * sign, y: tangent.x * sign };
|
|
@@ -28395,15 +28395,15 @@ function sourceOriginRouteIsSelfClear(params) {
|
|
|
28395
28395
|
const radius = (viaDiameter + traceWidth) / 2 + clearance;
|
|
28396
28396
|
const incident = /* @__PURE__ */ new Set();
|
|
28397
28397
|
for (const direction of [-1, 1]) {
|
|
28398
|
-
let point6 = via.center,
|
|
28398
|
+
let point6 = via.center, length8 = 0;
|
|
28399
28399
|
const z18 = direction === -1 ? via.fromZ : via.toZ;
|
|
28400
28400
|
for (let edge = via.edge + direction; edge >= 0 && edge + 1 < points.length; edge += direction) {
|
|
28401
28401
|
const a = points[edge], b = points[edge + 1];
|
|
28402
28402
|
const near = direction === -1 ? b : a, far = direction === -1 ? a : b;
|
|
28403
|
-
if (a.z !== z18 || b.z !== z18 || distance9(point6, near) > 1e-7 ||
|
|
28403
|
+
if (a.z !== z18 || b.z !== z18 || distance9(point6, near) > 1e-7 || length8 > radius + 1e-7)
|
|
28404
28404
|
break;
|
|
28405
28405
|
incident.add(edge);
|
|
28406
|
-
|
|
28406
|
+
length8 += distance9(near, far);
|
|
28407
28407
|
point6 = far;
|
|
28408
28408
|
}
|
|
28409
28409
|
}
|
|
@@ -28466,10 +28466,10 @@ function shortcutSection(points, width, clear) {
|
|
|
28466
28466
|
const lowerBound = Math.max(dx, dy) + (Math.SQRT2 - 1) * Math.min(dx, dy);
|
|
28467
28467
|
if (cost[i] + lowerBound >= cost[j] - EPSILON10) continue;
|
|
28468
28468
|
for (const path of connectorVariants(a, b)) {
|
|
28469
|
-
const
|
|
28470
|
-
if (cost[i] +
|
|
28469
|
+
const length8 = path.slice(1).reduce((sum, p, index) => sum + distance9(path[index], p), 0);
|
|
28470
|
+
if (cost[i] + length8 >= cost[j] - EPSILON10 || !path.slice(1).every((p, index) => clear(path[index], p)))
|
|
28471
28471
|
continue;
|
|
28472
|
-
cost[j] = cost[i] +
|
|
28472
|
+
cost[j] = cost[i] + length8;
|
|
28473
28473
|
edges[j] = { previous: i, points: path };
|
|
28474
28474
|
}
|
|
28475
28475
|
}
|
|
@@ -28814,14 +28814,14 @@ var intersectsRegion = (regions, a, b = a) => regions.some(
|
|
|
28814
28814
|
);
|
|
28815
28815
|
function terminalSuffixAt(segments, point6, layer) {
|
|
28816
28816
|
const positions = [];
|
|
28817
|
-
let
|
|
28817
|
+
let length8 = 0;
|
|
28818
28818
|
for (const [index2, segment2] of segments.entries()) {
|
|
28819
28819
|
if (segment2.layer === layer && distancePointToSegment(point6, segment2.start, segment2.end) < 1e-8) {
|
|
28820
|
-
const offset =
|
|
28820
|
+
const offset = length8 + distance9(segment2.start, point6);
|
|
28821
28821
|
if (!positions.some((p) => Math.abs(p.offset - offset) < 1e-8))
|
|
28822
28822
|
positions.push({ index: index2, offset });
|
|
28823
28823
|
}
|
|
28824
|
-
|
|
28824
|
+
length8 += distance9(segment2.start, segment2.end);
|
|
28825
28825
|
}
|
|
28826
28826
|
if (positions.length !== 1) return null;
|
|
28827
28827
|
let index = positions[0].index;
|
|
@@ -28884,12 +28884,12 @@ function boundaryTerminalPlanIsSelfClear(params) {
|
|
|
28884
28884
|
if (Math.abs(ux * vy - uy * vx) >= 1e-10 || ux * vx + uy * vy < 0) break;
|
|
28885
28885
|
runStart = previous.start;
|
|
28886
28886
|
}
|
|
28887
|
-
const
|
|
28888
|
-
if (
|
|
28889
|
-
const trim = Math.min(maximumJoinLength,
|
|
28887
|
+
const length8 = distance9(runStart, cut);
|
|
28888
|
+
if (length8 < 1e-10) return false;
|
|
28889
|
+
const trim = Math.min(maximumJoinLength, length8 / 3);
|
|
28890
28890
|
cut = {
|
|
28891
|
-
x: cut.x + (runStart.x - cut.x) * trim /
|
|
28892
|
-
y: cut.y + (runStart.y - cut.y) * trim /
|
|
28891
|
+
x: cut.x + (runStart.x - cut.x) * trim / length8,
|
|
28892
|
+
y: cut.y + (runStart.y - cut.y) * trim / length8
|
|
28893
28893
|
};
|
|
28894
28894
|
}
|
|
28895
28895
|
const suffix = terminalSuffixAt(plan.segments, cut, start.layer);
|
|
@@ -33562,13 +33562,13 @@ function* sourcePrefixFoldShortcuts(plan, clearance) {
|
|
|
33562
33562
|
if (first < 0) return;
|
|
33563
33563
|
const pitch = prefix[first].width + clearance;
|
|
33564
33564
|
for (let start = first; start >= Math.max(0, first - 3); start--) {
|
|
33565
|
-
let
|
|
33565
|
+
let length8 = 0;
|
|
33566
33566
|
for (let end = start; end < Math.min(prefix.length, first + 8); end++) {
|
|
33567
33567
|
const segment2 = prefix[end];
|
|
33568
33568
|
if (segment2.layer !== plan.sourceLayer || end > start && distance9(prefix[end - 1].end, segment2.start) > 1e-7)
|
|
33569
33569
|
break;
|
|
33570
|
-
|
|
33571
|
-
if (
|
|
33570
|
+
length8 += distance9(segment2.start, segment2.end);
|
|
33571
|
+
if (length8 > 4 * pitch + 1e-7) break;
|
|
33572
33572
|
if (end <= first) continue;
|
|
33573
33573
|
const a = prefix[start].start, b = segment2.end, dx = b.x - a.x, dy = b.y - a.y, diagonal = Math.min(Math.abs(dx), Math.abs(dy));
|
|
33574
33574
|
for (const bend of [
|
|
@@ -33581,7 +33581,7 @@ function* sourcePrefixFoldShortcuts(plan, clearance) {
|
|
|
33581
33581
|
y: b.y - Math.sign(dy) * diagonal
|
|
33582
33582
|
}
|
|
33583
33583
|
]) {
|
|
33584
|
-
if (distance9(a, bend) + distance9(bend, b) >=
|
|
33584
|
+
if (distance9(a, bend) + distance9(bend, b) >= length8 - 1e-7) continue;
|
|
33585
33585
|
yield [
|
|
33586
33586
|
prefix[0].start,
|
|
33587
33587
|
...prefix.slice(0, start).map((s) => s.end),
|
|
@@ -33711,8 +33711,8 @@ function repairSourcePadReentries(params) {
|
|
|
33711
33711
|
const key = JSON.stringify([anchor, points]);
|
|
33712
33712
|
if (seen.has(key)) continue;
|
|
33713
33713
|
seen.add(key);
|
|
33714
|
-
const
|
|
33715
|
-
proposals.push({ anchor, points, length:
|
|
33714
|
+
const length8 = points.slice(1).reduce((sum, p, i) => sum + distance9(points[i], p), 0) + prefix.slice(anchor).reduce((sum, s) => sum + distance9(s.start, s.end), 0);
|
|
33715
|
+
proposals.push({ anchor, points, length: length8 });
|
|
33716
33716
|
}
|
|
33717
33717
|
}
|
|
33718
33718
|
}
|
|
@@ -37514,9 +37514,9 @@ function getFreeBoundaryTracks(params) {
|
|
|
37514
37514
|
for (const via of vias) {
|
|
37515
37515
|
if (!via.spanLayers.includes(targetLayer2)) continue;
|
|
37516
37516
|
const radius = via.diameter / 2 + traceWidth / 2 + clearance;
|
|
37517
|
-
const
|
|
37518
|
-
if (
|
|
37519
|
-
const extent = Math.sqrt(radius * radius -
|
|
37517
|
+
const distance23 = Math.abs(via.center[across] - edge);
|
|
37518
|
+
if (distance23 >= radius) continue;
|
|
37519
|
+
const extent = Math.sqrt(radius * radius - distance23 * distance23);
|
|
37520
37520
|
blocked.push([via.center[along] - extent, via.center[along] + extent]);
|
|
37521
37521
|
}
|
|
37522
37522
|
const gaps = [];
|
|
@@ -38731,8 +38731,8 @@ var LayerRoutingAttempts = class {
|
|
|
38731
38731
|
|
|
38732
38732
|
// node_modules/@tscircuit/fanout-solver/lib/get-boundary-approach-reservations.ts
|
|
38733
38733
|
function getBoundaryApproachReservations(params) {
|
|
38734
|
-
const
|
|
38735
|
-
if (!Number.isFinite(
|
|
38734
|
+
const length8 = params.traceWidth + params.clearance;
|
|
38735
|
+
if (!Number.isFinite(length8) || !(params.traceWidth > 0) || params.clearance < 0)
|
|
38736
38736
|
throw new Error("Boundary approach reservations require valid trace rules");
|
|
38737
38737
|
return params.buses.filter(
|
|
38738
38738
|
(bus) => bus.termination.type === "boundary" && !params.excludedBusIds.has(bus.busId)
|
|
@@ -38749,10 +38749,10 @@ function getBoundaryApproachReservations(params) {
|
|
|
38749
38749
|
`Missing boundary approach target for ${connection.connectionIndex}`
|
|
38750
38750
|
);
|
|
38751
38751
|
const start = { ...end };
|
|
38752
|
-
if (bus.exitEdge === "bottom") start.y +=
|
|
38753
|
-
else if (bus.exitEdge === "top") start.y -=
|
|
38754
|
-
else if (bus.exitEdge === "left") start.x +=
|
|
38755
|
-
else start.x -=
|
|
38752
|
+
if (bus.exitEdge === "bottom") start.y += length8;
|
|
38753
|
+
else if (bus.exitEdge === "top") start.y -= length8;
|
|
38754
|
+
else if (bus.exitEdge === "left") start.x += length8;
|
|
38755
|
+
else start.x -= length8;
|
|
38756
38756
|
return {
|
|
38757
38757
|
type: "pcb_trace",
|
|
38758
38758
|
pcb_trace_id: `fanout-approach-reservation:${connection.connectionIndex}`,
|
|
@@ -43010,7 +43010,7 @@ function validateDifferentialPairs(inputSrj, plansByConnection, issues) {
|
|
|
43010
43010
|
0
|
|
43011
43011
|
)
|
|
43012
43012
|
);
|
|
43013
|
-
if (lengths.some((
|
|
43013
|
+
if (lengths.some((length8) => !Number.isFinite(length8))) {
|
|
43014
43014
|
addIssue2(
|
|
43015
43015
|
issues,
|
|
43016
43016
|
"invalid-differential-pair",
|
|
@@ -49205,6 +49205,8 @@ function getPresetAutoroutingConfig(autorouterConfig, platformConfig) {
|
|
|
49205
49205
|
groupMode: "subcircuit",
|
|
49206
49206
|
preset: "single_layer_fanout"
|
|
49207
49207
|
};
|
|
49208
|
+
case "bus-lanes":
|
|
49209
|
+
return { local: true, groupMode: "subcircuit", preset: "bus_lanes" };
|
|
49208
49210
|
case "fanout":
|
|
49209
49211
|
return {
|
|
49210
49212
|
local: true,
|
|
@@ -49267,6 +49269,1153 @@ function getPresetAutoroutingConfig(autorouterConfig, platformConfig) {
|
|
|
49267
49269
|
}
|
|
49268
49270
|
}
|
|
49269
49271
|
|
|
49272
|
+
// node_modules/@tscircuit/bus-lanes-solver/lib/bus-lanes-solver.ts
|
|
49273
|
+
import { BaseSolver as BaseSolver4 } from "@tscircuit/solver-utils";
|
|
49274
|
+
|
|
49275
|
+
// node_modules/@tscircuit/bus-lanes-solver/lib/geometry.ts
|
|
49276
|
+
var distance12 = (a, b) => Math.hypot(a.x - b.x, a.y - b.y);
|
|
49277
|
+
function pointSegmentDistance(p, edge) {
|
|
49278
|
+
const [a, b] = edge, dx = b.x - a.x, dy = b.y - a.y, t = Math.max(
|
|
49279
|
+
0,
|
|
49280
|
+
Math.min(
|
|
49281
|
+
1,
|
|
49282
|
+
((p.x - a.x) * dx + (p.y - a.y) * dy) / (dx * dx + dy * dy || 1)
|
|
49283
|
+
)
|
|
49284
|
+
);
|
|
49285
|
+
return Math.hypot(p.x - a.x - t * dx, p.y - a.y - t * dy);
|
|
49286
|
+
}
|
|
49287
|
+
var cross2 = (a, b, c) => (b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x);
|
|
49288
|
+
function segmentDistance(ab, cd) {
|
|
49289
|
+
const [a, b] = ab, [c, d] = cd;
|
|
49290
|
+
if (Math.max(a.x, b.x) >= Math.min(c.x, d.x) && Math.max(c.x, d.x) >= Math.min(a.x, b.x) && Math.max(a.y, b.y) >= Math.min(c.y, d.y) && Math.max(c.y, d.y) >= Math.min(a.y, b.y) && cross2(a, b, c) * cross2(a, b, d) <= 0 && cross2(c, d, a) * cross2(c, d, b) <= 0)
|
|
49291
|
+
return 0;
|
|
49292
|
+
return Math.min(
|
|
49293
|
+
pointSegmentDistance(a, cd),
|
|
49294
|
+
pointSegmentDistance(b, cd),
|
|
49295
|
+
pointSegmentDistance(c, ab),
|
|
49296
|
+
pointSegmentDistance(d, ab)
|
|
49297
|
+
);
|
|
49298
|
+
}
|
|
49299
|
+
var length = (path) => path.slice(1).reduce((sum, p, i) => sum + distance12(path[i], p), 0);
|
|
49300
|
+
function simplify(path) {
|
|
49301
|
+
return path.filter(
|
|
49302
|
+
(p, i) => !i || i === path.length - 1 || Math.abs(cross2(path[i - 1], p, path[i + 1])) > 1e-9
|
|
49303
|
+
);
|
|
49304
|
+
}
|
|
49305
|
+
|
|
49306
|
+
// node_modules/@tscircuit/bus-lanes-solver/lib/vector-scene.ts
|
|
49307
|
+
function fixedCopper(input) {
|
|
49308
|
+
const result = [];
|
|
49309
|
+
for (const o of input.obstacles)
|
|
49310
|
+
for (const layer of o.layers)
|
|
49311
|
+
result.push({
|
|
49312
|
+
a: o.center,
|
|
49313
|
+
b: o.center,
|
|
49314
|
+
radius: 0,
|
|
49315
|
+
layer,
|
|
49316
|
+
owners: o.connectedTo,
|
|
49317
|
+
rect: {
|
|
49318
|
+
minX: o.center.x - o.width / 2,
|
|
49319
|
+
maxX: o.center.x + o.width / 2,
|
|
49320
|
+
minY: o.center.y - o.height / 2,
|
|
49321
|
+
maxY: o.center.y + o.height / 2
|
|
49322
|
+
}
|
|
49323
|
+
});
|
|
49324
|
+
const layers = Array.from(
|
|
49325
|
+
{ length: input.layerCount },
|
|
49326
|
+
(_, i) => i === 0 ? "top" : i === input.layerCount - 1 ? "bottom" : `inner${i}`
|
|
49327
|
+
);
|
|
49328
|
+
for (const t of input.traces ?? [])
|
|
49329
|
+
for (let i = 0; i < t.route.length; i++) {
|
|
49330
|
+
const p = t.route[i], q = t.route[i + 1], owners = [t.connection_name ?? "", t.source_trace_id ?? ""];
|
|
49331
|
+
if (p.route_type === "via") {
|
|
49332
|
+
const a = layers.indexOf(p.from_layer), b = layers.indexOf(p.to_layer);
|
|
49333
|
+
for (const layer of p.layers ?? layers.slice(Math.min(a, b), Math.max(a, b) + 1))
|
|
49334
|
+
result.push({
|
|
49335
|
+
a: p,
|
|
49336
|
+
b: p,
|
|
49337
|
+
radius: (p.via_diameter ?? 0.3) / 2,
|
|
49338
|
+
layer,
|
|
49339
|
+
owners
|
|
49340
|
+
});
|
|
49341
|
+
} else if (q?.route_type === "wire") {
|
|
49342
|
+
if (p.layer !== q.layer)
|
|
49343
|
+
throw Error("Fixed trace changes layer without a via");
|
|
49344
|
+
result.push({ a: p, b: q, radius: p.width / 2, layer: p.layer, owners });
|
|
49345
|
+
}
|
|
49346
|
+
if (q && p.route_type !== q.route_type && distance12(p, q) > 1e-10) {
|
|
49347
|
+
const wire = p.route_type === "wire" ? p : q;
|
|
49348
|
+
result.push({
|
|
49349
|
+
a: p,
|
|
49350
|
+
b: q,
|
|
49351
|
+
radius: wire.width / 2,
|
|
49352
|
+
layer: wire.layer,
|
|
49353
|
+
owners
|
|
49354
|
+
});
|
|
49355
|
+
}
|
|
49356
|
+
}
|
|
49357
|
+
return result;
|
|
49358
|
+
}
|
|
49359
|
+
function routeCopper(t) {
|
|
49360
|
+
return t.route.slice(1).map((p, i) => ({
|
|
49361
|
+
a: t.route[i],
|
|
49362
|
+
b: p,
|
|
49363
|
+
radius: p.width / 2,
|
|
49364
|
+
layer: p.layer,
|
|
49365
|
+
owners: [t.connection_name ?? ""]
|
|
49366
|
+
}));
|
|
49367
|
+
}
|
|
49368
|
+
var intersectsRect = (a, b, r) => {
|
|
49369
|
+
let t0 = 0, t1 = 1;
|
|
49370
|
+
for (const [origin, delta, min, max] of [
|
|
49371
|
+
[a.x, b.x - a.x, r.minX, r.maxX],
|
|
49372
|
+
[a.y, b.y - a.y, r.minY, r.maxY]
|
|
49373
|
+
]) {
|
|
49374
|
+
if (Math.abs(delta) < 1e-12) {
|
|
49375
|
+
if (origin < min || origin > max) return false;
|
|
49376
|
+
continue;
|
|
49377
|
+
}
|
|
49378
|
+
let lo = (min - origin) / delta, hi = (max - origin) / delta;
|
|
49379
|
+
if (lo > hi) [lo, hi] = [hi, lo];
|
|
49380
|
+
t0 = Math.max(t0, lo);
|
|
49381
|
+
t1 = Math.min(t1, hi);
|
|
49382
|
+
if (t0 > t1) return false;
|
|
49383
|
+
}
|
|
49384
|
+
return true;
|
|
49385
|
+
};
|
|
49386
|
+
function clearanceToCopper(a, b, c) {
|
|
49387
|
+
if (!c.rect) return segmentDistance([a, b], [c.a, c.b]) - c.radius;
|
|
49388
|
+
const r = c.rect;
|
|
49389
|
+
if (intersectsRect(a, b, r)) return 0;
|
|
49390
|
+
const corners = [
|
|
49391
|
+
{ x: r.minX, y: r.minY },
|
|
49392
|
+
{ x: r.maxX, y: r.minY },
|
|
49393
|
+
{ x: r.maxX, y: r.maxY },
|
|
49394
|
+
{ x: r.minX, y: r.maxY }
|
|
49395
|
+
];
|
|
49396
|
+
return Math.min(
|
|
49397
|
+
...corners.map(
|
|
49398
|
+
(p, i) => segmentDistance([a, b], [p, corners[(i + 1) % 4]])
|
|
49399
|
+
)
|
|
49400
|
+
);
|
|
49401
|
+
}
|
|
49402
|
+
var VectorScene = class {
|
|
49403
|
+
constructor(input, connection, width, all) {
|
|
49404
|
+
this.input = input;
|
|
49405
|
+
this.connection = connection;
|
|
49406
|
+
this.width = width;
|
|
49407
|
+
this.owners = new Set(
|
|
49408
|
+
[
|
|
49409
|
+
connection.name,
|
|
49410
|
+
connection.source_trace_id,
|
|
49411
|
+
...connection.pointsToConnect.flatMap((p) => [
|
|
49412
|
+
p.pointId,
|
|
49413
|
+
p.pcb_port_id
|
|
49414
|
+
])
|
|
49415
|
+
].filter((s) => !!s)
|
|
49416
|
+
);
|
|
49417
|
+
this.copper = all.filter(
|
|
49418
|
+
(c) => c.layer === connection.pointsToConnect[0].layer && !c.owners.some((n) => this.owners.has(n))
|
|
49419
|
+
);
|
|
49420
|
+
this.margin = width / 2 + (input.minTraceToPadEdgeClearance ?? input.defaultObstacleMargin ?? 0.075);
|
|
49421
|
+
}
|
|
49422
|
+
input;
|
|
49423
|
+
connection;
|
|
49424
|
+
width;
|
|
49425
|
+
copper;
|
|
49426
|
+
owners;
|
|
49427
|
+
margin;
|
|
49428
|
+
visible(a, b) {
|
|
49429
|
+
const m = this.width / 2 + (this.input.minBoardEdgeClearance ?? 0), r = this.input.bounds;
|
|
49430
|
+
if ([a, b].some(
|
|
49431
|
+
(p) => p.x < r.minX + m - 1e-9 || p.x > r.maxX - m + 1e-9 || p.y < r.minY + m - 1e-9 || p.y > r.maxY - m + 1e-9
|
|
49432
|
+
))
|
|
49433
|
+
return false;
|
|
49434
|
+
const minX = Math.min(a.x, b.x) - this.margin, maxX = Math.max(a.x, b.x) + this.margin, minY = Math.min(a.y, b.y) - this.margin, maxY = Math.max(a.y, b.y) + this.margin;
|
|
49435
|
+
for (const c of this.copper) {
|
|
49436
|
+
const r2 = c.rect ?? {
|
|
49437
|
+
minX: Math.min(c.a.x, c.b.x) - c.radius,
|
|
49438
|
+
maxX: Math.max(c.a.x, c.b.x) + c.radius,
|
|
49439
|
+
minY: Math.min(c.a.y, c.b.y) - c.radius,
|
|
49440
|
+
maxY: Math.max(c.a.y, c.b.y) + c.radius
|
|
49441
|
+
};
|
|
49442
|
+
if (r2.minX > maxX || r2.maxX < minX || r2.minY > maxY || r2.maxY < minY)
|
|
49443
|
+
continue;
|
|
49444
|
+
if (clearanceToCopper(a, b, c) < this.margin - 1e-8) return false;
|
|
49445
|
+
}
|
|
49446
|
+
return true;
|
|
49447
|
+
}
|
|
49448
|
+
pathVisible(path) {
|
|
49449
|
+
return path.slice(1).every((b, i) => this.visible(path[i], b));
|
|
49450
|
+
}
|
|
49451
|
+
/** Vertices of circumscribed octagonal Minkowski offsets. Their edges are
|
|
49452
|
+
* horizontal, vertical or 45 degrees, including circular vias and trace caps. */
|
|
49453
|
+
vertices() {
|
|
49454
|
+
const result = [], k = Math.SQRT2 - 1, epsilon = 1e-5;
|
|
49455
|
+
for (const c of this.copper) {
|
|
49456
|
+
if (c.rect) {
|
|
49457
|
+
const r = c.rect, m = this.margin + epsilon;
|
|
49458
|
+
result.push(
|
|
49459
|
+
{ x: r.minX - m, y: r.minY - m },
|
|
49460
|
+
{ x: r.minX - m, y: r.maxY + m },
|
|
49461
|
+
{ x: r.maxX + m, y: r.minY - m },
|
|
49462
|
+
{ x: r.maxX + m, y: r.maxY + m }
|
|
49463
|
+
);
|
|
49464
|
+
} else {
|
|
49465
|
+
const r = c.radius + this.margin + epsilon;
|
|
49466
|
+
for (const p of distance12(c.a, c.b) < 1e-9 ? [c.a] : [c.a, c.b])
|
|
49467
|
+
for (const [x, y] of [
|
|
49468
|
+
[1, k],
|
|
49469
|
+
[k, 1],
|
|
49470
|
+
[-k, 1],
|
|
49471
|
+
[-1, k],
|
|
49472
|
+
[-1, -k],
|
|
49473
|
+
[-k, -1],
|
|
49474
|
+
[k, -1],
|
|
49475
|
+
[1, -k]
|
|
49476
|
+
])
|
|
49477
|
+
result.push({ x: p.x + x * r, y: p.y + y * r });
|
|
49478
|
+
}
|
|
49479
|
+
}
|
|
49480
|
+
const seen = /* @__PURE__ */ new Set();
|
|
49481
|
+
return result.filter((p) => {
|
|
49482
|
+
const key = `${p.x.toFixed(9)},${p.y.toFixed(9)}`;
|
|
49483
|
+
if (seen.has(key)) return false;
|
|
49484
|
+
seen.add(key);
|
|
49485
|
+
return this.visible(p, p);
|
|
49486
|
+
});
|
|
49487
|
+
}
|
|
49488
|
+
};
|
|
49489
|
+
|
|
49490
|
+
// node_modules/@tscircuit/bus-lanes-solver/lib/min-heap.ts
|
|
49491
|
+
var MinHeap2 = class {
|
|
49492
|
+
entries = [];
|
|
49493
|
+
sequence = 0;
|
|
49494
|
+
get length() {
|
|
49495
|
+
return this.entries.length;
|
|
49496
|
+
}
|
|
49497
|
+
values() {
|
|
49498
|
+
return this.entries.map((e) => e.value);
|
|
49499
|
+
}
|
|
49500
|
+
before(a, b) {
|
|
49501
|
+
return a.value.f < b.value.f || a.value.f === b.value.f && a.sequence < b.sequence;
|
|
49502
|
+
}
|
|
49503
|
+
push(value) {
|
|
49504
|
+
const entry = { value, sequence: this.sequence++ };
|
|
49505
|
+
let i = this.entries.length;
|
|
49506
|
+
this.entries.push(entry);
|
|
49507
|
+
while (i > 0) {
|
|
49508
|
+
const parent = i - 1 >> 1;
|
|
49509
|
+
if (!this.before(entry, this.entries[parent])) break;
|
|
49510
|
+
this.entries[i] = this.entries[parent];
|
|
49511
|
+
i = parent;
|
|
49512
|
+
}
|
|
49513
|
+
this.entries[i] = entry;
|
|
49514
|
+
}
|
|
49515
|
+
pop() {
|
|
49516
|
+
const first = this.entries[0], last = this.entries.pop();
|
|
49517
|
+
if (this.entries.length) {
|
|
49518
|
+
let i = 0;
|
|
49519
|
+
while (i * 2 + 1 < this.entries.length) {
|
|
49520
|
+
let child = i * 2 + 1;
|
|
49521
|
+
if (child + 1 < this.entries.length && this.before(this.entries[child + 1], this.entries[child]))
|
|
49522
|
+
child++;
|
|
49523
|
+
if (!this.before(this.entries[child], last)) break;
|
|
49524
|
+
this.entries[i] = this.entries[child];
|
|
49525
|
+
i = child;
|
|
49526
|
+
}
|
|
49527
|
+
this.entries[i] = last;
|
|
49528
|
+
}
|
|
49529
|
+
return first.value;
|
|
49530
|
+
}
|
|
49531
|
+
};
|
|
49532
|
+
|
|
49533
|
+
// node_modules/@tscircuit/bus-lanes-solver/lib/vector-visibility.ts
|
|
49534
|
+
function connectors(a, b) {
|
|
49535
|
+
const dx = b.x - a.x, dy = b.y - a.y, sx = Math.sign(dx), sy = Math.sign(dy), d = Math.min(Math.abs(dx), Math.abs(dy));
|
|
49536
|
+
if (Math.min(Math.abs(dx), Math.abs(dy)) < 1e-10 || Math.abs(Math.abs(dx) - Math.abs(dy)) < 1e-10)
|
|
49537
|
+
return [[a, b]];
|
|
49538
|
+
const lead = (Math.max(Math.abs(dx), Math.abs(dy)) - d) / 2;
|
|
49539
|
+
const centered = Math.abs(dx) > Math.abs(dy) ? [a, { x: a.x + sx * lead, y: a.y }, { x: b.x - sx * lead, y: b.y }, b] : [a, { x: a.x, y: a.y + sy * lead }, { x: b.x, y: b.y - sy * lead }, b];
|
|
49540
|
+
return [
|
|
49541
|
+
centered,
|
|
49542
|
+
[a, { x: a.x + sx * d, y: a.y + sy * d }, b],
|
|
49543
|
+
[a, { x: b.x - sx * d, y: b.y - sy * d }, b],
|
|
49544
|
+
[a, { x: a.x, y: b.y }, b],
|
|
49545
|
+
[a, { x: b.x, y: a.y }, b]
|
|
49546
|
+
];
|
|
49547
|
+
}
|
|
49548
|
+
var VectorVisibilitySearch = class {
|
|
49549
|
+
constructor(scene, start, end) {
|
|
49550
|
+
this.scene = scene;
|
|
49551
|
+
this.start = start;
|
|
49552
|
+
this.end = end;
|
|
49553
|
+
this.vertices = [start, end];
|
|
49554
|
+
this.open.push({ id: 0, g: 0, f: distance12(start, end) });
|
|
49555
|
+
this.best.set(0, 0);
|
|
49556
|
+
}
|
|
49557
|
+
scene;
|
|
49558
|
+
start;
|
|
49559
|
+
end;
|
|
49560
|
+
vertices;
|
|
49561
|
+
open = new MinHeap2();
|
|
49562
|
+
best = /* @__PURE__ */ new Map();
|
|
49563
|
+
expanded = 0;
|
|
49564
|
+
failed = false;
|
|
49565
|
+
solved = false;
|
|
49566
|
+
result = [];
|
|
49567
|
+
geometryLoaded = false;
|
|
49568
|
+
current;
|
|
49569
|
+
visibleEdges = [];
|
|
49570
|
+
step() {
|
|
49571
|
+
if (!this.geometryLoaded) {
|
|
49572
|
+
this.geometryLoaded = true;
|
|
49573
|
+
const lowerBound = Math.max(
|
|
49574
|
+
Math.abs(this.end.x - this.start.x),
|
|
49575
|
+
Math.abs(this.end.y - this.start.y)
|
|
49576
|
+
) + (Math.SQRT2 - 1) * Math.min(
|
|
49577
|
+
Math.abs(this.end.x - this.start.x),
|
|
49578
|
+
Math.abs(this.end.y - this.start.y)
|
|
49579
|
+
);
|
|
49580
|
+
for (const path of connectors(this.start, this.end)) {
|
|
49581
|
+
if (length(path) > lowerBound + 1e-9 || !this.scene.pathVisible(path))
|
|
49582
|
+
continue;
|
|
49583
|
+
this.visibleEdges = [path];
|
|
49584
|
+
this.result = simplify(path);
|
|
49585
|
+
this.solved = true;
|
|
49586
|
+
this.expanded = 1;
|
|
49587
|
+
return;
|
|
49588
|
+
}
|
|
49589
|
+
this.vertices.push(...this.scene.vertices());
|
|
49590
|
+
}
|
|
49591
|
+
if (!this.open.length) {
|
|
49592
|
+
this.failed = true;
|
|
49593
|
+
return;
|
|
49594
|
+
}
|
|
49595
|
+
const cur = this.open.pop();
|
|
49596
|
+
if (cur.g > (this.best.get(cur.id) ?? Infinity) + 1e-9) return;
|
|
49597
|
+
this.current = cur;
|
|
49598
|
+
this.expanded++;
|
|
49599
|
+
this.visibleEdges = [];
|
|
49600
|
+
if (cur.id === 1) {
|
|
49601
|
+
const edges = [];
|
|
49602
|
+
for (let c = cur; c?.parent; c = c.parent)
|
|
49603
|
+
edges.push(c.edge);
|
|
49604
|
+
this.result = simplify([
|
|
49605
|
+
this.start,
|
|
49606
|
+
...edges.reverse().flatMap((p) => p.slice(1))
|
|
49607
|
+
]);
|
|
49608
|
+
this.solved = true;
|
|
49609
|
+
return;
|
|
49610
|
+
}
|
|
49611
|
+
const from = this.vertices[cur.id];
|
|
49612
|
+
for (let id = 1; id < this.vertices.length; id++) {
|
|
49613
|
+
if (id === cur.id) continue;
|
|
49614
|
+
const to = this.vertices[id], lower = cur.g + distance12(from, to);
|
|
49615
|
+
if (lower >= (this.best.get(id) ?? Infinity) - 1e-9) continue;
|
|
49616
|
+
const candidates = connectors(from, to).sort(
|
|
49617
|
+
(a, b) => length(a) - length(b)
|
|
49618
|
+
);
|
|
49619
|
+
for (const path of candidates) {
|
|
49620
|
+
const g = cur.g + length(path);
|
|
49621
|
+
if (g >= (this.best.get(id) ?? Infinity) - 1e-9) continue;
|
|
49622
|
+
if (!this.scene.pathVisible(path)) continue;
|
|
49623
|
+
this.best.set(id, g);
|
|
49624
|
+
this.open.push({
|
|
49625
|
+
id,
|
|
49626
|
+
g,
|
|
49627
|
+
f: g + distance12(to, this.end),
|
|
49628
|
+
parent: cur,
|
|
49629
|
+
edge: path
|
|
49630
|
+
});
|
|
49631
|
+
if (this.visibleEdges.length < 100) this.visibleEdges.push(path);
|
|
49632
|
+
break;
|
|
49633
|
+
}
|
|
49634
|
+
}
|
|
49635
|
+
}
|
|
49636
|
+
currentPath() {
|
|
49637
|
+
const edges = [];
|
|
49638
|
+
for (let c = this.current; c?.parent; c = c.parent) edges.push(c.edge);
|
|
49639
|
+
return [this.start, ...edges.reverse().flatMap((e) => e.slice(1))];
|
|
49640
|
+
}
|
|
49641
|
+
};
|
|
49642
|
+
|
|
49643
|
+
// node_modules/@tscircuit/bus-lanes-solver/lib/winding-orders.ts
|
|
49644
|
+
function windingOrders(connections) {
|
|
49645
|
+
const orders = [];
|
|
49646
|
+
const seen = /* @__PURE__ */ new Set();
|
|
49647
|
+
const add = (order) => {
|
|
49648
|
+
const key = order.map((c) => c.name).join("\0");
|
|
49649
|
+
if (!seen.has(key)) {
|
|
49650
|
+
seen.add(key);
|
|
49651
|
+
orders.push(order);
|
|
49652
|
+
}
|
|
49653
|
+
};
|
|
49654
|
+
const direction = connections.reduce(
|
|
49655
|
+
(v, c) => ({
|
|
49656
|
+
x: v.x + c.pointsToConnect[1].x - c.pointsToConnect[0].x,
|
|
49657
|
+
y: v.y + c.pointsToConnect[1].y - c.pointsToConnect[0].y
|
|
49658
|
+
}),
|
|
49659
|
+
{ x: 0, y: 0 }
|
|
49660
|
+
);
|
|
49661
|
+
const transverse = (c) => -direction.y * c.pointsToConnect[0].x + direction.x * c.pointsToConnect[0].y;
|
|
49662
|
+
const sweep = [...connections].sort(
|
|
49663
|
+
(a, b) => a.pointsToConnect[0].layer.localeCompare(b.pointsToConnect[0].layer) || transverse(a) - transverse(b) || a.name.localeCompare(b.name)
|
|
49664
|
+
);
|
|
49665
|
+
const span = (endpoint, axis) => Math.max(...connections.map((c) => c.pointsToConnect[endpoint][axis])) - Math.min(...connections.map((c) => c.pointsToConnect[endpoint][axis]));
|
|
49666
|
+
const transverseAxis = span(0, "x") < 1e-7 && span(1, "x") < 1e-7 ? "y" : span(0, "y") < 1e-7 && span(1, "y") < 1e-7 ? "x" : void 0;
|
|
49667
|
+
if (transverseAxis) {
|
|
49668
|
+
const drift = connections.reduce(
|
|
49669
|
+
(s, c) => s + c.pointsToConnect[1][transverseAxis] - c.pointsToConnect[0][transverseAxis],
|
|
49670
|
+
0
|
|
49671
|
+
);
|
|
49672
|
+
if (Math.abs(drift) > 1e-7)
|
|
49673
|
+
add(
|
|
49674
|
+
[...connections].sort(
|
|
49675
|
+
(a, b) => a.pointsToConnect[0].layer.localeCompare(
|
|
49676
|
+
b.pointsToConnect[0].layer
|
|
49677
|
+
) || -Math.sign(drift) * (a.pointsToConnect[0][transverseAxis] - b.pointsToConnect[0][transverseAxis]) || a.name.localeCompare(b.name)
|
|
49678
|
+
)
|
|
49679
|
+
);
|
|
49680
|
+
}
|
|
49681
|
+
add(sweep);
|
|
49682
|
+
add([...sweep].reverse());
|
|
49683
|
+
add(connections);
|
|
49684
|
+
for (const endpoint of [1, 0]) {
|
|
49685
|
+
const center = connections.reduce(
|
|
49686
|
+
(p, c) => ({
|
|
49687
|
+
x: p.x + c.pointsToConnect[endpoint].x / connections.length,
|
|
49688
|
+
y: p.y + c.pointsToConnect[endpoint].y / connections.length
|
|
49689
|
+
}),
|
|
49690
|
+
{ x: 0, y: 0 }
|
|
49691
|
+
);
|
|
49692
|
+
const angle = (c) => Math.atan2(
|
|
49693
|
+
c.pointsToConnect[endpoint].y - center.y,
|
|
49694
|
+
c.pointsToConnect[endpoint].x - center.x
|
|
49695
|
+
);
|
|
49696
|
+
const angular = [...connections].sort(
|
|
49697
|
+
(a, b) => angle(a) - angle(b) || a.name.localeCompare(b.name)
|
|
49698
|
+
);
|
|
49699
|
+
add(angular);
|
|
49700
|
+
add([...angular].reverse());
|
|
49701
|
+
for (const axis of ["x", "y"]) {
|
|
49702
|
+
const other = axis === "x" ? "y" : "x";
|
|
49703
|
+
const sorted = [...connections].sort(
|
|
49704
|
+
(a, b) => a.pointsToConnect[endpoint][axis] - b.pointsToConnect[endpoint][axis] || a.pointsToConnect[endpoint][other] - b.pointsToConnect[endpoint][other]
|
|
49705
|
+
);
|
|
49706
|
+
add(sorted);
|
|
49707
|
+
add([...sorted].reverse());
|
|
49708
|
+
}
|
|
49709
|
+
for (let i = 1; i < angular.length; i++) {
|
|
49710
|
+
const rotated = [...angular.slice(i), ...angular.slice(0, i)];
|
|
49711
|
+
add(rotated);
|
|
49712
|
+
add([...rotated].reverse());
|
|
49713
|
+
}
|
|
49714
|
+
}
|
|
49715
|
+
return orders;
|
|
49716
|
+
}
|
|
49717
|
+
|
|
49718
|
+
// node_modules/@tscircuit/bus-lanes-solver/lib/route-lengths.ts
|
|
49719
|
+
function fixedRouteLength(input, name) {
|
|
49720
|
+
const connection = input.connections.find((c) => c.name === name);
|
|
49721
|
+
return (input.traces ?? []).filter(
|
|
49722
|
+
(t) => t.connection_name === name || t.source_trace_id === (connection?.source_trace_id ?? name)
|
|
49723
|
+
).reduce((sum, t) => sum + length(t.route), 0);
|
|
49724
|
+
}
|
|
49725
|
+
function busLengthReports(input, traces) {
|
|
49726
|
+
return (input.buses ?? []).map((bus) => {
|
|
49727
|
+
const lengths = bus.connectionNames.map((name) => {
|
|
49728
|
+
const route = traces.find((t) => t.connection_name === name);
|
|
49729
|
+
return {
|
|
49730
|
+
name,
|
|
49731
|
+
carrierLengthMm: route ? length(route.route) : null,
|
|
49732
|
+
fixedLengthMm: fixedRouteLength(input, name),
|
|
49733
|
+
totalLengthMm: route ? length(route.route) + fixedRouteLength(input, name) : null
|
|
49734
|
+
};
|
|
49735
|
+
});
|
|
49736
|
+
const complete = lengths.every((l) => l.totalLengthMm !== null);
|
|
49737
|
+
const values = lengths.map((l) => l.totalLengthMm ?? 0);
|
|
49738
|
+
const skewMm = complete && values.length ? Math.max(...values) - Math.min(...values) : null;
|
|
49739
|
+
return {
|
|
49740
|
+
busId: bus.busId,
|
|
49741
|
+
toleranceMm: bus.maxLengthSkew ?? null,
|
|
49742
|
+
skewMm,
|
|
49743
|
+
matched: bus.maxLengthSkew !== void 0 && skewMm !== null && skewMm <= bus.maxLengthSkew + 1e-7,
|
|
49744
|
+
lengths
|
|
49745
|
+
};
|
|
49746
|
+
});
|
|
49747
|
+
}
|
|
49748
|
+
function lengthConstraints(input) {
|
|
49749
|
+
return [
|
|
49750
|
+
...(input.buses ?? []).filter((b) => b.maxLengthSkew !== void 0).map((b) => ({
|
|
49751
|
+
names: b.connectionNames,
|
|
49752
|
+
tolerance: b.maxLengthSkew
|
|
49753
|
+
})),
|
|
49754
|
+
...(input.differentialPairs ?? []).map((p) => ({
|
|
49755
|
+
names: p.connectionNames,
|
|
49756
|
+
tolerance: p.lengthTolerance
|
|
49757
|
+
}))
|
|
49758
|
+
];
|
|
49759
|
+
}
|
|
49760
|
+
function minimumLengthTargets(input, traces) {
|
|
49761
|
+
const targets = new Map(
|
|
49762
|
+
traces.map((t) => [
|
|
49763
|
+
t.connection_name,
|
|
49764
|
+
length(t.route) + fixedRouteLength(input, t.connection_name)
|
|
49765
|
+
])
|
|
49766
|
+
);
|
|
49767
|
+
const constraints = lengthConstraints(input);
|
|
49768
|
+
for (let pass = 0; pass < targets.size; pass++) {
|
|
49769
|
+
let changed = false;
|
|
49770
|
+
for (const { names, tolerance } of constraints) {
|
|
49771
|
+
const floor = Math.max(...names.map((n) => targets.get(n))) - tolerance;
|
|
49772
|
+
for (const name of names)
|
|
49773
|
+
if (targets.get(name) < floor - 1e-9) {
|
|
49774
|
+
targets.set(name, floor);
|
|
49775
|
+
changed = true;
|
|
49776
|
+
}
|
|
49777
|
+
}
|
|
49778
|
+
if (!changed) break;
|
|
49779
|
+
}
|
|
49780
|
+
return targets;
|
|
49781
|
+
}
|
|
49782
|
+
function pairLengthReports(input, traces) {
|
|
49783
|
+
return busLengthReports(
|
|
49784
|
+
{
|
|
49785
|
+
...input,
|
|
49786
|
+
buses: (input.differentialPairs ?? []).map((p, i) => ({
|
|
49787
|
+
busId: `pair_${i}`,
|
|
49788
|
+
connectionNames: p.connectionNames,
|
|
49789
|
+
maxLengthSkew: p.lengthTolerance
|
|
49790
|
+
}))
|
|
49791
|
+
},
|
|
49792
|
+
traces
|
|
49793
|
+
);
|
|
49794
|
+
}
|
|
49795
|
+
|
|
49796
|
+
// node_modules/@tscircuit/bus-lanes-solver/lib/spread-tuning-lanes.ts
|
|
49797
|
+
function spreadTuningLanes(input, traces, pitch) {
|
|
49798
|
+
const dx = traces.reduce((s, t) => s + t.route.at(-1).x - t.route[0].x, 0);
|
|
49799
|
+
const dy = traces.reduce((s, t) => s + t.route.at(-1).y - t.route[0].y, 0);
|
|
49800
|
+
const angle = Math.round(Math.atan2(dy, dx) / (Math.PI / 4)) * Math.PI / 4, ux = Math.cos(angle), uy = Math.sin(angle);
|
|
49801
|
+
const uv = (p) => ({ u: p.x * ux + p.y * uy, v: -p.x * uy + p.y * ux });
|
|
49802
|
+
const xy = (u, v) => ({
|
|
49803
|
+
x: u * ux - v * uy,
|
|
49804
|
+
y: u * uy + v * ux
|
|
49805
|
+
});
|
|
49806
|
+
const result = [];
|
|
49807
|
+
for (const layer of new Set(traces.map((t) => t.route[0].layer))) {
|
|
49808
|
+
const group = traces.filter((t) => t.route[0].layer === layer).sort((a, b) => uv(a.route[0]).v - uv(b.route[0]).v);
|
|
49809
|
+
const center = group.reduce(
|
|
49810
|
+
(s, t) => s + (uv(t.route[0]).v + uv(t.route.at(-1)).v) / 2,
|
|
49811
|
+
0
|
|
49812
|
+
) / group.length;
|
|
49813
|
+
for (const [index, t] of group.entries()) {
|
|
49814
|
+
const a = uv(t.route[0]), b = uv(t.route.at(-1)), v = center + (index - (group.length - 1) / 2) * pitch;
|
|
49815
|
+
const da = Math.abs(v - a.v), db = Math.abs(v - b.v), space = b.u - a.u - da - db;
|
|
49816
|
+
if (space < 1) return null;
|
|
49817
|
+
const lead = space * 0.15;
|
|
49818
|
+
const points = simplify([
|
|
49819
|
+
xy(a.u, a.v),
|
|
49820
|
+
xy(a.u + lead, a.v),
|
|
49821
|
+
xy(a.u + lead + da, v),
|
|
49822
|
+
xy(b.u - lead - db, v),
|
|
49823
|
+
xy(b.u - lead, b.v),
|
|
49824
|
+
xy(b.u, b.v)
|
|
49825
|
+
]);
|
|
49826
|
+
result.push({
|
|
49827
|
+
...t,
|
|
49828
|
+
route: points.map((p) => ({
|
|
49829
|
+
...p,
|
|
49830
|
+
route_type: "wire",
|
|
49831
|
+
layer,
|
|
49832
|
+
width: t.route[0].width
|
|
49833
|
+
}))
|
|
49834
|
+
});
|
|
49835
|
+
}
|
|
49836
|
+
}
|
|
49837
|
+
const copper = [...fixedCopper(input), ...result.flatMap(routeCopper)];
|
|
49838
|
+
for (const t of result) {
|
|
49839
|
+
const c = input.connections.find((c2) => c2.name === t.connection_name);
|
|
49840
|
+
if (!new VectorScene(
|
|
49841
|
+
input,
|
|
49842
|
+
c,
|
|
49843
|
+
t.route[0].width,
|
|
49844
|
+
copper
|
|
49845
|
+
).pathVisible(t.route))
|
|
49846
|
+
return null;
|
|
49847
|
+
}
|
|
49848
|
+
return traces.map(
|
|
49849
|
+
(t) => result.find((r) => r.connection_name === t.connection_name)
|
|
49850
|
+
);
|
|
49851
|
+
}
|
|
49852
|
+
|
|
49853
|
+
// node_modules/@tscircuit/bus-lanes-solver/lib/length-tuning.ts
|
|
49854
|
+
function tuneLengths(input, traces, targets) {
|
|
49855
|
+
const fixed = fixedCopper(input);
|
|
49856
|
+
function* candidates(t, scene) {
|
|
49857
|
+
const connection = input.connections.find(
|
|
49858
|
+
(c) => c.name === t.connection_name
|
|
49859
|
+
);
|
|
49860
|
+
const width = t.route[0].width;
|
|
49861
|
+
const delta = targets.get(connection.name) - length(t.route) - fixedRouteLength(input, connection.name);
|
|
49862
|
+
if (delta < 1e-8) {
|
|
49863
|
+
yield t;
|
|
49864
|
+
return;
|
|
49865
|
+
}
|
|
49866
|
+
const clearance = input.minTraceToPadEdgeClearance ?? input.defaultObstacleMargin ?? 0.075;
|
|
49867
|
+
const returnSpacing = Math.max(width + clearance, 3 * width);
|
|
49868
|
+
const pitch = 2 * (returnSpacing + 2 * width);
|
|
49869
|
+
const segments = t.route.slice(1).map((p, i) => ({ i, span: distance12(t.route[i], p) })).sort((a, b) => b.span - a.span);
|
|
49870
|
+
for (const { i } of segments) {
|
|
49871
|
+
const a = t.route[i], b = t.route[i + 1], span = distance12(a, b);
|
|
49872
|
+
if (span < 0.01) continue;
|
|
49873
|
+
const ux = (b.x - a.x) / span, uy = (b.y - a.y) / span;
|
|
49874
|
+
const maximumTeeth = Math.floor(span * 0.9 / pitch);
|
|
49875
|
+
const preferredTeeth = Math.min(
|
|
49876
|
+
maximumTeeth,
|
|
49877
|
+
Math.max(2, Math.ceil(delta / (12 * width)))
|
|
49878
|
+
);
|
|
49879
|
+
const counts = Array.from({ length: maximumTeeth }, (_, i2) => i2 + 1).sort(
|
|
49880
|
+
(a2, b2) => Math.abs(a2 - preferredTeeth) - Math.abs(b2 - preferredTeeth) || b2 - a2
|
|
49881
|
+
);
|
|
49882
|
+
for (const teeth of counts) {
|
|
49883
|
+
for (const fraction of [0.9, 0.65, 0.4]) {
|
|
49884
|
+
const w = span * fraction / teeth;
|
|
49885
|
+
if (w < pitch) continue;
|
|
49886
|
+
const c = Math.min(
|
|
49887
|
+
delta / (2 * teeth),
|
|
49888
|
+
w / 10,
|
|
49889
|
+
(w / 2 - returnSpacing) / 2
|
|
49890
|
+
);
|
|
49891
|
+
const h = delta / (2 * teeth) + 2 * c * (2 - Math.SQRT2);
|
|
49892
|
+
for (const phase of [0.5, 0, 1])
|
|
49893
|
+
for (const side of [1, -1]) {
|
|
49894
|
+
const at = (x, y) => ({
|
|
49895
|
+
x: a.x + ux * x - uy * y * side,
|
|
49896
|
+
y: a.y + uy * x + ux * y * side
|
|
49897
|
+
});
|
|
49898
|
+
const bump = [at(0, 0)];
|
|
49899
|
+
for (let tooth = 0; tooth < teeth; tooth++) {
|
|
49900
|
+
const offset = span * (1 - fraction) * (0.05 + 0.9 * phase) + tooth * w, gap = w * 0.5;
|
|
49901
|
+
bump.push(
|
|
49902
|
+
...[
|
|
49903
|
+
[offset, 0],
|
|
49904
|
+
[offset + c, c],
|
|
49905
|
+
[offset + c, h - c],
|
|
49906
|
+
[offset + 2 * c, h],
|
|
49907
|
+
[offset + gap - 2 * c, h],
|
|
49908
|
+
[offset + gap - c, h - c],
|
|
49909
|
+
[offset + gap - c, c],
|
|
49910
|
+
[offset + gap, 0]
|
|
49911
|
+
].map(([x, y]) => at(x, y))
|
|
49912
|
+
);
|
|
49913
|
+
}
|
|
49914
|
+
bump.push(at(span, 0));
|
|
49915
|
+
if (!scene.pathVisible(bump)) continue;
|
|
49916
|
+
const next = simplify([
|
|
49917
|
+
...t.route.slice(0, i),
|
|
49918
|
+
...bump,
|
|
49919
|
+
...t.route.slice(i + 2)
|
|
49920
|
+
]);
|
|
49921
|
+
if (Math.abs(
|
|
49922
|
+
length(next) + fixedRouteLength(input, connection.name) - targets.get(connection.name)
|
|
49923
|
+
) > 1e-6)
|
|
49924
|
+
continue;
|
|
49925
|
+
if (!tuningPathIsSelfClear(next, returnSpacing)) continue;
|
|
49926
|
+
yield {
|
|
49927
|
+
...t,
|
|
49928
|
+
route: next.map((p) => ({
|
|
49929
|
+
...p,
|
|
49930
|
+
route_type: "wire",
|
|
49931
|
+
layer: connection.pointsToConnect[0].layer,
|
|
49932
|
+
width
|
|
49933
|
+
}))
|
|
49934
|
+
};
|
|
49935
|
+
}
|
|
49936
|
+
}
|
|
49937
|
+
}
|
|
49938
|
+
}
|
|
49939
|
+
}
|
|
49940
|
+
const result = [...traces];
|
|
49941
|
+
const pending = new Set(traces.map((_, i) => i));
|
|
49942
|
+
let changed = true;
|
|
49943
|
+
while (pending.size && changed) {
|
|
49944
|
+
changed = false;
|
|
49945
|
+
for (const index of pending) {
|
|
49946
|
+
const connection = input.connections.find(
|
|
49947
|
+
(c) => c.name === traces[index].connection_name
|
|
49948
|
+
);
|
|
49949
|
+
const scene = new VectorScene(
|
|
49950
|
+
input,
|
|
49951
|
+
connection,
|
|
49952
|
+
traces[index].route[0].width,
|
|
49953
|
+
[...fixed, ...result.flatMap(routeCopper)]
|
|
49954
|
+
);
|
|
49955
|
+
const next = candidates(traces[index], scene).next().value;
|
|
49956
|
+
if (!next) continue;
|
|
49957
|
+
result[index] = next;
|
|
49958
|
+
pending.delete(index);
|
|
49959
|
+
changed = true;
|
|
49960
|
+
}
|
|
49961
|
+
}
|
|
49962
|
+
if (pending.size)
|
|
49963
|
+
throw Error(
|
|
49964
|
+
`Insufficient tuning clearance for ${[...pending].map((i) => traces[i].connection_name).join(", ")}`
|
|
49965
|
+
);
|
|
49966
|
+
return result;
|
|
49967
|
+
}
|
|
49968
|
+
function tuningPathIsSelfClear(path, required) {
|
|
49969
|
+
const cumulative = [0];
|
|
49970
|
+
for (let i = 1; i < path.length; i++)
|
|
49971
|
+
cumulative.push(cumulative[i - 1] + distance12(path[i - 1], path[i]));
|
|
49972
|
+
for (let i = 0; i < path.length - 1; i++)
|
|
49973
|
+
for (let j = i + 2; j < path.length - 1; j++) {
|
|
49974
|
+
if (cumulative[j] - cumulative[i + 1] <= required + 1e-8) continue;
|
|
49975
|
+
const a = path[i], b = path[i + 1], c = path[j], d = path[j + 1];
|
|
49976
|
+
if (Math.max(a.x, b.x) + required < Math.min(c.x, d.x) || Math.max(c.x, d.x) + required < Math.min(a.x, b.x) || Math.max(a.y, b.y) + required < Math.min(c.y, d.y) || Math.max(c.y, d.y) + required < Math.min(a.y, b.y))
|
|
49977
|
+
continue;
|
|
49978
|
+
if (segmentDistance([a, b], [c, d]) >= required - 1e-8) continue;
|
|
49979
|
+
let sx = 0, sy = 0;
|
|
49980
|
+
for (let k = i; k <= j; k++) {
|
|
49981
|
+
const dx = path[k + 1].x - path[k].x, dy = path[k + 1].y - path[k].y;
|
|
49982
|
+
if (Math.abs(dx) > 1e-8) {
|
|
49983
|
+
if (sx && sx !== Math.sign(dx)) return false;
|
|
49984
|
+
sx = Math.sign(dx);
|
|
49985
|
+
}
|
|
49986
|
+
if (Math.abs(dy) > 1e-8) {
|
|
49987
|
+
if (sy && sy !== Math.sign(dy)) return false;
|
|
49988
|
+
sy = Math.sign(dy);
|
|
49989
|
+
}
|
|
49990
|
+
}
|
|
49991
|
+
}
|
|
49992
|
+
return true;
|
|
49993
|
+
}
|
|
49994
|
+
|
|
49995
|
+
// node_modules/@tscircuit/bus-lanes-solver/lib/layer-colors.ts
|
|
49996
|
+
var layerColors = {
|
|
49997
|
+
top: "#dc2626",
|
|
49998
|
+
inner1: "#ca8a04",
|
|
49999
|
+
inner2: "#16a34a",
|
|
50000
|
+
inner3: "#0891b2",
|
|
50001
|
+
inner4: "#9333ea",
|
|
50002
|
+
inner5: "#ea580c",
|
|
50003
|
+
inner6: "#db2777",
|
|
50004
|
+
bottom: "#2563eb"
|
|
50005
|
+
};
|
|
50006
|
+
var layerColor = (layer) => layerColors[layer] ?? "#64748b";
|
|
50007
|
+
|
|
50008
|
+
// node_modules/@tscircuit/bus-lanes-solver/lib/bus-lanes-solver.ts
|
|
50009
|
+
var BusLanesSolver = class extends BaseSolver4 {
|
|
50010
|
+
input;
|
|
50011
|
+
options;
|
|
50012
|
+
phase = "validate";
|
|
50013
|
+
failureCode = null;
|
|
50014
|
+
traces = [];
|
|
50015
|
+
widths = /* @__PURE__ */ new Map();
|
|
50016
|
+
fixed = [];
|
|
50017
|
+
orders = [];
|
|
50018
|
+
attempt = 0;
|
|
50019
|
+
lane = 0;
|
|
50020
|
+
search;
|
|
50021
|
+
bestPartial = [];
|
|
50022
|
+
constructor(input, options = {}) {
|
|
50023
|
+
super();
|
|
50024
|
+
this.input = structuredClone(input);
|
|
50025
|
+
this.options = options;
|
|
50026
|
+
this.MAX_ITERATIONS = options.maxSearchIterations ?? 2e5;
|
|
50027
|
+
}
|
|
50028
|
+
getConstructorParams() {
|
|
50029
|
+
return [this.input, this.options];
|
|
50030
|
+
}
|
|
50031
|
+
getOutput() {
|
|
50032
|
+
if (!this.solved) throw Error(this.error ?? "Bus lanes are not solved");
|
|
50033
|
+
return {
|
|
50034
|
+
...this.input,
|
|
50035
|
+
traces: [...this.input.traces ?? [], ...this.traces]
|
|
50036
|
+
};
|
|
50037
|
+
}
|
|
50038
|
+
fail(code, message) {
|
|
50039
|
+
this.failureCode = code;
|
|
50040
|
+
this.error = message;
|
|
50041
|
+
this.failed = true;
|
|
50042
|
+
this.phase = "failed";
|
|
50043
|
+
}
|
|
50044
|
+
tryFinalAcceptance() {
|
|
50045
|
+
if (!this.solved)
|
|
50046
|
+
this.fail(
|
|
50047
|
+
"search_budget_exhausted",
|
|
50048
|
+
"Vector visibility search budget exhausted"
|
|
50049
|
+
);
|
|
50050
|
+
}
|
|
50051
|
+
initialize() {
|
|
50052
|
+
const input = this.input;
|
|
50053
|
+
if (input.outline?.length) {
|
|
50054
|
+
this.fail("unsupported_outline", "Custom board outlines are unsupported");
|
|
50055
|
+
return;
|
|
50056
|
+
}
|
|
50057
|
+
if (input.differentialPairs?.some(
|
|
50058
|
+
(p) => p.traceGap !== void 0 || p.maxUncoupledLength !== void 0
|
|
50059
|
+
)) {
|
|
50060
|
+
this.fail(
|
|
50061
|
+
"unsupported_coupling",
|
|
50062
|
+
"Coupled differential geometry is not supported"
|
|
50063
|
+
);
|
|
50064
|
+
return;
|
|
50065
|
+
}
|
|
50066
|
+
const names = /* @__PURE__ */ new Set();
|
|
50067
|
+
for (const c of input.connections) {
|
|
50068
|
+
if (names.has(c.name)) throw Error(`Duplicate connection ${c.name}`);
|
|
50069
|
+
names.add(c.name);
|
|
50070
|
+
if (c.pointsToConnect.length !== 2) {
|
|
50071
|
+
this.fail(
|
|
50072
|
+
"invalid_terminals",
|
|
50073
|
+
`${c.name}: exactly two terminals required`
|
|
50074
|
+
);
|
|
50075
|
+
return;
|
|
50076
|
+
}
|
|
50077
|
+
const [a, b] = c.pointsToConnect;
|
|
50078
|
+
if (a.layers || b.layers || a.layer !== b.layer) {
|
|
50079
|
+
this.fail(
|
|
50080
|
+
"layer_change_required",
|
|
50081
|
+
`${c.name}: ${a.layer} \u2192 ${b.layer}; a common fixed layer is required; fanout handoff layers must agree`
|
|
50082
|
+
);
|
|
50083
|
+
return;
|
|
50084
|
+
}
|
|
50085
|
+
if (![a.x, a.y, b.x, b.y].every(Number.isFinite))
|
|
50086
|
+
throw Error("Nonfinite terminal");
|
|
50087
|
+
this.widths.set(
|
|
50088
|
+
c.name,
|
|
50089
|
+
c.nominalTraceWidth ?? c.width ?? input.minTraceWidth
|
|
50090
|
+
);
|
|
50091
|
+
}
|
|
50092
|
+
for (const b of input.buses ?? [])
|
|
50093
|
+
if (b.maxLengthSkew !== void 0 && (!Number.isFinite(b.maxLengthSkew) || b.maxLengthSkew < 0))
|
|
50094
|
+
throw Error("Invalid maximum length skew");
|
|
50095
|
+
for (const { names: members, tolerance } of lengthConstraints(input)) {
|
|
50096
|
+
if (!Number.isFinite(tolerance) || tolerance < 0)
|
|
50097
|
+
throw Error("Invalid maximum length skew");
|
|
50098
|
+
if (members.length < 1 || new Set(members).size !== members.length || members.some((n) => !names.has(n)))
|
|
50099
|
+
throw Error("Invalid length matching members");
|
|
50100
|
+
}
|
|
50101
|
+
const claimed = /* @__PURE__ */ new Set();
|
|
50102
|
+
for (const b of input.buses ?? [])
|
|
50103
|
+
for (const name of b.connectionNames) {
|
|
50104
|
+
const c = input.connections.find((c2) => c2.name === name);
|
|
50105
|
+
if (!c || claimed.has(name))
|
|
50106
|
+
throw Error(`Missing or duplicated bus member ${name}`);
|
|
50107
|
+
claimed.add(name);
|
|
50108
|
+
const layer = c.pointsToConnect[0].layer;
|
|
50109
|
+
if (b.allowedLayers && !b.allowedLayers.includes(layer))
|
|
50110
|
+
throw Error(`${b.busId}: forbidden layer ${layer}`);
|
|
50111
|
+
const width = b.traceWidth;
|
|
50112
|
+
if (width !== void 0) this.widths.set(name, width);
|
|
50113
|
+
}
|
|
50114
|
+
for (const width of this.widths.values())
|
|
50115
|
+
if (!Number.isFinite(width) || width <= 0 || width < input.minTraceWidth)
|
|
50116
|
+
throw Error("Invalid trace width");
|
|
50117
|
+
this.fixed = fixedCopper(input);
|
|
50118
|
+
for (const c of input.connections)
|
|
50119
|
+
for (const p of c.pointsToConnect)
|
|
50120
|
+
this.fixed.push({
|
|
50121
|
+
a: p,
|
|
50122
|
+
b: p,
|
|
50123
|
+
layer: p.layer,
|
|
50124
|
+
radius: this.widths.get(c.name) / 2,
|
|
50125
|
+
owners: [c.name]
|
|
50126
|
+
});
|
|
50127
|
+
this.orders = windingOrders(input.connections);
|
|
50128
|
+
if (!input.connections.length) {
|
|
50129
|
+
this.solved = true;
|
|
50130
|
+
this.phase = "solved";
|
|
50131
|
+
return;
|
|
50132
|
+
}
|
|
50133
|
+
this.phase = "route";
|
|
50134
|
+
this.startLane();
|
|
50135
|
+
}
|
|
50136
|
+
scene(c) {
|
|
50137
|
+
return new VectorScene(this.input, c, this.widths.get(c.name), [
|
|
50138
|
+
...this.fixed,
|
|
50139
|
+
...this.traces.flatMap(routeCopper)
|
|
50140
|
+
]);
|
|
50141
|
+
}
|
|
50142
|
+
startLane() {
|
|
50143
|
+
if (this.lane === this.input.connections.length) {
|
|
50144
|
+
this.phase = "match";
|
|
50145
|
+
return;
|
|
50146
|
+
}
|
|
50147
|
+
const c = this.orders[this.attempt][this.lane], [a, b] = c.pointsToConnect;
|
|
50148
|
+
this.search = new VectorVisibilitySearch(this.scene(c), a, b);
|
|
50149
|
+
}
|
|
50150
|
+
retry() {
|
|
50151
|
+
if (this.traces.length > this.bestPartial.length)
|
|
50152
|
+
this.bestPartial = structuredClone(this.traces);
|
|
50153
|
+
this.attempt++;
|
|
50154
|
+
if (this.attempt >= this.orders.length) {
|
|
50155
|
+
this.traces = this.bestPartial;
|
|
50156
|
+
this.fail(
|
|
50157
|
+
"no_planar_route",
|
|
50158
|
+
"No collision-free routing found in the vector visibility graph"
|
|
50159
|
+
);
|
|
50160
|
+
return;
|
|
50161
|
+
}
|
|
50162
|
+
this.traces = [];
|
|
50163
|
+
this.lane = 0;
|
|
50164
|
+
this.startLane();
|
|
50165
|
+
}
|
|
50166
|
+
route() {
|
|
50167
|
+
const s = this.search;
|
|
50168
|
+
s.step();
|
|
50169
|
+
if (s.solved) {
|
|
50170
|
+
const c = this.orders[this.attempt][this.lane];
|
|
50171
|
+
this.traces.push({
|
|
50172
|
+
type: "pcb_trace",
|
|
50173
|
+
pcb_trace_id: `bus_lane_${c.name}`,
|
|
50174
|
+
connection_name: c.name,
|
|
50175
|
+
source_trace_id: c.source_trace_id ?? c.name,
|
|
50176
|
+
route: s.result.map((p) => ({
|
|
50177
|
+
route_type: "wire",
|
|
50178
|
+
x: p.x,
|
|
50179
|
+
y: p.y,
|
|
50180
|
+
layer: c.pointsToConnect[0].layer,
|
|
50181
|
+
width: this.widths.get(c.name)
|
|
50182
|
+
}))
|
|
50183
|
+
});
|
|
50184
|
+
this.lane++;
|
|
50185
|
+
this.startLane();
|
|
50186
|
+
} else if (s.failed || s.expanded >= (this.options.maxLaneIterations ?? 4e3))
|
|
50187
|
+
this.retry();
|
|
50188
|
+
}
|
|
50189
|
+
match() {
|
|
50190
|
+
const original = this.traces;
|
|
50191
|
+
const input = this.input;
|
|
50192
|
+
function* candidates() {
|
|
50193
|
+
yield original;
|
|
50194
|
+
const width = Math.max(...original.map((t) => t.route[0].width));
|
|
50195
|
+
for (const multiplier of [16, 24, 28, 32]) {
|
|
50196
|
+
const spread = spreadTuningLanes(input, original, width * multiplier);
|
|
50197
|
+
if (spread) yield spread;
|
|
50198
|
+
}
|
|
50199
|
+
}
|
|
50200
|
+
let error;
|
|
50201
|
+
for (const candidate of candidates()) {
|
|
50202
|
+
const targets = minimumLengthTargets(input, candidate);
|
|
50203
|
+
try {
|
|
50204
|
+
this.traces = tuneLengths(input, candidate, targets);
|
|
50205
|
+
this.phase = "validate_output";
|
|
50206
|
+
return;
|
|
50207
|
+
} catch (e) {
|
|
50208
|
+
error = e;
|
|
50209
|
+
}
|
|
50210
|
+
}
|
|
50211
|
+
this.fail("length_matching_failed", String(error));
|
|
50212
|
+
return;
|
|
50213
|
+
}
|
|
50214
|
+
validateOutput() {
|
|
50215
|
+
for (const c of this.input.connections) {
|
|
50216
|
+
const t = this.traces.find((t2) => t2.connection_name === c.name);
|
|
50217
|
+
if (!t) throw Error("Missing lane");
|
|
50218
|
+
const scene = this.scene(c);
|
|
50219
|
+
if (distance12(t.route[0], c.pointsToConnect[0]) > 1e-8 || distance12(t.route.at(-1), c.pointsToConnect[1]) > 1e-8)
|
|
50220
|
+
throw Error("Broken lane endpoints");
|
|
50221
|
+
for (let i = 1; i < t.route.length; i++) {
|
|
50222
|
+
const a = t.route[i - 1], b = t.route[i], dx = Math.abs(a.x - b.x), dy = Math.abs(a.y - b.y);
|
|
50223
|
+
if (a.route_type !== "wire" || b.route_type !== "wire" || a.layer !== b.layer)
|
|
50224
|
+
throw Error("Forbidden layer transition");
|
|
50225
|
+
if (Math.min(dx, dy) > 1e-8 && Math.abs(dx - dy) > 1e-8)
|
|
50226
|
+
throw Error("Non-octilinear segment");
|
|
50227
|
+
if (!scene.visible(a, b))
|
|
50228
|
+
throw Error("Final copper clearance violation");
|
|
50229
|
+
}
|
|
50230
|
+
}
|
|
50231
|
+
if ([
|
|
50232
|
+
...busLengthReports(this.input, this.traces),
|
|
50233
|
+
...pairLengthReports(this.input, this.traces)
|
|
50234
|
+
].some((b) => b.toleranceMm !== null && !b.matched))
|
|
50235
|
+
throw Error("Final bus length skew violation");
|
|
50236
|
+
this.phase = "solved";
|
|
50237
|
+
this.solved = true;
|
|
50238
|
+
}
|
|
50239
|
+
_step() {
|
|
50240
|
+
try {
|
|
50241
|
+
if (this.phase === "validate") this.initialize();
|
|
50242
|
+
else if (this.phase === "route") this.route();
|
|
50243
|
+
else if (this.phase === "match") this.match();
|
|
50244
|
+
else if (this.phase === "validate_output") this.validateOutput();
|
|
50245
|
+
} catch (e) {
|
|
50246
|
+
this.fail("constraint_error", String(e));
|
|
50247
|
+
}
|
|
50248
|
+
this.progress = this.lane / Math.max(1, this.input.connections.length);
|
|
50249
|
+
this.stats = {
|
|
50250
|
+
busLengths: busLengthReports(this.input, this.traces),
|
|
50251
|
+
pairLengths: pairLengthReports(this.input, this.traces),
|
|
50252
|
+
phase: this.phase,
|
|
50253
|
+
algorithm: "octilinear_visibility",
|
|
50254
|
+
attempt: this.attempt,
|
|
50255
|
+
lane: this.lane,
|
|
50256
|
+
totalLanes: this.input.connections.length,
|
|
50257
|
+
vertices: this.search?.vertices.length ?? 0,
|
|
50258
|
+
expandedVertices: this.search?.expanded ?? 0,
|
|
50259
|
+
frontier: this.search?.open.length ?? 0,
|
|
50260
|
+
failureCode: this.failureCode,
|
|
50261
|
+
traceLengthsMm: this.traces.map((t) => ({
|
|
50262
|
+
name: t.connection_name,
|
|
50263
|
+
length: length(t.route)
|
|
50264
|
+
}))
|
|
50265
|
+
};
|
|
50266
|
+
}
|
|
50267
|
+
visualize() {
|
|
50268
|
+
const lines = [], points = [], rects = [], circles = [];
|
|
50269
|
+
for (const c of fixedCopper(this.input)) {
|
|
50270
|
+
if (c.rect) {
|
|
50271
|
+
rects.push({
|
|
50272
|
+
center: {
|
|
50273
|
+
x: (c.rect.minX + c.rect.maxX) / 2,
|
|
50274
|
+
y: (c.rect.minY + c.rect.maxY) / 2
|
|
50275
|
+
},
|
|
50276
|
+
width: c.rect.maxX - c.rect.minX,
|
|
50277
|
+
height: c.rect.maxY - c.rect.minY,
|
|
50278
|
+
layer: c.layer,
|
|
50279
|
+
fill: `${layerColor(c.layer)}30`,
|
|
50280
|
+
stroke: layerColor(c.layer)
|
|
50281
|
+
});
|
|
50282
|
+
continue;
|
|
50283
|
+
}
|
|
50284
|
+
if (distance12(c.a, c.b) < 1e-9)
|
|
50285
|
+
circles.push({
|
|
50286
|
+
center: c.a,
|
|
50287
|
+
radius: c.radius,
|
|
50288
|
+
layer: c.layer,
|
|
50289
|
+
fill: "transparent",
|
|
50290
|
+
stroke: layerColor(c.layer)
|
|
50291
|
+
});
|
|
50292
|
+
else
|
|
50293
|
+
lines.push({
|
|
50294
|
+
points: [
|
|
50295
|
+
{ x: c.a.x, y: c.a.y },
|
|
50296
|
+
{ x: c.b.x, y: c.b.y }
|
|
50297
|
+
],
|
|
50298
|
+
strokeWidth: c.radius * 2,
|
|
50299
|
+
strokeColor: layerColor(c.layer),
|
|
50300
|
+
layer: c.layer,
|
|
50301
|
+
label: `Fixed fanout [${c.layer}]`
|
|
50302
|
+
});
|
|
50303
|
+
}
|
|
50304
|
+
for (const t of this.traces)
|
|
50305
|
+
lines.push({
|
|
50306
|
+
points: t.route.map(({ x, y }) => ({ x, y })),
|
|
50307
|
+
strokeWidth: t.route[0].width,
|
|
50308
|
+
strokeColor: layerColor(t.route[0].layer),
|
|
50309
|
+
layer: t.route[0].layer,
|
|
50310
|
+
label: t.connection_name
|
|
50311
|
+
});
|
|
50312
|
+
for (const c of this.input.connections)
|
|
50313
|
+
for (const [i, p] of c.pointsToConnect.entries())
|
|
50314
|
+
points.push({
|
|
50315
|
+
...p,
|
|
50316
|
+
color: i ? "#d97706" : "#2563eb",
|
|
50317
|
+
label: `${c.name} ${i ? "target" : "source"} [${p.layer}]`
|
|
50318
|
+
});
|
|
50319
|
+
if (this.search && this.phase === "route") {
|
|
50320
|
+
const layer = this.orders[this.attempt][this.lane]?.pointsToConnect[0].layer;
|
|
50321
|
+
for (const edge of this.search.visibleEdges)
|
|
50322
|
+
lines.push({
|
|
50323
|
+
points: edge,
|
|
50324
|
+
strokeWidth: 0.02,
|
|
50325
|
+
strokeColor: "#67e8f980",
|
|
50326
|
+
layer
|
|
50327
|
+
});
|
|
50328
|
+
for (const n of this.search.open.values().slice(0, 80))
|
|
50329
|
+
points.push({ ...this.search.vertices[n.id], color: "#06b6d4", layer });
|
|
50330
|
+
lines.push({
|
|
50331
|
+
points: this.search.currentPath(),
|
|
50332
|
+
strokeColor: "#f43f5e",
|
|
50333
|
+
strokeWidth: 0.09,
|
|
50334
|
+
layer
|
|
50335
|
+
});
|
|
50336
|
+
}
|
|
50337
|
+
return {
|
|
50338
|
+
title: `Vector bus lanes \xB7 ${this.phase}`,
|
|
50339
|
+
lines,
|
|
50340
|
+
points,
|
|
50341
|
+
rects,
|
|
50342
|
+
circles
|
|
50343
|
+
};
|
|
50344
|
+
}
|
|
50345
|
+
};
|
|
50346
|
+
|
|
50347
|
+
// lib/utils/autorouting/BusLanesAutorouter.ts
|
|
50348
|
+
var BusLanesAutorouter = class {
|
|
50349
|
+
constructor(input) {
|
|
50350
|
+
this.input = input;
|
|
50351
|
+
this.solver = new BusLanesSolver(input);
|
|
50352
|
+
}
|
|
50353
|
+
input;
|
|
50354
|
+
isRouting = false;
|
|
50355
|
+
solver;
|
|
50356
|
+
timer;
|
|
50357
|
+
listeners = [];
|
|
50358
|
+
on(event, callback) {
|
|
50359
|
+
this.listeners.push({
|
|
50360
|
+
event,
|
|
50361
|
+
callback
|
|
50362
|
+
});
|
|
50363
|
+
}
|
|
50364
|
+
emit(event) {
|
|
50365
|
+
for (const listener of this.listeners)
|
|
50366
|
+
if (listener.event === event.type) listener.callback(event);
|
|
50367
|
+
}
|
|
50368
|
+
start() {
|
|
50369
|
+
if (this.isRouting) return;
|
|
50370
|
+
this.isRouting = true;
|
|
50371
|
+
const tick = () => {
|
|
50372
|
+
if (!this.isRouting) return;
|
|
50373
|
+
try {
|
|
50374
|
+
for (let i = 0; i < 200 && !this.solver.solved && !this.solver.failed; i++)
|
|
50375
|
+
this.solver.step();
|
|
50376
|
+
if (this.solver.failed) {
|
|
50377
|
+
this.isRouting = false;
|
|
50378
|
+
this.emit({
|
|
50379
|
+
type: "error",
|
|
50380
|
+
error: new Error(this.solver.error ?? "Bus lanes routing failed")
|
|
50381
|
+
});
|
|
50382
|
+
return;
|
|
50383
|
+
}
|
|
50384
|
+
if (this.solver.solved) {
|
|
50385
|
+
this.isRouting = false;
|
|
50386
|
+
this.emit({ type: "complete", traces: this.solver.traces });
|
|
50387
|
+
return;
|
|
50388
|
+
}
|
|
50389
|
+
this.emit({
|
|
50390
|
+
type: "progress",
|
|
50391
|
+
steps: this.solver.iterations,
|
|
50392
|
+
progress: this.solver.progress,
|
|
50393
|
+
phase: this.solver.phase,
|
|
50394
|
+
debugGraphics: this.solver.visualize()
|
|
50395
|
+
});
|
|
50396
|
+
this.timer = setTimeout(tick, 0);
|
|
50397
|
+
} catch (error) {
|
|
50398
|
+
this.isRouting = false;
|
|
50399
|
+
this.emit({
|
|
50400
|
+
type: "error",
|
|
50401
|
+
error: error instanceof Error ? error : new Error(String(error))
|
|
50402
|
+
});
|
|
50403
|
+
}
|
|
50404
|
+
};
|
|
50405
|
+
this.timer = setTimeout(tick, 0);
|
|
50406
|
+
}
|
|
50407
|
+
stop() {
|
|
50408
|
+
this.isRouting = false;
|
|
50409
|
+
if (this.timer) clearTimeout(this.timer);
|
|
50410
|
+
}
|
|
50411
|
+
solveSync() {
|
|
50412
|
+
this.solver.solve();
|
|
50413
|
+
if (this.solver.failed)
|
|
50414
|
+
throw new Error(this.solver.error ?? "Bus lanes routing failed");
|
|
50415
|
+
return this.solver.traces;
|
|
50416
|
+
}
|
|
50417
|
+
};
|
|
50418
|
+
|
|
49270
50419
|
// lib/utils/autorouting/CapacityMeshAutorouter.ts
|
|
49271
50420
|
import {
|
|
49272
50421
|
AutoroutingPipelineSolver9_Networked as AutoroutingPipelineSolver9_Networked2
|
|
@@ -49293,7 +50442,7 @@ import { CreateFdmEnclosureSolver } from "@tscircuit/create-fdm-enclosure";
|
|
|
49293
50442
|
// node_modules/@tscircuit/implicit-copper-pour-solver/lib/implicit-copper-pour-pipeline-solver.ts
|
|
49294
50443
|
import {
|
|
49295
50444
|
BasePipelineSolver,
|
|
49296
|
-
BaseSolver as
|
|
50445
|
+
BaseSolver as BaseSolver5,
|
|
49297
50446
|
definePipelineStep
|
|
49298
50447
|
} from "@tscircuit/solver-utils";
|
|
49299
50448
|
|
|
@@ -49311,7 +50460,7 @@ import { applyToPoint as applyToPoint27, compose as compose9, scale as scale2, t
|
|
|
49311
50460
|
// node_modules/@tscircuit/implicit-copper-pour-solver/lib/geometry.ts
|
|
49312
50461
|
import {
|
|
49313
50462
|
clamp,
|
|
49314
|
-
distance as
|
|
50463
|
+
distance as distance13,
|
|
49315
50464
|
doBoundsOverlap as doBoundsOverlap2,
|
|
49316
50465
|
getBoundsFromPoints as getBoundsFromPoints3,
|
|
49317
50466
|
getUnitVectorFromPointAToB as getUnitVectorFromPointAToB2,
|
|
@@ -49360,7 +50509,7 @@ var distanceToPolygon = (point6, polygon) => {
|
|
|
49360
50509
|
var distanceToPrimitive = (primitive, px, py) => {
|
|
49361
50510
|
const point6 = { x: px, y: py };
|
|
49362
50511
|
if (primitive.kind === "circle") {
|
|
49363
|
-
return Math.max(
|
|
50512
|
+
return Math.max(distance13(point6, primitive) - primitive.radius, 0);
|
|
49364
50513
|
}
|
|
49365
50514
|
if (primitive.kind === "segment") {
|
|
49366
50515
|
return Math.max(
|
|
@@ -49411,7 +50560,7 @@ var getClosestPointOnPrimitive = (primitive, point6) => {
|
|
|
49411
50560
|
const start = primitive.points[index];
|
|
49412
50561
|
const end = primitive.points[(index + 1) % primitive.points.length];
|
|
49413
50562
|
const candidate = pointToSegmentClosestPoint(point6, start, end);
|
|
49414
|
-
const candidateDistance =
|
|
50563
|
+
const candidateDistance = distance13(point6, candidate);
|
|
49415
50564
|
if (candidateDistance < bestDistance) {
|
|
49416
50565
|
bestDistance = candidateDistance;
|
|
49417
50566
|
closestPoint = candidate;
|
|
@@ -50467,7 +51616,7 @@ var prepareCircuitJson = (input) => {
|
|
|
50467
51616
|
|
|
50468
51617
|
// node_modules/@tscircuit/implicit-copper-pour-solver/lib/simplify-polygon-edges.ts
|
|
50469
51618
|
import {
|
|
50470
|
-
distance as
|
|
51619
|
+
distance as distance14,
|
|
50471
51620
|
doSegmentsIntersect,
|
|
50472
51621
|
onSegment,
|
|
50473
51622
|
pointToSegmentDistance as pointToSegmentDistance2
|
|
@@ -50486,13 +51635,13 @@ var simplifyRdpPath = (points, tolerance) => {
|
|
|
50486
51635
|
let furthestIndex = -1;
|
|
50487
51636
|
let furthestDistance = tolerance;
|
|
50488
51637
|
for (let index = firstIndex + 1; index < lastIndex; index++) {
|
|
50489
|
-
const
|
|
51638
|
+
const segmentDistance2 = pointToSegmentDistance2(
|
|
50490
51639
|
points[index],
|
|
50491
51640
|
first,
|
|
50492
51641
|
last
|
|
50493
51642
|
);
|
|
50494
|
-
if (
|
|
50495
|
-
furthestDistance =
|
|
51643
|
+
if (segmentDistance2 > furthestDistance) {
|
|
51644
|
+
furthestDistance = segmentDistance2;
|
|
50496
51645
|
furthestIndex = index;
|
|
50497
51646
|
}
|
|
50498
51647
|
}
|
|
@@ -50530,8 +51679,8 @@ var simplifyOpenPath = (points, tolerance) => {
|
|
|
50530
51679
|
const point6 = points[index];
|
|
50531
51680
|
const next = points[index + 1];
|
|
50532
51681
|
const shortestLeg = Math.min(
|
|
50533
|
-
|
|
50534
|
-
|
|
51682
|
+
distance14(point6, previous),
|
|
51683
|
+
distance14(next, point6)
|
|
50535
51684
|
);
|
|
50536
51685
|
if (repeatsTurnDirection || shortestLeg > tolerance) {
|
|
50537
51686
|
anchorIndices.push(index);
|
|
@@ -50580,8 +51729,8 @@ var normalizePolygon = (polygon) => {
|
|
|
50580
51729
|
};
|
|
50581
51730
|
var isPointStrictlyInsideSegment = (point6, start, end) => {
|
|
50582
51731
|
if (pointsEqual(point6, start) || pointsEqual(point6, end)) return false;
|
|
50583
|
-
const
|
|
50584
|
-
if (Math.abs(
|
|
51732
|
+
const cross4 = crossProduct(start, end, point6);
|
|
51733
|
+
if (Math.abs(cross4) > 1e-9) return false;
|
|
50585
51734
|
return onSegment(start, point6, end);
|
|
50586
51735
|
};
|
|
50587
51736
|
var splitEdgesAtVertices = (polygon, allVertices) => {
|
|
@@ -50933,7 +52082,7 @@ var mergeSolverGraphics = (source, overlay) => {
|
|
|
50933
52082
|
};
|
|
50934
52083
|
|
|
50935
52084
|
// node_modules/@tscircuit/implicit-copper-pour-solver/lib/implicit-copper-pour-pipeline-solver.ts
|
|
50936
|
-
var PrepareCircuitJsonSolver = class extends
|
|
52085
|
+
var PrepareCircuitJsonSolver = class extends BaseSolver5 {
|
|
50937
52086
|
constructor(input) {
|
|
50938
52087
|
super();
|
|
50939
52088
|
this.input = input;
|
|
@@ -50949,7 +52098,7 @@ var PrepareCircuitJsonSolver = class extends BaseSolver4 {
|
|
|
50949
52098
|
return this.output;
|
|
50950
52099
|
}
|
|
50951
52100
|
};
|
|
50952
|
-
var AssignGridCellsSolver = class extends
|
|
52101
|
+
var AssignGridCellsSolver = class extends BaseSolver5 {
|
|
50953
52102
|
constructor(input) {
|
|
50954
52103
|
super();
|
|
50955
52104
|
this.input = input;
|
|
@@ -50972,7 +52121,7 @@ var AssignGridCellsSolver = class extends BaseSolver4 {
|
|
|
50972
52121
|
return this.output;
|
|
50973
52122
|
}
|
|
50974
52123
|
};
|
|
50975
|
-
var TracePowerPolygonsSolver = class extends
|
|
52124
|
+
var TracePowerPolygonsSolver = class extends BaseSolver5 {
|
|
50976
52125
|
constructor(input) {
|
|
50977
52126
|
super();
|
|
50978
52127
|
this.input = input;
|
|
@@ -51008,7 +52157,7 @@ var TracePowerPolygonsSolver = class extends BaseSolver4 {
|
|
|
51008
52157
|
};
|
|
51009
52158
|
}
|
|
51010
52159
|
};
|
|
51011
|
-
var SimplifyPolygonEdgesSolver = class extends
|
|
52160
|
+
var SimplifyPolygonEdgesSolver = class extends BaseSolver5 {
|
|
51012
52161
|
constructor(input) {
|
|
51013
52162
|
super();
|
|
51014
52163
|
this.input = input;
|
|
@@ -51146,13 +52295,13 @@ import { LayoutPipelineSolver } from "@tscircuit/matchpack";
|
|
|
51146
52295
|
import { SchematicTracePipelineSolver } from "@tscircuit/schematic-trace-solver";
|
|
51147
52296
|
|
|
51148
52297
|
// node_modules/@tscircuit/via-stitch-solver/lib/solvers/ViaStitchSolver.ts
|
|
51149
|
-
import { BaseSolver as
|
|
52298
|
+
import { BaseSolver as BaseSolver6 } from "@tscircuit/solver-utils";
|
|
51150
52299
|
|
|
51151
52300
|
// node_modules/@tscircuit/via-stitch-solver/lib/geometry/brep-point-containment.ts
|
|
51152
52301
|
var POINT_EPSILON = 1e-8;
|
|
51153
52302
|
var isPointOnSegment = (point6, start, end) => {
|
|
51154
|
-
const
|
|
51155
|
-
if (Math.abs(
|
|
52303
|
+
const cross4 = (point6.y - start.y) * (end.x - start.x) - (point6.x - start.x) * (end.y - start.y);
|
|
52304
|
+
if (Math.abs(cross4) > POINT_EPSILON) return false;
|
|
51156
52305
|
const dot = (point6.x - start.x) * (end.x - start.x) + (point6.y - start.y) * (end.y - start.y);
|
|
51157
52306
|
if (dot < -POINT_EPSILON) return false;
|
|
51158
52307
|
const squaredLength = (end.x - start.x) ** 2 + (end.y - start.y) ** 2;
|
|
@@ -51473,7 +52622,7 @@ var getGridCoordinates = ({
|
|
|
51473
52622
|
}
|
|
51474
52623
|
return coordinates;
|
|
51475
52624
|
};
|
|
51476
|
-
var ViaStitchSolver = class extends
|
|
52625
|
+
var ViaStitchSolver = class extends BaseSolver6 {
|
|
51477
52626
|
constructor(input) {
|
|
51478
52627
|
super();
|
|
51479
52628
|
this.input = input;
|
|
@@ -51620,6 +52769,7 @@ var ViaStitchSolver = class extends BaseSolver5 {
|
|
|
51620
52769
|
// lib/solvers.ts
|
|
51621
52770
|
import { PackSolver2 } from "calculate-packing";
|
|
51622
52771
|
var SOLVERS = {
|
|
52772
|
+
BusLanesSolver,
|
|
51623
52773
|
PackSolver2,
|
|
51624
52774
|
LayoutPipelineSolver,
|
|
51625
52775
|
AutoroutingPipelineSolver,
|
|
@@ -52082,6 +53232,22 @@ var localAutorouterStrategies = /* @__PURE__ */ new Map([
|
|
|
52082
53232
|
createFanoutAutorouterStrategy("single_layer_fanout")
|
|
52083
53233
|
],
|
|
52084
53234
|
["fanout", createFanoutAutorouterStrategy("fanout")],
|
|
53235
|
+
[
|
|
53236
|
+
"bus_lanes",
|
|
53237
|
+
{
|
|
53238
|
+
name: "bus_lanes",
|
|
53239
|
+
cacheable: false,
|
|
53240
|
+
getSolverName: () => "BusLanesSolver",
|
|
53241
|
+
create: ({ simpleRouteJson, onSolverStarted }) => {
|
|
53242
|
+
onSolverStarted?.({
|
|
53243
|
+
solverName: "BusLanesSolver",
|
|
53244
|
+
solverParams: simpleRouteJson,
|
|
53245
|
+
solverConstructorArgs: [simpleRouteJson]
|
|
53246
|
+
});
|
|
53247
|
+
return new BusLanesAutorouter(simpleRouteJson);
|
|
53248
|
+
}
|
|
53249
|
+
}
|
|
53250
|
+
],
|
|
52085
53251
|
["simplify", simplificationLocalAutorouterStrategy]
|
|
52086
53252
|
]);
|
|
52087
53253
|
var getLocalAutorouterStrategy = (preset) => localAutorouterStrategies.get(preset ?? "") ?? defaultLocalAutorouterStrategy;
|
|
@@ -54640,7 +55806,7 @@ function Group_doInitialPcbComponentAnchorAlignment(group) {
|
|
|
54640
55806
|
// lib/components/primitive-components/Group/Group_doInitialPcbLayoutFlex.ts
|
|
54641
55807
|
import { getMinimumFlexContainer } from "@tscircuit/circuit-json-util";
|
|
54642
55808
|
import { RootFlexBox } from "@tscircuit/miniflex";
|
|
54643
|
-
import { length } from "circuit-json";
|
|
55809
|
+
import { length as length2 } from "circuit-json";
|
|
54644
55810
|
var Group_doInitialPcbLayoutFlex = (group) => {
|
|
54645
55811
|
const { db } = group.root;
|
|
54646
55812
|
const { _parsedProps: props } = group;
|
|
@@ -54692,8 +55858,8 @@ var Group_doInitialPcbLayoutFlex = (group) => {
|
|
|
54692
55858
|
rowGap = rawGap;
|
|
54693
55859
|
columnGap = rawGap;
|
|
54694
55860
|
} else if (typeof rawGap === "string") {
|
|
54695
|
-
rowGap =
|
|
54696
|
-
columnGap =
|
|
55861
|
+
rowGap = length2.parse(rawGap);
|
|
55862
|
+
columnGap = length2.parse(rawGap);
|
|
54697
55863
|
}
|
|
54698
55864
|
let minFlexContainer;
|
|
54699
55865
|
let width = props.width ?? props.pcbWidth ?? void 0;
|
|
@@ -54773,7 +55939,7 @@ import {
|
|
|
54773
55939
|
repositionPcbComponentTo as repositionPcbComponentTo2,
|
|
54774
55940
|
repositionPcbGroupTo as repositionPcbGroupTo2
|
|
54775
55941
|
} from "@tscircuit/circuit-json-util";
|
|
54776
|
-
import { length as
|
|
55942
|
+
import { length as length3 } from "circuit-json";
|
|
54777
55943
|
import { CssGrid } from "minicssgrid";
|
|
54778
55944
|
var MIN_GAP = 1;
|
|
54779
55945
|
function Group_doInitialPcbLayoutGrid(group) {
|
|
@@ -54835,7 +56001,7 @@ function parseGridConfiguration(props) {
|
|
|
54835
56001
|
const templateRows = props.pcbGridTemplateRows;
|
|
54836
56002
|
const parseGap = (gapValue) => {
|
|
54837
56003
|
if (gapValue === void 0) return MIN_GAP;
|
|
54838
|
-
return typeof gapValue === "number" ? gapValue :
|
|
56004
|
+
return typeof gapValue === "number" ? gapValue : length3.parse(gapValue);
|
|
54839
56005
|
};
|
|
54840
56006
|
const gridGapOption = props.pcbGridGap ?? props.gridGap ?? props.pcbLayout?.gridGap;
|
|
54841
56007
|
const rowGapOption = props.pcbGridRowGap ?? props.gridRowGap ?? props.pcbLayout?.gridRowGap;
|
|
@@ -54986,7 +56152,7 @@ import {
|
|
|
54986
56152
|
convertPackOutputToPackInput,
|
|
54987
56153
|
getGraphicsFromPackOutput
|
|
54988
56154
|
} from "calculate-packing";
|
|
54989
|
-
import { length as
|
|
56155
|
+
import { length as length4 } from "circuit-json";
|
|
54990
56156
|
import Debug6 from "debug";
|
|
54991
56157
|
|
|
54992
56158
|
// lib/utils/packing/solvePackSolverWithTimeout.ts
|
|
@@ -55495,16 +56661,16 @@ var Group_doInitialPcbLayoutPack = (group) => {
|
|
|
55495
56661
|
pcbPackGap
|
|
55496
56662
|
} = props;
|
|
55497
56663
|
const gap = pcbPackGap ?? pcbGap ?? gapProp;
|
|
55498
|
-
const gapMm =
|
|
56664
|
+
const gapMm = length4.parse(gap ?? DEFAULT_MIN_GAP);
|
|
55499
56665
|
const chipMarginsMap = {};
|
|
55500
56666
|
const staticPcbComponentIds = /* @__PURE__ */ new Set();
|
|
55501
56667
|
const collectMargins = (comp) => {
|
|
55502
56668
|
if (comp?.pcb_component_id && comp?._parsedProps) {
|
|
55503
56669
|
const props2 = comp._parsedProps;
|
|
55504
|
-
const left =
|
|
55505
|
-
const right =
|
|
55506
|
-
const top =
|
|
55507
|
-
const bottom =
|
|
56670
|
+
const left = length4.parse(props2.pcbMarginLeft ?? props2.pcbMarginX ?? 0);
|
|
56671
|
+
const right = length4.parse(props2.pcbMarginRight ?? props2.pcbMarginX ?? 0);
|
|
56672
|
+
const top = length4.parse(props2.pcbMarginTop ?? props2.pcbMarginY ?? 0);
|
|
56673
|
+
const bottom = length4.parse(
|
|
55508
56674
|
props2.pcbMarginBottom ?? props2.pcbMarginY ?? 0
|
|
55509
56675
|
);
|
|
55510
56676
|
if (left || right || top || bottom) {
|
|
@@ -55553,8 +56719,8 @@ var Group_doInitialPcbLayoutPack = (group) => {
|
|
|
55553
56719
|
const filteredCircuitJson = db.toArray();
|
|
55554
56720
|
let bounds;
|
|
55555
56721
|
if (props.width !== void 0 && props.height !== void 0) {
|
|
55556
|
-
const widthMm =
|
|
55557
|
-
const heightMm =
|
|
56722
|
+
const widthMm = length4.parse(props.width);
|
|
56723
|
+
const heightMm = length4.parse(props.height);
|
|
55558
56724
|
bounds = {
|
|
55559
56725
|
minX: -widthMm / 2,
|
|
55560
56726
|
maxX: widthMm / 2,
|
|
@@ -55859,7 +57025,7 @@ import {
|
|
|
55859
57025
|
repositionSchematicGroupTo
|
|
55860
57026
|
} from "@tscircuit/circuit-json-util";
|
|
55861
57027
|
import { RootFlexBox as RootFlexBox2 } from "@tscircuit/miniflex";
|
|
55862
|
-
import { length as
|
|
57028
|
+
import { length as length5 } from "circuit-json";
|
|
55863
57029
|
var getSizeOfTreeNodeChild = (db, child) => {
|
|
55864
57030
|
const { sourceComponent, sourceGroup } = child;
|
|
55865
57031
|
if (child.nodeType === "component") {
|
|
@@ -55952,8 +57118,8 @@ var Group_doInitialSchematicLayoutFlex = (group) => {
|
|
|
55952
57118
|
rowGap = rawGap;
|
|
55953
57119
|
columnGap = rawGap;
|
|
55954
57120
|
} else if (typeof rawGap === "string") {
|
|
55955
|
-
rowGap =
|
|
55956
|
-
columnGap =
|
|
57121
|
+
rowGap = length5.parse(rawGap);
|
|
57122
|
+
columnGap = length5.parse(rawGap);
|
|
55957
57123
|
}
|
|
55958
57124
|
let minFlexContainer;
|
|
55959
57125
|
let width = props.width ?? props.schWidth ?? void 0;
|
|
@@ -56047,7 +57213,7 @@ var Group_doInitialSchematicLayoutFlex = (group) => {
|
|
|
56047
57213
|
};
|
|
56048
57214
|
|
|
56049
57215
|
// lib/components/primitive-components/Group/Group_doInitialSchematicLayoutGrid.ts
|
|
56050
|
-
import { length as
|
|
57216
|
+
import { length as length6 } from "circuit-json";
|
|
56051
57217
|
|
|
56052
57218
|
// lib/components/primitive-components/Group/utils/updateSchematicPrimitivesForLayoutShift.ts
|
|
56053
57219
|
function updateSchematicPrimitivesForLayoutShift({
|
|
@@ -56151,7 +57317,7 @@ function Group_doInitialSchematicLayoutGrid(group) {
|
|
|
56151
57317
|
let gridGapY;
|
|
56152
57318
|
const parseGap = (val) => {
|
|
56153
57319
|
if (val === void 0) return void 0;
|
|
56154
|
-
return typeof val === "number" ? val :
|
|
57320
|
+
return typeof val === "number" ? val : length6.parse(val);
|
|
56155
57321
|
};
|
|
56156
57322
|
if (gridRowGapOption !== void 0 || gridColumnGapOption !== void 0) {
|
|
56157
57323
|
const fallbackX = typeof gridGapOption === "object" && gridGapOption !== null ? gridGapOption.x : gridGapOption;
|
|
@@ -56162,14 +57328,14 @@ function Group_doInitialSchematicLayoutGrid(group) {
|
|
|
56162
57328
|
gridGapX = gridGapOption;
|
|
56163
57329
|
gridGapY = gridGapOption;
|
|
56164
57330
|
} else if (typeof gridGapOption === "string") {
|
|
56165
|
-
const parsed =
|
|
57331
|
+
const parsed = length6.parse(gridGapOption);
|
|
56166
57332
|
gridGapX = parsed;
|
|
56167
57333
|
gridGapY = parsed;
|
|
56168
57334
|
} else if (typeof gridGapOption === "object" && gridGapOption !== null) {
|
|
56169
57335
|
const xRaw = gridGapOption.x;
|
|
56170
57336
|
const yRaw = gridGapOption.y;
|
|
56171
|
-
gridGapX = typeof xRaw === "number" ? xRaw :
|
|
56172
|
-
gridGapY = typeof yRaw === "number" ? yRaw :
|
|
57337
|
+
gridGapX = typeof xRaw === "number" ? xRaw : length6.parse(xRaw ?? "0mm");
|
|
57338
|
+
gridGapY = typeof yRaw === "number" ? yRaw : length6.parse(yRaw ?? "0mm");
|
|
56173
57339
|
} else {
|
|
56174
57340
|
gridGapX = 1;
|
|
56175
57341
|
gridGapY = 1;
|
|
@@ -58402,19 +59568,19 @@ import Debug12 from "debug";
|
|
|
58402
59568
|
import { isValidElement as isValidElement2 } from "react";
|
|
58403
59569
|
|
|
58404
59570
|
// lib/components/primitive-components/Group/Group_doInitialSchematicTraceRender/segment-intersection.ts
|
|
58405
|
-
var
|
|
59571
|
+
var cross3 = (ax, ay, bx, by) => {
|
|
58406
59572
|
return ax * by - ay * bx;
|
|
58407
59573
|
};
|
|
58408
59574
|
function segmentIntersection(p1, p2, q1, q2, tol) {
|
|
58409
59575
|
const r = { x: p2.x - p1.x, y: p2.y - p1.y };
|
|
58410
59576
|
const s = { x: q2.x - q1.x, y: q2.y - q1.y };
|
|
58411
|
-
const rxs =
|
|
59577
|
+
const rxs = cross3(r.x, r.y, s.x, s.y);
|
|
58412
59578
|
const q_p = { x: q1.x - p1.x, y: q1.y - p1.y };
|
|
58413
|
-
const q_pxr =
|
|
59579
|
+
const q_pxr = cross3(q_p.x, q_p.y, r.x, r.y);
|
|
58414
59580
|
if (Math.abs(rxs) < tol && Math.abs(q_pxr) < tol) return null;
|
|
58415
59581
|
if (Math.abs(rxs) < tol && Math.abs(q_pxr) >= tol) return null;
|
|
58416
|
-
const t =
|
|
58417
|
-
const u =
|
|
59582
|
+
const t = cross3(q_p.x, q_p.y, s.x, s.y) / rxs;
|
|
59583
|
+
const u = cross3(q_p.x, q_p.y, r.x, r.y) / rxs;
|
|
58418
59584
|
if (t < -tol || t > 1 + tol || u < -tol || u > 1 + tol) return null;
|
|
58419
59585
|
return { x: p1.x + t * r.x, y: p1.y + t * r.y };
|
|
58420
59586
|
}
|
|
@@ -58426,14 +59592,14 @@ function isHorizontalEdge(edge) {
|
|
|
58426
59592
|
const dy = Math.abs(edge.to.y - edge.from.y);
|
|
58427
59593
|
return dx >= dy;
|
|
58428
59594
|
}
|
|
58429
|
-
function
|
|
59595
|
+
function length7(a, b) {
|
|
58430
59596
|
return Math.hypot(b.x - a.x, b.y - a.y);
|
|
58431
59597
|
}
|
|
58432
59598
|
function pointAt(a, b, t) {
|
|
58433
59599
|
return { x: a.x + (b.x - a.x) * t, y: a.y + (b.y - a.y) * t };
|
|
58434
59600
|
}
|
|
58435
59601
|
function paramAlong(a, b, p) {
|
|
58436
|
-
const L =
|
|
59602
|
+
const L = length7(a, b);
|
|
58437
59603
|
if (L < TOL) return 0;
|
|
58438
59604
|
const t = ((p.x - a.x) * (b.x - a.x) + (p.y - a.y) * (b.y - a.y)) / ((b.x - a.x) * (b.x - a.x) + (b.y - a.y) * (b.y - a.y));
|
|
58439
59605
|
return Math.max(0, Math.min(1, t)) * L;
|
|
@@ -58456,7 +59622,7 @@ function mergeIntervals(intervals, tol = TOL) {
|
|
|
58456
59622
|
return merged;
|
|
58457
59623
|
}
|
|
58458
59624
|
function splitEdgeByCrossings(edge, crossingDistances, crossLen) {
|
|
58459
|
-
const L =
|
|
59625
|
+
const L = length7(edge.from, edge.to);
|
|
58460
59626
|
if (L < TOL || crossingDistances.length === 0) return [edge];
|
|
58461
59627
|
const half = crossLen / 2;
|
|
58462
59628
|
const rawIntervals = crossingDistances.map((d) => ({
|
|
@@ -58508,8 +59674,8 @@ function computeCrossings(traces, opts = {}) {
|
|
|
58508
59674
|
}
|
|
58509
59675
|
const P = segmentIntersection(eA.from, eA.to, eB.from, eB.to, tol);
|
|
58510
59676
|
if (!P) continue;
|
|
58511
|
-
const LA =
|
|
58512
|
-
const LB =
|
|
59677
|
+
const LA = length7(eA.from, eA.to);
|
|
59678
|
+
const LB = length7(eB.from, eB.to);
|
|
58513
59679
|
if (LA < tol || LB < tol) continue;
|
|
58514
59680
|
const dA = paramAlong(eA.from, eA.to, P);
|
|
58515
59681
|
const dB = paramAlong(eB.from, eB.to, P);
|
|
@@ -58607,8 +59773,8 @@ function isParallel(e1, e2, tol = TOL2) {
|
|
|
58607
59773
|
const L1 = Math.hypot(v1.x, v1.y);
|
|
58608
59774
|
const L2 = Math.hypot(v2.x, v2.y);
|
|
58609
59775
|
if (L1 < tol || L2 < tol) return true;
|
|
58610
|
-
const
|
|
58611
|
-
return Math.abs(
|
|
59776
|
+
const cross4 = v1.x * v2.y - v1.y * v2.x;
|
|
59777
|
+
return Math.abs(cross4) <= tol * L1 * L2;
|
|
58612
59778
|
}
|
|
58613
59779
|
function incidentEdgesAtPoint(trace, p, tol = TOL2) {
|
|
58614
59780
|
return trace.edges.filter(
|
|
@@ -58758,7 +59924,7 @@ function isCollinear(a, b, tol = TOL3) {
|
|
|
58758
59924
|
function splitEdgeAroundIntervals(edge, intervals) {
|
|
58759
59925
|
const merged = mergeIntervals(intervals);
|
|
58760
59926
|
if (merged.length === 0) return [edge];
|
|
58761
|
-
const edgeLength =
|
|
59927
|
+
const edgeLength = length7(edge.from, edge.to);
|
|
58762
59928
|
if (edgeLength <= TOL3) return [edge];
|
|
58763
59929
|
const result = [];
|
|
58764
59930
|
let cursor = 0;
|
|
@@ -58792,7 +59958,7 @@ function removeOverlappingSameNetCrossingSegments(traces) {
|
|
|
58792
59958
|
const crossingTrace = traces[crossingTraceIndex];
|
|
58793
59959
|
if (!crossingTrace.connectivity_key) continue;
|
|
58794
59960
|
for (const crossingEdge of crossingTrace.edges) {
|
|
58795
|
-
if (!crossingEdge.is_crossing ||
|
|
59961
|
+
if (!crossingEdge.is_crossing || length7(crossingEdge.from, crossingEdge.to) <= TOL3)
|
|
58796
59962
|
continue;
|
|
58797
59963
|
for (let traceIndex = 0; traceIndex < traces.length; traceIndex++) {
|
|
58798
59964
|
const candidateTrace = traces[traceIndex];
|
|
@@ -58801,7 +59967,7 @@ function removeOverlappingSameNetCrossingSegments(traces) {
|
|
|
58801
59967
|
}
|
|
58802
59968
|
for (let edgeIndex = 0; edgeIndex < candidateTrace.edges.length; edgeIndex++) {
|
|
58803
59969
|
const candidateEdge = candidateTrace.edges[edgeIndex];
|
|
58804
|
-
const candidateLength =
|
|
59970
|
+
const candidateLength = length7(candidateEdge.from, candidateEdge.to);
|
|
58805
59971
|
if (candidateEdge.is_crossing || candidateLength <= TOL3) continue;
|
|
58806
59972
|
if (!isCollinear(candidateEdge, crossingEdge)) continue;
|
|
58807
59973
|
const start = Math.max(
|
|
@@ -62116,7 +63282,7 @@ function Group_getRoutingPhasePlans(group) {
|
|
|
62116
63282
|
var package_default = {
|
|
62117
63283
|
name: "@tscircuit/core",
|
|
62118
63284
|
type: "module",
|
|
62119
|
-
version: "0.0.
|
|
63285
|
+
version: "0.0.1915",
|
|
62120
63286
|
types: "dist/index.d.ts",
|
|
62121
63287
|
main: "dist/index.js",
|
|
62122
63288
|
module: "dist/index.js",
|
|
@@ -62150,6 +63316,7 @@ var package_default = {
|
|
|
62150
63316
|
"@tsci/tscircuit.ti": "github:tscircuit/ti#57e314be4b2b06bc546d4def7453e619604d1157",
|
|
62151
63317
|
"@tscircuit/alphabet": "0.0.25",
|
|
62152
63318
|
"@tscircuit/bga-fanout-solver": "github:tscircuit/bga-fanout-solver#247c835cb8d69b65e53891dcf869731079415b39",
|
|
63319
|
+
"@tscircuit/bus-lanes-solver": "github:tscircuit/bus-lanes-solver#0bc8d071241b18a3e7465a878881abe4998f6384",
|
|
62153
63320
|
"@tscircuit/capacity-autorouter": "^0.0.900",
|
|
62154
63321
|
"@tscircuit/checks": "^0.0.192",
|
|
62155
63322
|
"@tscircuit/circuit-json-util": "^0.0.113",
|
|
@@ -62848,7 +64015,7 @@ function getAccumulatedPcbTracesWithStageOutputReplacements({
|
|
|
62848
64015
|
}
|
|
62849
64016
|
|
|
62850
64017
|
// lib/components/primitive-components/Group/get-source-trace-id-for-routed-trace.ts
|
|
62851
|
-
import { distance as
|
|
64018
|
+
import { distance as distance15, pointToSegmentDistance as pointToSegmentDistance3 } from "@tscircuit/math-utils";
|
|
62852
64019
|
import { ConnectivityMap as ConnectivityMap5 } from "circuit-json-to-connectivity-map";
|
|
62853
64020
|
var POINT_EPSILON2 = 1e-6;
|
|
62854
64021
|
function isPointOnWireSegment({
|
|
@@ -62870,7 +64037,7 @@ function isPointInSmtPad({
|
|
|
62870
64037
|
return Math.abs(point6.x - pad.x) <= pad.width / 2 + traceWidth / 2 && Math.abs(point6.y - pad.y) <= pad.height / 2 + traceWidth / 2;
|
|
62871
64038
|
}
|
|
62872
64039
|
if (pad.shape === "circle") {
|
|
62873
|
-
return
|
|
64040
|
+
return distance15(point6, pad) <= pad.radius + traceWidth / 2;
|
|
62874
64041
|
}
|
|
62875
64042
|
return false;
|
|
62876
64043
|
}
|
|
@@ -62879,7 +64046,7 @@ function isPointInPlatedHole({
|
|
|
62879
64046
|
hole,
|
|
62880
64047
|
traceWidth = 0
|
|
62881
64048
|
}) {
|
|
62882
|
-
return
|
|
64049
|
+
return distance15(point6, hole) <= (hole.outer_diameter ?? hole.hole_diameter ?? 0) / 2 + traceWidth / 2;
|
|
62883
64050
|
}
|
|
62884
64051
|
function getEndpointSourcePortIdsFromGeometry(db, trace) {
|
|
62885
64052
|
const sourcePortIds = /* @__PURE__ */ new Set();
|
|
@@ -62892,7 +64059,7 @@ function getEndpointSourcePortIdsFromGeometry(db, trace) {
|
|
|
62892
64059
|
if (!pcbPort.source_port_id) continue;
|
|
62893
64060
|
if (endpoint.layer && pcbPort.layers && !pcbPort.layers.includes(endpoint.layer))
|
|
62894
64061
|
continue;
|
|
62895
|
-
if (
|
|
64062
|
+
if (distance15(endpoint, pcbPort) <= 0.01) {
|
|
62896
64063
|
sourcePortIds.add(pcbPort.source_port_id);
|
|
62897
64064
|
}
|
|
62898
64065
|
}
|
|
@@ -63576,8 +64743,8 @@ var Group5 = class extends NormalComponent3 {
|
|
|
63576
64743
|
const groupProps2 = props;
|
|
63577
64744
|
const hasOutline = groupProps2.outline && groupProps2.outline.length > 0;
|
|
63578
64745
|
const numericOutline = hasOutline ? groupProps2.outline.map((point6) => ({
|
|
63579
|
-
x:
|
|
63580
|
-
y:
|
|
64746
|
+
x: distance16.parse(point6.x),
|
|
64747
|
+
y: distance16.parse(point6.y)
|
|
63581
64748
|
})) : void 0;
|
|
63582
64749
|
const ctx = this.props;
|
|
63583
64750
|
const anchorPosition = this._getGlobalPcbPositionBeforeLayout();
|
|
@@ -63615,8 +64782,8 @@ var Group5 = class extends NormalComponent3 {
|
|
|
63615
64782
|
const hasExplicitPositioning = this._parsedProps.pcbX !== void 0 || this._parsedProps.pcbY !== void 0;
|
|
63616
64783
|
if (hasOutline) {
|
|
63617
64784
|
const numericOutline = props.outline.map((point6) => ({
|
|
63618
|
-
x:
|
|
63619
|
-
y:
|
|
64785
|
+
x: distance16.parse(point6.x),
|
|
64786
|
+
y: distance16.parse(point6.y)
|
|
63620
64787
|
}));
|
|
63621
64788
|
const outlineBounds = getBoundsFromPoints9(numericOutline);
|
|
63622
64789
|
if (!outlineBounds) return;
|
|
@@ -64242,10 +65409,12 @@ var Group5 = class extends NormalComponent3 {
|
|
|
64242
65409
|
})
|
|
64243
65410
|
};
|
|
64244
65411
|
}
|
|
64245
|
-
|
|
64246
|
-
simpleRouteJson
|
|
64247
|
-
|
|
64248
|
-
|
|
65412
|
+
if (phaseAutorouterConfig.preset !== "bus_lanes") {
|
|
65413
|
+
simpleRouteJson = withFixedFanoutTraces(
|
|
65414
|
+
simpleRouteJson,
|
|
65415
|
+
fixedFanoutTraceIds
|
|
65416
|
+
);
|
|
65417
|
+
}
|
|
64249
65418
|
simpleRouteJson = Group_applyDrcTolerancesToSimpleRouteJson(
|
|
64250
65419
|
simpleRouteJson,
|
|
64251
65420
|
routingPhasePlan.drcTolerances
|
|
@@ -65430,8 +66599,8 @@ var Led_addPolarityFabricationSymbol = (led) => {
|
|
|
65430
66599
|
const a = db.pcb_port.getWhere({ source_port_id: anode.source_port_id });
|
|
65431
66600
|
const k = db.pcb_port.getWhere({ source_port_id: cathode.source_port_id });
|
|
65432
66601
|
if (!a || !k) return;
|
|
65433
|
-
const
|
|
65434
|
-
if (
|
|
66602
|
+
const distance23 = Math.hypot(k.x - a.x, k.y - a.y);
|
|
66603
|
+
if (distance23 < 1e-6) return;
|
|
65435
66604
|
const angle = Math.atan2(k.y - a.y, k.x - a.x);
|
|
65436
66605
|
const frame = compose14(
|
|
65437
66606
|
translate14((a.x + k.x) / 2, (a.y + k.y) / 2),
|
|
@@ -65445,10 +66614,10 @@ var Led_addPolarityFabricationSymbol = (led) => {
|
|
|
65445
66614
|
};
|
|
65446
66615
|
const notes = [];
|
|
65447
66616
|
generatedNotes.set(led, notes);
|
|
65448
|
-
const halfLength = Math.min(
|
|
66617
|
+
const halfLength = Math.min(distance23 * 0.2, 0.4);
|
|
65449
66618
|
const halfHeight = halfLength * 0.75;
|
|
65450
66619
|
const routes = [
|
|
65451
|
-
[point6(-
|
|
66620
|
+
[point6(-distance23 / 2, 0), point6(-halfLength, 0)],
|
|
65452
66621
|
[
|
|
65453
66622
|
point6(-halfLength, -halfHeight),
|
|
65454
66623
|
point6(halfLength, 0),
|
|
@@ -65456,7 +66625,7 @@ var Led_addPolarityFabricationSymbol = (led) => {
|
|
|
65456
66625
|
point6(-halfLength, -halfHeight)
|
|
65457
66626
|
],
|
|
65458
66627
|
[point6(halfLength, -halfHeight), point6(halfLength, halfHeight)],
|
|
65459
|
-
[point6(halfLength, 0), point6(
|
|
66628
|
+
[point6(halfLength, 0), point6(distance23 / 2, 0)]
|
|
65460
66629
|
];
|
|
65461
66630
|
for (const route of routes) {
|
|
65462
66631
|
notes.push(
|
|
@@ -67180,8 +68349,8 @@ import {
|
|
|
67180
68349
|
var EPSILON24 = 1e-9;
|
|
67181
68350
|
var isWireRoutePoint = (routePoint) => routePoint.route_type === "wire";
|
|
67182
68351
|
var isPointOnSegment2 = (p, a, b) => {
|
|
67183
|
-
const
|
|
67184
|
-
if (Math.abs(
|
|
68352
|
+
const cross4 = (p.y - a.y) * (b.x - a.x) - (p.x - a.x) * (b.y - a.y);
|
|
68353
|
+
if (Math.abs(cross4) > EPSILON24) return false;
|
|
67185
68354
|
const dot = (p.x - a.x) * (b.x - a.x) + (p.y - a.y) * (b.y - a.y);
|
|
67186
68355
|
if (dot < -EPSILON24) return false;
|
|
67187
68356
|
const squaredLength = (b.x - a.x) ** 2 + (b.y - a.y) ** 2;
|
|
@@ -67242,8 +68411,8 @@ var isTraceConnectedToSourceNet = (trace, sourceNetId, sourceTraceById) => {
|
|
|
67242
68411
|
var isSegmentFullyInsideCopperPour = (start, end, pour) => {
|
|
67243
68412
|
const dx = end.x - start.x;
|
|
67244
68413
|
const dy = end.y - start.y;
|
|
67245
|
-
const
|
|
67246
|
-
if (
|
|
68414
|
+
const length8 = Math.hypot(dx, dy);
|
|
68415
|
+
if (length8 <= EPSILON24) return false;
|
|
67247
68416
|
const samples = [0, 0.25, 0.5, 0.75, 1];
|
|
67248
68417
|
return samples.every(
|
|
67249
68418
|
(t) => isPointInCopperPour(
|
|
@@ -67711,13 +68880,13 @@ var getPlatedHolePolygon = (pad, componentRotation = 0) => {
|
|
|
67711
68880
|
);
|
|
67712
68881
|
};
|
|
67713
68882
|
var getTraceSegmentPolygon = (start, end, startWidth, endWidth = startWidth) => {
|
|
67714
|
-
const
|
|
68883
|
+
const length8 = Math.hypot(end.x - start.x, end.y - start.y);
|
|
67715
68884
|
const r1 = startWidth / 2;
|
|
67716
68885
|
const r2 = endWidth / 2;
|
|
67717
|
-
if (
|
|
68886
|
+
if (length8 <= Math.abs(r2 - r1))
|
|
67718
68887
|
return circlePolygon(r1 >= r2 ? start : end, Math.max(r1, r2));
|
|
67719
68888
|
const angle = Math.atan2(end.y - start.y, end.x - start.x);
|
|
67720
|
-
const tangent = Math.acos((r1 - r2) /
|
|
68889
|
+
const tangent = Math.acos((r1 - r2) / length8);
|
|
67721
68890
|
const first = new Arc(
|
|
67722
68891
|
new Point(start.x, start.y),
|
|
67723
68892
|
r1,
|
|
@@ -68022,7 +69191,7 @@ var Board_doInitialPcbPlacementDesignRuleChecks = (board) => {
|
|
|
68022
69191
|
|
|
68023
69192
|
// lib/components/normal-components/board-castellated-hole.ts
|
|
68024
69193
|
import {
|
|
68025
|
-
distance as
|
|
69194
|
+
distance as distance17
|
|
68026
69195
|
} from "circuit-json";
|
|
68027
69196
|
var CASTELLATED_HOLE_ENDPOINT_TOLERANCE_MM = 1e-6;
|
|
68028
69197
|
var getConnectionTargets2 = (connectsTo) => {
|
|
@@ -68043,8 +69212,8 @@ var BoardCastellatedHole = class _BoardCastellatedHole extends PlatedHole {
|
|
|
68043
69212
|
constructor(outlinePoint, outlinePointIndex) {
|
|
68044
69213
|
const name = `castellated_hole_${outlinePointIndex + 1}`;
|
|
68045
69214
|
const connectionTargets = getConnectionTargets2(outlinePoint.connectsTo);
|
|
68046
|
-
const holeDiameter =
|
|
68047
|
-
const padDiameter =
|
|
69215
|
+
const holeDiameter = distance17.parse(outlinePoint.holeDiameter);
|
|
69216
|
+
const padDiameter = distance17.parse(outlinePoint.padDiameter);
|
|
68048
69217
|
super({
|
|
68049
69218
|
shape: "circle",
|
|
68050
69219
|
holeDiameter,
|
|
@@ -68888,11 +70057,11 @@ var MountedBoard = class extends Subcircuit {
|
|
|
68888
70057
|
|
|
68889
70058
|
// lib/components/normal-components/Panel.ts
|
|
68890
70059
|
import { panelProps } from "@tscircuit/props";
|
|
68891
|
-
import { distance as
|
|
70060
|
+
import { distance as distance21 } from "circuit-json";
|
|
68892
70061
|
|
|
68893
70062
|
// lib/components/normal-components/Subpanel.ts
|
|
68894
70063
|
import { subpanelProps } from "@tscircuit/props";
|
|
68895
|
-
import { distance as
|
|
70064
|
+
import { distance as distance20 } from "circuit-json";
|
|
68896
70065
|
import { compose as compose17, identity as identity8, translate as translate17 } from "transformation-matrix";
|
|
68897
70066
|
|
|
68898
70067
|
// lib/utils/panels/generate-panel-tabs-and-mouse-bites.ts
|
|
@@ -69156,15 +70325,15 @@ function generatePanelOutlineRoutingCutouts(boards, options) {
|
|
|
69156
70325
|
}
|
|
69157
70326
|
|
|
69158
70327
|
// lib/utils/panels/pack-into-grid.ts
|
|
69159
|
-
import { distance as
|
|
70328
|
+
import { distance as distance19 } from "circuit-json";
|
|
69160
70329
|
|
|
69161
70330
|
// lib/utils/panels/get-board-dimensions-from-props.ts
|
|
69162
70331
|
import { getBoundsFromPoints as getBoundsFromPoints11 } from "@tscircuit/math-utils";
|
|
69163
|
-
import { distance as
|
|
70332
|
+
import { distance as distance18 } from "circuit-json";
|
|
69164
70333
|
var getBoardDimensionsFromProps = (board) => {
|
|
69165
70334
|
const props = board._parsedProps;
|
|
69166
|
-
let width = props.width != null ?
|
|
69167
|
-
let height = props.height != null ?
|
|
70335
|
+
let width = props.width != null ? distance18.parse(props.width) : void 0;
|
|
70336
|
+
let height = props.height != null ? distance18.parse(props.height) : void 0;
|
|
69168
70337
|
if ((width === void 0 || height === void 0) && props.outline?.length) {
|
|
69169
70338
|
const outlineBounds = getBoundsFromPoints11(props.outline);
|
|
69170
70339
|
if (outlineBounds) {
|
|
@@ -69208,8 +70377,8 @@ function packIntoGrid({
|
|
|
69208
70377
|
}
|
|
69209
70378
|
let cols;
|
|
69210
70379
|
let rows;
|
|
69211
|
-
const minCellWidth = cellWidth ?
|
|
69212
|
-
const minCellHeight = cellHeight ?
|
|
70380
|
+
const minCellWidth = cellWidth ? distance19.parse(cellWidth) : 0;
|
|
70381
|
+
const minCellHeight = cellHeight ? distance19.parse(cellHeight) : 0;
|
|
69213
70382
|
if (col !== void 0) {
|
|
69214
70383
|
cols = col;
|
|
69215
70384
|
rows = row ?? Math.ceil(itemsWithDims.length / cols);
|
|
@@ -69308,8 +70477,8 @@ function getItemDimensions(item, db) {
|
|
|
69308
70477
|
const props = subpanel._parsedProps;
|
|
69309
70478
|
if (props.width !== void 0 && props.height !== void 0) {
|
|
69310
70479
|
return {
|
|
69311
|
-
width:
|
|
69312
|
-
height:
|
|
70480
|
+
width: distance19.parse(props.width),
|
|
70481
|
+
height: distance19.parse(props.height)
|
|
69313
70482
|
};
|
|
69314
70483
|
}
|
|
69315
70484
|
const directBoards = subpanel._getDirectBoardChildren();
|
|
@@ -69336,7 +70505,7 @@ function getItemDimensions(item, db) {
|
|
|
69336
70505
|
return getBoardDimensionsFromProps(directBoards[0]);
|
|
69337
70506
|
}
|
|
69338
70507
|
if (subpanel._cachedGridWidth > 0 && subpanel._cachedGridHeight > 0) {
|
|
69339
|
-
const edgePadding =
|
|
70508
|
+
const edgePadding = distance19.parse(props.edgePadding ?? 5);
|
|
69340
70509
|
return {
|
|
69341
70510
|
width: subpanel._cachedGridWidth + edgePadding * 2,
|
|
69342
70511
|
height: subpanel._cachedGridHeight + edgePadding * 2
|
|
@@ -69494,17 +70663,17 @@ var Subpanel = class _Subpanel extends Group5 {
|
|
|
69494
70663
|
edgePaddingTop: edgePaddingTopProp,
|
|
69495
70664
|
edgePaddingBottom: edgePaddingBottomProp
|
|
69496
70665
|
} = this._parsedProps;
|
|
69497
|
-
const edgePadding =
|
|
69498
|
-
const edgePaddingLeft =
|
|
69499
|
-
const edgePaddingRight =
|
|
70666
|
+
const edgePadding = distance20.parse(edgePaddingProp ?? 5);
|
|
70667
|
+
const edgePaddingLeft = distance20.parse(edgePaddingLeftProp ?? edgePadding);
|
|
70668
|
+
const edgePaddingRight = distance20.parse(
|
|
69500
70669
|
edgePaddingRightProp ?? edgePadding
|
|
69501
70670
|
);
|
|
69502
|
-
const edgePaddingTop =
|
|
69503
|
-
const edgePaddingBottom =
|
|
70671
|
+
const edgePaddingTop = distance20.parse(edgePaddingTopProp ?? edgePadding);
|
|
70672
|
+
const edgePaddingBottom = distance20.parse(
|
|
69504
70673
|
edgePaddingBottomProp ?? edgePadding
|
|
69505
70674
|
);
|
|
69506
|
-
const panelWidth =
|
|
69507
|
-
const panelHeight =
|
|
70675
|
+
const panelWidth = distance20.parse(this._parsedProps.width);
|
|
70676
|
+
const panelHeight = distance20.parse(this._parsedProps.height);
|
|
69508
70677
|
availablePanelWidth = panelWidth - edgePaddingLeft - edgePaddingRight;
|
|
69509
70678
|
availablePanelHeight = panelHeight - edgePaddingTop - edgePaddingBottom;
|
|
69510
70679
|
}
|
|
@@ -69579,8 +70748,8 @@ var Subpanel = class _Subpanel extends Group5 {
|
|
|
69579
70748
|
if (!this.pcb_group_id) return;
|
|
69580
70749
|
if (hasExplicitWidth && hasExplicitHeight) {
|
|
69581
70750
|
db.pcb_group.update(this.pcb_group_id, {
|
|
69582
|
-
width:
|
|
69583
|
-
height:
|
|
70751
|
+
width: distance20.parse(this._parsedProps.width),
|
|
70752
|
+
height: distance20.parse(this._parsedProps.height)
|
|
69584
70753
|
});
|
|
69585
70754
|
} else if (gridWidth > 0 || gridHeight > 0) {
|
|
69586
70755
|
const {
|
|
@@ -69590,18 +70759,18 @@ var Subpanel = class _Subpanel extends Group5 {
|
|
|
69590
70759
|
edgePaddingTop: edgePaddingTopProp,
|
|
69591
70760
|
edgePaddingBottom: edgePaddingBottomProp
|
|
69592
70761
|
} = this._parsedProps;
|
|
69593
|
-
const edgePadding =
|
|
69594
|
-
const edgePaddingLeft =
|
|
69595
|
-
const edgePaddingRight =
|
|
70762
|
+
const edgePadding = distance20.parse(edgePaddingProp ?? 5);
|
|
70763
|
+
const edgePaddingLeft = distance20.parse(edgePaddingLeftProp ?? edgePadding);
|
|
70764
|
+
const edgePaddingRight = distance20.parse(
|
|
69596
70765
|
edgePaddingRightProp ?? edgePadding
|
|
69597
70766
|
);
|
|
69598
|
-
const edgePaddingTop =
|
|
69599
|
-
const edgePaddingBottom =
|
|
70767
|
+
const edgePaddingTop = distance20.parse(edgePaddingTopProp ?? edgePadding);
|
|
70768
|
+
const edgePaddingBottom = distance20.parse(
|
|
69600
70769
|
edgePaddingBottomProp ?? edgePadding
|
|
69601
70770
|
);
|
|
69602
70771
|
db.pcb_group.update(this.pcb_group_id, {
|
|
69603
|
-
width: hasExplicitWidth ?
|
|
69604
|
-
height: hasExplicitHeight ?
|
|
70772
|
+
width: hasExplicitWidth ? distance20.parse(this._parsedProps.width) : gridWidth + edgePaddingLeft + edgePaddingRight,
|
|
70773
|
+
height: hasExplicitHeight ? distance20.parse(this._parsedProps.height) : gridHeight + edgePaddingTop + edgePaddingBottom
|
|
69605
70774
|
});
|
|
69606
70775
|
}
|
|
69607
70776
|
}
|
|
@@ -69689,8 +70858,8 @@ var Panel = class extends Subpanel {
|
|
|
69689
70858
|
const { db } = this.root;
|
|
69690
70859
|
const props = this._parsedProps;
|
|
69691
70860
|
const inserted = db.pcb_panel.insert({
|
|
69692
|
-
width: props.width !== void 0 ?
|
|
69693
|
-
height: props.height !== void 0 ?
|
|
70861
|
+
width: props.width !== void 0 ? distance21.parse(props.width) : 0,
|
|
70862
|
+
height: props.height !== void 0 ? distance21.parse(props.height) : 0,
|
|
69694
70863
|
thickness: 1.6,
|
|
69695
70864
|
center: this._getGlobalPcbPositionBeforeLayout(),
|
|
69696
70865
|
covered_with_solder_mask: !(props.noSolderMask ?? false)
|
|
@@ -69709,8 +70878,8 @@ var Panel = class extends Subpanel {
|
|
|
69709
70878
|
if (!this.pcb_panel_id) return;
|
|
69710
70879
|
if (hasExplicitWidth && hasExplicitHeight) {
|
|
69711
70880
|
db.pcb_panel.update(this.pcb_panel_id, {
|
|
69712
|
-
width:
|
|
69713
|
-
height:
|
|
70881
|
+
width: distance21.parse(this._parsedProps.width),
|
|
70882
|
+
height: distance21.parse(this._parsedProps.height)
|
|
69714
70883
|
});
|
|
69715
70884
|
} else if (gridWidth > 0 || gridHeight > 0) {
|
|
69716
70885
|
const {
|
|
@@ -69720,18 +70889,18 @@ var Panel = class extends Subpanel {
|
|
|
69720
70889
|
edgePaddingTop: edgePaddingTopProp,
|
|
69721
70890
|
edgePaddingBottom: edgePaddingBottomProp
|
|
69722
70891
|
} = this._parsedProps;
|
|
69723
|
-
const edgePadding =
|
|
69724
|
-
const edgePaddingLeft =
|
|
69725
|
-
const edgePaddingRight =
|
|
70892
|
+
const edgePadding = distance21.parse(edgePaddingProp ?? 5);
|
|
70893
|
+
const edgePaddingLeft = distance21.parse(edgePaddingLeftProp ?? edgePadding);
|
|
70894
|
+
const edgePaddingRight = distance21.parse(
|
|
69726
70895
|
edgePaddingRightProp ?? edgePadding
|
|
69727
70896
|
);
|
|
69728
|
-
const edgePaddingTop =
|
|
69729
|
-
const edgePaddingBottom =
|
|
70897
|
+
const edgePaddingTop = distance21.parse(edgePaddingTopProp ?? edgePadding);
|
|
70898
|
+
const edgePaddingBottom = distance21.parse(
|
|
69730
70899
|
edgePaddingBottomProp ?? edgePadding
|
|
69731
70900
|
);
|
|
69732
70901
|
db.pcb_panel.update(this.pcb_panel_id, {
|
|
69733
|
-
width: hasExplicitWidth ?
|
|
69734
|
-
height: hasExplicitHeight ?
|
|
70902
|
+
width: hasExplicitWidth ? distance21.parse(this._parsedProps.width) : gridWidth + edgePaddingLeft + edgePaddingRight,
|
|
70903
|
+
height: hasExplicitHeight ? distance21.parse(this._parsedProps.height) : gridHeight + edgePaddingTop + edgePaddingBottom
|
|
69735
70904
|
});
|
|
69736
70905
|
}
|
|
69737
70906
|
}
|
|
@@ -69742,8 +70911,8 @@ var Panel = class extends Subpanel {
|
|
|
69742
70911
|
const props = this._parsedProps;
|
|
69743
70912
|
const currentPanel = db.pcb_panel.get(this.pcb_panel_id);
|
|
69744
70913
|
db.pcb_panel.update(this.pcb_panel_id, {
|
|
69745
|
-
width: props.width !== void 0 ?
|
|
69746
|
-
height: props.height !== void 0 ?
|
|
70914
|
+
width: props.width !== void 0 ? distance21.parse(props.width) : currentPanel?.width,
|
|
70915
|
+
height: props.height !== void 0 ? distance21.parse(props.height) : currentPanel?.height,
|
|
69747
70916
|
center: this._getGlobalPcbPositionBeforeLayout(),
|
|
69748
70917
|
covered_with_solder_mask: !(props.noSolderMask ?? false)
|
|
69749
70918
|
});
|
|
@@ -72049,7 +73218,7 @@ var validateWindingBreakoutInput = (input) => {
|
|
|
72049
73218
|
};
|
|
72050
73219
|
|
|
72051
73220
|
// node_modules/@tscircuit/winding-breakout-point-solver/lib/solvers/GatePlacementSolver.ts
|
|
72052
|
-
import { BaseSolver as
|
|
73221
|
+
import { BaseSolver as BaseSolver7 } from "@tscircuit/solver-utils";
|
|
72053
73222
|
|
|
72054
73223
|
// node_modules/@tscircuit/winding-breakout-point-solver/lib/gate-placement/place-breakout-gates.ts
|
|
72055
73224
|
var GEOMETRY_EPSILON = 1e-9;
|
|
@@ -72579,7 +73748,7 @@ var getSharedGateSlotCount = (points) => new Set(
|
|
|
72579
73748
|
(point6) => `${point6.regionId}:${point6.x.toFixed(9)}:${point6.y.toFixed(9)}`
|
|
72580
73749
|
)
|
|
72581
73750
|
).size;
|
|
72582
|
-
var GatePlacementSolver = class extends
|
|
73751
|
+
var GatePlacementSolver = class extends BaseSolver7 {
|
|
72583
73752
|
constructor(params) {
|
|
72584
73753
|
super();
|
|
72585
73754
|
this.params = params;
|
|
@@ -72718,7 +73887,7 @@ var GatePlacementSolver = class extends BaseSolver6 {
|
|
|
72718
73887
|
};
|
|
72719
73888
|
|
|
72720
73889
|
// node_modules/@tscircuit/winding-breakout-point-solver/lib/solvers/ReferenceOrderingSolver.ts
|
|
72721
|
-
import { BaseSolver as
|
|
73890
|
+
import { BaseSolver as BaseSolver8 } from "@tscircuit/solver-utils";
|
|
72722
73891
|
|
|
72723
73892
|
// node_modules/@tscircuit/winding-breakout-point-solver/lib/ordering/get-natural-winding-order.ts
|
|
72724
73893
|
var getNaturalWindingOrder = (region, connections) => connections.map((connection) => {
|
|
@@ -72785,7 +73954,7 @@ var getReferenceWindingOrder = (naturalOrder, atomicGroups, buses) => {
|
|
|
72785
73954
|
};
|
|
72786
73955
|
|
|
72787
73956
|
// node_modules/@tscircuit/winding-breakout-point-solver/lib/solvers/ReferenceOrderingSolver.ts
|
|
72788
|
-
var ReferenceOrderingSolver = class extends
|
|
73957
|
+
var ReferenceOrderingSolver = class extends BaseSolver8 {
|
|
72789
73958
|
constructor(params) {
|
|
72790
73959
|
super();
|
|
72791
73960
|
this.params = params;
|
|
@@ -74130,7 +75299,7 @@ var SilkscreenGraphic = class extends PrimitiveComponent2 {
|
|
|
74130
75299
|
|
|
74131
75300
|
// lib/components/primitive-components/Fiducial.ts
|
|
74132
75301
|
import "zod";
|
|
74133
|
-
import { distance as
|
|
75302
|
+
import { distance as distance22 } from "circuit-json";
|
|
74134
75303
|
import { fiducialProps as fiducialProps2 } from "@tscircuit/props";
|
|
74135
75304
|
var Fiducial = class extends PrimitiveComponent2 {
|
|
74136
75305
|
pcb_smtpad_id = null;
|
|
@@ -74155,15 +75324,15 @@ var Fiducial = class extends PrimitiveComponent2 {
|
|
|
74155
75324
|
shape: "circle",
|
|
74156
75325
|
x: position.x,
|
|
74157
75326
|
y: position.y,
|
|
74158
|
-
radius:
|
|
74159
|
-
soldermask_margin: props.soldermaskPullback ?
|
|
75327
|
+
radius: distance22.parse(props.padDiameter) / 2,
|
|
75328
|
+
soldermask_margin: props.soldermaskPullback ? distance22.parse(props.soldermaskPullback) : distance22.parse(props.padDiameter) / 2,
|
|
74160
75329
|
is_covered_with_solder_mask: true
|
|
74161
75330
|
});
|
|
74162
75331
|
this.pcb_smtpad_id = pcb_smtpad.pcb_smtpad_id;
|
|
74163
75332
|
}
|
|
74164
75333
|
getPcbSize() {
|
|
74165
75334
|
const { _parsedProps: props } = this;
|
|
74166
|
-
const d =
|
|
75335
|
+
const d = distance22.parse(props.padDiameter);
|
|
74167
75336
|
return { width: d, height: d };
|
|
74168
75337
|
}
|
|
74169
75338
|
_setPositionFromLayout(newCenter) {
|