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