@tscircuit/schematic-trace-solver 0.0.189 → 0.0.191
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 +680 -428
- package/lib/solvers/InlineNetLabelSolver/getLocalTraceLabelShifts.ts +29 -0
- package/lib/solvers/LongDistancePairSolver/LongDistancePairSolver.ts +7 -0
- package/lib/solvers/LongDistancePairSolver/getParallelNetLabelPolicy.ts +98 -0
- package/lib/solvers/MspConnectionPairSolver/MspConnectionPairSolver.ts +24 -2
- package/lib/solvers/MspConnectionPairSolver/getParallelRailPairs.ts +178 -0
- package/lib/solvers/NetLabelToTraceSolver/NetLabelToTraceSolver.ts +13 -0
- package/lib/solvers/SameNetJunctionAlignmentSolver/SameNetJunctionAlignmentSolver.ts +4 -9
- package/lib/solvers/SameNetJunctionAlignmentSolver/alignSameNetJunctions.ts +10 -2
- package/lib/solvers/SameNetJunctionAlignmentSolver/collapseSameNetCycles.ts +75 -38
- package/package.json +1 -1
- package/tests/bug-reports/bug-report-20260706T213649Z/__snapshots__/bug-report-20260706T213649Z.snap.svg +837 -799
- package/tests/bug-reports/bug-report-20260706T220324Z/__snapshots__/bug-report-20260706T220324Z.snap.svg +904 -866
- package/tests/bug-reports/bug-report-20260707T092615Z/__snapshots__/bug-report-20260707T092615Z.snap.svg +533 -524
- package/tests/bug-reports/bug-report-20260804T171919Z/__snapshots__/bug-report-20260804T171919Z.snap.svg +2 -2
- package/tests/bug-reports/bug-report-20260806T093501Z/__snapshots__/bug-report-20260806T093501Z.snap.svg +94 -94
- package/tests/bug-reports/bug-report-20260901T064117Z/bug-report-20260901T064117Z.test.ts +13 -2
- package/tests/bug-reports/bug-report-20260902T092425Z/__snapshots__/bug-report-20260902T092425Z.snap.svg +2 -2
- package/tests/bug-reports/bug-report-20260902T092425Z/bug-report-20260902T092425Z.test.ts +16 -2
- package/tests/bug-reports/bug-report-20260905T041712Z/__snapshots__/bug-report-20260905T041712Z.snap.svg +2 -2
- package/tests/bug-reports/bug-report-20260907T110144Z/__snapshots__/bug-report-20260907T110144Z.snap.svg +19 -58
- package/tests/bug-reports/bug-report-20260907T110144Z/bug-report-20260907T110144Z.test.ts +2 -2
- package/tests/bug-reports/bug-report-20260907T145640Z/__snapshots__/bug-report-20260907T145640Z.snap.svg +917 -933
- package/tests/repros/__snapshots__/repro-pmp11282-isolated-dcdc.snap.svg +18 -18
- package/tests/repros/__snapshots__/repro-repeated-power-rail-junctions.snap.svg +255 -0
- package/tests/repros/__snapshots__/repro-smartwatch-power-sheet.snap.svg +111 -75
- package/tests/repros/assets/repro-repeated-power-rail-junctions.input.json +927 -0
- package/tests/repros/repro-repeated-power-rail-junctions.test.ts +22 -0
- package/tests/repros/repro-trellis-core-decoupling-snake-traces.test.ts +66 -0
- package/tests/solvers/InlineNetLabelSolver/local-trace-label-shifts.test.ts +62 -0
- package/tests/solvers/LongDistancePairSolver/__snapshots__/decoupling-mixed-supplies.snap.svg +112 -0
- package/tests/solvers/LongDistancePairSolver/__snapshots__/horizontal-rails.snap.svg +79 -0
- package/tests/solvers/LongDistancePairSolver/__snapshots__/vertical-rails.snap.svg +86 -0
- package/tests/solvers/LongDistancePairSolver/parallel-decoupling-labels.test.ts +505 -0
- package/tests/solvers/SameNetJunctionAlignmentSolver/collapse-same-net-cycles.test.ts +30 -0
package/dist/index.js
CHANGED
|
@@ -342,19 +342,19 @@ var doesPairCrossRestrictedCenterLines = (params) => {
|
|
|
342
342
|
chipMap
|
|
343
343
|
});
|
|
344
344
|
if (restrictedCenterLines.size === 0) return false;
|
|
345
|
-
const
|
|
345
|
+
const EPS19 = 1e-9;
|
|
346
346
|
const crossesSegment = (a, b) => {
|
|
347
347
|
for (const [, rcl] of restrictedCenterLines) {
|
|
348
348
|
if (rcl.axes.has("x") && typeof rcl.x === "number") {
|
|
349
|
-
if ((a.x - rcl.x) * (b.x - rcl.x) < -
|
|
349
|
+
if ((a.x - rcl.x) * (b.x - rcl.x) < -EPS19) return true;
|
|
350
350
|
}
|
|
351
351
|
if (rcl.axes.has("y") && typeof rcl.y === "number") {
|
|
352
|
-
if ((a.y - rcl.y) * (b.y - rcl.y) < -
|
|
352
|
+
if ((a.y - rcl.y) * (b.y - rcl.y) < -EPS19) return true;
|
|
353
353
|
}
|
|
354
354
|
}
|
|
355
355
|
return false;
|
|
356
356
|
};
|
|
357
|
-
if (Math.abs(p1.x - p2.x) <
|
|
357
|
+
if (Math.abs(p1.x - p2.x) < EPS19 || Math.abs(p1.y - p2.y) < EPS19) {
|
|
358
358
|
return crossesSegment({ x: p1.x, y: p1.y }, { x: p2.x, y: p2.y });
|
|
359
359
|
}
|
|
360
360
|
const elbowHV = { x: p2.x, y: p1.y };
|
|
@@ -608,6 +608,126 @@ function shouldSeparateGroundNetRows({
|
|
|
608
608
|
return isGroupedHorizontalRail({ pin: pin1, netPins }) && isGroupedHorizontalRail({ pin: pin2, netPins });
|
|
609
609
|
}
|
|
610
610
|
|
|
611
|
+
// lib/solvers/MspConnectionPairSolver/getParallelRailPairs.ts
|
|
612
|
+
var EPS = 1e-6;
|
|
613
|
+
var MAX_RAIL_SPACING_IN_TERMINAL_SPANS = 4;
|
|
614
|
+
var MAX_RAIL_SPACING_MULTIPLIER = 2;
|
|
615
|
+
var getRailPairKey = (first, second) => JSON.stringify([first, second].sort());
|
|
616
|
+
var getParallelRailPairs = (inputProblem, netConnMap, maxMspPairDistance) => {
|
|
617
|
+
const groundNetIds = /* @__PURE__ */ new Set();
|
|
618
|
+
const namedPinIds = /* @__PURE__ */ new Set();
|
|
619
|
+
const wiredPinIds = /* @__PURE__ */ new Set();
|
|
620
|
+
for (const connection of inputProblem.netConnections) {
|
|
621
|
+
for (const pinId of connection.pinIds) namedPinIds.add(pinId);
|
|
622
|
+
const netId = netConnMap.getNetConnectedToId(connection.netId);
|
|
623
|
+
if (netId && connection.isGround) {
|
|
624
|
+
groundNetIds.add(netId);
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
for (const connection of inputProblem.directConnections) {
|
|
628
|
+
const pinIds = connection.netLabelWidth === void 0 ? wiredPinIds : namedPinIds;
|
|
629
|
+
for (const pinId of connection.pinIds) pinIds.add(pinId);
|
|
630
|
+
}
|
|
631
|
+
const rows = [];
|
|
632
|
+
for (const chip of inputProblem.chips) {
|
|
633
|
+
if (chip.pins.length !== 2 || chip.symbolName && !chip.symbolName.startsWith("capacitor") || !chip.pins.every((pin) => namedPinIds.has(pin.pinId)) || chip.pins.some((pin) => wiredPinIds.has(pin.pinId)))
|
|
634
|
+
continue;
|
|
635
|
+
const nets = chip.pins.map(
|
|
636
|
+
(pin) => netConnMap.getNetConnectedToId(pin.pinId)
|
|
637
|
+
);
|
|
638
|
+
if (!nets[0] || !nets[1] || nets[0] === nets[1] || groundNetIds.has(nets[0]) === groundNetIds.has(nets[1]))
|
|
639
|
+
continue;
|
|
640
|
+
const directions = chip.pins.map(
|
|
641
|
+
(pin) => pin._facingDirection ?? getPinDirection(pin, chip)
|
|
642
|
+
);
|
|
643
|
+
if (directions[0][0] !== directions[1][0] || directions[0] === directions[1])
|
|
644
|
+
continue;
|
|
645
|
+
const axis = directions[0][0];
|
|
646
|
+
const along = axis === "x" ? "y" : "x";
|
|
647
|
+
if (Math.abs(chip.pins[0][along] - chip.pins[1][along]) > EPS) continue;
|
|
648
|
+
for (const [index, pin] of chip.pins.entries()) {
|
|
649
|
+
const direction = directions[index];
|
|
650
|
+
let row = rows.find(
|
|
651
|
+
(candidate) => candidate.sectionId === chip.sectionId && candidate.direction === direction && Math.abs(candidate.coordinate - pin[axis]) <= EPS
|
|
652
|
+
);
|
|
653
|
+
if (!row) {
|
|
654
|
+
row = {
|
|
655
|
+
sectionId: chip.sectionId,
|
|
656
|
+
direction,
|
|
657
|
+
coordinate: pin[axis],
|
|
658
|
+
axis,
|
|
659
|
+
pins: []
|
|
660
|
+
};
|
|
661
|
+
rows.push(row);
|
|
662
|
+
}
|
|
663
|
+
row.pins.push({
|
|
664
|
+
...pin,
|
|
665
|
+
chipId: chip.chipId,
|
|
666
|
+
oppositeCoordinate: chip.pins[1 - index][axis]
|
|
667
|
+
});
|
|
668
|
+
}
|
|
669
|
+
}
|
|
670
|
+
const pairKeys = /* @__PURE__ */ new Set();
|
|
671
|
+
const extendedRailPinIds = /* @__PURE__ */ new Set();
|
|
672
|
+
const separatedRailPinIds = /* @__PURE__ */ new Set();
|
|
673
|
+
for (const row of rows) {
|
|
674
|
+
const along = row.axis === "x" ? "y" : "x";
|
|
675
|
+
row.pins.sort(
|
|
676
|
+
(a, b) => a[along] - b[along] || a.pinId.localeCompare(b.pinId)
|
|
677
|
+
);
|
|
678
|
+
for (let index = 1; index < row.pins.length; index++) {
|
|
679
|
+
const first = row.pins[index - 1];
|
|
680
|
+
const second = row.pins[index];
|
|
681
|
+
const spacing = second[along] - first[along];
|
|
682
|
+
const neighboringSpacings = [
|
|
683
|
+
first[along] - (row.pins[index - 2]?.[along] ?? first[along]),
|
|
684
|
+
(row.pins[index + 1]?.[along] ?? second[along]) - second[along]
|
|
685
|
+
].filter((gap) => gap > EPS);
|
|
686
|
+
const maxRailSpacing = Math.max(
|
|
687
|
+
MAX_RAIL_SPACING_MULTIPLIER * maxMspPairDistance,
|
|
688
|
+
MAX_RAIL_SPACING_MULTIPLIER * (neighboringSpacings.length ? Math.min(...neighboringSpacings) : 0),
|
|
689
|
+
MAX_RAIL_SPACING_IN_TERMINAL_SPANS * Math.max(
|
|
690
|
+
Math.abs(first[row.axis] - first.oppositeCoordinate),
|
|
691
|
+
Math.abs(second[row.axis] - second.oppositeCoordinate)
|
|
692
|
+
)
|
|
693
|
+
);
|
|
694
|
+
if (spacing <= EPS || netConnMap.getNetConnectedToId(first.pinId) !== netConnMap.getNetConnectedToId(second.pinId))
|
|
695
|
+
continue;
|
|
696
|
+
if (spacing > maxRailSpacing + EPS) {
|
|
697
|
+
separatedRailPinIds.add(first.pinId);
|
|
698
|
+
separatedRailPinIds.add(second.pinId);
|
|
699
|
+
continue;
|
|
700
|
+
}
|
|
701
|
+
const minAcross = Math.min(
|
|
702
|
+
first[row.axis],
|
|
703
|
+
second[row.axis],
|
|
704
|
+
first.oppositeCoordinate,
|
|
705
|
+
second.oppositeCoordinate
|
|
706
|
+
);
|
|
707
|
+
const maxAcross = Math.max(
|
|
708
|
+
first[row.axis],
|
|
709
|
+
second[row.axis],
|
|
710
|
+
first.oppositeCoordinate,
|
|
711
|
+
second.oppositeCoordinate
|
|
712
|
+
);
|
|
713
|
+
if (inputProblem.chips.some((chip) => {
|
|
714
|
+
if (chip.chipId === first.chipId || chip.chipId === second.chipId)
|
|
715
|
+
return false;
|
|
716
|
+
const acrossSize = row.axis === "x" ? chip.width : chip.height;
|
|
717
|
+
const alongSize = along === "x" ? chip.width : chip.height;
|
|
718
|
+
return chip.center[row.axis] + acrossSize / 2 >= minAcross - EPS && chip.center[row.axis] - acrossSize / 2 <= maxAcross + EPS && chip.center[along] + alongSize / 2 > first[along] + EPS && chip.center[along] - alongSize / 2 < second[along] - EPS;
|
|
719
|
+
}))
|
|
720
|
+
continue;
|
|
721
|
+
pairKeys.add(getRailPairKey(first.pinId, second.pinId));
|
|
722
|
+
if (spacing > maxMspPairDistance) {
|
|
723
|
+
extendedRailPinIds.add(first.pinId);
|
|
724
|
+
extendedRailPinIds.add(second.pinId);
|
|
725
|
+
}
|
|
726
|
+
}
|
|
727
|
+
}
|
|
728
|
+
return { pairKeys, extendedRailPinIds, separatedRailPinIds };
|
|
729
|
+
};
|
|
730
|
+
|
|
611
731
|
// lib/solvers/MspConnectionPairSolver/MspConnectionPairSolver.ts
|
|
612
732
|
var DEFAULT_MAX_MSP_PAIR_DISTANCE = 1;
|
|
613
733
|
var getPinPairKey = (pinIds) => [...pinIds].sort().join("::");
|
|
@@ -624,6 +744,7 @@ var MspConnectionPairSolver = class extends BaseSolver {
|
|
|
624
744
|
userNetIdByPinId;
|
|
625
745
|
directConnectionPinPairKeys;
|
|
626
746
|
canRouteGroundPair;
|
|
747
|
+
parallelRailPairKeys;
|
|
627
748
|
constructor({ inputProblem }) {
|
|
628
749
|
super();
|
|
629
750
|
this.inputProblem = inputProblem;
|
|
@@ -632,6 +753,11 @@ var MspConnectionPairSolver = class extends BaseSolver {
|
|
|
632
753
|
const { directConnMap, netConnMap } = getConnectivityMapsFromInputProblem(inputProblem);
|
|
633
754
|
this.dcConnMap = directConnMap;
|
|
634
755
|
this.globalConnMap = netConnMap;
|
|
756
|
+
this.parallelRailPairKeys = getParallelRailPairs(
|
|
757
|
+
inputProblem,
|
|
758
|
+
netConnMap,
|
|
759
|
+
this.maxMspPairDistance
|
|
760
|
+
).pairKeys;
|
|
635
761
|
this.pinMap = {};
|
|
636
762
|
for (const chip of inputProblem.chips) {
|
|
637
763
|
for (const pin of chip.pins) {
|
|
@@ -695,7 +821,7 @@ var MspConnectionPairSolver = class extends BaseSolver {
|
|
|
695
821
|
chipMap: this.chipMap,
|
|
696
822
|
pins: [p1, p2]
|
|
697
823
|
});
|
|
698
|
-
if (pairDistance > this.maxMspPairDistance && !labeledConnectionRouteReason) {
|
|
824
|
+
if (pairDistance > this.maxMspPairDistance && !this.parallelRailPairKeys.has(getRailPairKey(pin1, pin2)) && !labeledConnectionRouteReason) {
|
|
699
825
|
return;
|
|
700
826
|
}
|
|
701
827
|
if (arePinsInDifferentSchematicSections(this.inputProblem, p1, p2)) {
|
|
@@ -733,8 +859,7 @@ var MspConnectionPairSolver = class extends BaseSolver {
|
|
|
733
859
|
(pinId) => this.pinMap[pinId]
|
|
734
860
|
);
|
|
735
861
|
const msp = getOrthogonalMinimumSpanningTree(directlyConnectedPinObjects, {
|
|
736
|
-
|
|
737
|
-
forbidEdge: (a, b) => !this.canRouteGroundPair(a.pinId, b.pinId) || shouldSeparateGroundNetRows({
|
|
862
|
+
forbidEdge: (a, b) => Math.abs(a.x - b.x) + Math.abs(a.y - b.y) > this.maxMspPairDistance && !this.parallelRailPairKeys.has(getRailPairKey(a.pinId, b.pinId)) || !this.canRouteGroundPair(a.pinId, b.pinId) || shouldSeparateGroundNetRows({
|
|
738
863
|
netConnection,
|
|
739
864
|
netPins: directlyConnectedPinObjects,
|
|
740
865
|
pin1: a,
|
|
@@ -747,7 +872,11 @@ var MspConnectionPairSolver = class extends BaseSolver {
|
|
|
747
872
|
p2: b
|
|
748
873
|
})
|
|
749
874
|
});
|
|
750
|
-
for (
|
|
875
|
+
for (let [pin1, pin2] of msp) {
|
|
876
|
+
if (this.parallelRailPairKeys.has(getRailPairKey(pin1, pin2)) && Math.abs(this.pinMap[pin1].x - this.pinMap[pin2].x) + Math.abs(this.pinMap[pin1].y - this.pinMap[pin2].y) > this.maxMspPairDistance && directlyConnectedPins.indexOf(pin1) > directlyConnectedPins.indexOf(pin2)) {
|
|
877
|
+
;
|
|
878
|
+
[pin1, pin2] = [pin2, pin1];
|
|
879
|
+
}
|
|
751
880
|
const p1Obj = this.pinMap[pin1];
|
|
752
881
|
const p2Obj = this.pinMap[pin2];
|
|
753
882
|
if (arePinsInDifferentSchematicSections(this.inputProblem, p1Obj, p2Obj)) {
|
|
@@ -971,10 +1100,10 @@ function calculateDirectShortPath(pin1, pin2) {
|
|
|
971
1100
|
}
|
|
972
1101
|
|
|
973
1102
|
// lib/solvers/SchematicTraceLinesSolver/SchematicTraceSingleLineSolver2/collisions.ts
|
|
974
|
-
var
|
|
975
|
-
var isVertical = (a, b, eps =
|
|
976
|
-
var isHorizontal = (a, b, eps =
|
|
977
|
-
var segmentIntersectsRect = (a, b, r, eps =
|
|
1103
|
+
var EPS2 = 1e-9;
|
|
1104
|
+
var isVertical = (a, b, eps = EPS2) => Math.abs(a.x - b.x) < eps;
|
|
1105
|
+
var isHorizontal = (a, b, eps = EPS2) => Math.abs(a.y - b.y) < eps;
|
|
1106
|
+
var segmentIntersectsRect = (a, b, r, eps = EPS2) => {
|
|
978
1107
|
const vert = isVertical(a, b, eps);
|
|
979
1108
|
const horz = isHorizontal(a, b, eps);
|
|
980
1109
|
if (!vert && !horz) return false;
|
|
@@ -994,7 +1123,7 @@ var segmentIntersectsRect = (a, b, r, eps = EPS) => {
|
|
|
994
1123
|
return overlap > eps;
|
|
995
1124
|
}
|
|
996
1125
|
};
|
|
997
|
-
var segmentOverlapsRectBoundary = (a, b, r, eps =
|
|
1126
|
+
var segmentOverlapsRectBoundary = (a, b, r, eps = EPS2) => {
|
|
998
1127
|
if (isVertical(a, b, eps)) {
|
|
999
1128
|
const onVerticalBoundary = Math.abs(a.x - r.minX) <= eps || Math.abs(a.x - r.maxX) <= eps;
|
|
1000
1129
|
if (!onVerticalBoundary) return false;
|
|
@@ -1035,7 +1164,7 @@ var isPathCollidingWithObstacles = (path, obstacles) => {
|
|
|
1035
1164
|
};
|
|
1036
1165
|
|
|
1037
1166
|
// lib/solvers/SchematicTraceLinesSolver/SchematicTraceSingleLineSolver2/mid.ts
|
|
1038
|
-
var
|
|
1167
|
+
var EPS3 = 1e-9;
|
|
1039
1168
|
var OBSTACLE_CLEARANCE = 0.2;
|
|
1040
1169
|
var aabbFromPoints = (a, b) => ({
|
|
1041
1170
|
minX: Math.min(a.x, b.x),
|
|
@@ -1043,7 +1172,7 @@ var aabbFromPoints = (a, b) => ({
|
|
|
1043
1172
|
minY: Math.min(a.y, b.y),
|
|
1044
1173
|
maxY: Math.max(a.y, b.y)
|
|
1045
1174
|
});
|
|
1046
|
-
var midBetweenPointAndRect = (axis, p, r, eps =
|
|
1175
|
+
var midBetweenPointAndRect = (axis, p, r, eps = EPS3) => {
|
|
1047
1176
|
if (axis === "x") {
|
|
1048
1177
|
if (p.x < r.minX - eps) {
|
|
1049
1178
|
return [(p.x + r.minX) / 2];
|
|
@@ -1063,7 +1192,7 @@ var midBetweenPointAndRect = (axis, p, r, eps = EPS2) => {
|
|
|
1063
1192
|
}
|
|
1064
1193
|
};
|
|
1065
1194
|
var candidateMidsFromSet = (axis, colliding, collisionRects, aabb, opts = {}) => {
|
|
1066
|
-
const { allowOpenSideCandidates = false, eps =
|
|
1195
|
+
const { allowOpenSideCandidates = false, eps = EPS3 } = opts;
|
|
1067
1196
|
const setRects = [...collisionRects];
|
|
1068
1197
|
if (axis === "x") {
|
|
1069
1198
|
const leftBoundaries = [aabb.minX, ...setRects.map((r) => r.maxX)].filter(
|
|
@@ -1111,7 +1240,7 @@ var candidateMidsFromSet = (axis, colliding, collisionRects, aabb, opts = {}) =>
|
|
|
1111
1240
|
};
|
|
1112
1241
|
|
|
1113
1242
|
// lib/solvers/SchematicTraceLinesSolver/SchematicTraceSingleLineSolver2/pathOps.ts
|
|
1114
|
-
var
|
|
1243
|
+
var EPS4 = 1e-9;
|
|
1115
1244
|
var hasOnlyNonzeroOrthogonalSegments = (path) => path.every((point, index) => {
|
|
1116
1245
|
const nextPoint = path[index + 1];
|
|
1117
1246
|
if (!nextPoint) return true;
|
|
@@ -1120,7 +1249,7 @@ var hasOnlyNonzeroOrthogonalSegments = (path) => path.every((point, index) => {
|
|
|
1120
1249
|
}
|
|
1121
1250
|
return Math.abs(point.x - nextPoint.x) + Math.abs(point.y - nextPoint.y) > 0;
|
|
1122
1251
|
});
|
|
1123
|
-
var shiftSegmentOrth = (pts, segIndex, axis, newCoord, eps =
|
|
1252
|
+
var shiftSegmentOrth = (pts, segIndex, axis, newCoord, eps = EPS4) => {
|
|
1124
1253
|
if (segIndex < 0 || segIndex >= pts.length - 1) {
|
|
1125
1254
|
return null;
|
|
1126
1255
|
}
|
|
@@ -1237,9 +1366,9 @@ var generateEndpointCollisionDetours = ({
|
|
|
1237
1366
|
};
|
|
1238
1367
|
|
|
1239
1368
|
// lib/solvers/SchematicTraceLinesSolver/SchematicTraceSingleLineSolver2/generateInternalSegmentCollisionDetours.ts
|
|
1240
|
-
var
|
|
1369
|
+
var EPS5 = 1e-9;
|
|
1241
1370
|
var DEFAULT_CLEARANCE = 0.2;
|
|
1242
|
-
var isStrictlyBetween = (value, a, b) => value > Math.min(a, b) +
|
|
1371
|
+
var isStrictlyBetween = (value, a, b) => value > Math.min(a, b) + EPS5 && value < Math.max(a, b) - EPS5;
|
|
1243
1372
|
var generateInternalSegmentCollisionDetours = ({
|
|
1244
1373
|
path,
|
|
1245
1374
|
collidingSegmentIndex,
|
|
@@ -1657,8 +1786,8 @@ var SchematicTraceSingleLineSolver2 = class extends BaseSolver {
|
|
|
1657
1786
|
if (!collision) {
|
|
1658
1787
|
const first = path[0];
|
|
1659
1788
|
const last = path[path.length - 1];
|
|
1660
|
-
const
|
|
1661
|
-
const samePoint = (p, q) => Math.abs(p.x - q.x) <
|
|
1789
|
+
const EPS19 = 1e-9;
|
|
1790
|
+
const samePoint = (p, q) => Math.abs(p.x - q.x) < EPS19 && Math.abs(p.y - q.y) < EPS19;
|
|
1662
1791
|
if (samePoint(first, { x: PA.x, y: PA.y }) && samePoint(last, { x: PB.x, y: PB.y }) && (!this.hasAmbiguousPinDirections || pathMatchesPinDirections({
|
|
1663
1792
|
path,
|
|
1664
1793
|
pin1: { ...PA, _facingDirection: directions[0] },
|
|
@@ -2013,13 +2142,13 @@ var applyJogToTerminalSegment = ({
|
|
|
2013
2142
|
segmentIndex: si,
|
|
2014
2143
|
offset,
|
|
2015
2144
|
JOG_SIZE,
|
|
2016
|
-
EPS:
|
|
2145
|
+
EPS: EPS19 = 1e-6
|
|
2017
2146
|
}) => {
|
|
2018
2147
|
if (si !== 0 && si !== pts.length - 2) return;
|
|
2019
2148
|
const start = pts[si];
|
|
2020
2149
|
const end = pts[si + 1];
|
|
2021
|
-
const isVertical6 = Math.abs(start.x - end.x) <
|
|
2022
|
-
const isHorizontal5 = Math.abs(start.y - end.y) <
|
|
2150
|
+
const isVertical6 = Math.abs(start.x - end.x) < EPS19;
|
|
2151
|
+
const isHorizontal5 = Math.abs(start.y - end.y) < EPS19;
|
|
2023
2152
|
if (!isVertical6 && !isHorizontal5) return;
|
|
2024
2153
|
const segDir = isVertical6 ? end.y > start.y ? 1 : -1 : end.x > start.x ? 1 : -1;
|
|
2025
2154
|
if (pts.length === 2) {
|
|
@@ -2092,7 +2221,7 @@ var applyJogToTerminalSegment = ({
|
|
|
2092
2221
|
};
|
|
2093
2222
|
|
|
2094
2223
|
// lib/solvers/TraceOverlapShiftSolver/TraceOverlapIssueSolver/TraceOverlapIssueSolver.ts
|
|
2095
|
-
var
|
|
2224
|
+
var EPS6 = 1e-6;
|
|
2096
2225
|
var TraceOverlapIssueSolver = class extends BaseSolver {
|
|
2097
2226
|
overlappingTraceSegments;
|
|
2098
2227
|
interactionKind;
|
|
@@ -2189,7 +2318,7 @@ var TraceOverlapIssueSolver = class extends BaseSolver {
|
|
|
2189
2318
|
}
|
|
2190
2319
|
applyOffsets(offsets) {
|
|
2191
2320
|
const correctedTraceMap = { ...this.correctedTraceMap };
|
|
2192
|
-
const eq = (a, b) => Math.abs(a - b) <
|
|
2321
|
+
const eq = (a, b) => Math.abs(a - b) < EPS6;
|
|
2193
2322
|
const samePoint = (p, q) => !!p && !!q && eq(p.x, q.x) && eq(p.y, q.y);
|
|
2194
2323
|
this.overlappingTraceSegments.forEach((group, groupIndex) => {
|
|
2195
2324
|
const offset = offsets[groupIndex];
|
|
@@ -2211,9 +2340,9 @@ var TraceOverlapIssueSolver = class extends BaseSolver {
|
|
|
2211
2340
|
const start = pts[si];
|
|
2212
2341
|
const end = pts[si + 1];
|
|
2213
2342
|
if (!start || !end) continue;
|
|
2214
|
-
if (Math.abs(start.x - end.x) <
|
|
2343
|
+
if (Math.abs(start.x - end.x) < EPS6) {
|
|
2215
2344
|
segmentAxes.set(si, "vertical");
|
|
2216
|
-
} else if (Math.abs(start.y - end.y) <
|
|
2345
|
+
} else if (Math.abs(start.y - end.y) < EPS6) {
|
|
2217
2346
|
segmentAxes.set(si, "horizontal");
|
|
2218
2347
|
}
|
|
2219
2348
|
}
|
|
@@ -2228,7 +2357,7 @@ var TraceOverlapIssueSolver = class extends BaseSolver {
|
|
|
2228
2357
|
segmentIndex: si,
|
|
2229
2358
|
offset,
|
|
2230
2359
|
JOG_SIZE,
|
|
2231
|
-
EPS:
|
|
2360
|
+
EPS: EPS6
|
|
2232
2361
|
});
|
|
2233
2362
|
} else {
|
|
2234
2363
|
const start = pts[si];
|
|
@@ -2315,7 +2444,7 @@ var TraceOverlapIssueSolver = class extends BaseSolver {
|
|
|
2315
2444
|
max = obstacle.maxY;
|
|
2316
2445
|
}
|
|
2317
2446
|
const next = orig + candidateOffset;
|
|
2318
|
-
return orig <= min +
|
|
2447
|
+
return orig <= min + EPS6 && next >= max - EPS6 || orig >= max - EPS6 && next <= min + EPS6;
|
|
2319
2448
|
});
|
|
2320
2449
|
const edges = blockingCollisions.map(({ start, isVertical: isVertical6, obstacle }) => {
|
|
2321
2450
|
if (isVertical6) {
|
|
@@ -2352,8 +2481,8 @@ var TraceOverlapIssueSolver = class extends BaseSolver {
|
|
|
2352
2481
|
const start = trace.tracePath[traceSegmentIndex];
|
|
2353
2482
|
const end = trace.tracePath[traceSegmentIndex + 1];
|
|
2354
2483
|
if (!start || !end) continue;
|
|
2355
|
-
const isVertical6 = Math.abs(start.x - end.x) <
|
|
2356
|
-
const isHorizontal5 = Math.abs(start.y - end.y) <
|
|
2484
|
+
const isVertical6 = Math.abs(start.x - end.x) < EPS6;
|
|
2485
|
+
const isHorizontal5 = Math.abs(start.y - end.y) < EPS6;
|
|
2357
2486
|
if (!isVertical6 && !isHorizontal5) continue;
|
|
2358
2487
|
const shiftedSegment = isVertical6 ? [
|
|
2359
2488
|
{ ...start, x: start.x + offset },
|
|
@@ -2453,7 +2582,7 @@ var TraceOverlapShiftSolver = class extends BaseSolver {
|
|
|
2453
2582
|
return islands;
|
|
2454
2583
|
}
|
|
2455
2584
|
findNextOverlapIssue() {
|
|
2456
|
-
const
|
|
2585
|
+
const EPS19 = 2e-3;
|
|
2457
2586
|
const netIds = Object.keys(this.traceNetIslands);
|
|
2458
2587
|
for (let i = 0; i < netIds.length; i++) {
|
|
2459
2588
|
for (let j = i + 1; j < netIds.length; j++) {
|
|
@@ -2480,7 +2609,7 @@ var TraceOverlapShiftSolver = class extends BaseSolver {
|
|
|
2480
2609
|
segmentBIndex,
|
|
2481
2610
|
rangeOverlap
|
|
2482
2611
|
}) => {
|
|
2483
|
-
if (rangeOverlap >
|
|
2612
|
+
if (rangeOverlap > EPS19) {
|
|
2484
2613
|
const keyA = `${pathAIndex}:${segmentAIndex}`;
|
|
2485
2614
|
const keyB = `${pathBIndex}:${segmentBIndex}`;
|
|
2486
2615
|
if (!seenA.has(keyA)) {
|
|
@@ -2499,7 +2628,7 @@ var TraceOverlapShiftSolver = class extends BaseSolver {
|
|
|
2499
2628
|
}
|
|
2500
2629
|
return;
|
|
2501
2630
|
}
|
|
2502
|
-
if (rangeOverlap < -
|
|
2631
|
+
if (rangeOverlap < -EPS19) return;
|
|
2503
2632
|
const pathA = pathsA[pathAIndex].tracePath;
|
|
2504
2633
|
const pathB = pathsB[pathBIndex].tracePath;
|
|
2505
2634
|
const segmentAStart = pathA[segmentAIndex];
|
|
@@ -2522,8 +2651,8 @@ var TraceOverlapShiftSolver = class extends BaseSolver {
|
|
|
2522
2651
|
for (let sa = 0; sa < ptsA.length - 1; sa++) {
|
|
2523
2652
|
const a1 = ptsA[sa];
|
|
2524
2653
|
const a2 = ptsA[sa + 1];
|
|
2525
|
-
const aVert = Math.abs(a1.x - a2.x) <
|
|
2526
|
-
const aHorz = Math.abs(a1.y - a2.y) <
|
|
2654
|
+
const aVert = Math.abs(a1.x - a2.x) < EPS19;
|
|
2655
|
+
const aHorz = Math.abs(a1.y - a2.y) < EPS19;
|
|
2527
2656
|
if (!aVert && !aHorz) continue;
|
|
2528
2657
|
for (let pb = 0; pb < pathsB.length; pb++) {
|
|
2529
2658
|
const pathB = pathsB[pb];
|
|
@@ -2534,11 +2663,11 @@ var TraceOverlapShiftSolver = class extends BaseSolver {
|
|
|
2534
2663
|
for (let sb = 0; sb < ptsB.length - 1; sb++) {
|
|
2535
2664
|
const b1 = ptsB[sb];
|
|
2536
2665
|
const b2 = ptsB[sb + 1];
|
|
2537
|
-
const bVert = Math.abs(b1.x - b2.x) <
|
|
2538
|
-
const bHorz = Math.abs(b1.y - b2.y) <
|
|
2666
|
+
const bVert = Math.abs(b1.x - b2.x) < EPS19;
|
|
2667
|
+
const bHorz = Math.abs(b1.y - b2.y) < EPS19;
|
|
2539
2668
|
if (!bVert && !bHorz) continue;
|
|
2540
2669
|
if (aVert && bVert) {
|
|
2541
|
-
if (Math.abs(a1.x - b1.x) <
|
|
2670
|
+
if (Math.abs(a1.x - b1.x) < EPS19) {
|
|
2542
2671
|
recordCollinearInteraction({
|
|
2543
2672
|
pathAIndex: pa,
|
|
2544
2673
|
segmentAIndex: sa,
|
|
@@ -2548,7 +2677,7 @@ var TraceOverlapShiftSolver = class extends BaseSolver {
|
|
|
2548
2677
|
});
|
|
2549
2678
|
}
|
|
2550
2679
|
} else if (aHorz && bHorz) {
|
|
2551
|
-
if (Math.abs(a1.y - b1.y) <
|
|
2680
|
+
if (Math.abs(a1.y - b1.y) < EPS19) {
|
|
2552
2681
|
recordCollinearInteraction({
|
|
2553
2682
|
pathAIndex: pa,
|
|
2554
2683
|
segmentAIndex: sa,
|
|
@@ -2604,14 +2733,14 @@ var TraceOverlapShiftSolver = class extends BaseSolver {
|
|
|
2604
2733
|
return null;
|
|
2605
2734
|
}
|
|
2606
2735
|
findNextDiagonalSegment() {
|
|
2607
|
-
const
|
|
2736
|
+
const EPS19 = 2e-3;
|
|
2608
2737
|
for (const mspPairId in this.correctedTraceMap) {
|
|
2609
2738
|
const tracePath = this.correctedTraceMap[mspPairId].tracePath;
|
|
2610
2739
|
for (let i = 0; i < tracePath.length - 1; i++) {
|
|
2611
2740
|
const p1 = tracePath[i];
|
|
2612
2741
|
const p2 = tracePath[i + 1];
|
|
2613
|
-
const isHorizontal5 = Math.abs(p1.y - p2.y) <
|
|
2614
|
-
const isVertical6 = Math.abs(p1.x - p2.x) <
|
|
2742
|
+
const isHorizontal5 = Math.abs(p1.y - p2.y) < EPS19;
|
|
2743
|
+
const isVertical6 = Math.abs(p1.x - p2.x) < EPS19;
|
|
2615
2744
|
if (!isHorizontal5 && !isVertical6) {
|
|
2616
2745
|
return { mspPairId, tracePath, i, p1, p2 };
|
|
2617
2746
|
}
|
|
@@ -2625,13 +2754,13 @@ var TraceOverlapShiftSolver = class extends BaseSolver {
|
|
|
2625
2754
|
return false;
|
|
2626
2755
|
}
|
|
2627
2756
|
const { mspPairId, tracePath, i, p1, p2 } = diagonalInfo;
|
|
2628
|
-
const
|
|
2757
|
+
const EPS19 = 2e-3;
|
|
2629
2758
|
const p0 = i > 0 ? tracePath[i - 1] : null;
|
|
2630
2759
|
const p3 = i + 2 < tracePath.length ? tracePath[i + 2] : null;
|
|
2631
|
-
const prevIsVertical = p0 ? Math.abs(p0.x - p1.x) <
|
|
2632
|
-
const prevIsHorizontal = p0 ? Math.abs(p0.y - p1.y) <
|
|
2633
|
-
const nextIsVertical = p3 ? Math.abs(p2.x - p3.x) <
|
|
2634
|
-
const nextIsHorizontal = p3 ? Math.abs(p2.y - p3.y) <
|
|
2760
|
+
const prevIsVertical = p0 ? Math.abs(p0.x - p1.x) < EPS19 : false;
|
|
2761
|
+
const prevIsHorizontal = p0 ? Math.abs(p0.y - p1.y) < EPS19 : false;
|
|
2762
|
+
const nextIsVertical = p3 ? Math.abs(p2.x - p3.x) < EPS19 : false;
|
|
2763
|
+
const nextIsHorizontal = p3 ? Math.abs(p2.y - p3.y) < EPS19 : false;
|
|
2635
2764
|
const elbow1 = { x: p1.x, y: p2.y };
|
|
2636
2765
|
const elbow2 = { x: p2.x, y: p1.y };
|
|
2637
2766
|
let score1 = 0;
|
|
@@ -2793,24 +2922,24 @@ var ChipObstacleSpatialIndex = class {
|
|
|
2793
2922
|
};
|
|
2794
2923
|
|
|
2795
2924
|
// lib/solvers/NetLabelPlacementSolver/SingleNetLabelPlacementSolver/collisions.ts
|
|
2796
|
-
function segmentIntersectsRect2(p1, p2, rect,
|
|
2797
|
-
const isVert = Math.abs(p1.x - p2.x) <
|
|
2798
|
-
const isHorz = Math.abs(p1.y - p2.y) <
|
|
2925
|
+
function segmentIntersectsRect2(p1, p2, rect, EPS19 = 1e-9) {
|
|
2926
|
+
const isVert = Math.abs(p1.x - p2.x) < EPS19;
|
|
2927
|
+
const isHorz = Math.abs(p1.y - p2.y) < EPS19;
|
|
2799
2928
|
if (!isVert && !isHorz) return false;
|
|
2800
2929
|
if (isVert) {
|
|
2801
2930
|
const x = p1.x;
|
|
2802
|
-
if (x < rect.minX -
|
|
2931
|
+
if (x < rect.minX - EPS19 || x > rect.maxX + EPS19) return false;
|
|
2803
2932
|
const segMinY = Math.min(p1.y, p2.y);
|
|
2804
2933
|
const segMaxY = Math.max(p1.y, p2.y);
|
|
2805
2934
|
const overlap = Math.min(segMaxY, rect.maxY) - Math.max(segMinY, rect.minY);
|
|
2806
|
-
return overlap >
|
|
2935
|
+
return overlap > EPS19;
|
|
2807
2936
|
} else {
|
|
2808
2937
|
const y = p1.y;
|
|
2809
|
-
if (y < rect.minY -
|
|
2938
|
+
if (y < rect.minY - EPS19 || y > rect.maxY + EPS19) return false;
|
|
2810
2939
|
const segMinX = Math.min(p1.x, p2.x);
|
|
2811
2940
|
const segMaxX = Math.max(p1.x, p2.x);
|
|
2812
2941
|
const overlap = Math.min(segMaxX, rect.maxX) - Math.max(segMinX, rect.minX);
|
|
2813
|
-
return overlap >
|
|
2942
|
+
return overlap > EPS19;
|
|
2814
2943
|
}
|
|
2815
2944
|
}
|
|
2816
2945
|
function rectIntersectsAnyTrace(bounds, inputTraceMap, hostPathId, hostSegIndex) {
|
|
@@ -3209,14 +3338,14 @@ var SingleNetLabelPlacementSolver = class extends BaseSolver {
|
|
|
3209
3338
|
};
|
|
3210
3339
|
let bestCandidate = null;
|
|
3211
3340
|
let bestScore = -Infinity;
|
|
3212
|
-
const
|
|
3341
|
+
const EPS19 = 1e-6;
|
|
3213
3342
|
for (const curr of tracesToScan) {
|
|
3214
3343
|
const pts = curr.tracePath.slice();
|
|
3215
3344
|
for (let si = 0; si < pts.length - 1; si++) {
|
|
3216
3345
|
const a = pts[si];
|
|
3217
3346
|
const b = pts[si + 1];
|
|
3218
|
-
const isH = Math.abs(a.y - b.y) <
|
|
3219
|
-
const isV = Math.abs(a.x - b.x) <
|
|
3347
|
+
const isH = Math.abs(a.y - b.y) < EPS19;
|
|
3348
|
+
const isV = Math.abs(a.x - b.x) < EPS19;
|
|
3220
3349
|
if (!isH && !isV) continue;
|
|
3221
3350
|
const segmentAllowed = isH ? ["y+", "y-"] : ["x+", "x-"];
|
|
3222
3351
|
const candidateOrients = orientations.filter(
|
|
@@ -4992,19 +5121,81 @@ function doesTraceOverlapWithExistingTraces(newTracePath, existingTraces) {
|
|
|
4992
5121
|
return false;
|
|
4993
5122
|
}
|
|
4994
5123
|
|
|
5124
|
+
// lib/solvers/LongDistancePairSolver/getParallelNetLabelPolicy.ts
|
|
5125
|
+
import { ConnectivityMap as ConnectivityMap3 } from "connectivity-map";
|
|
5126
|
+
var getParallelNetLabelPolicy = (inputProblem, netConnMap, connectedPinIds) => {
|
|
5127
|
+
const maxDistance = inputProblem.maxMspPairDistance ?? DEFAULT_MAX_MSP_PAIR_DISTANCE;
|
|
5128
|
+
const { extendedRailPinIds, separatedRailPinIds } = getParallelRailPairs(
|
|
5129
|
+
inputProblem,
|
|
5130
|
+
netConnMap,
|
|
5131
|
+
maxDistance
|
|
5132
|
+
);
|
|
5133
|
+
const groundNetIds = /* @__PURE__ */ new Set();
|
|
5134
|
+
const namedPinIds = /* @__PURE__ */ new Set();
|
|
5135
|
+
for (const connection of inputProblem.netConnections) {
|
|
5136
|
+
const netId = netConnMap.getNetConnectedToId(connection.netId);
|
|
5137
|
+
if (!netId) continue;
|
|
5138
|
+
for (const pinId of connection.pinIds) namedPinIds.add(pinId);
|
|
5139
|
+
if (connection.isGround) {
|
|
5140
|
+
groundNetIds.add(netId);
|
|
5141
|
+
}
|
|
5142
|
+
}
|
|
5143
|
+
const banks = /* @__PURE__ */ new Map();
|
|
5144
|
+
for (const chip of inputProblem.chips) {
|
|
5145
|
+
if (chip.pins.length !== 2 || !chip.pins.every((pin) => namedPinIds.has(pin.pinId)) || chip.pins.some(
|
|
5146
|
+
(pin) => connectedPinIds.has(pin.pinId) && !extendedRailPinIds.has(pin.pinId)
|
|
5147
|
+
))
|
|
5148
|
+
continue;
|
|
5149
|
+
const [first, second] = chip.pins.map(
|
|
5150
|
+
(pin) => netConnMap.getNetConnectedToId(pin.pinId)
|
|
5151
|
+
);
|
|
5152
|
+
if (!first || !second || first === second || groundNetIds.has(first) === groundNetIds.has(second)) {
|
|
5153
|
+
continue;
|
|
5154
|
+
}
|
|
5155
|
+
const key = JSON.stringify([
|
|
5156
|
+
chip.sectionId ?? null,
|
|
5157
|
+
...[first, second].sort()
|
|
5158
|
+
]);
|
|
5159
|
+
const bank = banks.get(key) ?? [];
|
|
5160
|
+
bank.push(chip.pins.map((pin) => pin.pinId));
|
|
5161
|
+
banks.set(key, bank);
|
|
5162
|
+
}
|
|
5163
|
+
const bankPinIds = new Set(
|
|
5164
|
+
[...banks.values()].filter((bank) => bank.length > 1).flat(2)
|
|
5165
|
+
);
|
|
5166
|
+
for (const pinId of [...extendedRailPinIds, ...separatedRailPinIds]) {
|
|
5167
|
+
bankPinIds.add(pinId);
|
|
5168
|
+
}
|
|
5169
|
+
const physicalConnMap = new ConnectivityMap3({});
|
|
5170
|
+
for (const connection of inputProblem.directConnections) {
|
|
5171
|
+
if (connection.netLabelWidth === void 0) {
|
|
5172
|
+
physicalConnMap.addConnections([connection.pinIds]);
|
|
5173
|
+
}
|
|
5174
|
+
}
|
|
5175
|
+
return (first, second) => {
|
|
5176
|
+
if (!bankPinIds.has(first.pinId) && !bankPinIds.has(second.pinId))
|
|
5177
|
+
return true;
|
|
5178
|
+
if (Math.abs(first.x - second.x) + Math.abs(first.y - second.y) <= maxDistance) {
|
|
5179
|
+
return true;
|
|
5180
|
+
}
|
|
5181
|
+
const physicalNetId = physicalConnMap.getNetConnectedToId(first.pinId);
|
|
5182
|
+
return physicalNetId !== void 0 && physicalNetId === physicalConnMap.getNetConnectedToId(second.pinId);
|
|
5183
|
+
};
|
|
5184
|
+
};
|
|
5185
|
+
|
|
4995
5186
|
// lib/solvers/LongDistancePairSolver/LongDistancePairSolver.ts
|
|
4996
5187
|
var NEAREST_NEIGHBOR_COUNT = 3;
|
|
4997
5188
|
var distance3 = (p1, p2) => {
|
|
4998
5189
|
return Math.sqrt(Math.pow(p1.x - p2.x, 2) + Math.pow(p1.y - p2.y, 2));
|
|
4999
5190
|
};
|
|
5000
5191
|
var manhattanDistance = (p1, p2) => Math.abs(p1.x - p2.x) + Math.abs(p1.y - p2.y);
|
|
5001
|
-
var
|
|
5002
|
-
var between = (value, first, second) => value >= Math.min(first, second) -
|
|
5192
|
+
var EPS7 = 1e-9;
|
|
5193
|
+
var between = (value, first, second) => value >= Math.min(first, second) - EPS7 && value <= Math.max(first, second) + EPS7;
|
|
5003
5194
|
var getAxisAlignedIntersection = (firstStart, firstEnd, secondStart, secondEnd) => {
|
|
5004
|
-
const firstIsHorizontal = Math.abs(firstStart.y - firstEnd.y) <=
|
|
5005
|
-
const firstIsVertical = Math.abs(firstStart.x - firstEnd.x) <=
|
|
5006
|
-
const secondIsHorizontal = Math.abs(secondStart.y - secondEnd.y) <=
|
|
5007
|
-
const secondIsVertical = Math.abs(secondStart.x - secondEnd.x) <=
|
|
5195
|
+
const firstIsHorizontal = Math.abs(firstStart.y - firstEnd.y) <= EPS7;
|
|
5196
|
+
const firstIsVertical = Math.abs(firstStart.x - firstEnd.x) <= EPS7;
|
|
5197
|
+
const secondIsHorizontal = Math.abs(secondStart.y - secondEnd.y) <= EPS7;
|
|
5198
|
+
const secondIsVertical = Math.abs(secondStart.x - secondEnd.x) <= EPS7;
|
|
5008
5199
|
if (firstIsHorizontal && secondIsVertical) {
|
|
5009
5200
|
const point = { x: secondStart.x, y: firstStart.y };
|
|
5010
5201
|
return between(point.x, firstStart.x, firstEnd.x) && between(point.y, secondStart.y, secondEnd.y) ? point : null;
|
|
@@ -5013,7 +5204,7 @@ var getAxisAlignedIntersection = (firstStart, firstEnd, secondStart, secondEnd)
|
|
|
5013
5204
|
const point = { x: firstStart.x, y: secondStart.y };
|
|
5014
5205
|
return between(point.y, firstStart.y, firstEnd.y) && between(point.x, secondStart.x, secondEnd.x) ? point : null;
|
|
5015
5206
|
}
|
|
5016
|
-
if (firstIsHorizontal && secondIsHorizontal && Math.abs(firstStart.y - secondStart.y) <=
|
|
5207
|
+
if (firstIsHorizontal && secondIsHorizontal && Math.abs(firstStart.y - secondStart.y) <= EPS7) {
|
|
5017
5208
|
const overlapMin = Math.max(
|
|
5018
5209
|
Math.min(firstStart.x, firstEnd.x),
|
|
5019
5210
|
Math.min(secondStart.x, secondEnd.x)
|
|
@@ -5022,13 +5213,13 @@ var getAxisAlignedIntersection = (firstStart, firstEnd, secondStart, secondEnd)
|
|
|
5022
5213
|
Math.max(firstStart.x, firstEnd.x),
|
|
5023
5214
|
Math.max(secondStart.x, secondEnd.x)
|
|
5024
5215
|
);
|
|
5025
|
-
if (overlapMin > overlapMax +
|
|
5216
|
+
if (overlapMin > overlapMax + EPS7) return null;
|
|
5026
5217
|
return {
|
|
5027
5218
|
x: Math.max(overlapMin, Math.min(firstStart.x, overlapMax)),
|
|
5028
5219
|
y: firstStart.y
|
|
5029
5220
|
};
|
|
5030
5221
|
}
|
|
5031
|
-
if (firstIsVertical && secondIsVertical && Math.abs(firstStart.x - secondStart.x) <=
|
|
5222
|
+
if (firstIsVertical && secondIsVertical && Math.abs(firstStart.x - secondStart.x) <= EPS7) {
|
|
5032
5223
|
const overlapMin = Math.max(
|
|
5033
5224
|
Math.min(firstStart.y, firstEnd.y),
|
|
5034
5225
|
Math.min(secondStart.y, secondEnd.y)
|
|
@@ -5037,7 +5228,7 @@ var getAxisAlignedIntersection = (firstStart, firstEnd, secondStart, secondEnd)
|
|
|
5037
5228
|
Math.max(firstStart.y, firstEnd.y),
|
|
5038
5229
|
Math.max(secondStart.y, secondEnd.y)
|
|
5039
5230
|
);
|
|
5040
|
-
if (overlapMin > overlapMax +
|
|
5231
|
+
if (overlapMin > overlapMax + EPS7) return null;
|
|
5041
5232
|
return {
|
|
5042
5233
|
x: firstStart.x,
|
|
5043
5234
|
y: Math.max(overlapMin, Math.min(firstStart.y, overlapMax))
|
|
@@ -5066,7 +5257,7 @@ var clipPathAtFirstIntersection = (tracePath, existingTraces) => {
|
|
|
5066
5257
|
const intersection = intersections2[0];
|
|
5067
5258
|
if (!intersection) continue;
|
|
5068
5259
|
const clippedPath = tracePath.slice(0, pathIndex + 1);
|
|
5069
|
-
if (distance3(clippedPath.at(-1), intersection) >
|
|
5260
|
+
if (distance3(clippedPath.at(-1), intersection) > EPS7) {
|
|
5070
5261
|
clippedPath.push(intersection);
|
|
5071
5262
|
}
|
|
5072
5263
|
return clippedPath;
|
|
@@ -5089,6 +5280,11 @@ var LongDistancePairSolver = class extends BaseSolver {
|
|
|
5089
5280
|
}
|
|
5090
5281
|
const { netConnMap } = getConnectivityMapsFromInputProblem(inputProblem);
|
|
5091
5282
|
this.netConnMap = netConnMap;
|
|
5283
|
+
const canRecoverParallelPair = getParallelNetLabelPolicy(
|
|
5284
|
+
inputProblem,
|
|
5285
|
+
netConnMap,
|
|
5286
|
+
primaryConnectedPinIds
|
|
5287
|
+
);
|
|
5092
5288
|
const pinMap = /* @__PURE__ */ new Map();
|
|
5093
5289
|
for (const chip of inputProblem.chips) {
|
|
5094
5290
|
this.chipMap[chip.chipId] = chip;
|
|
@@ -5121,6 +5317,7 @@ var LongDistancePairSolver = class extends BaseSolver {
|
|
|
5121
5317
|
const targetPin = pinMap.get(otherPinId);
|
|
5122
5318
|
if (!targetPin) return [];
|
|
5123
5319
|
if (!canRouteGroundPair(sourcePin.pinId, targetPin.pinId)) return [];
|
|
5320
|
+
if (!canRecoverParallelPair(sourcePin, targetPin)) return [];
|
|
5124
5321
|
const isNamedTwoPinConnection = inputProblem.netConnections.some(
|
|
5125
5322
|
(connection) => connection.pinIds.length === 2 && connection.pinIds.includes(sourcePin.pinId) && connection.pinIds.includes(targetPin.pinId)
|
|
5126
5323
|
);
|
|
@@ -6065,9 +6262,9 @@ var getRailAlignmentFallbackCoordinates = ({
|
|
|
6065
6262
|
import { distance as distance4 } from "@tscircuit/math-utils";
|
|
6066
6263
|
|
|
6067
6264
|
// lib/solvers/RailNetLabelCornerPlacementSolver/geometry.ts
|
|
6068
|
-
var
|
|
6265
|
+
var EPS8 = 1e-6;
|
|
6069
6266
|
var isTraceLine = (trace) => getUniquePinCount(trace.pinIds) >= 2;
|
|
6070
|
-
var rectsOverlap = (a, b) => Math.min(a.maxX, b.maxX) - Math.max(a.minX, b.minX) >
|
|
6267
|
+
var rectsOverlap = (a, b) => Math.min(a.maxX, b.maxX) - Math.max(a.minX, b.minX) > EPS8 && Math.min(a.maxY, b.maxY) - Math.max(a.minY, b.minY) > EPS8;
|
|
6071
6268
|
var getTraceCorners = (path) => {
|
|
6072
6269
|
const corners = [];
|
|
6073
6270
|
for (let i = 1; i < path.length - 1; i++) {
|
|
@@ -6091,11 +6288,11 @@ var getUniquePinCount = (pinIds) => new Set(pinIds).size;
|
|
|
6091
6288
|
var isTraceCorner = (a, b, c) => getSegmentOrientation(a, b) !== getSegmentOrientation(b, c);
|
|
6092
6289
|
var isPointOnSegment = (point, start, end) => {
|
|
6093
6290
|
if (getSegmentOrientation(start, end) === "horizontal") {
|
|
6094
|
-
return Math.abs(point.y - start.y) <=
|
|
6291
|
+
return Math.abs(point.y - start.y) <= EPS8 && point.x >= Math.min(start.x, end.x) - EPS8 && point.x <= Math.max(start.x, end.x) + EPS8;
|
|
6095
6292
|
}
|
|
6096
|
-
return Math.abs(point.x - start.x) <=
|
|
6293
|
+
return Math.abs(point.x - start.x) <= EPS8 && point.y >= Math.min(start.y, end.y) - EPS8 && point.y <= Math.max(start.y, end.y) + EPS8;
|
|
6097
6294
|
};
|
|
6098
|
-
var getSegmentOrientation = (a, b) => Math.abs(a.y - b.y) <=
|
|
6295
|
+
var getSegmentOrientation = (a, b) => Math.abs(a.y - b.y) <= EPS8 ? "horizontal" : "vertical";
|
|
6099
6296
|
|
|
6100
6297
|
// lib/solvers/TraceCleanupSolver/sameNetRailAlignment/getFixedLabelCoordinate.ts
|
|
6101
6298
|
var getTransitivelyConnectedTraceIds = (group, traces) => {
|
|
@@ -6220,17 +6417,17 @@ var preservesLabelAnchors = (labels, before, after) => labels.every((label) => {
|
|
|
6220
6417
|
});
|
|
6221
6418
|
|
|
6222
6419
|
// lib/solvers/Example28Solver/types.ts
|
|
6223
|
-
var
|
|
6420
|
+
var EPS9 = 1e-9;
|
|
6224
6421
|
|
|
6225
6422
|
// lib/solvers/Example28Solver/segmentRunsAlongRectBoundary.ts
|
|
6226
6423
|
var segmentRunsAlongRectBoundary = (start, end, rect) => {
|
|
6227
|
-
const isVertical6 = Math.abs(start.x - end.x) <
|
|
6228
|
-
const isHorizontal5 = Math.abs(start.y - end.y) <
|
|
6424
|
+
const isVertical6 = Math.abs(start.x - end.x) < EPS9;
|
|
6425
|
+
const isHorizontal5 = Math.abs(start.y - end.y) < EPS9;
|
|
6229
6426
|
if (isVertical6) {
|
|
6230
|
-
return Math.abs(start.x - rect.minX) <
|
|
6427
|
+
return Math.abs(start.x - rect.minX) < EPS9 || Math.abs(start.x - rect.maxX) < EPS9;
|
|
6231
6428
|
}
|
|
6232
6429
|
if (isHorizontal5) {
|
|
6233
|
-
return Math.abs(start.y - rect.minY) <
|
|
6430
|
+
return Math.abs(start.y - rect.minY) < EPS9 || Math.abs(start.y - rect.maxY) < EPS9;
|
|
6234
6431
|
}
|
|
6235
6432
|
return false;
|
|
6236
6433
|
};
|
|
@@ -6245,10 +6442,10 @@ var getPathLength4 = (path) => {
|
|
|
6245
6442
|
return length;
|
|
6246
6443
|
};
|
|
6247
6444
|
var getDistance2 = (a, b) => Math.abs(a.x - b.x) + Math.abs(a.y - b.y);
|
|
6248
|
-
var isAxisAlignedSegment = (start, end) => Math.abs(start.x - end.x) <
|
|
6249
|
-
var getSegmentOrientation2 = (start, end) => Math.abs(start.y - end.y) <
|
|
6445
|
+
var isAxisAlignedSegment = (start, end) => Math.abs(start.x - end.x) < EPS9 || Math.abs(start.y - end.y) < EPS9;
|
|
6446
|
+
var getSegmentOrientation2 = (start, end) => Math.abs(start.y - end.y) < EPS9 ? "horizontal" : "vertical";
|
|
6250
6447
|
var projectPointToSegment = (point, start, end) => {
|
|
6251
|
-
if (Math.abs(start.x - end.x) <
|
|
6448
|
+
if (Math.abs(start.x - end.x) < EPS9) {
|
|
6252
6449
|
return {
|
|
6253
6450
|
x: start.x,
|
|
6254
6451
|
y: Math.min(
|
|
@@ -6257,7 +6454,7 @@ var projectPointToSegment = (point, start, end) => {
|
|
|
6257
6454
|
)
|
|
6258
6455
|
};
|
|
6259
6456
|
}
|
|
6260
|
-
if (Math.abs(start.y - end.y) <
|
|
6457
|
+
if (Math.abs(start.y - end.y) < EPS9) {
|
|
6261
6458
|
return {
|
|
6262
6459
|
x: Math.min(
|
|
6263
6460
|
Math.max(point.x, Math.min(start.x, end.x)),
|
|
@@ -6300,9 +6497,9 @@ var findSegmentContainingPoint = (path, point) => {
|
|
|
6300
6497
|
};
|
|
6301
6498
|
var isPointWithinSegmentPrimaryRange = (point, segment) => {
|
|
6302
6499
|
if (segment.orientation === "horizontal") {
|
|
6303
|
-
return point.x >= Math.min(segment.start.x, segment.end.x) -
|
|
6500
|
+
return point.x >= Math.min(segment.start.x, segment.end.x) - EPS9 && point.x <= Math.max(segment.start.x, segment.end.x) + EPS9;
|
|
6304
6501
|
}
|
|
6305
|
-
return point.y >= Math.min(segment.start.y, segment.end.y) -
|
|
6502
|
+
return point.y >= Math.min(segment.start.y, segment.end.y) - EPS9 && point.y <= Math.max(segment.start.y, segment.end.y) + EPS9;
|
|
6306
6503
|
};
|
|
6307
6504
|
var findPreferredReroutedSegment = (path, originalSegmentIndex, originalSegmentCount, orientation, anchorPoint) => {
|
|
6308
6505
|
const matchingSegments = getSegments(path).filter(
|
|
@@ -6330,18 +6527,18 @@ var projectPointToPath = (point, path) => {
|
|
|
6330
6527
|
return bestPoint;
|
|
6331
6528
|
};
|
|
6332
6529
|
var segmentsIntersect = (a1, a2, b1, b2) => {
|
|
6333
|
-
const aVertical = Math.abs(a1.x - a2.x) <
|
|
6334
|
-
const bVertical = Math.abs(b1.x - b2.x) <
|
|
6335
|
-
const between2 = (value, p1, p2) => value >= Math.min(p1, p2) -
|
|
6530
|
+
const aVertical = Math.abs(a1.x - a2.x) < EPS9;
|
|
6531
|
+
const bVertical = Math.abs(b1.x - b2.x) < EPS9;
|
|
6532
|
+
const between2 = (value, p1, p2) => value >= Math.min(p1, p2) - EPS9 && value <= Math.max(p1, p2) + EPS9;
|
|
6336
6533
|
if (aVertical && bVertical) {
|
|
6337
|
-
if (Math.abs(a1.x - b1.x) >
|
|
6534
|
+
if (Math.abs(a1.x - b1.x) > EPS9) return false;
|
|
6338
6535
|
const overlap = Math.min(Math.max(a1.y, a2.y), Math.max(b1.y, b2.y)) - Math.max(Math.min(a1.y, a2.y), Math.min(b1.y, b2.y));
|
|
6339
|
-
return overlap >
|
|
6536
|
+
return overlap > EPS9;
|
|
6340
6537
|
}
|
|
6341
6538
|
if (!aVertical && !bVertical) {
|
|
6342
|
-
if (Math.abs(a1.y - b1.y) >
|
|
6539
|
+
if (Math.abs(a1.y - b1.y) > EPS9) return false;
|
|
6343
6540
|
const overlap = Math.min(Math.max(a1.x, a2.x), Math.max(b1.x, b2.x)) - Math.max(Math.min(a1.x, a2.x), Math.min(b1.x, b2.x));
|
|
6344
|
-
return overlap >
|
|
6541
|
+
return overlap > EPS9;
|
|
6345
6542
|
}
|
|
6346
6543
|
const verticalA = aVertical ? a1 : b1;
|
|
6347
6544
|
const verticalB = aVertical ? a2 : b2;
|
|
@@ -6798,7 +6995,7 @@ var getTraceObstacles = (allTraces, excludeTraceId) => {
|
|
|
6798
6995
|
|
|
6799
6996
|
// lib/solvers/TraceCleanupSolver/sub-solver/findIntersectionsWithObstacles.ts
|
|
6800
6997
|
import { getSegmentIntersection } from "@tscircuit/math-utils/line-intersections";
|
|
6801
|
-
var
|
|
6998
|
+
var EPS10 = 1e-6;
|
|
6802
6999
|
var findIntersectionsWithObstacles = (p1, p2, obstacles) => {
|
|
6803
7000
|
const intersections2 = [];
|
|
6804
7001
|
for (const obstacle of obstacles) {
|
|
@@ -6817,7 +7014,7 @@ var findIntersectionsWithObstacles = (p1, p2, obstacles) => {
|
|
|
6817
7014
|
}
|
|
6818
7015
|
return intersections2;
|
|
6819
7016
|
};
|
|
6820
|
-
var isSamePoint = (first, second) => Math.abs(first.x - second.x) <
|
|
7017
|
+
var isSamePoint = (first, second) => Math.abs(first.x - second.x) < EPS10 && Math.abs(first.y - second.y) < EPS10;
|
|
6821
7018
|
var findPerpendicularPathCrossings = (path, otherPath, options = {}) => {
|
|
6822
7019
|
const crossings = [];
|
|
6823
7020
|
const firstPathSegmentIndex = options.includeTerminalSegments ? 0 : 1;
|
|
@@ -6827,11 +7024,11 @@ var findPerpendicularPathCrossings = (path, otherPath, options = {}) => {
|
|
|
6827
7024
|
for (let pathSegmentIndex = firstPathSegmentIndex; pathSegmentIndex < lastPathSegmentIndex; pathSegmentIndex++) {
|
|
6828
7025
|
const start = path[pathSegmentIndex];
|
|
6829
7026
|
const end = path[pathSegmentIndex + 1];
|
|
6830
|
-
const isVertical6 = Math.abs(start.x - end.x) <
|
|
7027
|
+
const isVertical6 = Math.abs(start.x - end.x) < EPS10;
|
|
6831
7028
|
for (let otherPathSegmentIndex = firstOtherPathSegmentIndex; otherPathSegmentIndex < lastOtherPathSegmentIndex; otherPathSegmentIndex++) {
|
|
6832
7029
|
const otherStart = otherPath[otherPathSegmentIndex];
|
|
6833
7030
|
const otherEnd = otherPath[otherPathSegmentIndex + 1];
|
|
6834
|
-
const otherIsVertical = Math.abs(otherStart.x - otherEnd.x) <
|
|
7031
|
+
const otherIsVertical = Math.abs(otherStart.x - otherEnd.x) < EPS10;
|
|
6835
7032
|
if (isVertical6 === otherIsVertical) continue;
|
|
6836
7033
|
const intersection = getSegmentIntersection(
|
|
6837
7034
|
start,
|
|
@@ -6851,8 +7048,8 @@ var findPerpendicularPathCrossings = (path, otherPath, options = {}) => {
|
|
|
6851
7048
|
};
|
|
6852
7049
|
|
|
6853
7050
|
// lib/solvers/TraceCleanupSolver/sub-solver/generateLShapeRerouteCandidates.ts
|
|
6854
|
-
var
|
|
6855
|
-
var isVertical3 = (a, b, eps =
|
|
7051
|
+
var EPS11 = 1e-6;
|
|
7052
|
+
var isVertical3 = (a, b, eps = EPS11) => Math.abs(a.x - b.x) < eps;
|
|
6856
7053
|
var generateLShapeRerouteCandidates = ({
|
|
6857
7054
|
lShape,
|
|
6858
7055
|
rectangle,
|
|
@@ -6865,7 +7062,7 @@ var generateLShapeRerouteCandidates = ({
|
|
|
6865
7062
|
let c2;
|
|
6866
7063
|
let i1_padded = interactionPoint1;
|
|
6867
7064
|
let i2_padded = interactionPoint2;
|
|
6868
|
-
if (Math.abs(p2.x - x) <
|
|
7065
|
+
if (Math.abs(p2.x - x) < EPS11 && Math.abs(p2.y - (y + height)) < EPS11) {
|
|
6869
7066
|
c2 = { x: x + width + padding, y: y - padding };
|
|
6870
7067
|
if (isVertical3(p1, p2)) {
|
|
6871
7068
|
i1_padded = { x: interactionPoint1.x, y: interactionPoint1.y - padding };
|
|
@@ -6877,7 +7074,7 @@ var generateLShapeRerouteCandidates = ({
|
|
|
6877
7074
|
} else {
|
|
6878
7075
|
i2_padded = { x: interactionPoint2.x + padding, y: interactionPoint2.y };
|
|
6879
7076
|
}
|
|
6880
|
-
} else if (Math.abs(p2.x - (x + width)) <
|
|
7077
|
+
} else if (Math.abs(p2.x - (x + width)) < EPS11 && Math.abs(p2.y - (y + height)) < EPS11) {
|
|
6881
7078
|
c2 = { x: x - padding, y: y - padding };
|
|
6882
7079
|
if (isVertical3(p1, p2)) {
|
|
6883
7080
|
i1_padded = { x: interactionPoint1.x, y: interactionPoint1.y - padding };
|
|
@@ -6889,7 +7086,7 @@ var generateLShapeRerouteCandidates = ({
|
|
|
6889
7086
|
} else {
|
|
6890
7087
|
i2_padded = { x: interactionPoint2.x - padding, y: interactionPoint2.y };
|
|
6891
7088
|
}
|
|
6892
|
-
} else if (Math.abs(p2.x - x) <
|
|
7089
|
+
} else if (Math.abs(p2.x - x) < EPS11 && Math.abs(p2.y - y) < EPS11) {
|
|
6893
7090
|
c2 = { x: x + width + padding, y: y + height + padding };
|
|
6894
7091
|
if (isVertical3(p1, p2)) {
|
|
6895
7092
|
i1_padded = { x: interactionPoint1.x, y: interactionPoint1.y + padding };
|
|
@@ -6901,7 +7098,7 @@ var generateLShapeRerouteCandidates = ({
|
|
|
6901
7098
|
} else {
|
|
6902
7099
|
i2_padded = { x: interactionPoint2.x + padding, y: interactionPoint2.y };
|
|
6903
7100
|
}
|
|
6904
|
-
} else if (Math.abs(p2.x - (x + width)) <
|
|
7101
|
+
} else if (Math.abs(p2.x - (x + width)) < EPS11 && Math.abs(p2.y - y) < EPS11) {
|
|
6905
7102
|
c2 = { x: x - padding, y: y + height + padding };
|
|
6906
7103
|
if (isVertical3(p1, p2)) {
|
|
6907
7104
|
i1_padded = { x: interactionPoint1.x, y: interactionPoint1.y + padding };
|
|
@@ -6975,7 +7172,7 @@ var generatePerpendicularTraceDetours = ({
|
|
|
6975
7172
|
const buildDetours = (path, index) => {
|
|
6976
7173
|
const start = path[index];
|
|
6977
7174
|
const end = path[index + 1];
|
|
6978
|
-
const movingAxis = Math.abs(start.x - end.x) <
|
|
7175
|
+
const movingAxis = Math.abs(start.x - end.x) < EPS11 ? "y" : "x";
|
|
6979
7176
|
const detourAxis = movingAxis === "x" ? "y" : "x";
|
|
6980
7177
|
const bounds = obstacleBounds ?? {
|
|
6981
7178
|
minX: Math.min(obstacleStart.x, obstacleEnd.x),
|
|
@@ -7602,9 +7799,9 @@ var UntangleTraceSubsolver = class extends BaseSolver {
|
|
|
7602
7799
|
};
|
|
7603
7800
|
|
|
7604
7801
|
// lib/solvers/TraceCleanupSolver/is4PointRectangle.ts
|
|
7605
|
-
var
|
|
7606
|
-
var sameX = (a, b) => Math.abs(a.x - b.x) <=
|
|
7607
|
-
var sameY = (a, b) => Math.abs(a.y - b.y) <=
|
|
7802
|
+
var EPS12 = 1e-6;
|
|
7803
|
+
var sameX = (a, b) => Math.abs(a.x - b.x) <= EPS12;
|
|
7804
|
+
var sameY = (a, b) => Math.abs(a.y - b.y) <= EPS12;
|
|
7608
7805
|
var is4PointRectangle = (path) => {
|
|
7609
7806
|
if (path.length !== 4) return false;
|
|
7610
7807
|
const [p0, p1, p2, p3] = path;
|
|
@@ -7614,7 +7811,7 @@ var is4PointRectangle = (path) => {
|
|
|
7614
7811
|
};
|
|
7615
7812
|
|
|
7616
7813
|
// lib/solvers/TraceCleanupSolver/rerouteGeneratedNetLabelConnectorCrossings.ts
|
|
7617
|
-
var
|
|
7814
|
+
var EPS13 = 1e-6;
|
|
7618
7815
|
var getConnectorObstacleBounds = (connector, segmentIndex, labels) => {
|
|
7619
7816
|
const start = connector.tracePath[segmentIndex];
|
|
7620
7817
|
const end = connector.tracePath[segmentIndex + 1];
|
|
@@ -7706,7 +7903,7 @@ var rerouteGeneratedNetLabelConnectorCrossings = ({
|
|
|
7706
7903
|
chipBounds: [],
|
|
7707
7904
|
clearance
|
|
7708
7905
|
}).filter(
|
|
7709
|
-
(candidate) => getPathLength4(candidate.path) <= getPathLength4(trace.tracePath) +
|
|
7906
|
+
(candidate) => getPathLength4(candidate.path) <= getPathLength4(trace.tracePath) + EPS13 && countTurns(candidate.path) <= countTurns(trace.tracePath) + 2 && !isPathCollidingWithObstacles(
|
|
7710
7907
|
candidate.path,
|
|
7711
7908
|
componentAndTextObstacles
|
|
7712
7909
|
) && !hasCollisionsWithLabels(candidate.path, foreignLabelBounds) && !isPathColliding(candidate.path, foreignTraces, trace.mspPairId).isColliding && !doesPathCoincideWithTraces(candidate.path, foreignTraces)
|
|
@@ -7717,7 +7914,7 @@ var rerouteGeneratedNetLabelConnectorCrossings = ({
|
|
|
7717
7914
|
});
|
|
7718
7915
|
candidates.sort((first, second) => {
|
|
7719
7916
|
const lengthDifference = getPathLength4(first.path) - getPathLength4(second.path);
|
|
7720
|
-
return Math.abs(lengthDifference) >
|
|
7917
|
+
return Math.abs(lengthDifference) > EPS13 ? lengthDifference : countTurns(first.path) - countTurns(second.path);
|
|
7721
7918
|
});
|
|
7722
7919
|
const bestCandidate = candidates[0];
|
|
7723
7920
|
if (!bestCandidate) break;
|
|
@@ -8099,7 +8296,7 @@ var doesPathRunAlongChipBoundary = (path, chipObstacles) => {
|
|
|
8099
8296
|
const end = path[i + 1];
|
|
8100
8297
|
for (const obstacle of chipObstacles) {
|
|
8101
8298
|
if (!segmentRunsAlongRectBoundary(start, end, obstacle)) continue;
|
|
8102
|
-
if (getSegmentOverlapWithRectSpan(start, end, obstacle) >
|
|
8299
|
+
if (getSegmentOverlapWithRectSpan(start, end, obstacle) > EPS9) {
|
|
8103
8300
|
return true;
|
|
8104
8301
|
}
|
|
8105
8302
|
}
|
|
@@ -8114,13 +8311,13 @@ var getChipBoundaryOverlap = (path, chipObstacles) => {
|
|
|
8114
8311
|
for (const obstacle of chipObstacles) {
|
|
8115
8312
|
if (!segmentRunsAlongRectBoundary(start, end, obstacle)) continue;
|
|
8116
8313
|
const overlap = getSegmentOverlapWithRectSpan(start, end, obstacle);
|
|
8117
|
-
if (overlap >
|
|
8314
|
+
if (overlap > EPS9) total += overlap;
|
|
8118
8315
|
}
|
|
8119
8316
|
}
|
|
8120
8317
|
return total;
|
|
8121
8318
|
};
|
|
8122
8319
|
var getSegmentOverlapWithRectSpan = (start, end, rect) => {
|
|
8123
|
-
const isVertical6 = Math.abs(start.x - end.x) <
|
|
8320
|
+
const isVertical6 = Math.abs(start.x - end.x) < EPS9;
|
|
8124
8321
|
if (isVertical6) {
|
|
8125
8322
|
return Math.min(Math.max(start.y, end.y), rect.maxY) - Math.max(Math.min(start.y, end.y), rect.minY);
|
|
8126
8323
|
}
|
|
@@ -8885,16 +9082,16 @@ var createPortOnlyLabelConnectorTrace = ({
|
|
|
8885
9082
|
var LABEL_SEARCH_STEP = 0.05;
|
|
8886
9083
|
var MAX_RECORDED_CANDIDATES = 2e3;
|
|
8887
9084
|
var WICK_CLEARANCE = 1e-3;
|
|
8888
|
-
var
|
|
8889
|
-
var TRACE_BOUNDARY_TOLERANCE = WICK_CLEARANCE +
|
|
9085
|
+
var EPS14 = 1e-9;
|
|
9086
|
+
var TRACE_BOUNDARY_TOLERANCE = WICK_CLEARANCE + EPS14;
|
|
8890
9087
|
var CANDIDATE_SELECTED_COLOR2 = "blue";
|
|
8891
9088
|
var CANDIDATE_REJECTED_COLOR2 = "red";
|
|
8892
9089
|
|
|
8893
9090
|
// lib/solvers/AvailableNetOrientationSolver/geometry.ts
|
|
8894
9091
|
var isYOrientation = (orientation) => orientation === "y+" || orientation === "y-";
|
|
8895
9092
|
var isXOrientation = (orientation) => orientation === "x+" || orientation === "x-";
|
|
8896
|
-
var rectsOverlap2 = (a, b) => Math.min(a.maxX, b.maxX) - Math.max(a.minX, b.minX) >
|
|
8897
|
-
var rangesOverlap = (minA, maxA, minB, maxB) => Math.min(maxA, maxB) - Math.max(minA, minB) >
|
|
9093
|
+
var rectsOverlap2 = (a, b) => Math.min(a.maxX, b.maxX) - Math.max(a.minX, b.minX) > EPS14 && Math.min(a.maxY, b.maxY) - Math.max(a.minY, b.minY) > EPS14;
|
|
9094
|
+
var rangesOverlap = (minA, maxA, minB, maxB) => Math.min(maxA, maxB) - Math.max(minA, minB) > EPS14;
|
|
8898
9095
|
var traceCrossesBoundsInterior = (bounds, traceMap) => {
|
|
8899
9096
|
for (const trace of Object.values(traceMap)) {
|
|
8900
9097
|
const points = trace.tracePath;
|
|
@@ -8917,7 +9114,7 @@ var segmentCrossesBoundsInterior = (p1, p2, bounds) => {
|
|
|
8917
9114
|
return false;
|
|
8918
9115
|
}
|
|
8919
9116
|
if (sameX2(p1, p2)) {
|
|
8920
|
-
if (p1.x <= interiorBounds.minX +
|
|
9117
|
+
if (p1.x <= interiorBounds.minX + EPS14 || p1.x >= interiorBounds.maxX - EPS14) {
|
|
8921
9118
|
return false;
|
|
8922
9119
|
}
|
|
8923
9120
|
return rangesOverlap(
|
|
@@ -8928,7 +9125,7 @@ var segmentCrossesBoundsInterior = (p1, p2, bounds) => {
|
|
|
8928
9125
|
);
|
|
8929
9126
|
}
|
|
8930
9127
|
if (sameY2(p1, p2)) {
|
|
8931
|
-
if (p1.y <= interiorBounds.minY +
|
|
9128
|
+
if (p1.y <= interiorBounds.minY + EPS14 || p1.y >= interiorBounds.maxY - EPS14) {
|
|
8932
9129
|
return false;
|
|
8933
9130
|
}
|
|
8934
9131
|
return rangesOverlap(
|
|
@@ -8976,8 +9173,8 @@ var simplifyOrthogonalPath = (path) => {
|
|
|
8976
9173
|
return simplified;
|
|
8977
9174
|
};
|
|
8978
9175
|
var pointsEqual3 = (a, b) => sameX2(a, b) && sameY2(a, b);
|
|
8979
|
-
var sameX2 = (a, b) => Math.abs(a.x - b.x) <=
|
|
8980
|
-
var sameY2 = (a, b) => Math.abs(a.y - b.y) <=
|
|
9176
|
+
var sameX2 = (a, b) => Math.abs(a.x - b.x) <= EPS14;
|
|
9177
|
+
var sameY2 = (a, b) => Math.abs(a.y - b.y) <= EPS14;
|
|
8981
9178
|
var getMaxSearchDistance = (inputProblem) => {
|
|
8982
9179
|
const maxChipWidth = Math.max(
|
|
8983
9180
|
...inputProblem.chips.map((chip) => chip.width),
|
|
@@ -9136,7 +9333,7 @@ var AvailableNetOrientationObstacleIndex = class {
|
|
|
9136
9333
|
}
|
|
9137
9334
|
getTraceSegmentsInBounds(bounds) {
|
|
9138
9335
|
if (!this.traceSegmentIndex) return [];
|
|
9139
|
-
const searchBounds = getPaddedBounds(bounds,
|
|
9336
|
+
const searchBounds = getPaddedBounds(bounds, EPS14);
|
|
9140
9337
|
return this.traceSegmentIndex.search(
|
|
9141
9338
|
searchBounds.minX,
|
|
9142
9339
|
searchBounds.minY,
|
|
@@ -9149,7 +9346,7 @@ var AvailableNetOrientationObstacleIndex = class {
|
|
|
9149
9346
|
for (let pointIndex = 0; pointIndex < tracePath.length - 1; pointIndex++) {
|
|
9150
9347
|
const segmentBounds = getPaddedBounds(
|
|
9151
9348
|
getSegmentBounds(tracePath[pointIndex], tracePath[pointIndex + 1]),
|
|
9152
|
-
|
|
9349
|
+
EPS14
|
|
9153
9350
|
);
|
|
9154
9351
|
for (const labelIndex of this.getLabelIndicesInBounds(segmentBounds)) {
|
|
9155
9352
|
labelIndices.add(labelIndex);
|
|
@@ -9162,7 +9359,7 @@ var AvailableNetOrientationObstacleIndex = class {
|
|
|
9162
9359
|
const start = tracePath[pointIndex];
|
|
9163
9360
|
const end = tracePath[pointIndex + 1];
|
|
9164
9361
|
const nearbyChips = this.chipObstacleSpatialIndex.getChipsInBounds(
|
|
9165
|
-
getPaddedBounds(getSegmentBounds(start, end),
|
|
9362
|
+
getPaddedBounds(getSegmentBounds(start, end), EPS14)
|
|
9166
9363
|
);
|
|
9167
9364
|
for (const chip of nearbyChips) {
|
|
9168
9365
|
if (segmentCrossesBoundsInterior(start, end, chip.bounds)) return true;
|
|
@@ -9619,7 +9816,7 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
|
|
|
9619
9816
|
labelIndex,
|
|
9620
9817
|
orientations
|
|
9621
9818
|
);
|
|
9622
|
-
const rotatedCandidateNeedsLateralBranch = rotatedCandidate !== null && Math.abs(rotatedCandidate.anchorPoint.x - label.anchorPoint.x) >
|
|
9819
|
+
const rotatedCandidateNeedsLateralBranch = rotatedCandidate !== null && Math.abs(rotatedCandidate.anchorPoint.x - label.anchorPoint.x) > EPS14;
|
|
9623
9820
|
if (isDownwardGroundRail && rotatedCandidateNeedsLateralBranch) {
|
|
9624
9821
|
const downwardRailCandidate = this.findValidCandidateInShiftColumn({
|
|
9625
9822
|
label,
|
|
@@ -9678,7 +9875,7 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
|
|
|
9678
9875
|
index,
|
|
9679
9876
|
pin: this.pinMap[otherLabel.pinIds[0]]
|
|
9680
9877
|
})).filter(
|
|
9681
|
-
({ index, pin: otherPin }) => this.crowdedPortOnlyLabelIndices.has(index) && otherPin?.chipId === pin.chipId && otherPin.x > pin.x +
|
|
9878
|
+
({ index, pin: otherPin }) => this.crowdedPortOnlyLabelIndices.has(index) && otherPin?.chipId === pin.chipId && otherPin.x > pin.x + EPS14
|
|
9682
9879
|
).sort((a, b) => a.pin.x - b.pin.x)[0]?.pin;
|
|
9683
9880
|
if (orientation === "y-" && nextPinToRight) return null;
|
|
9684
9881
|
const anchorX = orientation === "y-" ? Math.max(
|
|
@@ -9711,7 +9908,7 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
|
|
|
9711
9908
|
const centeredAnchorY = hasUpFacingStack ? (lowestUpFacingLabelY + highestUpFacingLabelY) / 2 : stackedAnchorY;
|
|
9712
9909
|
const anchorYs = orientation === "y-" ? [centeredAnchorY, stackedAnchorY] : [stackedAnchorY];
|
|
9713
9910
|
for (const anchorY of anchorYs) {
|
|
9714
|
-
if (anchorY - label.anchorPoint.y > this.maxSearchDistance +
|
|
9911
|
+
if (anchorY - label.anchorPoint.y > this.maxSearchDistance + EPS14) {
|
|
9715
9912
|
continue;
|
|
9716
9913
|
}
|
|
9717
9914
|
const candidate = this.createCandidate(
|
|
@@ -9740,11 +9937,11 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
|
|
|
9740
9937
|
if (trace.globalConnNetId !== label.globalConnNetId) return false;
|
|
9741
9938
|
const path = trace.tracePath;
|
|
9742
9939
|
return path.some((point, pointIndex) => {
|
|
9743
|
-
if (Math.abs(point.x - label.anchorPoint.x) >
|
|
9940
|
+
if (Math.abs(point.x - label.anchorPoint.x) > EPS14 || Math.abs(point.y - label.anchorPoint.y) > EPS14) {
|
|
9744
9941
|
return false;
|
|
9745
9942
|
}
|
|
9746
9943
|
return [path[pointIndex - 1], path[pointIndex + 1]].some(
|
|
9747
|
-
(neighbor) => neighbor && Math.abs(neighbor.x - point.x) <=
|
|
9944
|
+
(neighbor) => neighbor && Math.abs(neighbor.x - point.x) <= EPS14 && (neighbor.y - point.y) * direction.y > EPS14
|
|
9748
9945
|
);
|
|
9749
9946
|
});
|
|
9750
9947
|
});
|
|
@@ -9834,7 +10031,7 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
|
|
|
9834
10031
|
orientation
|
|
9835
10032
|
);
|
|
9836
10033
|
if (outwardDirection.x === 0 && outwardDirection.y === 0) continue;
|
|
9837
|
-
for (let distance7 = LABEL_SEARCH_STEP; distance7 <= this.maxSearchDistance +
|
|
10034
|
+
for (let distance7 = LABEL_SEARCH_STEP; distance7 <= this.maxSearchDistance + EPS14; distance7 += LABEL_SEARCH_STEP) {
|
|
9838
10035
|
const anchorPoint = {
|
|
9839
10036
|
x: connectorSource.x + outwardDirection.x * distance7,
|
|
9840
10037
|
y: connectorSource.y + outwardDirection.y * distance7
|
|
@@ -9912,7 +10109,7 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
|
|
|
9912
10109
|
const furthestRowPoints = points.filter(
|
|
9913
10110
|
(point) => Math.abs(
|
|
9914
10111
|
point.x * direction.x + point.y * direction.y - furthestAlong
|
|
9915
|
-
) <=
|
|
10112
|
+
) <= EPS14
|
|
9916
10113
|
);
|
|
9917
10114
|
const directHostPinIds = new Set(
|
|
9918
10115
|
[...directHostTraceIds].flatMap(
|
|
@@ -9933,7 +10130,7 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
|
|
|
9933
10130
|
preferNearestBendOnOutwardRow: adjacentTraces.some(
|
|
9934
10131
|
(trace) => furthestRowPoints.some(
|
|
9935
10132
|
(point) => trace.tracePath.some(
|
|
9936
|
-
(tracePoint) => Math.abs(tracePoint.x - point.x) <=
|
|
10133
|
+
(tracePoint) => Math.abs(tracePoint.x - point.x) <= EPS14 && Math.abs(tracePoint.y - point.y) <= EPS14
|
|
9937
10134
|
)
|
|
9938
10135
|
)
|
|
9939
10136
|
)
|
|
@@ -9945,7 +10142,7 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
|
|
|
9945
10142
|
for (let i = 0; i < otherTrace.tracePath.length - 1; i++) {
|
|
9946
10143
|
const start = otherTrace.tracePath[i];
|
|
9947
10144
|
const end = otherTrace.tracePath[i + 1];
|
|
9948
|
-
if (Math.abs(start.x - end.x) <=
|
|
10145
|
+
if (Math.abs(start.x - end.x) <= EPS14 && Math.abs(start.y - end.y) > EPS14) {
|
|
9949
10146
|
verticalRailXs.add(start.x);
|
|
9950
10147
|
}
|
|
9951
10148
|
}
|
|
@@ -9953,7 +10150,7 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
|
|
|
9953
10150
|
for (let i = 0; i < trace.tracePath.length - 1; i++) {
|
|
9954
10151
|
const start = trace.tracePath[i];
|
|
9955
10152
|
const end = trace.tracePath[i + 1];
|
|
9956
|
-
if (Math.abs(start.x - end.x) <=
|
|
10153
|
+
if (Math.abs(start.x - end.x) <= EPS14 && Math.abs(start.y - end.y) > EPS14 && [...verticalRailXs].some((x) => Math.abs(x - start.x) <= EPS14)) {
|
|
9957
10154
|
return true;
|
|
9958
10155
|
}
|
|
9959
10156
|
}
|
|
@@ -9972,7 +10169,7 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
|
|
|
9972
10169
|
);
|
|
9973
10170
|
const maxSearchDistance = this.getSearchDistanceLimit(label, orientation);
|
|
9974
10171
|
const maxOutwardDistance = outwardDirection.x === 0 && outwardDirection.y === 0 ? 0 : this.maxSearchDistance;
|
|
9975
|
-
for (let outwardDistance = 0; outwardDistance <= maxOutwardDistance +
|
|
10172
|
+
for (let outwardDistance = 0; outwardDistance <= maxOutwardDistance + EPS14; outwardDistance += LABEL_SEARCH_STEP) {
|
|
9976
10173
|
const baseAnchor = {
|
|
9977
10174
|
x: initialBaseAnchor.x + outwardDirection.x * outwardDistance,
|
|
9978
10175
|
y: initialBaseAnchor.y + outwardDirection.y * outwardDistance
|
|
@@ -10048,7 +10245,7 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
|
|
|
10048
10245
|
connectorSource,
|
|
10049
10246
|
startDistance = LABEL_SEARCH_STEP
|
|
10050
10247
|
} = params;
|
|
10051
|
-
for (let distance7 = startDistance; distance7 <= maxSearchDistance +
|
|
10248
|
+
for (let distance7 = startDistance; distance7 <= maxSearchDistance + EPS14; distance7 += LABEL_SEARCH_STEP) {
|
|
10052
10249
|
const anchorPoint = {
|
|
10053
10250
|
x: baseAnchor.x + direction.x * distance7,
|
|
10054
10251
|
y: baseAnchor.y + direction.y * distance7
|
|
@@ -10161,14 +10358,14 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
|
|
|
10161
10358
|
for (let pointIndex = 0; pointIndex < hostTrace.tracePath.length - 1; pointIndex++) {
|
|
10162
10359
|
const start = hostTrace.tracePath[pointIndex];
|
|
10163
10360
|
const end = hostTrace.tracePath[pointIndex + 1];
|
|
10164
|
-
const segmentIsPerpendicularToLabel = isYOrientation(orientation) ? Math.abs(start.y - end.y) <=
|
|
10361
|
+
const segmentIsPerpendicularToLabel = isYOrientation(orientation) ? Math.abs(start.y - end.y) <= EPS14 : Math.abs(start.x - end.x) <= EPS14;
|
|
10165
10362
|
if (!segmentIsPerpendicularToLabel) continue;
|
|
10166
10363
|
const source = isYOrientation(orientation) ? { x: targetAnchor.x, y: start.y } : { x: start.x, y: targetAnchor.y };
|
|
10167
10364
|
if (!tracePathContainsPoint([start, end], label.anchorPoint) || !tracePathContainsPoint([start, end], source)) {
|
|
10168
10365
|
continue;
|
|
10169
10366
|
}
|
|
10170
10367
|
const targetDistanceAlongOrientation = (targetAnchor.x - source.x) * orientationDirection.x + (targetAnchor.y - source.y) * orientationDirection.y;
|
|
10171
|
-
if (targetDistanceAlongOrientation >= -
|
|
10368
|
+
if (targetDistanceAlongOrientation >= -EPS14) {
|
|
10172
10369
|
projectedSources.push(source);
|
|
10173
10370
|
}
|
|
10174
10371
|
}
|
|
@@ -10427,9 +10624,9 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
|
|
|
10427
10624
|
const { anchorPoint, orientation } = candidate;
|
|
10428
10625
|
const chipBounds = chip.bounds;
|
|
10429
10626
|
if (isYOrientation(orientation)) {
|
|
10430
|
-
return anchorPoint.x < chipBounds.minX -
|
|
10627
|
+
return anchorPoint.x < chipBounds.minX - EPS14 || anchorPoint.x > chipBounds.maxX + EPS14;
|
|
10431
10628
|
}
|
|
10432
|
-
return anchorPoint.y < chipBounds.minY -
|
|
10629
|
+
return anchorPoint.y < chipBounds.minY - EPS14 || anchorPoint.y > chipBounds.maxY + EPS14;
|
|
10433
10630
|
});
|
|
10434
10631
|
}
|
|
10435
10632
|
staysOutsideConnectedPinRow(params) {
|
|
@@ -10437,9 +10634,9 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
|
|
|
10437
10634
|
const pin = this.pinMap[label.pinIds[0]];
|
|
10438
10635
|
if (!pin || !isYOrientation(candidate.orientation)) return false;
|
|
10439
10636
|
if (candidate.anchorPoint.x < pin.x) {
|
|
10440
|
-
return bounds.maxX <= pin.x + CONNECTED_PIN_ROW_OVERLAP_TOLERANCE +
|
|
10637
|
+
return bounds.maxX <= pin.x + CONNECTED_PIN_ROW_OVERLAP_TOLERANCE + EPS14;
|
|
10441
10638
|
}
|
|
10442
|
-
return bounds.minX >= pin.x - CONNECTED_PIN_ROW_OVERLAP_TOLERANCE -
|
|
10639
|
+
return bounds.minX >= pin.x - CONNECTED_PIN_ROW_OVERLAP_TOLERANCE - EPS14;
|
|
10443
10640
|
}
|
|
10444
10641
|
getBoundsStatus(candidateBoundsCheck) {
|
|
10445
10642
|
const { bounds, labelIndex, label, ignoreChipCollisions } = candidateBoundsCheck;
|
|
@@ -10520,14 +10717,14 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
|
|
|
10520
10717
|
candidate.width,
|
|
10521
10718
|
candidate.height
|
|
10522
10719
|
);
|
|
10523
|
-
if (labelBounds.minY < chip.bounds.minY -
|
|
10720
|
+
if (labelBounds.minY < chip.bounds.minY - EPS14 || labelBounds.maxY > chip.bounds.maxY + EPS14) {
|
|
10524
10721
|
return false;
|
|
10525
10722
|
}
|
|
10526
|
-
if (candidate.anchorPoint.x >= chip.bounds.minX -
|
|
10723
|
+
if (candidate.anchorPoint.x >= chip.bounds.minX - EPS14 && candidate.anchorPoint.x <= chip.bounds.maxX + EPS14) {
|
|
10527
10724
|
return false;
|
|
10528
10725
|
}
|
|
10529
10726
|
return chip.pins.every(
|
|
10530
|
-
(pin) => label.pinIds.includes(pin.pinId) || pin.y <= labelBounds.minY +
|
|
10727
|
+
(pin) => label.pinIds.includes(pin.pinId) || pin.y <= labelBounds.minY + EPS14 || pin.y >= labelBounds.maxY - EPS14
|
|
10531
10728
|
);
|
|
10532
10729
|
}
|
|
10533
10730
|
getTextBlockedMultiPinRailTraces(label, orientation) {
|
|
@@ -10554,20 +10751,20 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
|
|
|
10554
10751
|
const pins = [...connectedPinIds].map((pinId) => this.pinMap[pinId]);
|
|
10555
10752
|
const direction = dir(orientation);
|
|
10556
10753
|
const pinX = pins[0].x;
|
|
10557
|
-
if (pins.some((pin) => Math.abs(pin.x - pinX) >
|
|
10558
|
-
const sidePins = this.inputProblem.chips.find((chip) => chip.chipId === componentId).pins.filter((pin) => Math.abs(pin.x - pinX) <=
|
|
10754
|
+
if (pins.some((pin) => Math.abs(pin.x - pinX) > EPS14)) return null;
|
|
10755
|
+
const sidePins = this.inputProblem.chips.find((chip) => chip.chipId === componentId).pins.filter((pin) => Math.abs(pin.x - pinX) <= EPS14);
|
|
10559
10756
|
const minY = Math.min(...pins.map((pin) => pin.y));
|
|
10560
10757
|
const maxY = Math.max(...pins.map((pin) => pin.y));
|
|
10561
10758
|
if (sidePins.some(
|
|
10562
|
-
(pin) => pin.y >= minY -
|
|
10563
|
-
) || orientation === "y-" && minY > Math.min(...sidePins.map((pin) => pin.y)) +
|
|
10759
|
+
(pin) => pin.y >= minY - EPS14 && pin.y <= maxY + EPS14 && !connectedPinIds.has(pin.pinId)
|
|
10760
|
+
) || orientation === "y-" && minY > Math.min(...sidePins.map((pin) => pin.y)) + EPS14 || orientation === "y+" && maxY < Math.max(...sidePins.map((pin) => pin.y)) - EPS14) {
|
|
10564
10761
|
return null;
|
|
10565
10762
|
}
|
|
10566
10763
|
const outerPinPosition = Math.max(
|
|
10567
10764
|
...pins.map((pin) => pin.x * direction.x + pin.y * direction.y)
|
|
10568
10765
|
);
|
|
10569
10766
|
const blockedByText = (this.inputProblem.textBoxes ?? []).some(
|
|
10570
|
-
(textBox) => textBox.chipId === componentId && textBox.center.x * direction.x + textBox.center.y * direction.y > outerPinPosition +
|
|
10767
|
+
(textBox) => textBox.chipId === componentId && textBox.center.x * direction.x + textBox.center.y * direction.y > outerPinPosition + EPS14
|
|
10571
10768
|
);
|
|
10572
10769
|
return blockedByText ? [...connectedTraces] : null;
|
|
10573
10770
|
}
|
|
@@ -10583,7 +10780,7 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
|
|
|
10583
10780
|
...new Set(
|
|
10584
10781
|
localTraces.flatMap((trace) => trace.tracePath.map((point) => point.x))
|
|
10585
10782
|
)
|
|
10586
|
-
].filter((x) => Math.abs(x - pinX) >
|
|
10783
|
+
].filter((x) => Math.abs(x - pinX) > EPS14).sort((a, b) => Math.abs(a - pinX) - Math.abs(b - pinX));
|
|
10587
10784
|
for (const x of railXs) {
|
|
10588
10785
|
const connectorSource = { x, y: connectorY };
|
|
10589
10786
|
if (!Object.values(this.traceMap).some(
|
|
@@ -10646,8 +10843,8 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
|
|
|
10646
10843
|
if (!chip) return null;
|
|
10647
10844
|
const sides = new Set(
|
|
10648
10845
|
pins.map((pin) => {
|
|
10649
|
-
if (Math.abs(pin.x - chip.bounds.minX) <=
|
|
10650
|
-
if (Math.abs(pin.x - chip.bounds.maxX) <=
|
|
10846
|
+
if (Math.abs(pin.x - chip.bounds.minX) <= EPS14) return "left";
|
|
10847
|
+
if (Math.abs(pin.x - chip.bounds.maxX) <= EPS14) return "right";
|
|
10651
10848
|
return null;
|
|
10652
10849
|
})
|
|
10653
10850
|
);
|
|
@@ -10684,7 +10881,7 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
|
|
|
10684
10881
|
return null;
|
|
10685
10882
|
}
|
|
10686
10883
|
const renderedWidth = this.getNetConnectionForLabel(label)?.netLabelHeight;
|
|
10687
|
-
if (renderedWidth === void 0 || renderedWidth <= label.width + label.height +
|
|
10884
|
+
if (renderedWidth === void 0 || renderedWidth <= label.width + label.height + EPS14) {
|
|
10688
10885
|
return null;
|
|
10689
10886
|
}
|
|
10690
10887
|
const placementBaseCenter = getCenterFromAnchor(
|
|
@@ -10759,16 +10956,16 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
|
|
|
10759
10956
|
}
|
|
10760
10957
|
sharesChipBoundary(bounds) {
|
|
10761
10958
|
const boundarySearchBounds = {
|
|
10762
|
-
minX: bounds.minX - WICK_CLEARANCE -
|
|
10763
|
-
minY: bounds.minY - WICK_CLEARANCE -
|
|
10764
|
-
maxX: bounds.maxX + WICK_CLEARANCE +
|
|
10765
|
-
maxY: bounds.maxY + WICK_CLEARANCE +
|
|
10959
|
+
minX: bounds.minX - WICK_CLEARANCE - EPS14,
|
|
10960
|
+
minY: bounds.minY - WICK_CLEARANCE - EPS14,
|
|
10961
|
+
maxX: bounds.maxX + WICK_CLEARANCE + EPS14,
|
|
10962
|
+
maxY: bounds.maxY + WICK_CLEARANCE + EPS14
|
|
10766
10963
|
};
|
|
10767
10964
|
const nearbyChips = this.chipObstacleSpatialIndex.getChipsInBounds(boundarySearchBounds);
|
|
10768
10965
|
for (const chip of nearbyChips) {
|
|
10769
10966
|
const chipBounds = chip.bounds;
|
|
10770
|
-
const adjacentToVerticalSide = Math.abs(bounds.minX - chipBounds.maxX) <= WICK_CLEARANCE +
|
|
10771
|
-
const adjacentToHorizontalSide = Math.abs(bounds.minY - chipBounds.maxY) <= WICK_CLEARANCE +
|
|
10967
|
+
const adjacentToVerticalSide = Math.abs(bounds.minX - chipBounds.maxX) <= WICK_CLEARANCE + EPS14 || Math.abs(bounds.maxX - chipBounds.minX) <= WICK_CLEARANCE + EPS14;
|
|
10968
|
+
const adjacentToHorizontalSide = Math.abs(bounds.minY - chipBounds.maxY) <= WICK_CLEARANCE + EPS14 || Math.abs(bounds.maxY - chipBounds.minY) <= WICK_CLEARANCE + EPS14;
|
|
10772
10969
|
if (adjacentToVerticalSide && rangesOverlap(
|
|
10773
10970
|
bounds.minY,
|
|
10774
10971
|
bounds.maxY,
|
|
@@ -10830,7 +11027,7 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
|
|
|
10830
11027
|
let nearestDistance = Number.POSITIVE_INFINITY;
|
|
10831
11028
|
for (const chip of this.chipObstacleSpatialIndex.chips) {
|
|
10832
11029
|
const bounds = chip.bounds;
|
|
10833
|
-
if (point.x < bounds.minX -
|
|
11030
|
+
if (point.x < bounds.minX - EPS14 || point.x > bounds.maxX + EPS14 || point.y < bounds.minY - EPS14 || point.y > bounds.maxY + EPS14) {
|
|
10834
11031
|
continue;
|
|
10835
11032
|
}
|
|
10836
11033
|
for (const [side, distance7] of getSideDistances(point, bounds)) {
|
|
@@ -10847,8 +11044,8 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
|
|
|
10847
11044
|
let nearestDistanceSq = Number.POSITIVE_INFINITY;
|
|
10848
11045
|
for (const chip of this.chipObstacleSpatialIndex.chips) {
|
|
10849
11046
|
const bounds = chip.bounds;
|
|
10850
|
-
const dx = point.x < bounds.minX -
|
|
10851
|
-
const dy = point.y < bounds.minY -
|
|
11047
|
+
const dx = point.x < bounds.minX - EPS14 ? bounds.minX - point.x : point.x > bounds.maxX + EPS14 ? point.x - bounds.maxX : 0;
|
|
11048
|
+
const dy = point.y < bounds.minY - EPS14 ? bounds.minY - point.y : point.y > bounds.maxY + EPS14 ? point.y - bounds.maxY : 0;
|
|
10852
11049
|
if (dx === 0 && dy === 0) continue;
|
|
10853
11050
|
const distanceSq = dx ** 2 + dy ** 2;
|
|
10854
11051
|
if (distanceSq >= nearestDistanceSq) continue;
|
|
@@ -11164,7 +11361,7 @@ var RailNetLabelCornerPlacementSolver = class extends BaseSolver {
|
|
|
11164
11361
|
for (const anchorPoint of getTraceCorners(path)) {
|
|
11165
11362
|
const cornerIndex = path.indexOf(anchorPoint);
|
|
11166
11363
|
const anchorAlignedToPin = pins.some(
|
|
11167
|
-
(pin) => Math.abs(pin.x - anchorPoint.x) <=
|
|
11364
|
+
(pin) => Math.abs(pin.x - anchorPoint.x) <= EPS8
|
|
11168
11365
|
);
|
|
11169
11366
|
const pinAligned = anchorAlignedToPin || allowRailAlignedFallback && this.isPinAlignedCorner(path, cornerIndex);
|
|
11170
11367
|
if (!pinAligned) continue;
|
|
@@ -11204,12 +11401,12 @@ var RailNetLabelCornerPlacementSolver = class extends BaseSolver {
|
|
|
11204
11401
|
return traceCrossesBoundsInterior(bounds, otherNetTraceMap);
|
|
11205
11402
|
}
|
|
11206
11403
|
pointsEqual(a, b) {
|
|
11207
|
-
return Math.abs(a.x - b.x) <=
|
|
11404
|
+
return Math.abs(a.x - b.x) <= EPS8 && Math.abs(a.y - b.y) <= EPS8;
|
|
11208
11405
|
}
|
|
11209
11406
|
getVerticalSegmentPointIndices(path, cornerIndex) {
|
|
11210
11407
|
const corner = path[cornerIndex];
|
|
11211
|
-
const previousIsVertical = Math.abs(path[cornerIndex - 1].x - corner.x) <=
|
|
11212
|
-
const nextIsVertical = Math.abs(path[cornerIndex + 1].x - corner.x) <=
|
|
11408
|
+
const previousIsVertical = Math.abs(path[cornerIndex - 1].x - corner.x) <= EPS8;
|
|
11409
|
+
const nextIsVertical = Math.abs(path[cornerIndex + 1].x - corner.x) <= EPS8;
|
|
11213
11410
|
if (previousIsVertical === nextIsVertical) return null;
|
|
11214
11411
|
const indices = previousIsVertical ? [cornerIndex - 1, cornerIndex] : [cornerIndex, cornerIndex + 1];
|
|
11215
11412
|
return indices;
|
|
@@ -11259,7 +11456,7 @@ var RailNetLabelCornerPlacementSolver = class extends BaseSolver {
|
|
|
11259
11456
|
const end = otherTrace.tracePath[i + 1];
|
|
11260
11457
|
if (!segmentCrossesBoundsInterior(start, end, labelBounds)) continue;
|
|
11261
11458
|
const halfLabelWidth = label.width / 2;
|
|
11262
|
-
if (Math.abs(start.x - end.x) <=
|
|
11459
|
+
if (Math.abs(start.x - end.x) <= EPS8) {
|
|
11263
11460
|
shiftedCoordinates.add(
|
|
11264
11461
|
start.x - halfLabelWidth - LABEL_TRACE_CLEARANCE3
|
|
11265
11462
|
);
|
|
@@ -11277,7 +11474,7 @@ var RailNetLabelCornerPlacementSolver = class extends BaseSolver {
|
|
|
11277
11474
|
}
|
|
11278
11475
|
}
|
|
11279
11476
|
return [...shiftedCoordinates].flatMap((x) => {
|
|
11280
|
-
if (Math.abs(x - corner.x) <=
|
|
11477
|
+
if (Math.abs(x - corner.x) <= EPS8) return [];
|
|
11281
11478
|
const reroutedTracePath = simplifyPath(
|
|
11282
11479
|
path.map(
|
|
11283
11480
|
(point, pointIndex) => verticalPointIndices.includes(pointIndex) ? { ...point, x } : point
|
|
@@ -11408,11 +11605,11 @@ var getOrientationConstraint = (inputProblem, label) => {
|
|
|
11408
11605
|
};
|
|
11409
11606
|
|
|
11410
11607
|
// lib/solvers/TraceAnchoredNetLabelOverlapSolver/geometry.ts
|
|
11411
|
-
var
|
|
11608
|
+
var EPS15 = 1e-6;
|
|
11412
11609
|
var TRACE_BOUNDARY_TOLERANCE2 = 1e-6;
|
|
11413
11610
|
var getLabelBounds = (label) => getRectBounds(label.center, label.width, label.height);
|
|
11414
|
-
var rectsOverlap3 = (a, b) => Math.min(a.maxX, b.maxX) - Math.max(a.minX, b.minX) >
|
|
11415
|
-
var rectsTouchOrOverlap = (a, b) => Math.min(a.maxX, b.maxX) - Math.max(a.minX, b.minX) >= -
|
|
11611
|
+
var rectsOverlap3 = (a, b) => Math.min(a.maxX, b.maxX) - Math.max(a.minX, b.minX) > EPS15 && Math.min(a.maxY, b.maxY) - Math.max(a.minY, b.minY) > EPS15;
|
|
11612
|
+
var rectsTouchOrOverlap = (a, b) => Math.min(a.maxX, b.maxX) - Math.max(a.minX, b.minX) >= -EPS15 && Math.min(a.maxY, b.maxY) - Math.max(a.minY, b.minY) >= -EPS15;
|
|
11416
11613
|
var traceCrossesBoundsInterior2 = (bounds, traces) => {
|
|
11417
11614
|
for (const trace of traces) {
|
|
11418
11615
|
const points = trace.tracePath;
|
|
@@ -11458,7 +11655,7 @@ var getPointAtTraceDistance = (trace, distance7) => {
|
|
|
11458
11655
|
const end = trace.tracePath[i + 1];
|
|
11459
11656
|
const segmentLength = getManhattanDistance(start, end);
|
|
11460
11657
|
const nextDistance = pathDistance + segmentLength;
|
|
11461
|
-
if (distance7 <= nextDistance +
|
|
11658
|
+
if (distance7 <= nextDistance + EPS15) {
|
|
11462
11659
|
const offset = Math.max(
|
|
11463
11660
|
0,
|
|
11464
11661
|
Math.min(segmentLength, distance7 - pathDistance)
|
|
@@ -11497,7 +11694,7 @@ var segmentCrossesBoundsInterior2 = (start, end, bounds) => {
|
|
|
11497
11694
|
return false;
|
|
11498
11695
|
}
|
|
11499
11696
|
if (isVertical4(start, end)) {
|
|
11500
|
-
if (start.x <= interior.minX +
|
|
11697
|
+
if (start.x <= interior.minX + EPS15 || start.x >= interior.maxX - EPS15) {
|
|
11501
11698
|
return false;
|
|
11502
11699
|
}
|
|
11503
11700
|
return rangesOverlap2(
|
|
@@ -11508,7 +11705,7 @@ var segmentCrossesBoundsInterior2 = (start, end, bounds) => {
|
|
|
11508
11705
|
);
|
|
11509
11706
|
}
|
|
11510
11707
|
if (isHorizontal3(start, end)) {
|
|
11511
|
-
if (start.y <= interior.minY +
|
|
11708
|
+
if (start.y <= interior.minY + EPS15 || start.y >= interior.maxY - EPS15) {
|
|
11512
11709
|
return false;
|
|
11513
11710
|
}
|
|
11514
11711
|
return rangesOverlap2(
|
|
@@ -11522,10 +11719,10 @@ var segmentCrossesBoundsInterior2 = (start, end, bounds) => {
|
|
|
11522
11719
|
};
|
|
11523
11720
|
var isPointOnSegment2 = (point, start, end) => {
|
|
11524
11721
|
if (isHorizontal3(start, end)) {
|
|
11525
|
-
return Math.abs(point.y - start.y) <=
|
|
11722
|
+
return Math.abs(point.y - start.y) <= EPS15 && point.x >= Math.min(start.x, end.x) - EPS15 && point.x <= Math.max(start.x, end.x) + EPS15;
|
|
11526
11723
|
}
|
|
11527
11724
|
if (isVertical4(start, end)) {
|
|
11528
|
-
return Math.abs(point.x - start.x) <=
|
|
11725
|
+
return Math.abs(point.x - start.x) <= EPS15 && point.y >= Math.min(start.y, end.y) - EPS15 && point.y <= Math.max(start.y, end.y) + EPS15;
|
|
11529
11726
|
}
|
|
11530
11727
|
return false;
|
|
11531
11728
|
};
|
|
@@ -11533,9 +11730,9 @@ var getSegmentDirection = (start, end) => ({
|
|
|
11533
11730
|
x: isVertical4(start, end) ? 0 : Math.sign(end.x - start.x),
|
|
11534
11731
|
y: isHorizontal3(start, end) ? 0 : Math.sign(end.y - start.y)
|
|
11535
11732
|
});
|
|
11536
|
-
var isHorizontal3 = (start, end) => Math.abs(start.y - end.y) <=
|
|
11537
|
-
var isVertical4 = (start, end) => Math.abs(start.x - end.x) <=
|
|
11538
|
-
var rangesOverlap2 = (minA, maxA, minB, maxB) => Math.min(maxA, maxB) - Math.max(minA, minB) >
|
|
11733
|
+
var isHorizontal3 = (start, end) => Math.abs(start.y - end.y) <= EPS15;
|
|
11734
|
+
var isVertical4 = (start, end) => Math.abs(start.x - end.x) <= EPS15;
|
|
11735
|
+
var rangesOverlap2 = (minA, maxA, minB, maxB) => Math.min(maxA, maxB) - Math.max(minA, minB) > EPS15;
|
|
11539
11736
|
var getUniquePinCount2 = (pinIds) => new Set(pinIds).size;
|
|
11540
11737
|
|
|
11541
11738
|
// lib/solvers/TraceAnchoredNetLabelOverlapSolver/candidates.ts
|
|
@@ -11592,7 +11789,7 @@ var getCandidateDistances = (traceLength, vertexDistances) => {
|
|
|
11592
11789
|
for (const distance7 of vertexDistances) {
|
|
11593
11790
|
distances.add(roundDistance(distance7));
|
|
11594
11791
|
}
|
|
11595
|
-
return [...distances].filter((distance7) => distance7 >= -
|
|
11792
|
+
return [...distances].filter((distance7) => distance7 >= -EPS15 && distance7 <= traceLength + EPS15).sort((a, b) => a - b);
|
|
11596
11793
|
};
|
|
11597
11794
|
var getOrientationsForPoint = (params) => {
|
|
11598
11795
|
const { inputProblem, label, point, orientationConstraint } = params;
|
|
@@ -11681,13 +11878,13 @@ var getOutwardOrientationOptions = (point, chipBounds) => {
|
|
|
11681
11878
|
};
|
|
11682
11879
|
var getOutwardAxisOption = (params) => {
|
|
11683
11880
|
const { value, min, max, center, positiveOrientation, negativeOrientation } = params;
|
|
11684
|
-
if (value > max +
|
|
11881
|
+
if (value > max + EPS15) {
|
|
11685
11882
|
return {
|
|
11686
11883
|
orientation: positiveOrientation,
|
|
11687
11884
|
outwardScore: 1 + value - max
|
|
11688
11885
|
};
|
|
11689
11886
|
}
|
|
11690
|
-
if (value < min -
|
|
11887
|
+
if (value < min - EPS15) {
|
|
11691
11888
|
return {
|
|
11692
11889
|
orientation: negativeOrientation,
|
|
11693
11890
|
outwardScore: 1 + min - value
|
|
@@ -11698,7 +11895,7 @@ var getOutwardAxisOption = (params) => {
|
|
|
11698
11895
|
outwardScore: getNormalizedCenterDistance(value, center, max - min)
|
|
11699
11896
|
};
|
|
11700
11897
|
};
|
|
11701
|
-
var getNormalizedCenterDistance = (value, center, span) => Math.abs(value - center) / Math.max(
|
|
11898
|
+
var getNormalizedCenterDistance = (value, center, span) => Math.abs(value - center) / Math.max(EPS15, span / 2);
|
|
11702
11899
|
var ALL_ORIENTATIONS = ["x+", "x-", "y+", "y-"];
|
|
11703
11900
|
var getFlippedOrientation = (orientation) => {
|
|
11704
11901
|
switch (orientation) {
|
|
@@ -11766,7 +11963,7 @@ var getNetLabelHeight = (inputProblem, label) => {
|
|
|
11766
11963
|
)?.netLabelHeight;
|
|
11767
11964
|
};
|
|
11768
11965
|
var roundDistance = (distance7) => Number(distance7.toFixed(6));
|
|
11769
|
-
var isSamePlacement = (label, point, orientation) => Math.abs(point.x - label.anchorPoint.x) <=
|
|
11966
|
+
var isSamePlacement = (label, point, orientation) => Math.abs(point.x - label.anchorPoint.x) <= EPS15 && Math.abs(point.y - label.anchorPoint.y) <= EPS15 && orientation === label.orientation;
|
|
11770
11967
|
|
|
11771
11968
|
// lib/solvers/TraceAnchoredNetLabelOverlapSolver/visualize.ts
|
|
11772
11969
|
var CANDIDATE_SELECTED_COLOR4 = "blue";
|
|
@@ -13275,7 +13472,7 @@ var UnroutedTraceRecoverySolver = class extends BaseSolver {
|
|
|
13275
13472
|
};
|
|
13276
13473
|
|
|
13277
13474
|
// lib/solvers/SameNetJunctionAlignmentSolver/alignSameNetJunctions.ts
|
|
13278
|
-
import { getSegmentIntersection as
|
|
13475
|
+
import { getSegmentIntersection as getSegmentIntersection4 } from "@tscircuit/math-utils/line-intersections";
|
|
13279
13476
|
|
|
13280
13477
|
// lib/solvers/SameNetJunctionAlignmentSolver/pathIntersectsAnyNetLabel.ts
|
|
13281
13478
|
var NET_LABEL_INTERIOR_INSET = 1e-6;
|
|
@@ -13594,6 +13791,242 @@ var collapseRedundantSharedEndpointStubs = ({
|
|
|
13594
13791
|
return outputTraces;
|
|
13595
13792
|
};
|
|
13596
13793
|
|
|
13794
|
+
// lib/solvers/SameNetJunctionAlignmentSolver/collapseSameNetCycles.ts
|
|
13795
|
+
import { getSegmentIntersection as getSegmentIntersection3 } from "@tscircuit/math-utils/line-intersections";
|
|
13796
|
+
var TRACE_LENGTH_EPSILON = 1e-6;
|
|
13797
|
+
var getTracePathStartingAtPin = (trace, pin) => {
|
|
13798
|
+
const pathStart = trace.tracePath[0];
|
|
13799
|
+
const pathEnd = trace.tracePath.at(-1);
|
|
13800
|
+
if (!pathStart || !pathEnd) return null;
|
|
13801
|
+
if (pointsEqual2(pathStart, pin)) return trace.tracePath;
|
|
13802
|
+
if (pointsEqual2(pathEnd, pin)) return [...trace.tracePath].reverse();
|
|
13803
|
+
return null;
|
|
13804
|
+
};
|
|
13805
|
+
var getPerpendicularPathCrossings = (targetPath, donorPath) => {
|
|
13806
|
+
const crossings = [];
|
|
13807
|
+
const sharedEndpoint = targetPath[0];
|
|
13808
|
+
for (let targetSegmentIndex = 0; targetSegmentIndex < targetPath.length - 1; targetSegmentIndex++) {
|
|
13809
|
+
const targetStart = targetPath[targetSegmentIndex];
|
|
13810
|
+
const targetEnd = targetPath[targetSegmentIndex + 1];
|
|
13811
|
+
const targetOrientation = getRailOrientation(targetStart, targetEnd);
|
|
13812
|
+
if (!targetOrientation) continue;
|
|
13813
|
+
for (let donorSegmentIndex = 0; donorSegmentIndex < donorPath.length - 1; donorSegmentIndex++) {
|
|
13814
|
+
const donorStart = donorPath[donorSegmentIndex];
|
|
13815
|
+
const donorEnd = donorPath[donorSegmentIndex + 1];
|
|
13816
|
+
const donorOrientation = getRailOrientation(donorStart, donorEnd);
|
|
13817
|
+
if (!donorOrientation || donorOrientation === targetOrientation) continue;
|
|
13818
|
+
const intersectionPoint = getSegmentIntersection3(
|
|
13819
|
+
targetStart,
|
|
13820
|
+
targetEnd,
|
|
13821
|
+
donorStart,
|
|
13822
|
+
donorEnd
|
|
13823
|
+
);
|
|
13824
|
+
if (!intersectionPoint || pointsEqual2(intersectionPoint, sharedEndpoint)) {
|
|
13825
|
+
continue;
|
|
13826
|
+
}
|
|
13827
|
+
crossings.push({
|
|
13828
|
+
intersectionPoint,
|
|
13829
|
+
targetSegmentIndex,
|
|
13830
|
+
donorSegmentIndex
|
|
13831
|
+
});
|
|
13832
|
+
}
|
|
13833
|
+
}
|
|
13834
|
+
return crossings;
|
|
13835
|
+
};
|
|
13836
|
+
var buildCollapsedSelfCyclePath = (path, firstSegmentIndex, secondSegmentIndex) => {
|
|
13837
|
+
const intersectionPoint = getSegmentIntersection3(
|
|
13838
|
+
path[firstSegmentIndex],
|
|
13839
|
+
path[firstSegmentIndex + 1],
|
|
13840
|
+
path[secondSegmentIndex],
|
|
13841
|
+
path[secondSegmentIndex + 1]
|
|
13842
|
+
);
|
|
13843
|
+
if (!intersectionPoint) return path;
|
|
13844
|
+
return simplifyPath([
|
|
13845
|
+
...path.slice(0, firstSegmentIndex + 1),
|
|
13846
|
+
intersectionPoint,
|
|
13847
|
+
...path.slice(secondSegmentIndex + 1)
|
|
13848
|
+
]);
|
|
13849
|
+
};
|
|
13850
|
+
var buildCollapsedCyclePath = ({
|
|
13851
|
+
targetTrace,
|
|
13852
|
+
targetPath,
|
|
13853
|
+
donorPath,
|
|
13854
|
+
crossing
|
|
13855
|
+
}) => {
|
|
13856
|
+
const pathFromSharedPin = simplifyPath([
|
|
13857
|
+
...donorPath.slice(0, crossing.donorSegmentIndex + 1),
|
|
13858
|
+
crossing.intersectionPoint,
|
|
13859
|
+
...targetPath.slice(crossing.targetSegmentIndex + 1)
|
|
13860
|
+
]);
|
|
13861
|
+
if (pointsEqual2(targetTrace.tracePath[0], targetPath[0])) {
|
|
13862
|
+
return pathFromSharedPin;
|
|
13863
|
+
}
|
|
13864
|
+
return pathFromSharedPin.reverse();
|
|
13865
|
+
};
|
|
13866
|
+
var getNetLabelPlacementsForCycleCollapse = ({
|
|
13867
|
+
targetTrace,
|
|
13868
|
+
tracePath,
|
|
13869
|
+
netLabelPlacements
|
|
13870
|
+
}) => {
|
|
13871
|
+
const candidateNetLabelPlacements = moveAttachedLabelsToReroutedTrace({
|
|
13872
|
+
trace: targetTrace,
|
|
13873
|
+
originalTracePath: targetTrace.tracePath,
|
|
13874
|
+
reroutedTracePath: tracePath,
|
|
13875
|
+
netLabelPlacements
|
|
13876
|
+
});
|
|
13877
|
+
for (let labelIndex = 0; labelIndex < netLabelPlacements.length; labelIndex++) {
|
|
13878
|
+
const label = netLabelPlacements[labelIndex];
|
|
13879
|
+
if (label.globalConnNetId !== targetTrace.globalConnNetId) continue;
|
|
13880
|
+
if (!tracePathContainsPoint(targetTrace.tracePath, label.anchorPoint)) {
|
|
13881
|
+
continue;
|
|
13882
|
+
}
|
|
13883
|
+
const candidateLabel = candidateNetLabelPlacements[labelIndex];
|
|
13884
|
+
if (!tracePathContainsPoint(tracePath, candidateLabel.anchorPoint)) {
|
|
13885
|
+
return null;
|
|
13886
|
+
}
|
|
13887
|
+
}
|
|
13888
|
+
const otherNetLabelPlacements = candidateNetLabelPlacements.filter(
|
|
13889
|
+
(label) => label.globalConnNetId !== targetTrace.globalConnNetId
|
|
13890
|
+
);
|
|
13891
|
+
if (pathIntersectsAnyNetLabel({
|
|
13892
|
+
path: tracePath,
|
|
13893
|
+
netLabelPlacements: otherNetLabelPlacements
|
|
13894
|
+
})) {
|
|
13895
|
+
return null;
|
|
13896
|
+
}
|
|
13897
|
+
const sameNetLabelPlacements = candidateNetLabelPlacements.filter(
|
|
13898
|
+
(label) => label.globalConnNetId === targetTrace.globalConnNetId
|
|
13899
|
+
);
|
|
13900
|
+
if (pathEntersAnyNetLabel({
|
|
13901
|
+
path: tracePath,
|
|
13902
|
+
netLabelPlacements: sameNetLabelPlacements
|
|
13903
|
+
})) {
|
|
13904
|
+
return null;
|
|
13905
|
+
}
|
|
13906
|
+
return candidateNetLabelPlacements;
|
|
13907
|
+
};
|
|
13908
|
+
var candidateIsBetter = (candidate, bestCandidate) => {
|
|
13909
|
+
if (!bestCandidate) return true;
|
|
13910
|
+
const visibleLengthDelta = candidate.netVisibleLength - bestCandidate.netVisibleLength;
|
|
13911
|
+
if (Math.abs(visibleLengthDelta) > TRACE_LENGTH_EPSILON) {
|
|
13912
|
+
return visibleLengthDelta < 0;
|
|
13913
|
+
}
|
|
13914
|
+
return candidate.netVisibleSegmentCount < bestCandidate.netVisibleSegmentCount;
|
|
13915
|
+
};
|
|
13916
|
+
var getBestCycleCollapseCandidate = ({
|
|
13917
|
+
targetTrace,
|
|
13918
|
+
traces,
|
|
13919
|
+
netLabelPlacements
|
|
13920
|
+
}) => {
|
|
13921
|
+
const sameNetTraces = traces.filter(
|
|
13922
|
+
(trace) => trace.globalConnNetId === targetTrace.globalConnNetId
|
|
13923
|
+
);
|
|
13924
|
+
const baselineNetVisibleLength = getVisibleTraceLength(sameNetTraces);
|
|
13925
|
+
const baselineTargetVisibleLength = getVisibleTraceLength([targetTrace]);
|
|
13926
|
+
let bestCandidate = null;
|
|
13927
|
+
const considerTracePath = (tracePath) => {
|
|
13928
|
+
const candidateTrace = { ...targetTrace, tracePath };
|
|
13929
|
+
const candidateTargetVisibleLength = getVisibleTraceLength([candidateTrace]);
|
|
13930
|
+
if (candidateTargetVisibleLength > baselineTargetVisibleLength + TRACE_LENGTH_EPSILON) {
|
|
13931
|
+
return;
|
|
13932
|
+
}
|
|
13933
|
+
const candidateNetLabelPlacements = getNetLabelPlacementsForCycleCollapse({
|
|
13934
|
+
targetTrace,
|
|
13935
|
+
tracePath,
|
|
13936
|
+
netLabelPlacements
|
|
13937
|
+
});
|
|
13938
|
+
if (!candidateNetLabelPlacements) return;
|
|
13939
|
+
const candidateNetTraces = sameNetTraces.map((trace) => {
|
|
13940
|
+
if (trace.mspPairId === targetTrace.mspPairId) return candidateTrace;
|
|
13941
|
+
return trace;
|
|
13942
|
+
});
|
|
13943
|
+
const netVisibleLength = getVisibleTraceLength(candidateNetTraces);
|
|
13944
|
+
if (netVisibleLength >= baselineNetVisibleLength - TRACE_LENGTH_EPSILON) {
|
|
13945
|
+
return;
|
|
13946
|
+
}
|
|
13947
|
+
const candidate = {
|
|
13948
|
+
tracePath,
|
|
13949
|
+
netLabelPlacements: candidateNetLabelPlacements,
|
|
13950
|
+
netVisibleLength,
|
|
13951
|
+
netVisibleSegmentCount: getVisibleTraceSegmentCount(candidateNetTraces)
|
|
13952
|
+
};
|
|
13953
|
+
if (candidateIsBetter(candidate, bestCandidate)) {
|
|
13954
|
+
bestCandidate = candidate;
|
|
13955
|
+
}
|
|
13956
|
+
};
|
|
13957
|
+
const selfCrossings = findPerpendicularPathCrossings(
|
|
13958
|
+
targetTrace.tracePath,
|
|
13959
|
+
targetTrace.tracePath,
|
|
13960
|
+
{ includeTerminalSegments: true }
|
|
13961
|
+
).filter(
|
|
13962
|
+
({ pathSegmentIndex, otherPathSegmentIndex }) => pathSegmentIndex < otherPathSegmentIndex
|
|
13963
|
+
);
|
|
13964
|
+
for (const crossing of selfCrossings) {
|
|
13965
|
+
considerTracePath(
|
|
13966
|
+
buildCollapsedSelfCyclePath(
|
|
13967
|
+
targetTrace.tracePath,
|
|
13968
|
+
crossing.pathSegmentIndex,
|
|
13969
|
+
crossing.otherPathSegmentIndex
|
|
13970
|
+
)
|
|
13971
|
+
);
|
|
13972
|
+
}
|
|
13973
|
+
for (const donorTrace of sameNetTraces) {
|
|
13974
|
+
if (donorTrace.mspPairId === targetTrace.mspPairId) continue;
|
|
13975
|
+
const sharedPin = getSharedPin({
|
|
13976
|
+
donorTrace,
|
|
13977
|
+
branchTrace: targetTrace
|
|
13978
|
+
});
|
|
13979
|
+
if (!sharedPin) continue;
|
|
13980
|
+
const targetPath = getTracePathStartingAtPin(targetTrace, sharedPin);
|
|
13981
|
+
const donorPath = getTracePathStartingAtPin(donorTrace, sharedPin);
|
|
13982
|
+
if (!targetPath || !donorPath) continue;
|
|
13983
|
+
const crossings = getPerpendicularPathCrossings(targetPath, donorPath);
|
|
13984
|
+
for (const crossing of crossings) {
|
|
13985
|
+
const tracePath = buildCollapsedCyclePath({
|
|
13986
|
+
targetTrace,
|
|
13987
|
+
targetPath,
|
|
13988
|
+
donorPath,
|
|
13989
|
+
crossing
|
|
13990
|
+
});
|
|
13991
|
+
considerTracePath(tracePath);
|
|
13992
|
+
}
|
|
13993
|
+
}
|
|
13994
|
+
return bestCandidate;
|
|
13995
|
+
};
|
|
13996
|
+
var collapseSameNetCycles = ({
|
|
13997
|
+
traces,
|
|
13998
|
+
netLabelPlacements
|
|
13999
|
+
}) => {
|
|
14000
|
+
const outputTraces = [...traces];
|
|
14001
|
+
let outputNetLabelPlacements = [...netLabelPlacements];
|
|
14002
|
+
let collapsedCycleCount = 0;
|
|
14003
|
+
let traceIndex = 0;
|
|
14004
|
+
while (traceIndex < outputTraces.length) {
|
|
14005
|
+
const targetTrace = outputTraces[traceIndex];
|
|
14006
|
+
const candidate = getBestCycleCollapseCandidate({
|
|
14007
|
+
targetTrace,
|
|
14008
|
+
traces: outputTraces,
|
|
14009
|
+
netLabelPlacements: outputNetLabelPlacements
|
|
14010
|
+
});
|
|
14011
|
+
if (!candidate) {
|
|
14012
|
+
traceIndex++;
|
|
14013
|
+
continue;
|
|
14014
|
+
}
|
|
14015
|
+
outputTraces[traceIndex] = {
|
|
14016
|
+
...targetTrace,
|
|
14017
|
+
tracePath: candidate.tracePath
|
|
14018
|
+
};
|
|
14019
|
+
outputNetLabelPlacements = candidate.netLabelPlacements;
|
|
14020
|
+
collapsedCycleCount++;
|
|
14021
|
+
traceIndex = 0;
|
|
14022
|
+
}
|
|
14023
|
+
return {
|
|
14024
|
+
traces: outputTraces,
|
|
14025
|
+
netLabelPlacements: outputNetLabelPlacements,
|
|
14026
|
+
collapsedCycleCount
|
|
14027
|
+
};
|
|
14028
|
+
};
|
|
14029
|
+
|
|
13597
14030
|
// lib/solvers/SameNetJunctionAlignmentSolver/alignSameNetJunctions.ts
|
|
13598
14031
|
var MAX_ALIGNED_LOAD_PIN_OFFSET = 0.2;
|
|
13599
14032
|
var MAX_SAME_NET_LABEL_BOUNDARY_RAIL_OFFSET = 0.2;
|
|
@@ -13978,7 +14411,7 @@ var pathsIntersect = (firstPath, secondPath) => {
|
|
|
13978
14411
|
}
|
|
13979
14412
|
for (let firstIndex = 1; firstIndex < firstPath.length; firstIndex++) {
|
|
13980
14413
|
for (let secondIndex = 1; secondIndex < secondPath.length; secondIndex++) {
|
|
13981
|
-
if (
|
|
14414
|
+
if (getSegmentIntersection4(
|
|
13982
14415
|
firstPath[firstIndex - 1],
|
|
13983
14416
|
firstPath[firstIndex],
|
|
13984
14417
|
secondPath[secondIndex - 1],
|
|
@@ -14162,7 +14595,7 @@ var candidateIsClear = ({
|
|
|
14162
14595
|
const intersections2 = /* @__PURE__ */ new Set();
|
|
14163
14596
|
for (let i = 1; i < path.length; i++) {
|
|
14164
14597
|
for (let j = 1; j < otherTrace.tracePath.length; j++) {
|
|
14165
|
-
const point =
|
|
14598
|
+
const point = getSegmentIntersection4(
|
|
14166
14599
|
path[i - 1],
|
|
14167
14600
|
path[i],
|
|
14168
14601
|
otherTrace.tracePath[j - 1],
|
|
@@ -14445,225 +14878,22 @@ var alignSameNetJunctions = ({
|
|
|
14445
14878
|
}
|
|
14446
14879
|
}
|
|
14447
14880
|
}
|
|
14448
|
-
const
|
|
14881
|
+
const cycleCollapse = collapseSameNetCycles({
|
|
14449
14882
|
traces: outputTraces,
|
|
14450
|
-
netLabelPlacements: outputNetLabelPlacements
|
|
14883
|
+
netLabelPlacements: outputNetLabelPlacements
|
|
14884
|
+
});
|
|
14885
|
+
outputTraces = collapseRedundantSharedEndpointStubs({
|
|
14886
|
+
traces: cycleCollapse.traces,
|
|
14887
|
+
netLabelPlacements: cycleCollapse.netLabelPlacements,
|
|
14451
14888
|
netLabelConnectorTraceIds,
|
|
14452
14889
|
multiPinNetPinIds: getMultiPinNetPinIds(inputProblem)
|
|
14453
14890
|
});
|
|
14454
|
-
|
|
14891
|
+
outputNetLabelPlacements = cycleCollapse.netLabelPlacements;
|
|
14455
14892
|
return {
|
|
14456
14893
|
traces: outputTraces,
|
|
14457
14894
|
netLabelPlacements: outputNetLabelPlacements,
|
|
14458
|
-
alignedJunctionCount
|
|
14459
|
-
|
|
14460
|
-
};
|
|
14461
|
-
|
|
14462
|
-
// lib/solvers/SameNetJunctionAlignmentSolver/collapseSameNetCycles.ts
|
|
14463
|
-
import { getSegmentIntersection as getSegmentIntersection4 } from "@tscircuit/math-utils/line-intersections";
|
|
14464
|
-
var TRACE_LENGTH_EPSILON = 1e-6;
|
|
14465
|
-
var getTracePathStartingAtPin = (trace, pin) => {
|
|
14466
|
-
const pathStart = trace.tracePath[0];
|
|
14467
|
-
const pathEnd = trace.tracePath.at(-1);
|
|
14468
|
-
if (!pathStart || !pathEnd) return null;
|
|
14469
|
-
if (pointsEqual2(pathStart, pin)) return trace.tracePath;
|
|
14470
|
-
if (pointsEqual2(pathEnd, pin)) return [...trace.tracePath].reverse();
|
|
14471
|
-
return null;
|
|
14472
|
-
};
|
|
14473
|
-
var getPerpendicularPathCrossings = (targetPath, donorPath) => {
|
|
14474
|
-
const crossings = [];
|
|
14475
|
-
const sharedEndpoint = targetPath[0];
|
|
14476
|
-
for (let targetSegmentIndex = 0; targetSegmentIndex < targetPath.length - 1; targetSegmentIndex++) {
|
|
14477
|
-
const targetStart = targetPath[targetSegmentIndex];
|
|
14478
|
-
const targetEnd = targetPath[targetSegmentIndex + 1];
|
|
14479
|
-
const targetOrientation = getRailOrientation(targetStart, targetEnd);
|
|
14480
|
-
if (!targetOrientation) continue;
|
|
14481
|
-
for (let donorSegmentIndex = 0; donorSegmentIndex < donorPath.length - 1; donorSegmentIndex++) {
|
|
14482
|
-
const donorStart = donorPath[donorSegmentIndex];
|
|
14483
|
-
const donorEnd = donorPath[donorSegmentIndex + 1];
|
|
14484
|
-
const donorOrientation = getRailOrientation(donorStart, donorEnd);
|
|
14485
|
-
if (!donorOrientation || donorOrientation === targetOrientation) continue;
|
|
14486
|
-
const intersectionPoint = getSegmentIntersection4(
|
|
14487
|
-
targetStart,
|
|
14488
|
-
targetEnd,
|
|
14489
|
-
donorStart,
|
|
14490
|
-
donorEnd
|
|
14491
|
-
);
|
|
14492
|
-
if (!intersectionPoint || pointsEqual2(intersectionPoint, sharedEndpoint)) {
|
|
14493
|
-
continue;
|
|
14494
|
-
}
|
|
14495
|
-
crossings.push({
|
|
14496
|
-
intersectionPoint,
|
|
14497
|
-
targetSegmentIndex,
|
|
14498
|
-
donorSegmentIndex
|
|
14499
|
-
});
|
|
14500
|
-
}
|
|
14501
|
-
}
|
|
14502
|
-
return crossings;
|
|
14503
|
-
};
|
|
14504
|
-
var buildCollapsedCyclePath = ({
|
|
14505
|
-
targetTrace,
|
|
14506
|
-
targetPath,
|
|
14507
|
-
donorPath,
|
|
14508
|
-
crossing
|
|
14509
|
-
}) => {
|
|
14510
|
-
const pathFromSharedPin = simplifyPath([
|
|
14511
|
-
...donorPath.slice(0, crossing.donorSegmentIndex + 1),
|
|
14512
|
-
crossing.intersectionPoint,
|
|
14513
|
-
...targetPath.slice(crossing.targetSegmentIndex + 1)
|
|
14514
|
-
]);
|
|
14515
|
-
if (pointsEqual2(targetTrace.tracePath[0], targetPath[0])) {
|
|
14516
|
-
return pathFromSharedPin;
|
|
14517
|
-
}
|
|
14518
|
-
return pathFromSharedPin.reverse();
|
|
14519
|
-
};
|
|
14520
|
-
var getNetLabelPlacementsForCycleCollapse = ({
|
|
14521
|
-
targetTrace,
|
|
14522
|
-
tracePath,
|
|
14523
|
-
netLabelPlacements
|
|
14524
|
-
}) => {
|
|
14525
|
-
const candidateNetLabelPlacements = moveAttachedLabelsToReroutedTrace({
|
|
14526
|
-
trace: targetTrace,
|
|
14527
|
-
originalTracePath: targetTrace.tracePath,
|
|
14528
|
-
reroutedTracePath: tracePath,
|
|
14529
|
-
netLabelPlacements
|
|
14530
|
-
});
|
|
14531
|
-
for (let labelIndex = 0; labelIndex < netLabelPlacements.length; labelIndex++) {
|
|
14532
|
-
const label = netLabelPlacements[labelIndex];
|
|
14533
|
-
if (label.globalConnNetId !== targetTrace.globalConnNetId) continue;
|
|
14534
|
-
if (!tracePathContainsPoint(targetTrace.tracePath, label.anchorPoint)) {
|
|
14535
|
-
continue;
|
|
14536
|
-
}
|
|
14537
|
-
const candidateLabel = candidateNetLabelPlacements[labelIndex];
|
|
14538
|
-
if (!tracePathContainsPoint(tracePath, candidateLabel.anchorPoint)) {
|
|
14539
|
-
return null;
|
|
14540
|
-
}
|
|
14541
|
-
}
|
|
14542
|
-
const otherNetLabelPlacements = candidateNetLabelPlacements.filter(
|
|
14543
|
-
(label) => label.globalConnNetId !== targetTrace.globalConnNetId
|
|
14544
|
-
);
|
|
14545
|
-
if (pathIntersectsAnyNetLabel({
|
|
14546
|
-
path: tracePath,
|
|
14547
|
-
netLabelPlacements: otherNetLabelPlacements
|
|
14548
|
-
})) {
|
|
14549
|
-
return null;
|
|
14550
|
-
}
|
|
14551
|
-
const sameNetLabelPlacements = candidateNetLabelPlacements.filter(
|
|
14552
|
-
(label) => label.globalConnNetId === targetTrace.globalConnNetId
|
|
14553
|
-
);
|
|
14554
|
-
if (pathEntersAnyNetLabel({
|
|
14555
|
-
path: tracePath,
|
|
14556
|
-
netLabelPlacements: sameNetLabelPlacements
|
|
14557
|
-
})) {
|
|
14558
|
-
return null;
|
|
14559
|
-
}
|
|
14560
|
-
return candidateNetLabelPlacements;
|
|
14561
|
-
};
|
|
14562
|
-
var candidateIsBetter = (candidate, bestCandidate) => {
|
|
14563
|
-
if (!bestCandidate) return true;
|
|
14564
|
-
const visibleLengthDelta = candidate.netVisibleLength - bestCandidate.netVisibleLength;
|
|
14565
|
-
if (Math.abs(visibleLengthDelta) > TRACE_LENGTH_EPSILON) {
|
|
14566
|
-
return visibleLengthDelta < 0;
|
|
14567
|
-
}
|
|
14568
|
-
return candidate.netVisibleSegmentCount < bestCandidate.netVisibleSegmentCount;
|
|
14569
|
-
};
|
|
14570
|
-
var getBestCycleCollapseCandidate = ({
|
|
14571
|
-
targetTrace,
|
|
14572
|
-
traces,
|
|
14573
|
-
netLabelPlacements
|
|
14574
|
-
}) => {
|
|
14575
|
-
const sameNetTraces = traces.filter(
|
|
14576
|
-
(trace) => trace.globalConnNetId === targetTrace.globalConnNetId
|
|
14577
|
-
);
|
|
14578
|
-
const baselineNetVisibleLength = getVisibleTraceLength(sameNetTraces);
|
|
14579
|
-
const baselineTargetVisibleLength = getVisibleTraceLength([targetTrace]);
|
|
14580
|
-
let bestCandidate = null;
|
|
14581
|
-
for (const donorTrace of sameNetTraces) {
|
|
14582
|
-
if (donorTrace.mspPairId === targetTrace.mspPairId) continue;
|
|
14583
|
-
const sharedPin = getSharedPin({
|
|
14584
|
-
donorTrace,
|
|
14585
|
-
branchTrace: targetTrace
|
|
14586
|
-
});
|
|
14587
|
-
if (!sharedPin) continue;
|
|
14588
|
-
const targetPath = getTracePathStartingAtPin(targetTrace, sharedPin);
|
|
14589
|
-
const donorPath = getTracePathStartingAtPin(donorTrace, sharedPin);
|
|
14590
|
-
if (!targetPath || !donorPath) continue;
|
|
14591
|
-
const crossings = getPerpendicularPathCrossings(targetPath, donorPath);
|
|
14592
|
-
for (const crossing of crossings) {
|
|
14593
|
-
const tracePath = buildCollapsedCyclePath({
|
|
14594
|
-
targetTrace,
|
|
14595
|
-
targetPath,
|
|
14596
|
-
donorPath,
|
|
14597
|
-
crossing
|
|
14598
|
-
});
|
|
14599
|
-
const candidateTrace = { ...targetTrace, tracePath };
|
|
14600
|
-
const candidateTargetVisibleLength = getVisibleTraceLength([
|
|
14601
|
-
candidateTrace
|
|
14602
|
-
]);
|
|
14603
|
-
if (candidateTargetVisibleLength > baselineTargetVisibleLength + TRACE_LENGTH_EPSILON) {
|
|
14604
|
-
continue;
|
|
14605
|
-
}
|
|
14606
|
-
const candidateNetLabelPlacements = getNetLabelPlacementsForCycleCollapse(
|
|
14607
|
-
{
|
|
14608
|
-
targetTrace,
|
|
14609
|
-
tracePath,
|
|
14610
|
-
netLabelPlacements
|
|
14611
|
-
}
|
|
14612
|
-
);
|
|
14613
|
-
if (!candidateNetLabelPlacements) continue;
|
|
14614
|
-
const candidateNetTraces = sameNetTraces.map((trace) => {
|
|
14615
|
-
if (trace.mspPairId === targetTrace.mspPairId) return candidateTrace;
|
|
14616
|
-
return trace;
|
|
14617
|
-
});
|
|
14618
|
-
const netVisibleLength = getVisibleTraceLength(candidateNetTraces);
|
|
14619
|
-
if (netVisibleLength >= baselineNetVisibleLength - TRACE_LENGTH_EPSILON) {
|
|
14620
|
-
continue;
|
|
14621
|
-
}
|
|
14622
|
-
const netVisibleSegmentCount = getVisibleTraceSegmentCount(candidateNetTraces);
|
|
14623
|
-
const candidate = {
|
|
14624
|
-
tracePath,
|
|
14625
|
-
netLabelPlacements: candidateNetLabelPlacements,
|
|
14626
|
-
netVisibleLength,
|
|
14627
|
-
netVisibleSegmentCount
|
|
14628
|
-
};
|
|
14629
|
-
if (candidateIsBetter(candidate, bestCandidate)) {
|
|
14630
|
-
bestCandidate = candidate;
|
|
14631
|
-
}
|
|
14632
|
-
}
|
|
14633
|
-
}
|
|
14634
|
-
return bestCandidate;
|
|
14635
|
-
};
|
|
14636
|
-
var collapseSameNetCycles = ({
|
|
14637
|
-
traces,
|
|
14638
|
-
netLabelPlacements
|
|
14639
|
-
}) => {
|
|
14640
|
-
const outputTraces = [...traces];
|
|
14641
|
-
let outputNetLabelPlacements = [...netLabelPlacements];
|
|
14642
|
-
let collapsedCycleCount = 0;
|
|
14643
|
-
let traceIndex = 0;
|
|
14644
|
-
while (traceIndex < outputTraces.length) {
|
|
14645
|
-
const targetTrace = outputTraces[traceIndex];
|
|
14646
|
-
const candidate = getBestCycleCollapseCandidate({
|
|
14647
|
-
targetTrace,
|
|
14648
|
-
traces: outputTraces,
|
|
14649
|
-
netLabelPlacements: outputNetLabelPlacements
|
|
14650
|
-
});
|
|
14651
|
-
if (!candidate) {
|
|
14652
|
-
traceIndex++;
|
|
14653
|
-
continue;
|
|
14654
|
-
}
|
|
14655
|
-
outputTraces[traceIndex] = {
|
|
14656
|
-
...targetTrace,
|
|
14657
|
-
tracePath: candidate.tracePath
|
|
14658
|
-
};
|
|
14659
|
-
outputNetLabelPlacements = candidate.netLabelPlacements;
|
|
14660
|
-
collapsedCycleCount++;
|
|
14661
|
-
traceIndex = 0;
|
|
14662
|
-
}
|
|
14663
|
-
return {
|
|
14664
|
-
traces: outputTraces,
|
|
14665
|
-
netLabelPlacements: outputNetLabelPlacements,
|
|
14666
|
-
collapsedCycleCount
|
|
14895
|
+
alignedJunctionCount,
|
|
14896
|
+
collapsedCycleCount: cycleCollapse.collapsedCycleCount
|
|
14667
14897
|
};
|
|
14668
14898
|
};
|
|
14669
14899
|
|
|
@@ -14776,18 +15006,14 @@ var SameNetJunctionAlignmentSolver = class extends BaseSolver {
|
|
|
14776
15006
|
}
|
|
14777
15007
|
_step() {
|
|
14778
15008
|
const alignment = alignSameNetJunctions(this.input);
|
|
14779
|
-
|
|
14780
|
-
traces: alignment.traces,
|
|
14781
|
-
netLabelPlacements: alignment.netLabelPlacements
|
|
14782
|
-
});
|
|
14783
|
-
this.outputTraces = cycleCollapse.traces;
|
|
15009
|
+
this.outputTraces = alignment.traces;
|
|
14784
15010
|
this.outputNetLabelPlacements = placeGroundRailLabelsAtOuterEnd({
|
|
14785
15011
|
inputProblem: this.input.inputProblem,
|
|
14786
|
-
traces:
|
|
14787
|
-
netLabelPlacements:
|
|
15012
|
+
traces: alignment.traces,
|
|
15013
|
+
netLabelPlacements: alignment.netLabelPlacements
|
|
14788
15014
|
});
|
|
14789
15015
|
this.stats.alignedJunctionCount = alignment.alignedJunctionCount;
|
|
14790
|
-
this.stats.collapsedCycleCount =
|
|
15016
|
+
this.stats.collapsedCycleCount = alignment.collapsedCycleCount;
|
|
14791
15017
|
this.solved = true;
|
|
14792
15018
|
}
|
|
14793
15019
|
getOutput() {
|
|
@@ -15159,10 +15385,10 @@ var getInlineLabelObstacles = (inputProblem, placements) => {
|
|
|
15159
15385
|
};
|
|
15160
15386
|
|
|
15161
15387
|
// lib/solvers/InlineNetLabelSolver/getLocalTraceLabelShifts.ts
|
|
15162
|
-
var
|
|
15388
|
+
var EPS16 = 1e-6;
|
|
15163
15389
|
var CLEARANCE = 0.05;
|
|
15164
15390
|
var hits = (path, bounds) => path.slice(1).some((p, i) => segmentIntersectsRect(path[i], p, bounds));
|
|
15165
|
-
var same = (a, b) => Math.hypot(a.x - b.x, a.y - b.y) <
|
|
15391
|
+
var same = (a, b) => Math.hypot(a.x - b.x, a.y - b.y) < EPS16;
|
|
15166
15392
|
var translate = (p, axis, distance7) => ({
|
|
15167
15393
|
...p,
|
|
15168
15394
|
[axis]: p[axis] + distance7
|
|
@@ -15209,9 +15435,9 @@ function* getLocalTraceLabelShifts(inputProblem, output, pendingInlinePlacements
|
|
|
15209
15435
|
const path = simplifyPath(trace.tracePath);
|
|
15210
15436
|
for (let i = 0; i < path.length - 1; i++) {
|
|
15211
15437
|
const a = path[i], b = path[i + 1];
|
|
15212
|
-
const axis = Math.abs(a.x - b.x) <
|
|
15438
|
+
const axis = Math.abs(a.x - b.x) < EPS16 ? "x" : "y";
|
|
15213
15439
|
const along = axis === "x" ? "y" : "x";
|
|
15214
|
-
if (Math.abs(a[axis] - b[axis]) >
|
|
15440
|
+
if (Math.abs(a[axis] - b[axis]) > EPS16 || same(a, b)) continue;
|
|
15215
15441
|
const blocking = [
|
|
15216
15442
|
...output.netLabelPlacements.filter((label) => label.globalConnNetId !== trace.globalConnNetId).map(getAnchoredNetLabelRenderedBounds),
|
|
15217
15443
|
...inlineBounds,
|
|
@@ -15229,17 +15455,17 @@ function* getLocalTraceLabelShifts(inputProblem, output, pendingInlinePlacements
|
|
|
15229
15455
|
if (other.globalConnNetId !== trace.globalConnNetId) continue;
|
|
15230
15456
|
for (let j = 1; j < other.tracePath.length; j++) {
|
|
15231
15457
|
const p = other.tracePath[j - 1], q = other.tracePath[j];
|
|
15232
|
-
if (Math.abs(p[axis] - a[axis]) >
|
|
15458
|
+
if (Math.abs(p[axis] - a[axis]) > EPS16 || Math.abs(q[axis] - a[axis]) > EPS16)
|
|
15233
15459
|
continue;
|
|
15234
15460
|
const min = Math.min(p[along], q[along]), max = Math.max(p[along], q[along]);
|
|
15235
|
-
if (max < low -
|
|
15461
|
+
if (max < low - EPS16 || min > high + EPS16) continue;
|
|
15236
15462
|
if (min < low || max > high) expanded = true;
|
|
15237
15463
|
low = Math.min(low, min);
|
|
15238
15464
|
high = Math.max(high, max);
|
|
15239
15465
|
}
|
|
15240
15466
|
}
|
|
15241
15467
|
}
|
|
15242
|
-
const onRail = (p) => Math.abs(p[axis] - a[axis]) <
|
|
15468
|
+
const onRail = (p) => Math.abs(p[axis] - a[axis]) < EPS16 && p[along] >= low - EPS16 && p[along] <= high + EPS16;
|
|
15243
15469
|
if (pinPositions.some(onRail)) continue;
|
|
15244
15470
|
const minKey = axis === "x" ? "minX" : "minY";
|
|
15245
15471
|
const maxKey = axis === "x" ? "maxX" : "maxY";
|
|
@@ -15321,7 +15547,7 @@ function* getLocalTraceLabelShifts(inputProblem, output, pendingInlinePlacements
|
|
|
15321
15547
|
continue;
|
|
15322
15548
|
}
|
|
15323
15549
|
const [start, bend, end] = connector.tracePath;
|
|
15324
|
-
if (Math.abs(bend[axis] - end[axis]) >
|
|
15550
|
+
if (Math.abs(bend[axis] - end[axis]) > EPS16 || Math.abs(start[along] - bend[along]) > EPS16) {
|
|
15325
15551
|
blocked = true;
|
|
15326
15552
|
break;
|
|
15327
15553
|
}
|
|
@@ -15342,24 +15568,40 @@ function* getLocalTraceLabelShifts(inputProblem, output, pendingInlinePlacements
|
|
|
15342
15568
|
};
|
|
15343
15569
|
}
|
|
15344
15570
|
if (blocked) continue;
|
|
15571
|
+
for (const [index, other] of traces.entries()) {
|
|
15572
|
+
if (other.globalConnNetId === trace.globalConnNetId || simplifyPath(other.tracePath).length <= 4 || !shiftedPaths.some(
|
|
15573
|
+
(path2) => doesPathCoincideWithTraces(path2, [other])
|
|
15574
|
+
))
|
|
15575
|
+
continue;
|
|
15576
|
+
const simplified = minimizeTurnsWithFilteredLabels({
|
|
15577
|
+
inputProblem,
|
|
15578
|
+
traces: [...traces, ...terminalTraces],
|
|
15579
|
+
targetMspConnectionPairId: other.mspPairId,
|
|
15580
|
+
allLabelPlacements: [...labels, ...fixedLabels],
|
|
15581
|
+
mergedLabelNetIdMap: {},
|
|
15582
|
+
paddingBuffer: CLEARANCE
|
|
15583
|
+
});
|
|
15584
|
+
if (simplifyPath(simplified.tracePath).length < simplifyPath(other.tracePath).length && preservesLabelAnchors(labels, [other], [simplified]))
|
|
15585
|
+
traces[index] = simplified;
|
|
15586
|
+
}
|
|
15345
15587
|
for (const [index, proposed] of traces.entries()) {
|
|
15346
15588
|
const original = output.traces[index];
|
|
15347
15589
|
if (proposed === original) continue;
|
|
15348
15590
|
const candidate = proposed.tracePath;
|
|
15349
15591
|
const previous = original.tracePath;
|
|
15350
15592
|
if (candidate.slice(1).some(
|
|
15351
|
-
(p, index2) => Math.abs(p.x - candidate[index2].x) >
|
|
15593
|
+
(p, index2) => Math.abs(p.x - candidate[index2].x) > EPS16 && Math.abs(p.y - candidate[index2].y) > EPS16
|
|
15352
15594
|
)) {
|
|
15353
15595
|
blocked = true;
|
|
15354
15596
|
break;
|
|
15355
15597
|
}
|
|
15356
15598
|
const dot = (a2, b2, c, d) => (b2.x - a2.x) * (d.x - c.x) + (b2.y - a2.y) * (d.y - c.y);
|
|
15357
|
-
if (dot(previous[0], previous[1], candidate[0], candidate[1]) <=
|
|
15599
|
+
if (dot(previous[0], previous[1], candidate[0], candidate[1]) <= EPS16 || dot(
|
|
15358
15600
|
previous.at(-1),
|
|
15359
15601
|
previous.at(-2),
|
|
15360
15602
|
candidate.at(-1),
|
|
15361
15603
|
candidate.at(-2)
|
|
15362
|
-
) <=
|
|
15604
|
+
) <= EPS16) {
|
|
15363
15605
|
blocked = true;
|
|
15364
15606
|
break;
|
|
15365
15607
|
}
|
|
@@ -16315,15 +16557,15 @@ var pathIntersectsRenderedLabel = (path, label) => {
|
|
|
16315
16557
|
};
|
|
16316
16558
|
|
|
16317
16559
|
// lib/solvers/InlineNetLabelSolver/restoreReroutesAroundSupersededLabels.ts
|
|
16318
|
-
var
|
|
16560
|
+
var EPS17 = 1e-6;
|
|
16319
16561
|
var getPathLength7 = (path) => path.slice(1).reduce((length, point, pointIndex) => {
|
|
16320
16562
|
const previousPoint = path[pointIndex];
|
|
16321
16563
|
return length + Math.abs(point.x - previousPoint.x) + Math.abs(point.y - previousPoint.y);
|
|
16322
16564
|
}, 0);
|
|
16323
16565
|
var pathsEqual = (first, second) => first.length === second.length && first.every(
|
|
16324
|
-
(point, index) => Math.abs(point.x - second[index].x) <=
|
|
16566
|
+
(point, index) => Math.abs(point.x - second[index].x) <= EPS17 && Math.abs(point.y - second[index].y) <= EPS17
|
|
16325
16567
|
);
|
|
16326
|
-
var isStrictlySimpler = (candidate, current) => candidate.length < current.length && getPathLength7(candidate) <= getPathLength7(current) +
|
|
16568
|
+
var isStrictlySimpler = (candidate, current) => candidate.length < current.length && getPathLength7(candidate) <= getPathLength7(current) + EPS17;
|
|
16327
16569
|
var getIntersectionKeys = (path, otherPath) => {
|
|
16328
16570
|
const intersections2 = /* @__PURE__ */ new Set();
|
|
16329
16571
|
for (let pathIndex = 0; pathIndex < path.length - 1; pathIndex++) {
|
|
@@ -17623,12 +17865,12 @@ var getTraceRecoveryConnectivityMaps = (inputProblem) => {
|
|
|
17623
17865
|
};
|
|
17624
17866
|
|
|
17625
17867
|
// lib/solvers/NetLabelToTraceSolver/reduceTraceCrossings.ts
|
|
17626
|
-
var
|
|
17627
|
-
var isHorizontal4 = (start, end) => Math.abs(start.y - end.y) <
|
|
17628
|
-
var isVertical5 = (start, end) => Math.abs(start.x - end.x) <
|
|
17868
|
+
var EPS18 = 1e-9;
|
|
17869
|
+
var isHorizontal4 = (start, end) => Math.abs(start.y - end.y) < EPS18;
|
|
17870
|
+
var isVertical5 = (start, end) => Math.abs(start.x - end.x) < EPS18;
|
|
17629
17871
|
var compactConsecutivePoints = (path) => path.filter((point, index) => {
|
|
17630
17872
|
const previousPoint = path[index - 1];
|
|
17631
|
-
return !previousPoint || Math.abs(point.x - previousPoint.x) >=
|
|
17873
|
+
return !previousPoint || Math.abs(point.x - previousPoint.x) >= EPS18 || Math.abs(point.y - previousPoint.y) >= EPS18;
|
|
17632
17874
|
});
|
|
17633
17875
|
var isValidOrthogonalPath = (path) => {
|
|
17634
17876
|
if (path.length < 2 || !path.every((point, index) => {
|
|
@@ -17666,7 +17908,7 @@ var getEndpointAlignedSegmentCandidates = (tracePath) => {
|
|
|
17666
17908
|
}
|
|
17667
17909
|
const alignedCoordinates = segmentIsVertical ? [previousPoint.x, nextPoint.x] : [previousPoint.y, nextPoint.y];
|
|
17668
17910
|
for (const alignedCoordinate of alignedCoordinates) {
|
|
17669
|
-
if (Math.abs(alignedCoordinate - (segmentIsVertical ? start.x : start.y)) <
|
|
17911
|
+
if (Math.abs(alignedCoordinate - (segmentIsVertical ? start.x : start.y)) < EPS18) {
|
|
17670
17912
|
continue;
|
|
17671
17913
|
}
|
|
17672
17914
|
const candidate = tracePath.map((point) => ({ ...point }));
|
|
@@ -17755,6 +17997,13 @@ var NetLabelToTraceSolver = class extends BaseSolver {
|
|
|
17755
17997
|
);
|
|
17756
17998
|
this.chipMap = chipMap;
|
|
17757
17999
|
this.pinMap = pinMap;
|
|
18000
|
+
this.canRecoverParallelPair = getParallelNetLabelPolicy(
|
|
18001
|
+
this.inputProblem,
|
|
18002
|
+
getConnectivityMapsFromInputProblem(this.inputProblem).netConnMap,
|
|
18003
|
+
new Set(
|
|
18004
|
+
input.traces.filter((trace) => trace.pinIds.length > 1).flatMap((trace) => trace.pinIds)
|
|
18005
|
+
)
|
|
18006
|
+
);
|
|
17758
18007
|
this.queuedCandidates = this.buildCandidatePairs();
|
|
17759
18008
|
this.stats.candidateCount = this.queuedCandidates.length;
|
|
17760
18009
|
this.stats.recoveredTraceCount = 0;
|
|
@@ -17766,6 +18015,7 @@ var NetLabelToTraceSolver = class extends BaseSolver {
|
|
|
17766
18015
|
recoveredTraceIds = /* @__PURE__ */ new Set();
|
|
17767
18016
|
chipMap;
|
|
17768
18017
|
pinMap;
|
|
18018
|
+
canRecoverParallelPair;
|
|
17769
18019
|
queuedCandidates;
|
|
17770
18020
|
currentCandidate = null;
|
|
17771
18021
|
getConstructorParams() {
|
|
@@ -17816,6 +18066,7 @@ var NetLabelToTraceSolver = class extends BaseSolver {
|
|
|
17816
18066
|
const firstPin = this.pinMap.get(firstLabel.pinIds[0]);
|
|
17817
18067
|
const secondPin = this.pinMap.get(secondLabel.pinIds[0]);
|
|
17818
18068
|
if (!firstPin || !secondPin) continue;
|
|
18069
|
+
if (!this.canRecoverParallelPair(firstPin, secondPin)) continue;
|
|
17819
18070
|
const perpendicularOffset = getPerpendicularOffset(
|
|
17820
18071
|
firstPin,
|
|
17821
18072
|
secondPin
|
|
@@ -17934,6 +18185,7 @@ var NetLabelToTraceSolver = class extends BaseSolver {
|
|
|
17934
18185
|
const firstPin = this.pinMap.get(firstPinId);
|
|
17935
18186
|
const secondPin = this.pinMap.get(secondPinId);
|
|
17936
18187
|
if (!firstPin || !secondPin) continue;
|
|
18188
|
+
if (!this.canRecoverParallelPair(firstPin, secondPin)) continue;
|
|
17937
18189
|
if (isDirectConnection && firstPin.chipId === secondPin.chipId)
|
|
17938
18190
|
continue;
|
|
17939
18191
|
const perpendicularOffset = getPerpendicularOffset(
|