@tscircuit/schematic-trace-solver 0.0.107 → 0.0.109
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 +31 -3
- package/dist/index.js +784 -247
- package/lib/solvers/MspConnectionPairSolver/MspConnectionPairSolver.ts +3 -1
- package/lib/solvers/SchematicTraceLinesSolver/SchematicTraceSingleLineSolver2/SchematicTraceSingleLineSolver2.ts +58 -27
- package/lib/solvers/SchematicTraceLinesSolver/SchematicTraceSingleLineSolver2/generateEndpointCollisionDetours.ts +1 -10
- package/lib/solvers/SchematicTraceLinesSolver/SchematicTraceSingleLineSolver2/generateInternalSegmentCollisionDetours.ts +94 -0
- package/lib/solvers/SchematicTraceLinesSolver/SchematicTraceSingleLineSolver2/pathOps.ts +10 -0
- package/lib/solvers/SchematicTraceLinesSolver/SchematicTraceSingleLineSolver2/rect.ts +5 -1
- package/lib/solvers/SchematicTracePipelineSolver/SchematicTracePipelineSolver.ts +18 -3
- package/lib/solvers/UnroutedTraceRecoverySolver/UnroutedTraceRecoverySolver.ts +592 -0
- package/package.json +1 -1
- package/site/bug-reports/bug-report-20260724T175257Z.page.tsx +4 -0
- package/tests/bug-reports/bug-report-20260707T092615Z/__snapshots__/bug-report-20260707T092615Z.snap.svg +5 -9
- package/tests/bug-reports/bug-report-20260708T095725Z/__snapshots__/bug-report-20260708T095725Z.snap.svg +5 -5
- package/tests/bug-reports/bug-report-20260708T095725Z/bug-report-20260708T095725Z.test.ts +15 -0
- package/tests/bug-reports/bug-report-20260724T175257Z/__snapshots__/bug-report-20260724T175257Z.snap.svg +58 -0
- package/tests/bug-reports/bug-report-20260724T175257Z/bug-report-20260724T175257Z.json +138 -0
- package/tests/bug-reports/bug-report-20260724T175257Z/bug-report-20260724T175257Z.test.ts +12 -0
- package/tests/examples/__snapshots__/example04.snap.svg +7 -9
- package/tests/examples/__snapshots__/example08.snap.svg +16 -20
- package/tests/examples/__snapshots__/example13.snap.svg +2 -4
- package/tests/examples/__snapshots__/example32.snap.svg +64 -66
- package/tests/examples/__snapshots__/example46.snap.svg +1 -1
- package/tests/repros/__snapshots__/repro-netlabel-collision-687.snap.svg +81 -0
- package/tests/repros/__snapshots__/repro-netlabel-overlap-trace.snap.svg +16 -18
- package/tests/repros/__snapshots__/repro-tps61222-trace-intersection.snap.svg +63 -220
- package/tests/repros/assets/repro-netlabel-collision-687.input.json +212 -0
- package/tests/repros/repro-netlabel-collision-687.test.ts +59 -0
- package/tests/repros/repro-tps61222-trace-intersection.test.ts +27 -0
- package/tests/solvers/SchematicTraceSingleLineSolver2/generate-internal-segment-collision-detours.test.ts +49 -0
- package/tests/solvers/UnroutedTraceRecoverySolver/paired-junction-recovery.test.ts +49 -0
- package/tests/solvers/UnroutedTraceRecoverySolver/skip-ground.test.ts +30 -0
- package/tests/solvers/UnroutedTraceRecoverySolver/skip-long-connection.test.ts +24 -0
package/dist/index.js
CHANGED
|
@@ -325,19 +325,19 @@ var doesPairCrossRestrictedCenterLines = (params) => {
|
|
|
325
325
|
chipMap
|
|
326
326
|
});
|
|
327
327
|
if (restrictedCenterLines.size === 0) return false;
|
|
328
|
-
const
|
|
328
|
+
const EPS13 = 1e-9;
|
|
329
329
|
const crossesSegment = (a, b) => {
|
|
330
330
|
for (const [, rcl] of restrictedCenterLines) {
|
|
331
331
|
if (rcl.axes.has("x") && typeof rcl.x === "number") {
|
|
332
|
-
if ((a.x - rcl.x) * (b.x - rcl.x) < -
|
|
332
|
+
if ((a.x - rcl.x) * (b.x - rcl.x) < -EPS13) return true;
|
|
333
333
|
}
|
|
334
334
|
if (rcl.axes.has("y") && typeof rcl.y === "number") {
|
|
335
|
-
if ((a.y - rcl.y) * (b.y - rcl.y) < -
|
|
335
|
+
if ((a.y - rcl.y) * (b.y - rcl.y) < -EPS13) return true;
|
|
336
336
|
}
|
|
337
337
|
}
|
|
338
338
|
return false;
|
|
339
339
|
};
|
|
340
|
-
if (Math.abs(p1.x - p2.x) <
|
|
340
|
+
if (Math.abs(p1.x - p2.x) < EPS13 || Math.abs(p1.y - p2.y) < EPS13) {
|
|
341
341
|
return crossesSegment({ x: p1.x, y: p1.y }, { x: p2.x, y: p2.y });
|
|
342
342
|
}
|
|
343
343
|
const elbowHV = { x: p2.x, y: p1.y };
|
|
@@ -421,6 +421,7 @@ function getOrthogonalMinimumSpanningTree(pins, opts = {}) {
|
|
|
421
421
|
}
|
|
422
422
|
|
|
423
423
|
// lib/solvers/MspConnectionPairSolver/MspConnectionPairSolver.ts
|
|
424
|
+
var DEFAULT_MAX_MSP_PAIR_DISTANCE = 1;
|
|
424
425
|
var getPinPairKey = (pinIds) => [...pinIds].sort().join("::");
|
|
425
426
|
var MspConnectionPairSolver = class extends BaseSolver {
|
|
426
427
|
inputProblem;
|
|
@@ -436,7 +437,7 @@ var MspConnectionPairSolver = class extends BaseSolver {
|
|
|
436
437
|
constructor({ inputProblem }) {
|
|
437
438
|
super();
|
|
438
439
|
this.inputProblem = inputProblem;
|
|
439
|
-
this.maxMspPairDistance = inputProblem.maxMspPairDistance ??
|
|
440
|
+
this.maxMspPairDistance = inputProblem.maxMspPairDistance ?? DEFAULT_MAX_MSP_PAIR_DISTANCE;
|
|
440
441
|
const { directConnMap, netConnMap } = getConnectivityMapsFromInputProblem(inputProblem);
|
|
441
442
|
this.dcConnMap = directConnMap;
|
|
442
443
|
this.globalConnMap = netConnMap;
|
|
@@ -630,6 +631,25 @@ function getRectBounds(center, w, h) {
|
|
|
630
631
|
};
|
|
631
632
|
}
|
|
632
633
|
|
|
634
|
+
// lib/utils/textBoxBounds.ts
|
|
635
|
+
function getTextBoxBounds(textBox, padding = {}) {
|
|
636
|
+
return {
|
|
637
|
+
minX: textBox.center.x - textBox.width / 2 - (padding.minX ?? 0),
|
|
638
|
+
minY: textBox.center.y - textBox.height / 2 - (padding.minY ?? 0),
|
|
639
|
+
maxX: textBox.center.x + textBox.width / 2 + (padding.maxX ?? 0),
|
|
640
|
+
maxY: textBox.center.y + textBox.height / 2 + (padding.maxY ?? 0)
|
|
641
|
+
};
|
|
642
|
+
}
|
|
643
|
+
function boundsOverlap(a, b, eps = 1e-9) {
|
|
644
|
+
return a.minX < b.maxX - eps && a.maxX > b.minX + eps && a.minY < b.maxY - eps && a.maxY > b.minY + eps;
|
|
645
|
+
}
|
|
646
|
+
function rectIntersectsAnyTextBox(bounds, inputProblem) {
|
|
647
|
+
for (const textBox of inputProblem.textBoxes ?? []) {
|
|
648
|
+
if (boundsOverlap(bounds, getTextBoxBounds(textBox))) return true;
|
|
649
|
+
}
|
|
650
|
+
return false;
|
|
651
|
+
}
|
|
652
|
+
|
|
633
653
|
// lib/solvers/SchematicTraceLinesSolver/SchematicTraceSingleLineSolver2/calculateDirectShortPath.ts
|
|
634
654
|
import { calculateElbow } from "calculate-elbow";
|
|
635
655
|
var MAX_SHORT_TRACE_DISTANCE = 0.15;
|
|
@@ -875,12 +895,8 @@ var candidateMidsFromSet = (axis, colliding, collisionRects, aabb, opts = {}) =>
|
|
|
875
895
|
}
|
|
876
896
|
};
|
|
877
897
|
|
|
878
|
-
// lib/solvers/SchematicTraceLinesSolver/SchematicTraceSingleLineSolver2/
|
|
879
|
-
var
|
|
880
|
-
if (isVertical(start, end)) return "x";
|
|
881
|
-
if (isHorizontal(start, end)) return "y";
|
|
882
|
-
return null;
|
|
883
|
-
};
|
|
898
|
+
// lib/solvers/SchematicTraceLinesSolver/SchematicTraceSingleLineSolver2/pathOps.ts
|
|
899
|
+
var EPS3 = 1e-9;
|
|
884
900
|
var hasOnlyNonzeroOrthogonalSegments = (path) => path.every((point, index) => {
|
|
885
901
|
const nextPoint = path[index + 1];
|
|
886
902
|
if (!nextPoint) return true;
|
|
@@ -889,57 +905,6 @@ var hasOnlyNonzeroOrthogonalSegments = (path) => path.every((point, index) => {
|
|
|
889
905
|
}
|
|
890
906
|
return Math.abs(point.x - nextPoint.x) + Math.abs(point.y - nextPoint.y) > 0;
|
|
891
907
|
});
|
|
892
|
-
var generateEndpointCollisionDetours = ({
|
|
893
|
-
path,
|
|
894
|
-
collidingSegmentIndex,
|
|
895
|
-
obstacle
|
|
896
|
-
}) => {
|
|
897
|
-
if (path.length < 3 || path.length > 4) return [];
|
|
898
|
-
const lastSegmentIndex = path.length - 2;
|
|
899
|
-
if (collidingSegmentIndex !== 0 && collidingSegmentIndex !== lastSegmentIndex) {
|
|
900
|
-
return [];
|
|
901
|
-
}
|
|
902
|
-
const shouldReverse = collidingSegmentIndex === lastSegmentIndex;
|
|
903
|
-
const orderedPath = shouldReverse ? [...path].reverse() : path;
|
|
904
|
-
const [start, corner, end] = orderedPath;
|
|
905
|
-
const firstSegmentAxis = getSegmentAxis(start, corner);
|
|
906
|
-
const secondSegmentAxis = getSegmentAxis(corner, end);
|
|
907
|
-
if (!firstSegmentAxis || !secondSegmentAxis) return [];
|
|
908
|
-
if (firstSegmentAxis === secondSegmentAxis) return [];
|
|
909
|
-
const escapeCoordinates = [
|
|
910
|
-
...midBetweenPointAndRect(secondSegmentAxis, start, obstacle),
|
|
911
|
-
...midBetweenPointAndRect(secondSegmentAxis, end, obstacle)
|
|
912
|
-
];
|
|
913
|
-
const detourCoordinates = [
|
|
914
|
-
...midBetweenPointAndRect(firstSegmentAxis, start, obstacle),
|
|
915
|
-
...midBetweenPointAndRect(firstSegmentAxis, end, obstacle)
|
|
916
|
-
];
|
|
917
|
-
const detours = [];
|
|
918
|
-
for (const escapeCoordinate of [...new Set(escapeCoordinates)]) {
|
|
919
|
-
for (const detourCoordinate of [...new Set(detourCoordinates)]) {
|
|
920
|
-
const orderedDetourPrefix = firstSegmentAxis === "y" ? [
|
|
921
|
-
start,
|
|
922
|
-
{ x: escapeCoordinate, y: start.y },
|
|
923
|
-
{ x: escapeCoordinate, y: detourCoordinate },
|
|
924
|
-
{ x: end.x, y: detourCoordinate },
|
|
925
|
-
end
|
|
926
|
-
] : [
|
|
927
|
-
start,
|
|
928
|
-
{ x: start.x, y: escapeCoordinate },
|
|
929
|
-
{ x: detourCoordinate, y: escapeCoordinate },
|
|
930
|
-
{ x: detourCoordinate, y: end.y },
|
|
931
|
-
end
|
|
932
|
-
];
|
|
933
|
-
const orderedDetour = [...orderedDetourPrefix, ...orderedPath.slice(3)];
|
|
934
|
-
const detour = shouldReverse ? orderedDetour.reverse() : orderedDetour;
|
|
935
|
-
if (hasOnlyNonzeroOrthogonalSegments(detour)) detours.push(detour);
|
|
936
|
-
}
|
|
937
|
-
}
|
|
938
|
-
return detours;
|
|
939
|
-
};
|
|
940
|
-
|
|
941
|
-
// lib/solvers/SchematicTraceLinesSolver/SchematicTraceSingleLineSolver2/pathOps.ts
|
|
942
|
-
var EPS3 = 1e-9;
|
|
943
908
|
var shiftSegmentOrth = (pts, segIndex, axis, newCoord, eps = EPS3) => {
|
|
944
909
|
if (segIndex < 0 || segIndex >= pts.length - 1) {
|
|
945
910
|
return null;
|
|
@@ -1001,6 +966,121 @@ var pathKey = (pts, decimals = 6) => {
|
|
|
1001
966
|
return key;
|
|
1002
967
|
};
|
|
1003
968
|
|
|
969
|
+
// lib/solvers/SchematicTraceLinesSolver/SchematicTraceSingleLineSolver2/generateEndpointCollisionDetours.ts
|
|
970
|
+
var getSegmentAxis = (start, end) => {
|
|
971
|
+
if (isVertical(start, end)) return "x";
|
|
972
|
+
if (isHorizontal(start, end)) return "y";
|
|
973
|
+
return null;
|
|
974
|
+
};
|
|
975
|
+
var generateEndpointCollisionDetours = ({
|
|
976
|
+
path,
|
|
977
|
+
collidingSegmentIndex,
|
|
978
|
+
obstacle
|
|
979
|
+
}) => {
|
|
980
|
+
if (path.length < 3 || path.length > 4) return [];
|
|
981
|
+
const lastSegmentIndex = path.length - 2;
|
|
982
|
+
if (collidingSegmentIndex !== 0 && collidingSegmentIndex !== lastSegmentIndex) {
|
|
983
|
+
return [];
|
|
984
|
+
}
|
|
985
|
+
const shouldReverse = collidingSegmentIndex === lastSegmentIndex;
|
|
986
|
+
const orderedPath = shouldReverse ? [...path].reverse() : path;
|
|
987
|
+
const [start, corner, end] = orderedPath;
|
|
988
|
+
const firstSegmentAxis = getSegmentAxis(start, corner);
|
|
989
|
+
const secondSegmentAxis = getSegmentAxis(corner, end);
|
|
990
|
+
if (!firstSegmentAxis || !secondSegmentAxis) return [];
|
|
991
|
+
if (firstSegmentAxis === secondSegmentAxis) return [];
|
|
992
|
+
const escapeCoordinates = [
|
|
993
|
+
...midBetweenPointAndRect(secondSegmentAxis, start, obstacle),
|
|
994
|
+
...midBetweenPointAndRect(secondSegmentAxis, end, obstacle)
|
|
995
|
+
];
|
|
996
|
+
const detourCoordinates = [
|
|
997
|
+
...midBetweenPointAndRect(firstSegmentAxis, start, obstacle),
|
|
998
|
+
...midBetweenPointAndRect(firstSegmentAxis, end, obstacle)
|
|
999
|
+
];
|
|
1000
|
+
const detours = [];
|
|
1001
|
+
for (const escapeCoordinate of [...new Set(escapeCoordinates)]) {
|
|
1002
|
+
for (const detourCoordinate of [...new Set(detourCoordinates)]) {
|
|
1003
|
+
const orderedDetourPrefix = firstSegmentAxis === "y" ? [
|
|
1004
|
+
start,
|
|
1005
|
+
{ x: escapeCoordinate, y: start.y },
|
|
1006
|
+
{ x: escapeCoordinate, y: detourCoordinate },
|
|
1007
|
+
{ x: end.x, y: detourCoordinate },
|
|
1008
|
+
end
|
|
1009
|
+
] : [
|
|
1010
|
+
start,
|
|
1011
|
+
{ x: start.x, y: escapeCoordinate },
|
|
1012
|
+
{ x: detourCoordinate, y: escapeCoordinate },
|
|
1013
|
+
{ x: detourCoordinate, y: end.y },
|
|
1014
|
+
end
|
|
1015
|
+
];
|
|
1016
|
+
const orderedDetour = [...orderedDetourPrefix, ...orderedPath.slice(3)];
|
|
1017
|
+
const detour = shouldReverse ? orderedDetour.reverse() : orderedDetour;
|
|
1018
|
+
if (hasOnlyNonzeroOrthogonalSegments(detour)) detours.push(detour);
|
|
1019
|
+
}
|
|
1020
|
+
}
|
|
1021
|
+
return detours;
|
|
1022
|
+
};
|
|
1023
|
+
|
|
1024
|
+
// lib/solvers/SchematicTraceLinesSolver/SchematicTraceSingleLineSolver2/generateInternalSegmentCollisionDetours.ts
|
|
1025
|
+
var EPS4 = 1e-9;
|
|
1026
|
+
var DEFAULT_CLEARANCE = 0.2;
|
|
1027
|
+
var isStrictlyBetween = (value, a, b) => value > Math.min(a, b) + EPS4 && value < Math.max(a, b) - EPS4;
|
|
1028
|
+
var generateInternalSegmentCollisionDetours = ({
|
|
1029
|
+
path,
|
|
1030
|
+
collidingSegmentIndex,
|
|
1031
|
+
obstacle,
|
|
1032
|
+
clearance = DEFAULT_CLEARANCE
|
|
1033
|
+
}) => {
|
|
1034
|
+
if (collidingSegmentIndex <= 0 || collidingSegmentIndex >= path.length - 2) {
|
|
1035
|
+
return [];
|
|
1036
|
+
}
|
|
1037
|
+
const start = path[collidingSegmentIndex];
|
|
1038
|
+
const end = path[collidingSegmentIndex + 1];
|
|
1039
|
+
const detourPoints = [];
|
|
1040
|
+
if (isHorizontal(start, end)) {
|
|
1041
|
+
const movingRight = start.x < end.x;
|
|
1042
|
+
const entryX = movingRight ? obstacle.minX - clearance : obstacle.maxX + clearance;
|
|
1043
|
+
const exitX = movingRight ? obstacle.maxX + clearance : obstacle.minX - clearance;
|
|
1044
|
+
if (!isStrictlyBetween(entryX, start.x, end.x) || !isStrictlyBetween(exitX, start.x, end.x)) {
|
|
1045
|
+
return [];
|
|
1046
|
+
}
|
|
1047
|
+
for (const detourY of [
|
|
1048
|
+
obstacle.minY - clearance,
|
|
1049
|
+
obstacle.maxY + clearance
|
|
1050
|
+
]) {
|
|
1051
|
+
detourPoints.push([
|
|
1052
|
+
{ x: entryX, y: start.y },
|
|
1053
|
+
{ x: entryX, y: detourY },
|
|
1054
|
+
{ x: exitX, y: detourY },
|
|
1055
|
+
{ x: exitX, y: end.y }
|
|
1056
|
+
]);
|
|
1057
|
+
}
|
|
1058
|
+
} else if (isVertical(start, end)) {
|
|
1059
|
+
const movingUp = start.y < end.y;
|
|
1060
|
+
const entryY = movingUp ? obstacle.minY - clearance : obstacle.maxY + clearance;
|
|
1061
|
+
const exitY = movingUp ? obstacle.maxY + clearance : obstacle.minY - clearance;
|
|
1062
|
+
if (!isStrictlyBetween(entryY, start.y, end.y) || !isStrictlyBetween(exitY, start.y, end.y)) {
|
|
1063
|
+
return [];
|
|
1064
|
+
}
|
|
1065
|
+
for (const detourX of [
|
|
1066
|
+
obstacle.minX - clearance,
|
|
1067
|
+
obstacle.maxX + clearance
|
|
1068
|
+
]) {
|
|
1069
|
+
detourPoints.push([
|
|
1070
|
+
{ x: start.x, y: entryY },
|
|
1071
|
+
{ x: detourX, y: entryY },
|
|
1072
|
+
{ x: detourX, y: exitY },
|
|
1073
|
+
{ x: end.x, y: exitY }
|
|
1074
|
+
]);
|
|
1075
|
+
}
|
|
1076
|
+
}
|
|
1077
|
+
return detourPoints.map((points) => [
|
|
1078
|
+
...path.slice(0, collidingSegmentIndex + 1),
|
|
1079
|
+
...points,
|
|
1080
|
+
...path.slice(collidingSegmentIndex + 1)
|
|
1081
|
+
]).filter(hasOnlyNonzeroOrthogonalSegments);
|
|
1082
|
+
};
|
|
1083
|
+
|
|
1004
1084
|
// lib/solvers/GuidelinesSolver/getInputChipBounds.ts
|
|
1005
1085
|
function getInputChipBounds(chip) {
|
|
1006
1086
|
const halfWidth = chip.width / 2;
|
|
@@ -1013,26 +1093,8 @@ function getInputChipBounds(chip) {
|
|
|
1013
1093
|
};
|
|
1014
1094
|
}
|
|
1015
1095
|
|
|
1016
|
-
// lib/utils/textBoxBounds.ts
|
|
1017
|
-
function getTextBoxBounds(textBox, padding = {}) {
|
|
1018
|
-
return {
|
|
1019
|
-
minX: textBox.center.x - textBox.width / 2 - (padding.minX ?? 0),
|
|
1020
|
-
minY: textBox.center.y - textBox.height / 2 - (padding.minY ?? 0),
|
|
1021
|
-
maxX: textBox.center.x + textBox.width / 2 + (padding.maxX ?? 0),
|
|
1022
|
-
maxY: textBox.center.y + textBox.height / 2 + (padding.maxY ?? 0)
|
|
1023
|
-
};
|
|
1024
|
-
}
|
|
1025
|
-
function boundsOverlap(a, b, eps = 1e-9) {
|
|
1026
|
-
return a.minX < b.maxX - eps && a.maxX > b.minX + eps && a.minY < b.maxY - eps && a.maxY > b.minY + eps;
|
|
1027
|
-
}
|
|
1028
|
-
function rectIntersectsAnyTextBox(bounds, inputProblem) {
|
|
1029
|
-
for (const textBox of inputProblem.textBoxes ?? []) {
|
|
1030
|
-
if (boundsOverlap(bounds, getTextBoxBounds(textBox))) return true;
|
|
1031
|
-
}
|
|
1032
|
-
return false;
|
|
1033
|
-
}
|
|
1034
|
-
|
|
1035
1096
|
// lib/solvers/SchematicTraceLinesSolver/SchematicTraceSingleLineSolver2/rect.ts
|
|
1097
|
+
var isTextBoxObstacle = (obstacle) => obstacle.kind === "text_box";
|
|
1036
1098
|
var chipToRect = (chip) => {
|
|
1037
1099
|
const b = getInputChipBounds(chip);
|
|
1038
1100
|
return { kind: "chip", chipId: chip.chipId, ...b };
|
|
@@ -1096,13 +1158,11 @@ var SchematicTraceSingleLineSolver2 = class extends BaseSolver {
|
|
|
1096
1158
|
this.obstacles = getObstacleRects(this.inputProblem, {
|
|
1097
1159
|
textBoxPadding: this.getTextBoxPaddingForConnectionPair()
|
|
1098
1160
|
});
|
|
1099
|
-
this.textObstacles = new Set(
|
|
1100
|
-
this.obstacles.filter((r) => r.kind === "text_box")
|
|
1101
|
-
);
|
|
1161
|
+
this.textObstacles = new Set(this.obstacles.filter(isTextBoxObstacle));
|
|
1102
1162
|
const endpointChipIds = new Set(this.pins.map((pin) => pin.chipId));
|
|
1103
1163
|
this.endpointTextObstacles = new Set(
|
|
1104
|
-
endpointChipIds.size > 1 ? this.obstacles.filter(
|
|
1105
|
-
(
|
|
1164
|
+
endpointChipIds.size > 1 ? this.obstacles.filter(isTextBoxObstacle).filter(
|
|
1165
|
+
(obstacle) => obstacle.textBox.chipId !== void 0 && endpointChipIds.has(obstacle.textBox.chipId)
|
|
1106
1166
|
) : []
|
|
1107
1167
|
);
|
|
1108
1168
|
const [pin1, pin2] = this.pins;
|
|
@@ -1290,7 +1350,10 @@ var SchematicTraceSingleLineSolver2 = class extends BaseSolver {
|
|
|
1290
1350
|
path[adjacentEndpointSegIndex + 1]
|
|
1291
1351
|
)) {
|
|
1292
1352
|
for (const textObstacle of this.endpointTextObstacles) {
|
|
1293
|
-
|
|
1353
|
+
const textBounds = getTextBoxBounds(textObstacle.textBox);
|
|
1354
|
+
if (!segmentIntersectsRect(segmentStart, segmentEnd, textBounds)) {
|
|
1355
|
+
excludedRects.add(textObstacle);
|
|
1356
|
+
}
|
|
1294
1357
|
}
|
|
1295
1358
|
}
|
|
1296
1359
|
return excludedRects;
|
|
@@ -1299,8 +1362,8 @@ var SchematicTraceSingleLineSolver2 = class extends BaseSolver {
|
|
|
1299
1362
|
if (!collision) {
|
|
1300
1363
|
const first = path[0];
|
|
1301
1364
|
const last = path[path.length - 1];
|
|
1302
|
-
const
|
|
1303
|
-
const samePoint = (p, q) => Math.abs(p.x - q.x) <
|
|
1365
|
+
const EPS13 = 1e-9;
|
|
1366
|
+
const samePoint = (p, q) => Math.abs(p.x - q.x) < EPS13 && Math.abs(p.y - q.y) < EPS13;
|
|
1304
1367
|
if (samePoint(first, { x: PA.x, y: PA.y }) && samePoint(last, { x: PB.x, y: PB.y })) {
|
|
1305
1368
|
this.solvedTracePath = path;
|
|
1306
1369
|
this.solved = true;
|
|
@@ -1373,14 +1436,7 @@ var SchematicTraceSingleLineSolver2 = class extends BaseSolver {
|
|
|
1373
1436
|
candidates.push(...mids);
|
|
1374
1437
|
}
|
|
1375
1438
|
const newStates = [];
|
|
1376
|
-
const
|
|
1377
|
-
const newPath = shiftSegmentOrth(
|
|
1378
|
-
path,
|
|
1379
|
-
candidateSegIndex,
|
|
1380
|
-
candidateAxis,
|
|
1381
|
-
coord
|
|
1382
|
-
);
|
|
1383
|
-
if (!newPath) return;
|
|
1439
|
+
const addPathCandidate = (newPath) => {
|
|
1384
1440
|
const key = pathKey(newPath);
|
|
1385
1441
|
if (this.visited.has(key)) return;
|
|
1386
1442
|
this.visited.add(key);
|
|
@@ -1393,10 +1449,28 @@ var SchematicTraceSingleLineSolver2 = class extends BaseSolver {
|
|
|
1393
1449
|
pinBandPenalty: this.getPinBandPenalty(newPath)
|
|
1394
1450
|
});
|
|
1395
1451
|
};
|
|
1452
|
+
const addShiftedCandidate = (candidateSegIndex, candidateAxis, coord) => {
|
|
1453
|
+
const newPath = shiftSegmentOrth(
|
|
1454
|
+
path,
|
|
1455
|
+
candidateSegIndex,
|
|
1456
|
+
candidateAxis,
|
|
1457
|
+
coord
|
|
1458
|
+
);
|
|
1459
|
+
if (newPath) addPathCandidate(newPath);
|
|
1460
|
+
};
|
|
1461
|
+
const lastSegIndex = path.length - 2;
|
|
1462
|
+
if (this.connectionPair === void 0 && rect.kind === "text_box" && this.endpointTextObstacles.has(rect) && !collisionRects.has(rect) && originalSegIndex > 0 && originalSegIndex < lastSegIndex) {
|
|
1463
|
+
for (const detour of generateInternalSegmentCollisionDetours({
|
|
1464
|
+
path,
|
|
1465
|
+
collidingSegmentIndex: originalSegIndex,
|
|
1466
|
+
obstacle: rect
|
|
1467
|
+
})) {
|
|
1468
|
+
addPathCandidate(detour);
|
|
1469
|
+
}
|
|
1470
|
+
}
|
|
1396
1471
|
for (const coord of candidates) {
|
|
1397
1472
|
addShiftedCandidate(segIndex, axis, coord);
|
|
1398
1473
|
}
|
|
1399
|
-
const lastSegIndex = path.length - 2;
|
|
1400
1474
|
const adjacentSegmentIndexes = originalSegIndex === 1 ? [2] : originalSegIndex === lastSegIndex - 1 ? [lastSegIndex - 2] : [];
|
|
1401
1475
|
for (const adjacentSegIndex of adjacentSegmentIndexes) {
|
|
1402
1476
|
if (adjacentSegIndex < 0 || adjacentSegIndex >= lastSegIndex) continue;
|
|
@@ -1573,13 +1647,13 @@ var applyJogToTerminalSegment = ({
|
|
|
1573
1647
|
segmentIndex: si,
|
|
1574
1648
|
offset,
|
|
1575
1649
|
JOG_SIZE,
|
|
1576
|
-
EPS:
|
|
1650
|
+
EPS: EPS13 = 1e-6
|
|
1577
1651
|
}) => {
|
|
1578
1652
|
if (si !== 0 && si !== pts.length - 2) return;
|
|
1579
1653
|
const start = pts[si];
|
|
1580
1654
|
const end = pts[si + 1];
|
|
1581
|
-
const isVertical5 = Math.abs(start.x - end.x) <
|
|
1582
|
-
const isHorizontal4 = Math.abs(start.y - end.y) <
|
|
1655
|
+
const isVertical5 = Math.abs(start.x - end.x) < EPS13;
|
|
1656
|
+
const isHorizontal4 = Math.abs(start.y - end.y) < EPS13;
|
|
1583
1657
|
if (!isVertical5 && !isHorizontal4) return;
|
|
1584
1658
|
const segDir = isVertical5 ? end.y > start.y ? 1 : -1 : end.x > start.x ? 1 : -1;
|
|
1585
1659
|
if (pts.length === 2) {
|
|
@@ -1652,7 +1726,7 @@ var applyJogToTerminalSegment = ({
|
|
|
1652
1726
|
};
|
|
1653
1727
|
|
|
1654
1728
|
// lib/solvers/TraceOverlapShiftSolver/TraceOverlapIssueSolver/TraceOverlapIssueSolver.ts
|
|
1655
|
-
var
|
|
1729
|
+
var EPS5 = 1e-6;
|
|
1656
1730
|
var TraceOverlapIssueSolver = class extends BaseSolver {
|
|
1657
1731
|
overlappingTraceSegments;
|
|
1658
1732
|
interactionKind;
|
|
@@ -1741,7 +1815,7 @@ var TraceOverlapIssueSolver = class extends BaseSolver {
|
|
|
1741
1815
|
}
|
|
1742
1816
|
applyOffsets(offsets) {
|
|
1743
1817
|
const correctedTraceMap = { ...this.correctedTraceMap };
|
|
1744
|
-
const eq = (a, b) => Math.abs(a - b) <
|
|
1818
|
+
const eq = (a, b) => Math.abs(a - b) < EPS5;
|
|
1745
1819
|
const samePoint = (p, q) => !!p && !!q && eq(p.x, q.x) && eq(p.y, q.y);
|
|
1746
1820
|
this.overlappingTraceSegments.forEach((group, groupIndex) => {
|
|
1747
1821
|
const offset = offsets[groupIndex];
|
|
@@ -1763,9 +1837,9 @@ var TraceOverlapIssueSolver = class extends BaseSolver {
|
|
|
1763
1837
|
const start = pts[si];
|
|
1764
1838
|
const end = pts[si + 1];
|
|
1765
1839
|
if (!start || !end) continue;
|
|
1766
|
-
if (Math.abs(start.x - end.x) <
|
|
1840
|
+
if (Math.abs(start.x - end.x) < EPS5) {
|
|
1767
1841
|
segmentAxes.set(si, "vertical");
|
|
1768
|
-
} else if (Math.abs(start.y - end.y) <
|
|
1842
|
+
} else if (Math.abs(start.y - end.y) < EPS5) {
|
|
1769
1843
|
segmentAxes.set(si, "horizontal");
|
|
1770
1844
|
}
|
|
1771
1845
|
}
|
|
@@ -1780,7 +1854,7 @@ var TraceOverlapIssueSolver = class extends BaseSolver {
|
|
|
1780
1854
|
segmentIndex: si,
|
|
1781
1855
|
offset,
|
|
1782
1856
|
JOG_SIZE,
|
|
1783
|
-
EPS:
|
|
1857
|
+
EPS: EPS5
|
|
1784
1858
|
});
|
|
1785
1859
|
} else {
|
|
1786
1860
|
const start = pts[si];
|
|
@@ -1867,7 +1941,7 @@ var TraceOverlapIssueSolver = class extends BaseSolver {
|
|
|
1867
1941
|
max = obstacle.maxY;
|
|
1868
1942
|
}
|
|
1869
1943
|
const next = orig + candidateOffset;
|
|
1870
|
-
return orig <= min +
|
|
1944
|
+
return orig <= min + EPS5 && next >= max - EPS5 || orig >= max - EPS5 && next <= min + EPS5;
|
|
1871
1945
|
});
|
|
1872
1946
|
const edges = blockingCollisions.map(({ start, isVertical: isVertical5, obstacle }) => {
|
|
1873
1947
|
if (isVertical5) {
|
|
@@ -1904,8 +1978,8 @@ var TraceOverlapIssueSolver = class extends BaseSolver {
|
|
|
1904
1978
|
const start = trace.tracePath[traceSegmentIndex];
|
|
1905
1979
|
const end = trace.tracePath[traceSegmentIndex + 1];
|
|
1906
1980
|
if (!start || !end) continue;
|
|
1907
|
-
const isVertical5 = Math.abs(start.x - end.x) <
|
|
1908
|
-
const isHorizontal4 = Math.abs(start.y - end.y) <
|
|
1981
|
+
const isVertical5 = Math.abs(start.x - end.x) < EPS5;
|
|
1982
|
+
const isHorizontal4 = Math.abs(start.y - end.y) < EPS5;
|
|
1909
1983
|
if (!isVertical5 && !isHorizontal4) continue;
|
|
1910
1984
|
const shiftedSegment = isVertical5 ? [
|
|
1911
1985
|
{ ...start, x: start.x + offset },
|
|
@@ -1997,7 +2071,7 @@ var TraceOverlapShiftSolver = class extends BaseSolver {
|
|
|
1997
2071
|
return islands;
|
|
1998
2072
|
}
|
|
1999
2073
|
findNextOverlapIssue() {
|
|
2000
|
-
const
|
|
2074
|
+
const EPS13 = 2e-3;
|
|
2001
2075
|
const netIds = Object.keys(this.traceNetIslands);
|
|
2002
2076
|
for (let i = 0; i < netIds.length; i++) {
|
|
2003
2077
|
for (let j = i + 1; j < netIds.length; j++) {
|
|
@@ -2024,7 +2098,7 @@ var TraceOverlapShiftSolver = class extends BaseSolver {
|
|
|
2024
2098
|
segmentBIndex,
|
|
2025
2099
|
rangeOverlap
|
|
2026
2100
|
}) => {
|
|
2027
|
-
if (rangeOverlap >
|
|
2101
|
+
if (rangeOverlap > EPS13) {
|
|
2028
2102
|
const keyA = `${pathAIndex}:${segmentAIndex}`;
|
|
2029
2103
|
const keyB = `${pathBIndex}:${segmentBIndex}`;
|
|
2030
2104
|
if (!seenA.has(keyA)) {
|
|
@@ -2043,7 +2117,7 @@ var TraceOverlapShiftSolver = class extends BaseSolver {
|
|
|
2043
2117
|
}
|
|
2044
2118
|
return;
|
|
2045
2119
|
}
|
|
2046
|
-
if (rangeOverlap < -
|
|
2120
|
+
if (rangeOverlap < -EPS13) return;
|
|
2047
2121
|
const pathA = pathsA[pathAIndex].tracePath;
|
|
2048
2122
|
const pathB = pathsB[pathBIndex].tracePath;
|
|
2049
2123
|
const segmentAStart = pathA[segmentAIndex];
|
|
@@ -2066,8 +2140,8 @@ var TraceOverlapShiftSolver = class extends BaseSolver {
|
|
|
2066
2140
|
for (let sa = 0; sa < ptsA.length - 1; sa++) {
|
|
2067
2141
|
const a1 = ptsA[sa];
|
|
2068
2142
|
const a2 = ptsA[sa + 1];
|
|
2069
|
-
const aVert = Math.abs(a1.x - a2.x) <
|
|
2070
|
-
const aHorz = Math.abs(a1.y - a2.y) <
|
|
2143
|
+
const aVert = Math.abs(a1.x - a2.x) < EPS13;
|
|
2144
|
+
const aHorz = Math.abs(a1.y - a2.y) < EPS13;
|
|
2071
2145
|
if (!aVert && !aHorz) continue;
|
|
2072
2146
|
for (let pb = 0; pb < pathsB.length; pb++) {
|
|
2073
2147
|
const pathB = pathsB[pb];
|
|
@@ -2075,11 +2149,11 @@ var TraceOverlapShiftSolver = class extends BaseSolver {
|
|
|
2075
2149
|
for (let sb = 0; sb < ptsB.length - 1; sb++) {
|
|
2076
2150
|
const b1 = ptsB[sb];
|
|
2077
2151
|
const b2 = ptsB[sb + 1];
|
|
2078
|
-
const bVert = Math.abs(b1.x - b2.x) <
|
|
2079
|
-
const bHorz = Math.abs(b1.y - b2.y) <
|
|
2152
|
+
const bVert = Math.abs(b1.x - b2.x) < EPS13;
|
|
2153
|
+
const bHorz = Math.abs(b1.y - b2.y) < EPS13;
|
|
2080
2154
|
if (!bVert && !bHorz) continue;
|
|
2081
2155
|
if (aVert && bVert) {
|
|
2082
|
-
if (Math.abs(a1.x - b1.x) <
|
|
2156
|
+
if (Math.abs(a1.x - b1.x) < EPS13) {
|
|
2083
2157
|
recordCollinearInteraction({
|
|
2084
2158
|
pathAIndex: pa,
|
|
2085
2159
|
segmentAIndex: sa,
|
|
@@ -2089,7 +2163,7 @@ var TraceOverlapShiftSolver = class extends BaseSolver {
|
|
|
2089
2163
|
});
|
|
2090
2164
|
}
|
|
2091
2165
|
} else if (aHorz && bHorz) {
|
|
2092
|
-
if (Math.abs(a1.y - b1.y) <
|
|
2166
|
+
if (Math.abs(a1.y - b1.y) < EPS13) {
|
|
2093
2167
|
recordCollinearInteraction({
|
|
2094
2168
|
pathAIndex: pa,
|
|
2095
2169
|
segmentAIndex: sa,
|
|
@@ -2145,14 +2219,14 @@ var TraceOverlapShiftSolver = class extends BaseSolver {
|
|
|
2145
2219
|
return null;
|
|
2146
2220
|
}
|
|
2147
2221
|
findNextDiagonalSegment() {
|
|
2148
|
-
const
|
|
2222
|
+
const EPS13 = 2e-3;
|
|
2149
2223
|
for (const mspPairId in this.correctedTraceMap) {
|
|
2150
2224
|
const tracePath = this.correctedTraceMap[mspPairId].tracePath;
|
|
2151
2225
|
for (let i = 0; i < tracePath.length - 1; i++) {
|
|
2152
2226
|
const p1 = tracePath[i];
|
|
2153
2227
|
const p2 = tracePath[i + 1];
|
|
2154
|
-
const isHorizontal4 = Math.abs(p1.y - p2.y) <
|
|
2155
|
-
const isVertical5 = Math.abs(p1.x - p2.x) <
|
|
2228
|
+
const isHorizontal4 = Math.abs(p1.y - p2.y) < EPS13;
|
|
2229
|
+
const isVertical5 = Math.abs(p1.x - p2.x) < EPS13;
|
|
2156
2230
|
if (!isHorizontal4 && !isVertical5) {
|
|
2157
2231
|
return { mspPairId, tracePath, i, p1, p2 };
|
|
2158
2232
|
}
|
|
@@ -2166,13 +2240,13 @@ var TraceOverlapShiftSolver = class extends BaseSolver {
|
|
|
2166
2240
|
return false;
|
|
2167
2241
|
}
|
|
2168
2242
|
const { mspPairId, tracePath, i, p1, p2 } = diagonalInfo;
|
|
2169
|
-
const
|
|
2243
|
+
const EPS13 = 2e-3;
|
|
2170
2244
|
const p0 = i > 0 ? tracePath[i - 1] : null;
|
|
2171
2245
|
const p3 = i + 2 < tracePath.length ? tracePath[i + 2] : null;
|
|
2172
|
-
const prevIsVertical = p0 ? Math.abs(p0.x - p1.x) <
|
|
2173
|
-
const prevIsHorizontal = p0 ? Math.abs(p0.y - p1.y) <
|
|
2174
|
-
const nextIsVertical = p3 ? Math.abs(p2.x - p3.x) <
|
|
2175
|
-
const nextIsHorizontal = p3 ? Math.abs(p2.y - p3.y) <
|
|
2246
|
+
const prevIsVertical = p0 ? Math.abs(p0.x - p1.x) < EPS13 : false;
|
|
2247
|
+
const prevIsHorizontal = p0 ? Math.abs(p0.y - p1.y) < EPS13 : false;
|
|
2248
|
+
const nextIsVertical = p3 ? Math.abs(p2.x - p3.x) < EPS13 : false;
|
|
2249
|
+
const nextIsHorizontal = p3 ? Math.abs(p2.y - p3.y) < EPS13 : false;
|
|
2176
2250
|
const elbow1 = { x: p1.x, y: p2.y };
|
|
2177
2251
|
const elbow2 = { x: p2.x, y: p1.y };
|
|
2178
2252
|
let score1 = 0;
|
|
@@ -2299,24 +2373,24 @@ var ChipObstacleSpatialIndex = class {
|
|
|
2299
2373
|
};
|
|
2300
2374
|
|
|
2301
2375
|
// lib/solvers/NetLabelPlacementSolver/SingleNetLabelPlacementSolver/collisions.ts
|
|
2302
|
-
function segmentIntersectsRect2(p1, p2, rect,
|
|
2303
|
-
const isVert = Math.abs(p1.x - p2.x) <
|
|
2304
|
-
const isHorz = Math.abs(p1.y - p2.y) <
|
|
2376
|
+
function segmentIntersectsRect2(p1, p2, rect, EPS13 = 1e-9) {
|
|
2377
|
+
const isVert = Math.abs(p1.x - p2.x) < EPS13;
|
|
2378
|
+
const isHorz = Math.abs(p1.y - p2.y) < EPS13;
|
|
2305
2379
|
if (!isVert && !isHorz) return false;
|
|
2306
2380
|
if (isVert) {
|
|
2307
2381
|
const x = p1.x;
|
|
2308
|
-
if (x < rect.minX -
|
|
2382
|
+
if (x < rect.minX - EPS13 || x > rect.maxX + EPS13) return false;
|
|
2309
2383
|
const segMinY = Math.min(p1.y, p2.y);
|
|
2310
2384
|
const segMaxY = Math.max(p1.y, p2.y);
|
|
2311
2385
|
const overlap = Math.min(segMaxY, rect.maxY) - Math.max(segMinY, rect.minY);
|
|
2312
|
-
return overlap >
|
|
2386
|
+
return overlap > EPS13;
|
|
2313
2387
|
} else {
|
|
2314
2388
|
const y = p1.y;
|
|
2315
|
-
if (y < rect.minY -
|
|
2389
|
+
if (y < rect.minY - EPS13 || y > rect.maxY + EPS13) return false;
|
|
2316
2390
|
const segMinX = Math.min(p1.x, p2.x);
|
|
2317
2391
|
const segMaxX = Math.max(p1.x, p2.x);
|
|
2318
2392
|
const overlap = Math.min(segMaxX, rect.maxX) - Math.max(segMinX, rect.minX);
|
|
2319
|
-
return overlap >
|
|
2393
|
+
return overlap > EPS13;
|
|
2320
2394
|
}
|
|
2321
2395
|
}
|
|
2322
2396
|
function rectIntersectsAnyTrace(bounds, inputTraceMap, hostPathId, hostSegIndex) {
|
|
@@ -2713,14 +2787,14 @@ var SingleNetLabelPlacementSolver = class extends BaseSolver {
|
|
|
2713
2787
|
};
|
|
2714
2788
|
let bestCandidate = null;
|
|
2715
2789
|
let bestScore = -Infinity;
|
|
2716
|
-
const
|
|
2790
|
+
const EPS13 = 1e-6;
|
|
2717
2791
|
for (const curr of tracesToScan) {
|
|
2718
2792
|
const pts = curr.tracePath.slice();
|
|
2719
2793
|
for (let si = 0; si < pts.length - 1; si++) {
|
|
2720
2794
|
const a = pts[si];
|
|
2721
2795
|
const b = pts[si + 1];
|
|
2722
|
-
const isH = Math.abs(a.y - b.y) <
|
|
2723
|
-
const isV = Math.abs(a.x - b.x) <
|
|
2796
|
+
const isH = Math.abs(a.y - b.y) < EPS13;
|
|
2797
|
+
const isV = Math.abs(a.x - b.x) < EPS13;
|
|
2724
2798
|
if (!isH && !isV) continue;
|
|
2725
2799
|
const segmentAllowed = isH ? ["y+", "y-"] : ["x+", "x-"];
|
|
2726
2800
|
const candidateOrients = orientations.filter(
|
|
@@ -3820,7 +3894,7 @@ var SingleOverlapSolver = class extends BaseSolver {
|
|
|
3820
3894
|
paddingBuffer: effectivePadding
|
|
3821
3895
|
// Use the calculated, larger padding
|
|
3822
3896
|
});
|
|
3823
|
-
const
|
|
3897
|
+
const getPathLength3 = (pts) => {
|
|
3824
3898
|
let len = 0;
|
|
3825
3899
|
for (let i = 0; i < pts.length - 1; i++) {
|
|
3826
3900
|
const dx = pts[i + 1].x - pts[i].x;
|
|
@@ -3830,7 +3904,7 @@ var SingleOverlapSolver = class extends BaseSolver {
|
|
|
3830
3904
|
return len;
|
|
3831
3905
|
};
|
|
3832
3906
|
this.queuedCandidatePaths = candidates.sort(
|
|
3833
|
-
(a, b) =>
|
|
3907
|
+
(a, b) => getPathLength3(a) - getPathLength3(b)
|
|
3834
3908
|
);
|
|
3835
3909
|
this.obstacles = getObstacleRects(this.problem);
|
|
3836
3910
|
}
|
|
@@ -5123,9 +5197,9 @@ var moveRailSegments = (trace, segments, coordinate) => {
|
|
|
5123
5197
|
};
|
|
5124
5198
|
|
|
5125
5199
|
// lib/solvers/RailNetLabelCornerPlacementSolver/geometry.ts
|
|
5126
|
-
var
|
|
5200
|
+
var EPS6 = 1e-6;
|
|
5127
5201
|
var isTraceLine = (trace) => getUniquePinCount(trace.pinIds) >= 2;
|
|
5128
|
-
var rectsOverlap = (a, b) => Math.min(a.maxX, b.maxX) - Math.max(a.minX, b.minX) >
|
|
5202
|
+
var rectsOverlap = (a, b) => Math.min(a.maxX, b.maxX) - Math.max(a.minX, b.minX) > EPS6 && Math.min(a.maxY, b.maxY) - Math.max(a.minY, b.minY) > EPS6;
|
|
5129
5203
|
var getTraceCorners = (path) => {
|
|
5130
5204
|
const corners = [];
|
|
5131
5205
|
for (let i = 1; i < path.length - 1; i++) {
|
|
@@ -5149,11 +5223,11 @@ var getUniquePinCount = (pinIds) => new Set(pinIds).size;
|
|
|
5149
5223
|
var isTraceCorner = (a, b, c) => getSegmentOrientation(a, b) !== getSegmentOrientation(b, c);
|
|
5150
5224
|
var isPointOnSegment = (point, start, end) => {
|
|
5151
5225
|
if (getSegmentOrientation(start, end) === "horizontal") {
|
|
5152
|
-
return Math.abs(point.y - start.y) <=
|
|
5226
|
+
return Math.abs(point.y - start.y) <= EPS6 && point.x >= Math.min(start.x, end.x) - EPS6 && point.x <= Math.max(start.x, end.x) + EPS6;
|
|
5153
5227
|
}
|
|
5154
|
-
return Math.abs(point.x - start.x) <=
|
|
5228
|
+
return Math.abs(point.x - start.x) <= EPS6 && point.y >= Math.min(start.y, end.y) - EPS6 && point.y <= Math.max(start.y, end.y) + EPS6;
|
|
5155
5229
|
};
|
|
5156
|
-
var getSegmentOrientation = (a, b) => Math.abs(a.y - b.y) <=
|
|
5230
|
+
var getSegmentOrientation = (a, b) => Math.abs(a.y - b.y) <= EPS6 ? "horizontal" : "vertical";
|
|
5157
5231
|
|
|
5158
5232
|
// lib/solvers/TraceCleanupSolver/sameNetRailAlignment/preservesLabelAnchors.ts
|
|
5159
5233
|
var getAnchoredTraceIds = (label, traces) => new Set(
|
|
@@ -5169,17 +5243,17 @@ var preservesLabelAnchors = (labels, before, after) => labels.every((label) => {
|
|
|
5169
5243
|
});
|
|
5170
5244
|
|
|
5171
5245
|
// lib/solvers/Example28Solver/types.ts
|
|
5172
|
-
var
|
|
5246
|
+
var EPS7 = 1e-9;
|
|
5173
5247
|
|
|
5174
5248
|
// lib/solvers/Example28Solver/segmentRunsAlongRectBoundary.ts
|
|
5175
5249
|
var segmentRunsAlongRectBoundary = (start, end, rect) => {
|
|
5176
|
-
const isVertical5 = Math.abs(start.x - end.x) <
|
|
5177
|
-
const isHorizontal4 = Math.abs(start.y - end.y) <
|
|
5250
|
+
const isVertical5 = Math.abs(start.x - end.x) < EPS7;
|
|
5251
|
+
const isHorizontal4 = Math.abs(start.y - end.y) < EPS7;
|
|
5178
5252
|
if (isVertical5) {
|
|
5179
|
-
return Math.abs(start.x - rect.minX) <
|
|
5253
|
+
return Math.abs(start.x - rect.minX) < EPS7 || Math.abs(start.x - rect.maxX) < EPS7;
|
|
5180
5254
|
}
|
|
5181
5255
|
if (isHorizontal4) {
|
|
5182
|
-
return Math.abs(start.y - rect.minY) <
|
|
5256
|
+
return Math.abs(start.y - rect.minY) < EPS7 || Math.abs(start.y - rect.maxY) < EPS7;
|
|
5183
5257
|
}
|
|
5184
5258
|
return false;
|
|
5185
5259
|
};
|
|
@@ -5194,10 +5268,10 @@ var getPathLength = (path) => {
|
|
|
5194
5268
|
return length;
|
|
5195
5269
|
};
|
|
5196
5270
|
var getDistance2 = (a, b) => Math.abs(a.x - b.x) + Math.abs(a.y - b.y);
|
|
5197
|
-
var isAxisAlignedSegment = (start, end) => Math.abs(start.x - end.x) <
|
|
5198
|
-
var getSegmentOrientation2 = (start, end) => Math.abs(start.y - end.y) <
|
|
5271
|
+
var isAxisAlignedSegment = (start, end) => Math.abs(start.x - end.x) < EPS7 || Math.abs(start.y - end.y) < EPS7;
|
|
5272
|
+
var getSegmentOrientation2 = (start, end) => Math.abs(start.y - end.y) < EPS7 ? "horizontal" : "vertical";
|
|
5199
5273
|
var projectPointToSegment = (point, start, end) => {
|
|
5200
|
-
if (Math.abs(start.x - end.x) <
|
|
5274
|
+
if (Math.abs(start.x - end.x) < EPS7) {
|
|
5201
5275
|
return {
|
|
5202
5276
|
x: start.x,
|
|
5203
5277
|
y: Math.min(
|
|
@@ -5206,7 +5280,7 @@ var projectPointToSegment = (point, start, end) => {
|
|
|
5206
5280
|
)
|
|
5207
5281
|
};
|
|
5208
5282
|
}
|
|
5209
|
-
if (Math.abs(start.y - end.y) <
|
|
5283
|
+
if (Math.abs(start.y - end.y) < EPS7) {
|
|
5210
5284
|
return {
|
|
5211
5285
|
x: Math.min(
|
|
5212
5286
|
Math.max(point.x, Math.min(start.x, end.x)),
|
|
@@ -5249,9 +5323,9 @@ var findSegmentContainingPoint = (path, point) => {
|
|
|
5249
5323
|
};
|
|
5250
5324
|
var isPointWithinSegmentPrimaryRange = (point, segment) => {
|
|
5251
5325
|
if (segment.orientation === "horizontal") {
|
|
5252
|
-
return point.x >= Math.min(segment.start.x, segment.end.x) -
|
|
5326
|
+
return point.x >= Math.min(segment.start.x, segment.end.x) - EPS7 && point.x <= Math.max(segment.start.x, segment.end.x) + EPS7;
|
|
5253
5327
|
}
|
|
5254
|
-
return point.y >= Math.min(segment.start.y, segment.end.y) -
|
|
5328
|
+
return point.y >= Math.min(segment.start.y, segment.end.y) - EPS7 && point.y <= Math.max(segment.start.y, segment.end.y) + EPS7;
|
|
5255
5329
|
};
|
|
5256
5330
|
var findPreferredReroutedSegment = (path, originalSegmentIndex, originalSegmentCount, orientation, anchorPoint) => {
|
|
5257
5331
|
const matchingSegments = getSegments(path).filter(
|
|
@@ -5270,27 +5344,27 @@ var projectPointToPath = (point, path) => {
|
|
|
5270
5344
|
let bestDistance = Number.POSITIVE_INFINITY;
|
|
5271
5345
|
for (let i = 0; i < path.length - 1; i++) {
|
|
5272
5346
|
const projectedPoint = projectPointToSegment(point, path[i], path[i + 1]);
|
|
5273
|
-
const
|
|
5274
|
-
if (
|
|
5347
|
+
const distance5 = getDistance2(point, projectedPoint);
|
|
5348
|
+
if (distance5 < bestDistance) {
|
|
5275
5349
|
bestPoint = projectedPoint;
|
|
5276
|
-
bestDistance =
|
|
5350
|
+
bestDistance = distance5;
|
|
5277
5351
|
}
|
|
5278
5352
|
}
|
|
5279
5353
|
return bestPoint;
|
|
5280
5354
|
};
|
|
5281
5355
|
var segmentsIntersect = (a1, a2, b1, b2) => {
|
|
5282
|
-
const aVertical = Math.abs(a1.x - a2.x) <
|
|
5283
|
-
const bVertical = Math.abs(b1.x - b2.x) <
|
|
5284
|
-
const between = (value, p1, p2) => value >= Math.min(p1, p2) -
|
|
5356
|
+
const aVertical = Math.abs(a1.x - a2.x) < EPS7;
|
|
5357
|
+
const bVertical = Math.abs(b1.x - b2.x) < EPS7;
|
|
5358
|
+
const between = (value, p1, p2) => value >= Math.min(p1, p2) - EPS7 && value <= Math.max(p1, p2) + EPS7;
|
|
5285
5359
|
if (aVertical && bVertical) {
|
|
5286
|
-
if (Math.abs(a1.x - b1.x) >
|
|
5360
|
+
if (Math.abs(a1.x - b1.x) > EPS7) return false;
|
|
5287
5361
|
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));
|
|
5288
|
-
return overlap >
|
|
5362
|
+
return overlap > EPS7;
|
|
5289
5363
|
}
|
|
5290
5364
|
if (!aVertical && !bVertical) {
|
|
5291
|
-
if (Math.abs(a1.y - b1.y) >
|
|
5365
|
+
if (Math.abs(a1.y - b1.y) > EPS7) return false;
|
|
5292
5366
|
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));
|
|
5293
|
-
return overlap >
|
|
5367
|
+
return overlap > EPS7;
|
|
5294
5368
|
}
|
|
5295
5369
|
const verticalA = aVertical ? a1 : b1;
|
|
5296
5370
|
const verticalB = aVertical ? a2 : b2;
|
|
@@ -5652,7 +5726,7 @@ var getTraceObstacles = (allTraces, excludeTraceId) => {
|
|
|
5652
5726
|
|
|
5653
5727
|
// lib/solvers/TraceCleanupSolver/sub-solver/findIntersectionsWithObstacles.ts
|
|
5654
5728
|
import { getSegmentIntersection } from "@tscircuit/math-utils/line-intersections";
|
|
5655
|
-
var
|
|
5729
|
+
var EPS8 = 1e-6;
|
|
5656
5730
|
var findIntersectionsWithObstacles = (p1, p2, obstacles) => {
|
|
5657
5731
|
const intersections = [];
|
|
5658
5732
|
for (const obstacle of obstacles) {
|
|
@@ -5671,17 +5745,17 @@ var findIntersectionsWithObstacles = (p1, p2, obstacles) => {
|
|
|
5671
5745
|
}
|
|
5672
5746
|
return intersections;
|
|
5673
5747
|
};
|
|
5674
|
-
var isSamePoint = (first, second) => Math.abs(first.x - second.x) <
|
|
5748
|
+
var isSamePoint = (first, second) => Math.abs(first.x - second.x) < EPS8 && Math.abs(first.y - second.y) < EPS8;
|
|
5675
5749
|
var findPerpendicularPathCrossings = (path, otherPath) => {
|
|
5676
5750
|
const crossings = [];
|
|
5677
5751
|
for (let pathSegmentIndex = 1; pathSegmentIndex < path.length - 2; pathSegmentIndex++) {
|
|
5678
5752
|
const start = path[pathSegmentIndex];
|
|
5679
5753
|
const end = path[pathSegmentIndex + 1];
|
|
5680
|
-
const isVertical5 = Math.abs(start.x - end.x) <
|
|
5754
|
+
const isVertical5 = Math.abs(start.x - end.x) < EPS8;
|
|
5681
5755
|
for (let otherPathSegmentIndex = 1; otherPathSegmentIndex < otherPath.length - 2; otherPathSegmentIndex++) {
|
|
5682
5756
|
const otherStart = otherPath[otherPathSegmentIndex];
|
|
5683
5757
|
const otherEnd = otherPath[otherPathSegmentIndex + 1];
|
|
5684
|
-
const otherIsVertical = Math.abs(otherStart.x - otherEnd.x) <
|
|
5758
|
+
const otherIsVertical = Math.abs(otherStart.x - otherEnd.x) < EPS8;
|
|
5685
5759
|
if (isVertical5 === otherIsVertical) continue;
|
|
5686
5760
|
const intersection = getSegmentIntersection(
|
|
5687
5761
|
start,
|
|
@@ -5701,8 +5775,8 @@ var findPerpendicularPathCrossings = (path, otherPath) => {
|
|
|
5701
5775
|
};
|
|
5702
5776
|
|
|
5703
5777
|
// lib/solvers/TraceCleanupSolver/sub-solver/generateLShapeRerouteCandidates.ts
|
|
5704
|
-
var
|
|
5705
|
-
var isVertical3 = (a, b, eps =
|
|
5778
|
+
var EPS9 = 1e-6;
|
|
5779
|
+
var isVertical3 = (a, b, eps = EPS9) => Math.abs(a.x - b.x) < eps;
|
|
5706
5780
|
var generateLShapeRerouteCandidates = ({
|
|
5707
5781
|
lShape,
|
|
5708
5782
|
rectangle,
|
|
@@ -5715,7 +5789,7 @@ var generateLShapeRerouteCandidates = ({
|
|
|
5715
5789
|
let c2;
|
|
5716
5790
|
let i1_padded = interactionPoint1;
|
|
5717
5791
|
let i2_padded = interactionPoint2;
|
|
5718
|
-
if (Math.abs(p2.x - x) <
|
|
5792
|
+
if (Math.abs(p2.x - x) < EPS9 && Math.abs(p2.y - (y + height)) < EPS9) {
|
|
5719
5793
|
c2 = { x: x + width + padding, y: y - padding };
|
|
5720
5794
|
if (isVertical3(p1, p2)) {
|
|
5721
5795
|
i1_padded = { x: interactionPoint1.x, y: interactionPoint1.y - padding };
|
|
@@ -5727,7 +5801,7 @@ var generateLShapeRerouteCandidates = ({
|
|
|
5727
5801
|
} else {
|
|
5728
5802
|
i2_padded = { x: interactionPoint2.x + padding, y: interactionPoint2.y };
|
|
5729
5803
|
}
|
|
5730
|
-
} else if (Math.abs(p2.x - (x + width)) <
|
|
5804
|
+
} else if (Math.abs(p2.x - (x + width)) < EPS9 && Math.abs(p2.y - (y + height)) < EPS9) {
|
|
5731
5805
|
c2 = { x: x - padding, y: y - padding };
|
|
5732
5806
|
if (isVertical3(p1, p2)) {
|
|
5733
5807
|
i1_padded = { x: interactionPoint1.x, y: interactionPoint1.y - padding };
|
|
@@ -5739,7 +5813,7 @@ var generateLShapeRerouteCandidates = ({
|
|
|
5739
5813
|
} else {
|
|
5740
5814
|
i2_padded = { x: interactionPoint2.x - padding, y: interactionPoint2.y };
|
|
5741
5815
|
}
|
|
5742
|
-
} else if (Math.abs(p2.x - x) <
|
|
5816
|
+
} else if (Math.abs(p2.x - x) < EPS9 && Math.abs(p2.y - y) < EPS9) {
|
|
5743
5817
|
c2 = { x: x + width + padding, y: y + height + padding };
|
|
5744
5818
|
if (isVertical3(p1, p2)) {
|
|
5745
5819
|
i1_padded = { x: interactionPoint1.x, y: interactionPoint1.y + padding };
|
|
@@ -5751,7 +5825,7 @@ var generateLShapeRerouteCandidates = ({
|
|
|
5751
5825
|
} else {
|
|
5752
5826
|
i2_padded = { x: interactionPoint2.x + padding, y: interactionPoint2.y };
|
|
5753
5827
|
}
|
|
5754
|
-
} else if (Math.abs(p2.x - (x + width)) <
|
|
5828
|
+
} else if (Math.abs(p2.x - (x + width)) < EPS9 && Math.abs(p2.y - y) < EPS9) {
|
|
5755
5829
|
c2 = { x: x - padding, y: y + height + padding };
|
|
5756
5830
|
if (isVertical3(p1, p2)) {
|
|
5757
5831
|
i1_padded = { x: interactionPoint1.x, y: interactionPoint1.y + padding };
|
|
@@ -5779,7 +5853,7 @@ var generatePerpendicularTraceDetours = ({
|
|
|
5779
5853
|
const buildDetours = (path, index) => {
|
|
5780
5854
|
const start = path[index];
|
|
5781
5855
|
const end = path[index + 1];
|
|
5782
|
-
const movingAxis = Math.abs(start.x - end.x) <
|
|
5856
|
+
const movingAxis = Math.abs(start.x - end.x) < EPS9 ? "y" : "x";
|
|
5783
5857
|
const detourAxis = movingAxis === "x" ? "y" : "x";
|
|
5784
5858
|
const gate = obstacleStart[movingAxis] + Math.sign(start[movingAxis] - obstacleStart[movingAxis]) * clearance;
|
|
5785
5859
|
const obstacleRange = [obstacleStart[detourAxis], obstacleEnd[detourAxis]];
|
|
@@ -6377,9 +6451,9 @@ var UntangleTraceSubsolver = class extends BaseSolver {
|
|
|
6377
6451
|
};
|
|
6378
6452
|
|
|
6379
6453
|
// lib/solvers/TraceCleanupSolver/is4PointRectangle.ts
|
|
6380
|
-
var
|
|
6381
|
-
var sameX = (a, b) => Math.abs(a.x - b.x) <=
|
|
6382
|
-
var sameY = (a, b) => Math.abs(a.y - b.y) <=
|
|
6454
|
+
var EPS10 = 1e-6;
|
|
6455
|
+
var sameX = (a, b) => Math.abs(a.x - b.x) <= EPS10;
|
|
6456
|
+
var sameY = (a, b) => Math.abs(a.y - b.y) <= EPS10;
|
|
6383
6457
|
var is4PointRectangle = (path) => {
|
|
6384
6458
|
if (path.length !== 4) return false;
|
|
6385
6459
|
const [p0, p1, p2, p3] = path;
|
|
@@ -6654,7 +6728,7 @@ var doesPathRunAlongChipBoundary = (path, chipObstacles) => {
|
|
|
6654
6728
|
const end = path[i + 1];
|
|
6655
6729
|
for (const obstacle of chipObstacles) {
|
|
6656
6730
|
if (!segmentRunsAlongRectBoundary(start, end, obstacle)) continue;
|
|
6657
|
-
if (getSegmentOverlapWithRectSpan(start, end, obstacle) >
|
|
6731
|
+
if (getSegmentOverlapWithRectSpan(start, end, obstacle) > EPS7) {
|
|
6658
6732
|
return true;
|
|
6659
6733
|
}
|
|
6660
6734
|
}
|
|
@@ -6669,13 +6743,13 @@ var getChipBoundaryOverlap = (path, chipObstacles) => {
|
|
|
6669
6743
|
for (const obstacle of chipObstacles) {
|
|
6670
6744
|
if (!segmentRunsAlongRectBoundary(start, end, obstacle)) continue;
|
|
6671
6745
|
const overlap = getSegmentOverlapWithRectSpan(start, end, obstacle);
|
|
6672
|
-
if (overlap >
|
|
6746
|
+
if (overlap > EPS7) total += overlap;
|
|
6673
6747
|
}
|
|
6674
6748
|
}
|
|
6675
6749
|
return total;
|
|
6676
6750
|
};
|
|
6677
6751
|
var getSegmentOverlapWithRectSpan = (start, end, rect) => {
|
|
6678
|
-
const isVertical5 = Math.abs(start.x - end.x) <
|
|
6752
|
+
const isVertical5 = Math.abs(start.x - end.x) < EPS7;
|
|
6679
6753
|
if (isVertical5) {
|
|
6680
6754
|
return Math.min(Math.max(start.y, end.y), rect.maxY) - Math.max(Math.min(start.y, end.y), rect.minY);
|
|
6681
6755
|
}
|
|
@@ -7087,11 +7161,11 @@ var getLabelHugDistance = (tracePath, obstacleLabel) => {
|
|
|
7087
7161
|
obstacleLabel.width,
|
|
7088
7162
|
obstacleLabel.height
|
|
7089
7163
|
);
|
|
7090
|
-
let
|
|
7164
|
+
let distance5 = 0;
|
|
7091
7165
|
for (const point of tracePath) {
|
|
7092
|
-
|
|
7166
|
+
distance5 += getPointDistanceFromRect(point, bounds);
|
|
7093
7167
|
}
|
|
7094
|
-
return
|
|
7168
|
+
return distance5;
|
|
7095
7169
|
};
|
|
7096
7170
|
var getPointDistanceFromRect = (point, rect) => {
|
|
7097
7171
|
const dx = Math.max(rect.minX - point.x, 0, point.x - rect.maxX);
|
|
@@ -7368,16 +7442,16 @@ var Example28Solver = class extends BaseSolver {
|
|
|
7368
7442
|
const outward = dir(label.orientation);
|
|
7369
7443
|
if (outward.x === 0 && outward.y === 0) return null;
|
|
7370
7444
|
for (let step = 1; step <= LABEL_MAX_OUTWARD_STEPS; step++) {
|
|
7371
|
-
const
|
|
7445
|
+
const distance5 = step * LABEL_OUTWARD_STEP;
|
|
7372
7446
|
const candidate = {
|
|
7373
7447
|
...label,
|
|
7374
7448
|
anchorPoint: {
|
|
7375
|
-
x: label.anchorPoint.x + outward.x *
|
|
7376
|
-
y: label.anchorPoint.y + outward.y *
|
|
7449
|
+
x: label.anchorPoint.x + outward.x * distance5,
|
|
7450
|
+
y: label.anchorPoint.y + outward.y * distance5
|
|
7377
7451
|
},
|
|
7378
7452
|
center: {
|
|
7379
|
-
x: label.center.x + outward.x *
|
|
7380
|
-
y: label.center.y + outward.y *
|
|
7453
|
+
x: label.center.x + outward.x * distance5,
|
|
7454
|
+
y: label.center.y + outward.y * distance5
|
|
7381
7455
|
}
|
|
7382
7456
|
};
|
|
7383
7457
|
const candidateWithClearance = {
|
|
@@ -7439,16 +7513,16 @@ var createPortOnlyLabelConnectorTrace = ({
|
|
|
7439
7513
|
// lib/solvers/AvailableNetOrientationSolver/constants.ts
|
|
7440
7514
|
var LABEL_SEARCH_STEP = 0.05;
|
|
7441
7515
|
var WICK_CLEARANCE = 1e-3;
|
|
7442
|
-
var
|
|
7443
|
-
var TRACE_BOUNDARY_TOLERANCE = WICK_CLEARANCE +
|
|
7516
|
+
var EPS11 = 1e-9;
|
|
7517
|
+
var TRACE_BOUNDARY_TOLERANCE = WICK_CLEARANCE + EPS11;
|
|
7444
7518
|
var CANDIDATE_SELECTED_COLOR2 = "blue";
|
|
7445
7519
|
var CANDIDATE_REJECTED_COLOR2 = "red";
|
|
7446
7520
|
|
|
7447
7521
|
// lib/solvers/AvailableNetOrientationSolver/geometry.ts
|
|
7448
7522
|
var isYOrientation = (orientation) => orientation === "y+" || orientation === "y-";
|
|
7449
7523
|
var isXOrientation = (orientation) => orientation === "x+" || orientation === "x-";
|
|
7450
|
-
var rectsOverlap2 = (a, b) => Math.min(a.maxX, b.maxX) - Math.max(a.minX, b.minX) >
|
|
7451
|
-
var rangesOverlap = (minA, maxA, minB, maxB) => Math.min(maxA, maxB) - Math.max(minA, minB) >
|
|
7524
|
+
var rectsOverlap2 = (a, b) => Math.min(a.maxX, b.maxX) - Math.max(a.minX, b.minX) > EPS11 && Math.min(a.maxY, b.maxY) - Math.max(a.minY, b.minY) > EPS11;
|
|
7525
|
+
var rangesOverlap = (minA, maxA, minB, maxB) => Math.min(maxA, maxB) - Math.max(minA, minB) > EPS11;
|
|
7452
7526
|
var traceCrossesBoundsInterior = (bounds, traceMap) => {
|
|
7453
7527
|
for (const trace of Object.values(traceMap)) {
|
|
7454
7528
|
const points = trace.tracePath;
|
|
@@ -7471,7 +7545,7 @@ var segmentCrossesBoundsInterior = (p1, p2, bounds) => {
|
|
|
7471
7545
|
return false;
|
|
7472
7546
|
}
|
|
7473
7547
|
if (sameX2(p1, p2)) {
|
|
7474
|
-
if (p1.x <= interiorBounds.minX +
|
|
7548
|
+
if (p1.x <= interiorBounds.minX + EPS11 || p1.x >= interiorBounds.maxX - EPS11) {
|
|
7475
7549
|
return false;
|
|
7476
7550
|
}
|
|
7477
7551
|
return rangesOverlap(
|
|
@@ -7482,7 +7556,7 @@ var segmentCrossesBoundsInterior = (p1, p2, bounds) => {
|
|
|
7482
7556
|
);
|
|
7483
7557
|
}
|
|
7484
7558
|
if (sameY2(p1, p2)) {
|
|
7485
|
-
if (p1.y <= interiorBounds.minY +
|
|
7559
|
+
if (p1.y <= interiorBounds.minY + EPS11 || p1.y >= interiorBounds.maxY - EPS11) {
|
|
7486
7560
|
return false;
|
|
7487
7561
|
}
|
|
7488
7562
|
return rangesOverlap(
|
|
@@ -7538,8 +7612,8 @@ var simplifyOrthogonalPath = (path) => {
|
|
|
7538
7612
|
return simplified;
|
|
7539
7613
|
};
|
|
7540
7614
|
var pointsEqual2 = (a, b) => sameX2(a, b) && sameY2(a, b);
|
|
7541
|
-
var sameX2 = (a, b) => Math.abs(a.x - b.x) <=
|
|
7542
|
-
var sameY2 = (a, b) => Math.abs(a.y - b.y) <=
|
|
7615
|
+
var sameX2 = (a, b) => Math.abs(a.x - b.x) <= EPS11;
|
|
7616
|
+
var sameY2 = (a, b) => Math.abs(a.y - b.y) <= EPS11;
|
|
7543
7617
|
var getMaxSearchDistance = (inputProblem) => {
|
|
7544
7618
|
const maxChipWidth = Math.max(
|
|
7545
7619
|
...inputProblem.chips.map((chip) => chip.width),
|
|
@@ -7794,11 +7868,11 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
|
|
|
7794
7868
|
if (trace.globalConnNetId !== label.globalConnNetId) return false;
|
|
7795
7869
|
const path = trace.tracePath;
|
|
7796
7870
|
return path.some((point, pointIndex) => {
|
|
7797
|
-
if (Math.abs(point.x - label.anchorPoint.x) >
|
|
7871
|
+
if (Math.abs(point.x - label.anchorPoint.x) > EPS11 || Math.abs(point.y - label.anchorPoint.y) > EPS11) {
|
|
7798
7872
|
return false;
|
|
7799
7873
|
}
|
|
7800
7874
|
return [path[pointIndex - 1], path[pointIndex + 1]].some(
|
|
7801
|
-
(neighbor) => neighbor && Math.abs(neighbor.x - point.x) <=
|
|
7875
|
+
(neighbor) => neighbor && Math.abs(neighbor.x - point.x) <= EPS11 && (neighbor.y - point.y) * direction.y > EPS11
|
|
7802
7876
|
);
|
|
7803
7877
|
});
|
|
7804
7878
|
});
|
|
@@ -7877,7 +7951,7 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
|
|
|
7877
7951
|
);
|
|
7878
7952
|
const maxSearchDistance = this.getSearchDistanceLimit(label, orientation);
|
|
7879
7953
|
const maxOutwardDistance = outwardDirection.x === 0 && outwardDirection.y === 0 ? 0 : this.maxSearchDistance;
|
|
7880
|
-
for (let outwardDistance = 0; outwardDistance <= maxOutwardDistance +
|
|
7954
|
+
for (let outwardDistance = 0; outwardDistance <= maxOutwardDistance + EPS11; outwardDistance += LABEL_SEARCH_STEP) {
|
|
7881
7955
|
const baseAnchor = {
|
|
7882
7956
|
x: initialBaseAnchor.x + outwardDirection.x * outwardDistance,
|
|
7883
7957
|
y: initialBaseAnchor.y + outwardDirection.y * outwardDistance
|
|
@@ -7951,10 +8025,10 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
|
|
|
7951
8025
|
phase = "shift",
|
|
7952
8026
|
stopOnTraceCollision = true
|
|
7953
8027
|
} = params;
|
|
7954
|
-
for (let
|
|
8028
|
+
for (let distance5 = LABEL_SEARCH_STEP; distance5 <= maxSearchDistance + EPS11; distance5 += LABEL_SEARCH_STEP) {
|
|
7955
8029
|
const anchorPoint = {
|
|
7956
|
-
x: baseAnchor.x + direction.x *
|
|
7957
|
-
y: baseAnchor.y + direction.y *
|
|
8030
|
+
x: baseAnchor.x + direction.x * distance5,
|
|
8031
|
+
y: baseAnchor.y + direction.y * distance5
|
|
7958
8032
|
};
|
|
7959
8033
|
const candidate = this.createCandidate(label, anchorPoint, orientation);
|
|
7960
8034
|
const result = this.evaluateCandidate(
|
|
@@ -7962,7 +8036,7 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
|
|
|
7962
8036
|
label,
|
|
7963
8037
|
labelIndex,
|
|
7964
8038
|
phase,
|
|
7965
|
-
|
|
8039
|
+
distance5,
|
|
7966
8040
|
outwardDistance
|
|
7967
8041
|
);
|
|
7968
8042
|
this.currentCandidateResults.push(result);
|
|
@@ -7974,11 +8048,11 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
|
|
|
7974
8048
|
}
|
|
7975
8049
|
return null;
|
|
7976
8050
|
}
|
|
7977
|
-
evaluateCandidate(candidate, label, labelIndex, phase,
|
|
8051
|
+
evaluateCandidate(candidate, label, labelIndex, phase, distance5, outwardDistance) {
|
|
7978
8052
|
return {
|
|
7979
8053
|
...candidate,
|
|
7980
8054
|
phase,
|
|
7981
|
-
distance:
|
|
8055
|
+
distance: distance5,
|
|
7982
8056
|
outwardDistance,
|
|
7983
8057
|
selected: false,
|
|
7984
8058
|
status: this.getCandidateStatus({
|
|
@@ -8188,9 +8262,9 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
|
|
|
8188
8262
|
const { anchorPoint, orientation } = candidate;
|
|
8189
8263
|
const chipBounds = chip.bounds;
|
|
8190
8264
|
if (isYOrientation(orientation)) {
|
|
8191
|
-
return anchorPoint.x < chipBounds.minX -
|
|
8265
|
+
return anchorPoint.x < chipBounds.minX - EPS11 || anchorPoint.x > chipBounds.maxX + EPS11;
|
|
8192
8266
|
}
|
|
8193
|
-
return anchorPoint.y < chipBounds.minY -
|
|
8267
|
+
return anchorPoint.y < chipBounds.minY - EPS11 || anchorPoint.y > chipBounds.maxY + EPS11;
|
|
8194
8268
|
});
|
|
8195
8269
|
}
|
|
8196
8270
|
getBoundsStatus(candidateBoundsCheck) {
|
|
@@ -8264,8 +8338,8 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
|
|
|
8264
8338
|
sharesChipBoundary(bounds) {
|
|
8265
8339
|
for (const chip of this.chipObstacleSpatialIndex.chips) {
|
|
8266
8340
|
const chipBounds = chip.bounds;
|
|
8267
|
-
const adjacentToVerticalSide = Math.abs(bounds.minX - chipBounds.maxX) <= WICK_CLEARANCE +
|
|
8268
|
-
const adjacentToHorizontalSide = Math.abs(bounds.minY - chipBounds.maxY) <= WICK_CLEARANCE +
|
|
8341
|
+
const adjacentToVerticalSide = Math.abs(bounds.minX - chipBounds.maxX) <= WICK_CLEARANCE + EPS11 || Math.abs(bounds.maxX - chipBounds.minX) <= WICK_CLEARANCE + EPS11;
|
|
8342
|
+
const adjacentToHorizontalSide = Math.abs(bounds.minY - chipBounds.maxY) <= WICK_CLEARANCE + EPS11 || Math.abs(bounds.maxY - chipBounds.minY) <= WICK_CLEARANCE + EPS11;
|
|
8269
8343
|
if (adjacentToVerticalSide && rangesOverlap(
|
|
8270
8344
|
bounds.minY,
|
|
8271
8345
|
bounds.maxY,
|
|
@@ -8313,13 +8387,13 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
|
|
|
8313
8387
|
let nearestDistance = Number.POSITIVE_INFINITY;
|
|
8314
8388
|
for (const chip of this.chipObstacleSpatialIndex.chips) {
|
|
8315
8389
|
const bounds = chip.bounds;
|
|
8316
|
-
if (point.x < bounds.minX -
|
|
8390
|
+
if (point.x < bounds.minX - EPS11 || point.x > bounds.maxX + EPS11 || point.y < bounds.minY - EPS11 || point.y > bounds.maxY + EPS11) {
|
|
8317
8391
|
continue;
|
|
8318
8392
|
}
|
|
8319
|
-
for (const [side,
|
|
8320
|
-
if (
|
|
8393
|
+
for (const [side, distance5] of getSideDistances(point, bounds)) {
|
|
8394
|
+
if (distance5 < nearestDistance) {
|
|
8321
8395
|
nearestSide = side;
|
|
8322
|
-
nearestDistance =
|
|
8396
|
+
nearestDistance = distance5;
|
|
8323
8397
|
}
|
|
8324
8398
|
}
|
|
8325
8399
|
}
|
|
@@ -8330,8 +8404,8 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
|
|
|
8330
8404
|
let nearestDistanceSq = Number.POSITIVE_INFINITY;
|
|
8331
8405
|
for (const chip of this.chipObstacleSpatialIndex.chips) {
|
|
8332
8406
|
const bounds = chip.bounds;
|
|
8333
|
-
const dx = point.x < bounds.minX -
|
|
8334
|
-
const dy = point.y < bounds.minY -
|
|
8407
|
+
const dx = point.x < bounds.minX - EPS11 ? bounds.minX - point.x : point.x > bounds.maxX + EPS11 ? point.x - bounds.maxX : 0;
|
|
8408
|
+
const dy = point.y < bounds.minY - EPS11 ? bounds.minY - point.y : point.y > bounds.maxY + EPS11 ? point.y - bounds.maxY : 0;
|
|
8335
8409
|
if (dx === 0 && dy === 0) continue;
|
|
8336
8410
|
const distanceSq = dx ** 2 + dy ** 2;
|
|
8337
8411
|
if (distanceSq >= nearestDistanceSq) continue;
|
|
@@ -8348,10 +8422,10 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
|
|
|
8348
8422
|
let nearestSide = null;
|
|
8349
8423
|
let nearestDistance = Number.POSITIVE_INFINITY;
|
|
8350
8424
|
for (const chip of this.chipObstacleSpatialIndex.chips) {
|
|
8351
|
-
for (const [side,
|
|
8352
|
-
if (
|
|
8425
|
+
for (const [side, distance5] of getSideDistances(point, chip.bounds)) {
|
|
8426
|
+
if (distance5 < nearestDistance) {
|
|
8353
8427
|
nearestSide = side;
|
|
8354
|
-
nearestDistance =
|
|
8428
|
+
nearestDistance = distance5;
|
|
8355
8429
|
}
|
|
8356
8430
|
}
|
|
8357
8431
|
}
|
|
@@ -8615,8 +8689,8 @@ var RailNetLabelCornerPlacementSolver = class extends BaseSolver {
|
|
|
8615
8689
|
if (seenCornerKeys.has(key)) continue;
|
|
8616
8690
|
seenCornerKeys.add(key);
|
|
8617
8691
|
const pinAligned = pins.some((pin) => {
|
|
8618
|
-
if (isVertical5) return Math.abs(pin.x - anchorPoint.x) <
|
|
8619
|
-
return Math.abs(pin.y - anchorPoint.y) <
|
|
8692
|
+
if (isVertical5) return Math.abs(pin.x - anchorPoint.x) < EPS6;
|
|
8693
|
+
return Math.abs(pin.y - anchorPoint.y) < EPS6;
|
|
8620
8694
|
});
|
|
8621
8695
|
if (!pinAligned) continue;
|
|
8622
8696
|
candidates.push({
|
|
@@ -8709,11 +8783,11 @@ var getOrientationConstraint = (inputProblem, label) => {
|
|
|
8709
8783
|
};
|
|
8710
8784
|
|
|
8711
8785
|
// lib/solvers/TraceAnchoredNetLabelOverlapSolver/geometry.ts
|
|
8712
|
-
var
|
|
8786
|
+
var EPS12 = 1e-6;
|
|
8713
8787
|
var TRACE_BOUNDARY_TOLERANCE2 = 1e-6;
|
|
8714
8788
|
var getLabelBounds = (label) => getRectBounds(label.center, label.width, label.height);
|
|
8715
|
-
var rectsOverlap3 = (a, b) => Math.min(a.maxX, b.maxX) - Math.max(a.minX, b.minX) >
|
|
8716
|
-
var rectsTouchOrOverlap = (a, b) => Math.min(a.maxX, b.maxX) - Math.max(a.minX, b.minX) >= -
|
|
8789
|
+
var rectsOverlap3 = (a, b) => Math.min(a.maxX, b.maxX) - Math.max(a.minX, b.minX) > EPS12 && Math.min(a.maxY, b.maxY) - Math.max(a.minY, b.minY) > EPS12;
|
|
8790
|
+
var rectsTouchOrOverlap = (a, b) => Math.min(a.maxX, b.maxX) - Math.max(a.minX, b.minX) >= -EPS12 && Math.min(a.maxY, b.maxY) - Math.max(a.minY, b.minY) >= -EPS12;
|
|
8717
8791
|
var traceCrossesBoundsInterior2 = (bounds, traces) => {
|
|
8718
8792
|
for (const trace of traces) {
|
|
8719
8793
|
const points = trace.tracePath;
|
|
@@ -8752,17 +8826,17 @@ var getTraceLength = (trace) => {
|
|
|
8752
8826
|
}
|
|
8753
8827
|
return length;
|
|
8754
8828
|
};
|
|
8755
|
-
var getPointAtTraceDistance = (trace,
|
|
8829
|
+
var getPointAtTraceDistance = (trace, distance5) => {
|
|
8756
8830
|
let pathDistance = 0;
|
|
8757
8831
|
for (let i = 0; i < trace.tracePath.length - 1; i++) {
|
|
8758
8832
|
const start = trace.tracePath[i];
|
|
8759
8833
|
const end = trace.tracePath[i + 1];
|
|
8760
8834
|
const segmentLength = getManhattanDistance(start, end);
|
|
8761
8835
|
const nextDistance = pathDistance + segmentLength;
|
|
8762
|
-
if (
|
|
8836
|
+
if (distance5 <= nextDistance + EPS12) {
|
|
8763
8837
|
const offset = Math.max(
|
|
8764
8838
|
0,
|
|
8765
|
-
Math.min(segmentLength,
|
|
8839
|
+
Math.min(segmentLength, distance5 - pathDistance)
|
|
8766
8840
|
);
|
|
8767
8841
|
const direction = getSegmentDirection(start, end);
|
|
8768
8842
|
return {
|
|
@@ -8798,7 +8872,7 @@ var segmentCrossesBoundsInterior2 = (start, end, bounds) => {
|
|
|
8798
8872
|
return false;
|
|
8799
8873
|
}
|
|
8800
8874
|
if (isVertical4(start, end)) {
|
|
8801
|
-
if (start.x <= interior.minX +
|
|
8875
|
+
if (start.x <= interior.minX + EPS12 || start.x >= interior.maxX - EPS12) {
|
|
8802
8876
|
return false;
|
|
8803
8877
|
}
|
|
8804
8878
|
return rangesOverlap2(
|
|
@@ -8809,7 +8883,7 @@ var segmentCrossesBoundsInterior2 = (start, end, bounds) => {
|
|
|
8809
8883
|
);
|
|
8810
8884
|
}
|
|
8811
8885
|
if (isHorizontal3(start, end)) {
|
|
8812
|
-
if (start.y <= interior.minY +
|
|
8886
|
+
if (start.y <= interior.minY + EPS12 || start.y >= interior.maxY - EPS12) {
|
|
8813
8887
|
return false;
|
|
8814
8888
|
}
|
|
8815
8889
|
return rangesOverlap2(
|
|
@@ -8823,10 +8897,10 @@ var segmentCrossesBoundsInterior2 = (start, end, bounds) => {
|
|
|
8823
8897
|
};
|
|
8824
8898
|
var isPointOnSegment2 = (point, start, end) => {
|
|
8825
8899
|
if (isHorizontal3(start, end)) {
|
|
8826
|
-
return Math.abs(point.y - start.y) <=
|
|
8900
|
+
return Math.abs(point.y - start.y) <= EPS12 && point.x >= Math.min(start.x, end.x) - EPS12 && point.x <= Math.max(start.x, end.x) + EPS12;
|
|
8827
8901
|
}
|
|
8828
8902
|
if (isVertical4(start, end)) {
|
|
8829
|
-
return Math.abs(point.x - start.x) <=
|
|
8903
|
+
return Math.abs(point.x - start.x) <= EPS12 && point.y >= Math.min(start.y, end.y) - EPS12 && point.y <= Math.max(start.y, end.y) + EPS12;
|
|
8830
8904
|
}
|
|
8831
8905
|
return false;
|
|
8832
8906
|
};
|
|
@@ -8834,9 +8908,9 @@ var getSegmentDirection = (start, end) => ({
|
|
|
8834
8908
|
x: isVertical4(start, end) ? 0 : Math.sign(end.x - start.x),
|
|
8835
8909
|
y: isHorizontal3(start, end) ? 0 : Math.sign(end.y - start.y)
|
|
8836
8910
|
});
|
|
8837
|
-
var isHorizontal3 = (start, end) => Math.abs(start.y - end.y) <=
|
|
8838
|
-
var isVertical4 = (start, end) => Math.abs(start.x - end.x) <=
|
|
8839
|
-
var rangesOverlap2 = (minA, maxA, minB, maxB) => Math.min(maxA, maxB) - Math.max(minA, minB) >
|
|
8911
|
+
var isHorizontal3 = (start, end) => Math.abs(start.y - end.y) <= EPS12;
|
|
8912
|
+
var isVertical4 = (start, end) => Math.abs(start.x - end.x) <= EPS12;
|
|
8913
|
+
var rangesOverlap2 = (minA, maxA, minB, maxB) => Math.min(maxA, maxB) - Math.max(minA, minB) > EPS12;
|
|
8840
8914
|
var getUniquePinCount2 = (pinIds) => new Set(pinIds).size;
|
|
8841
8915
|
|
|
8842
8916
|
// lib/solvers/TraceAnchoredNetLabelOverlapSolver/candidates.ts
|
|
@@ -8887,13 +8961,13 @@ var getCandidateDistances = (traceLength, vertexDistances) => {
|
|
|
8887
8961
|
const distances = /* @__PURE__ */ new Set();
|
|
8888
8962
|
const maxSteps = Math.ceil(traceLength / CANDIDATE_STEP);
|
|
8889
8963
|
for (let i = 0; i <= maxSteps; i++) {
|
|
8890
|
-
const
|
|
8891
|
-
distances.add(roundDistance(
|
|
8964
|
+
const distance5 = Math.min(traceLength, i * CANDIDATE_STEP);
|
|
8965
|
+
distances.add(roundDistance(distance5));
|
|
8892
8966
|
}
|
|
8893
|
-
for (const
|
|
8894
|
-
distances.add(roundDistance(
|
|
8967
|
+
for (const distance5 of vertexDistances) {
|
|
8968
|
+
distances.add(roundDistance(distance5));
|
|
8895
8969
|
}
|
|
8896
|
-
return [...distances].filter((
|
|
8970
|
+
return [...distances].filter((distance5) => distance5 >= -EPS12 && distance5 <= traceLength + EPS12).sort((a, b) => a - b);
|
|
8897
8971
|
};
|
|
8898
8972
|
var getOrientationsForPoint = (params) => {
|
|
8899
8973
|
const { inputProblem, label, point, orientationConstraint } = params;
|
|
@@ -8982,13 +9056,13 @@ var getOutwardOrientationOptions = (point, chipBounds) => {
|
|
|
8982
9056
|
};
|
|
8983
9057
|
var getOutwardAxisOption = (params) => {
|
|
8984
9058
|
const { value, min, max, center, positiveOrientation, negativeOrientation } = params;
|
|
8985
|
-
if (value > max +
|
|
9059
|
+
if (value > max + EPS12) {
|
|
8986
9060
|
return {
|
|
8987
9061
|
orientation: positiveOrientation,
|
|
8988
9062
|
outwardScore: 1 + value - max
|
|
8989
9063
|
};
|
|
8990
9064
|
}
|
|
8991
|
-
if (value < min -
|
|
9065
|
+
if (value < min - EPS12) {
|
|
8992
9066
|
return {
|
|
8993
9067
|
orientation: negativeOrientation,
|
|
8994
9068
|
outwardScore: 1 + min - value
|
|
@@ -8999,7 +9073,7 @@ var getOutwardAxisOption = (params) => {
|
|
|
8999
9073
|
outwardScore: getNormalizedCenterDistance(value, center, max - min)
|
|
9000
9074
|
};
|
|
9001
9075
|
};
|
|
9002
|
-
var getNormalizedCenterDistance = (value, center, span) => Math.abs(value - center) / Math.max(
|
|
9076
|
+
var getNormalizedCenterDistance = (value, center, span) => Math.abs(value - center) / Math.max(EPS12, span / 2);
|
|
9003
9077
|
var ALL_ORIENTATIONS = ["x+", "x-", "y+", "y-"];
|
|
9004
9078
|
var getFlippedOrientation = (orientation) => {
|
|
9005
9079
|
switch (orientation) {
|
|
@@ -9071,8 +9145,8 @@ var getNetLabelHeight = (inputProblem, label) => {
|
|
|
9071
9145
|
(nc) => nc.pinIds.some((pid) => label.pinIds.includes(pid))
|
|
9072
9146
|
)?.netLabelHeight;
|
|
9073
9147
|
};
|
|
9074
|
-
var roundDistance = (
|
|
9075
|
-
var isSamePlacement = (label, point, orientation) => Math.abs(point.x - label.anchorPoint.x) <=
|
|
9148
|
+
var roundDistance = (distance5) => Number(distance5.toFixed(6));
|
|
9149
|
+
var isSamePlacement = (label, point, orientation) => Math.abs(point.x - label.anchorPoint.x) <= EPS12 && Math.abs(point.y - label.anchorPoint.y) <= EPS12 && orientation === label.orientation;
|
|
9076
9150
|
|
|
9077
9151
|
// lib/solvers/TraceAnchoredNetLabelOverlapSolver/visualize.ts
|
|
9078
9152
|
var CANDIDATE_SELECTED_COLOR4 = "blue";
|
|
@@ -10037,6 +10111,457 @@ ${c.status}`
|
|
|
10037
10111
|
}
|
|
10038
10112
|
};
|
|
10039
10113
|
|
|
10114
|
+
// lib/solvers/UnroutedTraceRecoverySolver/UnroutedTraceRecoverySolver.ts
|
|
10115
|
+
import { distance as distance4, doSegmentsIntersect as doSegmentsIntersect3 } from "@tscircuit/math-utils";
|
|
10116
|
+
var ROUTE_CLEARANCE = 0.2;
|
|
10117
|
+
var COORDINATE_TOLERANCE = 1e-9;
|
|
10118
|
+
var GROUND_NET_ID = "GND";
|
|
10119
|
+
var pointsAreEqual = (firstPoint, secondPoint) => {
|
|
10120
|
+
return Math.abs(firstPoint.x - secondPoint.x) <= COORDINATE_TOLERANCE && Math.abs(firstPoint.y - secondPoint.y) <= COORDINATE_TOLERANCE;
|
|
10121
|
+
};
|
|
10122
|
+
var removeConsecutiveDuplicatePoints = (path) => {
|
|
10123
|
+
const filteredPath = [];
|
|
10124
|
+
for (const point of path) {
|
|
10125
|
+
const previousPoint = filteredPath.at(-1);
|
|
10126
|
+
if (!previousPoint || !pointsAreEqual(previousPoint, point)) {
|
|
10127
|
+
filteredPath.push(point);
|
|
10128
|
+
}
|
|
10129
|
+
}
|
|
10130
|
+
return filteredPath;
|
|
10131
|
+
};
|
|
10132
|
+
var getPathLength2 = (path) => {
|
|
10133
|
+
let pathLength = 0;
|
|
10134
|
+
for (let pointIndex = 0; pointIndex < path.length - 1; pointIndex++) {
|
|
10135
|
+
const startPoint = path[pointIndex];
|
|
10136
|
+
const endPoint = path[pointIndex + 1];
|
|
10137
|
+
pathLength += Math.abs(endPoint.x - startPoint.x) + Math.abs(endPoint.y - startPoint.y);
|
|
10138
|
+
}
|
|
10139
|
+
return pathLength;
|
|
10140
|
+
};
|
|
10141
|
+
var getEscapePoint = ({
|
|
10142
|
+
pin,
|
|
10143
|
+
facingDirection
|
|
10144
|
+
}) => {
|
|
10145
|
+
const escapePoint = { x: pin.x, y: pin.y };
|
|
10146
|
+
if (facingDirection === "x+") {
|
|
10147
|
+
escapePoint.x += ROUTE_CLEARANCE;
|
|
10148
|
+
}
|
|
10149
|
+
if (facingDirection === "x-") {
|
|
10150
|
+
escapePoint.x -= ROUTE_CLEARANCE;
|
|
10151
|
+
}
|
|
10152
|
+
if (facingDirection === "y+") {
|
|
10153
|
+
escapePoint.y += ROUTE_CLEARANCE;
|
|
10154
|
+
}
|
|
10155
|
+
if (facingDirection === "y-") {
|
|
10156
|
+
escapePoint.y -= ROUTE_CLEARANCE;
|
|
10157
|
+
}
|
|
10158
|
+
return escapePoint;
|
|
10159
|
+
};
|
|
10160
|
+
var getOuterBounds = (obstacles) => {
|
|
10161
|
+
return {
|
|
10162
|
+
minX: Math.min(...obstacles.map((obstacle) => obstacle.minX)),
|
|
10163
|
+
minY: Math.min(...obstacles.map((obstacle) => obstacle.minY)),
|
|
10164
|
+
maxX: Math.max(...obstacles.map((obstacle) => obstacle.maxX)),
|
|
10165
|
+
maxY: Math.max(...obstacles.map((obstacle) => obstacle.maxY))
|
|
10166
|
+
};
|
|
10167
|
+
};
|
|
10168
|
+
var getPerimeterCandidates = ({
|
|
10169
|
+
connectionPair,
|
|
10170
|
+
obstacles
|
|
10171
|
+
}) => {
|
|
10172
|
+
const [firstPin, secondPin] = connectionPair.pins;
|
|
10173
|
+
const firstEscapePoint = getEscapePoint({
|
|
10174
|
+
pin: firstPin,
|
|
10175
|
+
facingDirection: firstPin._facingDirection
|
|
10176
|
+
});
|
|
10177
|
+
const secondEscapePoint = getEscapePoint({
|
|
10178
|
+
pin: secondPin,
|
|
10179
|
+
facingDirection: secondPin._facingDirection
|
|
10180
|
+
});
|
|
10181
|
+
const outerBounds = getOuterBounds(obstacles);
|
|
10182
|
+
const horizontalChannels = [
|
|
10183
|
+
outerBounds.minY - ROUTE_CLEARANCE,
|
|
10184
|
+
outerBounds.maxY + ROUTE_CLEARANCE
|
|
10185
|
+
];
|
|
10186
|
+
const verticalChannels = [
|
|
10187
|
+
outerBounds.minX - ROUTE_CLEARANCE,
|
|
10188
|
+
outerBounds.maxX + ROUTE_CLEARANCE
|
|
10189
|
+
];
|
|
10190
|
+
const candidates = [];
|
|
10191
|
+
for (const channelY of horizontalChannels) {
|
|
10192
|
+
candidates.push(
|
|
10193
|
+
removeConsecutiveDuplicatePoints([
|
|
10194
|
+
firstPin,
|
|
10195
|
+
firstEscapePoint,
|
|
10196
|
+
{ x: firstEscapePoint.x, y: channelY },
|
|
10197
|
+
{ x: secondEscapePoint.x, y: channelY },
|
|
10198
|
+
secondEscapePoint,
|
|
10199
|
+
secondPin
|
|
10200
|
+
])
|
|
10201
|
+
);
|
|
10202
|
+
}
|
|
10203
|
+
for (const channelX of verticalChannels) {
|
|
10204
|
+
candidates.push(
|
|
10205
|
+
removeConsecutiveDuplicatePoints([
|
|
10206
|
+
firstPin,
|
|
10207
|
+
firstEscapePoint,
|
|
10208
|
+
{ x: channelX, y: firstEscapePoint.y },
|
|
10209
|
+
{ x: channelX, y: secondEscapePoint.y },
|
|
10210
|
+
secondEscapePoint,
|
|
10211
|
+
secondPin
|
|
10212
|
+
])
|
|
10213
|
+
);
|
|
10214
|
+
}
|
|
10215
|
+
return candidates.sort(
|
|
10216
|
+
(firstPath, secondPath) => getPathLength2(firstPath) - getPathLength2(secondPath)
|
|
10217
|
+
);
|
|
10218
|
+
};
|
|
10219
|
+
var getSegmentMidpoint = (startPoint, endPoint) => {
|
|
10220
|
+
return {
|
|
10221
|
+
x: (startPoint.x + endPoint.x) / 2,
|
|
10222
|
+
y: (startPoint.y + endPoint.y) / 2
|
|
10223
|
+
};
|
|
10224
|
+
};
|
|
10225
|
+
var getJunctionPoints = (sameNetTraces) => {
|
|
10226
|
+
const junctionPoints = [];
|
|
10227
|
+
for (const trace of sameNetTraces) {
|
|
10228
|
+
for (let pointIndex = 0; pointIndex < trace.tracePath.length - 1; pointIndex++) {
|
|
10229
|
+
const startPoint = trace.tracePath[pointIndex];
|
|
10230
|
+
const endPoint = trace.tracePath[pointIndex + 1];
|
|
10231
|
+
junctionPoints.push(startPoint);
|
|
10232
|
+
junctionPoints.push(getSegmentMidpoint(startPoint, endPoint));
|
|
10233
|
+
}
|
|
10234
|
+
const lastPoint = trace.tracePath.at(-1);
|
|
10235
|
+
if (lastPoint) {
|
|
10236
|
+
junctionPoints.push(lastPoint);
|
|
10237
|
+
}
|
|
10238
|
+
}
|
|
10239
|
+
return junctionPoints;
|
|
10240
|
+
};
|
|
10241
|
+
var getUnconnectedPins = ({
|
|
10242
|
+
connectionPair,
|
|
10243
|
+
sameNetTraces
|
|
10244
|
+
}) => {
|
|
10245
|
+
const connectedPinIds = new Set(
|
|
10246
|
+
sameNetTraces.flatMap((trace) => trace.pinIds)
|
|
10247
|
+
);
|
|
10248
|
+
return connectionPair.pins.filter((pin) => !connectedPinIds.has(pin.pinId));
|
|
10249
|
+
};
|
|
10250
|
+
var getJunctionCandidates = ({
|
|
10251
|
+
connectionPair,
|
|
10252
|
+
sameNetTraces,
|
|
10253
|
+
obstacles,
|
|
10254
|
+
maxConnectionDistance
|
|
10255
|
+
}) => {
|
|
10256
|
+
const outerBounds = getOuterBounds(obstacles);
|
|
10257
|
+
const horizontalChannels = [
|
|
10258
|
+
outerBounds.minY - ROUTE_CLEARANCE,
|
|
10259
|
+
outerBounds.maxY + ROUTE_CLEARANCE
|
|
10260
|
+
];
|
|
10261
|
+
const verticalChannels = [
|
|
10262
|
+
outerBounds.minX - ROUTE_CLEARANCE,
|
|
10263
|
+
outerBounds.maxX + ROUTE_CLEARANCE
|
|
10264
|
+
];
|
|
10265
|
+
const candidates = [];
|
|
10266
|
+
const junctionPoints = getJunctionPoints(sameNetTraces);
|
|
10267
|
+
const unconnectedPins = getUnconnectedPins({
|
|
10268
|
+
connectionPair,
|
|
10269
|
+
sameNetTraces
|
|
10270
|
+
});
|
|
10271
|
+
for (const pin of unconnectedPins) {
|
|
10272
|
+
const escapePoint = getEscapePoint({
|
|
10273
|
+
pin,
|
|
10274
|
+
facingDirection: pin._facingDirection
|
|
10275
|
+
});
|
|
10276
|
+
for (const junctionPoint of junctionPoints) {
|
|
10277
|
+
if (distance4(pin, junctionPoint) > maxConnectionDistance) {
|
|
10278
|
+
continue;
|
|
10279
|
+
}
|
|
10280
|
+
candidates.push(
|
|
10281
|
+
removeConsecutiveDuplicatePoints([
|
|
10282
|
+
pin,
|
|
10283
|
+
escapePoint,
|
|
10284
|
+
{ x: escapePoint.x, y: junctionPoint.y },
|
|
10285
|
+
junctionPoint
|
|
10286
|
+
])
|
|
10287
|
+
);
|
|
10288
|
+
candidates.push(
|
|
10289
|
+
removeConsecutiveDuplicatePoints([
|
|
10290
|
+
pin,
|
|
10291
|
+
escapePoint,
|
|
10292
|
+
{ x: junctionPoint.x, y: escapePoint.y },
|
|
10293
|
+
junctionPoint
|
|
10294
|
+
])
|
|
10295
|
+
);
|
|
10296
|
+
for (const channelY of horizontalChannels) {
|
|
10297
|
+
candidates.push(
|
|
10298
|
+
removeConsecutiveDuplicatePoints([
|
|
10299
|
+
pin,
|
|
10300
|
+
escapePoint,
|
|
10301
|
+
{ x: escapePoint.x, y: channelY },
|
|
10302
|
+
{ x: junctionPoint.x, y: channelY },
|
|
10303
|
+
junctionPoint
|
|
10304
|
+
])
|
|
10305
|
+
);
|
|
10306
|
+
}
|
|
10307
|
+
for (const channelX of verticalChannels) {
|
|
10308
|
+
candidates.push(
|
|
10309
|
+
removeConsecutiveDuplicatePoints([
|
|
10310
|
+
pin,
|
|
10311
|
+
escapePoint,
|
|
10312
|
+
{ x: channelX, y: escapePoint.y },
|
|
10313
|
+
{ x: channelX, y: junctionPoint.y },
|
|
10314
|
+
junctionPoint
|
|
10315
|
+
])
|
|
10316
|
+
);
|
|
10317
|
+
}
|
|
10318
|
+
}
|
|
10319
|
+
}
|
|
10320
|
+
return candidates.sort(
|
|
10321
|
+
(firstPath, secondPath) => getPathLength2(firstPath) - getPathLength2(secondPath)
|
|
10322
|
+
);
|
|
10323
|
+
};
|
|
10324
|
+
var pathCollidesWithObstacles = ({
|
|
10325
|
+
path,
|
|
10326
|
+
obstacles,
|
|
10327
|
+
connectionPair,
|
|
10328
|
+
rejectComponentBoundaryTravel
|
|
10329
|
+
}) => {
|
|
10330
|
+
const firstPathPoint = path[0];
|
|
10331
|
+
const lastPathPoint = path.at(-1);
|
|
10332
|
+
const firstPathPin = connectionPair.pins.find(
|
|
10333
|
+
(pin) => pointsAreEqual(pin, firstPathPoint)
|
|
10334
|
+
);
|
|
10335
|
+
const lastPathPin = connectionPair.pins.find(
|
|
10336
|
+
(pin) => pointsAreEqual(pin, lastPathPoint)
|
|
10337
|
+
);
|
|
10338
|
+
const pathConnectsPairPins = firstPathPin !== void 0 && lastPathPin !== void 0;
|
|
10339
|
+
const firstChipObstacle = obstacles.find(
|
|
10340
|
+
(obstacle) => obstacle.kind === "chip" && obstacle.chipId === firstPathPin?.chipId
|
|
10341
|
+
);
|
|
10342
|
+
const secondChipObstacle = obstacles.find(
|
|
10343
|
+
(obstacle) => obstacle.kind === "chip" && obstacle.chipId === lastPathPin?.chipId
|
|
10344
|
+
);
|
|
10345
|
+
if (rejectComponentBoundaryTravel && firstChipObstacle && segmentOverlapsRectBoundary(path[0], path[1], firstChipObstacle)) {
|
|
10346
|
+
return true;
|
|
10347
|
+
}
|
|
10348
|
+
if (rejectComponentBoundaryTravel && secondChipObstacle && segmentOverlapsRectBoundary(
|
|
10349
|
+
path[path.length - 2],
|
|
10350
|
+
path[path.length - 1],
|
|
10351
|
+
secondChipObstacle
|
|
10352
|
+
)) {
|
|
10353
|
+
return true;
|
|
10354
|
+
}
|
|
10355
|
+
const collision = findFirstCollision(path, obstacles, {
|
|
10356
|
+
excludeRectsForSegment: (segmentIndex) => {
|
|
10357
|
+
const excludedObstacles = /* @__PURE__ */ new Set();
|
|
10358
|
+
if (segmentIndex === 0 && firstChipObstacle) {
|
|
10359
|
+
excludedObstacles.add(firstChipObstacle);
|
|
10360
|
+
}
|
|
10361
|
+
if (pathConnectsPairPins && segmentIndex === path.length - 2 && secondChipObstacle) {
|
|
10362
|
+
excludedObstacles.add(secondChipObstacle);
|
|
10363
|
+
}
|
|
10364
|
+
return excludedObstacles;
|
|
10365
|
+
}
|
|
10366
|
+
});
|
|
10367
|
+
return collision !== null;
|
|
10368
|
+
};
|
|
10369
|
+
var hasParallelFailedConnection = ({
|
|
10370
|
+
connectionPair,
|
|
10371
|
+
failedConnectionPairs
|
|
10372
|
+
}) => {
|
|
10373
|
+
const connectionChipIds = new Set(
|
|
10374
|
+
connectionPair.pins.map((pin) => pin.chipId)
|
|
10375
|
+
);
|
|
10376
|
+
return failedConnectionPairs.some((otherConnectionPair) => {
|
|
10377
|
+
if (otherConnectionPair.mspPairId === connectionPair.mspPairId) {
|
|
10378
|
+
return false;
|
|
10379
|
+
}
|
|
10380
|
+
return otherConnectionPair.pins.every(
|
|
10381
|
+
(pin) => connectionChipIds.has(pin.chipId)
|
|
10382
|
+
);
|
|
10383
|
+
});
|
|
10384
|
+
};
|
|
10385
|
+
var segmentsOverlapBeyondEndpoint = ({
|
|
10386
|
+
firstStart,
|
|
10387
|
+
firstEnd,
|
|
10388
|
+
secondStart,
|
|
10389
|
+
secondEnd
|
|
10390
|
+
}) => {
|
|
10391
|
+
if (isHorizontal(firstStart, firstEnd) && isHorizontal(secondStart, secondEnd)) {
|
|
10392
|
+
const overlapLength = Math.min(
|
|
10393
|
+
Math.max(firstStart.x, firstEnd.x),
|
|
10394
|
+
Math.max(secondStart.x, secondEnd.x)
|
|
10395
|
+
) - Math.max(
|
|
10396
|
+
Math.min(firstStart.x, firstEnd.x),
|
|
10397
|
+
Math.min(secondStart.x, secondEnd.x)
|
|
10398
|
+
);
|
|
10399
|
+
return overlapLength > COORDINATE_TOLERANCE;
|
|
10400
|
+
}
|
|
10401
|
+
if (isVertical(firstStart, firstEnd) && isVertical(secondStart, secondEnd)) {
|
|
10402
|
+
const overlapLength = Math.min(
|
|
10403
|
+
Math.max(firstStart.y, firstEnd.y),
|
|
10404
|
+
Math.max(secondStart.y, secondEnd.y)
|
|
10405
|
+
) - Math.max(
|
|
10406
|
+
Math.min(firstStart.y, firstEnd.y),
|
|
10407
|
+
Math.min(secondStart.y, secondEnd.y)
|
|
10408
|
+
);
|
|
10409
|
+
return overlapLength > COORDINATE_TOLERANCE;
|
|
10410
|
+
}
|
|
10411
|
+
return false;
|
|
10412
|
+
};
|
|
10413
|
+
var getAllowedJunctionPoints = ({
|
|
10414
|
+
connectionPair,
|
|
10415
|
+
existingTrace
|
|
10416
|
+
}) => {
|
|
10417
|
+
const existingPinIds = new Set(existingTrace.pinIds);
|
|
10418
|
+
return connectionPair.pins.filter((pin) => existingPinIds.has(pin.pinId));
|
|
10419
|
+
};
|
|
10420
|
+
var pathCrossesExistingTraces = ({
|
|
10421
|
+
path,
|
|
10422
|
+
connectionPair,
|
|
10423
|
+
existingTraces
|
|
10424
|
+
}) => {
|
|
10425
|
+
for (const existingTrace of existingTraces) {
|
|
10426
|
+
if (existingTrace.globalConnNetId === connectionPair.globalConnNetId) {
|
|
10427
|
+
continue;
|
|
10428
|
+
}
|
|
10429
|
+
const allowedJunctionPoints = getAllowedJunctionPoints({
|
|
10430
|
+
connectionPair,
|
|
10431
|
+
existingTrace
|
|
10432
|
+
});
|
|
10433
|
+
for (let pathIndex = 0; pathIndex < path.length - 1; pathIndex++) {
|
|
10434
|
+
const pathStart = path[pathIndex];
|
|
10435
|
+
const pathEnd = path[pathIndex + 1];
|
|
10436
|
+
for (let traceIndex = 0; traceIndex < existingTrace.tracePath.length - 1; traceIndex++) {
|
|
10437
|
+
const traceStart = existingTrace.tracePath[traceIndex];
|
|
10438
|
+
const traceEnd = existingTrace.tracePath[traceIndex + 1];
|
|
10439
|
+
if (!doSegmentsIntersect3(pathStart, pathEnd, traceStart, traceEnd)) {
|
|
10440
|
+
continue;
|
|
10441
|
+
}
|
|
10442
|
+
const intersectionIsAllowedJunction = allowedJunctionPoints.some(
|
|
10443
|
+
(junctionPoint) => (pointsAreEqual(pathStart, junctionPoint) || pointsAreEqual(pathEnd, junctionPoint)) && (pointsAreEqual(traceStart, junctionPoint) || pointsAreEqual(traceEnd, junctionPoint))
|
|
10444
|
+
);
|
|
10445
|
+
if (intersectionIsAllowedJunction && !segmentsOverlapBeyondEndpoint({
|
|
10446
|
+
firstStart: pathStart,
|
|
10447
|
+
firstEnd: pathEnd,
|
|
10448
|
+
secondStart: traceStart,
|
|
10449
|
+
secondEnd: traceEnd
|
|
10450
|
+
})) {
|
|
10451
|
+
continue;
|
|
10452
|
+
}
|
|
10453
|
+
return true;
|
|
10454
|
+
}
|
|
10455
|
+
}
|
|
10456
|
+
}
|
|
10457
|
+
return false;
|
|
10458
|
+
};
|
|
10459
|
+
var UnroutedTraceRecoverySolver = class extends BaseSolver {
|
|
10460
|
+
constructor(params) {
|
|
10461
|
+
super();
|
|
10462
|
+
this.params = params;
|
|
10463
|
+
this.inputProblem = params.inputProblem;
|
|
10464
|
+
this.alreadySolvedTraces = params.alreadySolvedTraces;
|
|
10465
|
+
this.failedConnectionPairs = params.failedConnectionPairs;
|
|
10466
|
+
this.queuedConnectionPairs = [...params.failedConnectionPairs];
|
|
10467
|
+
this.maxConnectionDistance = this.inputProblem.maxMspPairDistance ?? DEFAULT_MAX_MSP_PAIR_DISTANCE;
|
|
10468
|
+
const { netConnMap } = getConnectivityMapsFromInputProblem(
|
|
10469
|
+
this.inputProblem
|
|
10470
|
+
);
|
|
10471
|
+
this.groundGlobalConnNetId = netConnMap.getNetConnectedToId(GROUND_NET_ID) ?? void 0;
|
|
10472
|
+
}
|
|
10473
|
+
params;
|
|
10474
|
+
inputProblem;
|
|
10475
|
+
alreadySolvedTraces;
|
|
10476
|
+
failedConnectionPairs;
|
|
10477
|
+
queuedConnectionPairs;
|
|
10478
|
+
maxConnectionDistance;
|
|
10479
|
+
groundGlobalConnNetId;
|
|
10480
|
+
solvedUnroutedTraces = [];
|
|
10481
|
+
getConstructorParams() {
|
|
10482
|
+
return this.params;
|
|
10483
|
+
}
|
|
10484
|
+
_step() {
|
|
10485
|
+
const connectionPair = this.queuedConnectionPairs.shift();
|
|
10486
|
+
if (!connectionPair) {
|
|
10487
|
+
this.solved = true;
|
|
10488
|
+
return;
|
|
10489
|
+
}
|
|
10490
|
+
if (connectionPair.globalConnNetId === this.groundGlobalConnNetId) {
|
|
10491
|
+
return;
|
|
10492
|
+
}
|
|
10493
|
+
if (distance4(connectionPair.pins[0], connectionPair.pins[1]) > this.maxConnectionDistance) {
|
|
10494
|
+
return;
|
|
10495
|
+
}
|
|
10496
|
+
const obstacles = getObstacleRects(this.inputProblem);
|
|
10497
|
+
const existingTraces = [
|
|
10498
|
+
...this.alreadySolvedTraces,
|
|
10499
|
+
...this.solvedUnroutedTraces
|
|
10500
|
+
];
|
|
10501
|
+
const sameNetTraces = existingTraces.filter(
|
|
10502
|
+
(trace) => trace.globalConnNetId === connectionPair.globalConnNetId
|
|
10503
|
+
);
|
|
10504
|
+
const junctionCandidates = getJunctionCandidates({
|
|
10505
|
+
connectionPair,
|
|
10506
|
+
sameNetTraces,
|
|
10507
|
+
obstacles,
|
|
10508
|
+
maxConnectionDistance: this.maxConnectionDistance
|
|
10509
|
+
});
|
|
10510
|
+
const perimeterCandidates = getPerimeterCandidates({
|
|
10511
|
+
connectionPair,
|
|
10512
|
+
obstacles
|
|
10513
|
+
});
|
|
10514
|
+
const candidates = [...junctionCandidates, ...perimeterCandidates];
|
|
10515
|
+
const rejectComponentBoundaryTravel = hasParallelFailedConnection({
|
|
10516
|
+
connectionPair,
|
|
10517
|
+
failedConnectionPairs: this.failedConnectionPairs
|
|
10518
|
+
});
|
|
10519
|
+
for (const tracePath of candidates) {
|
|
10520
|
+
if (pathCollidesWithObstacles({
|
|
10521
|
+
path: tracePath,
|
|
10522
|
+
obstacles,
|
|
10523
|
+
connectionPair,
|
|
10524
|
+
rejectComponentBoundaryTravel
|
|
10525
|
+
})) {
|
|
10526
|
+
continue;
|
|
10527
|
+
}
|
|
10528
|
+
if (pathCrossesExistingTraces({
|
|
10529
|
+
path: tracePath,
|
|
10530
|
+
connectionPair,
|
|
10531
|
+
existingTraces
|
|
10532
|
+
})) {
|
|
10533
|
+
continue;
|
|
10534
|
+
}
|
|
10535
|
+
this.solvedUnroutedTraces.push({
|
|
10536
|
+
...connectionPair,
|
|
10537
|
+
tracePath,
|
|
10538
|
+
mspConnectionPairIds: [connectionPair.mspPairId],
|
|
10539
|
+
pinIds: connectionPair.pins.map((pin) => pin.pinId)
|
|
10540
|
+
});
|
|
10541
|
+
return;
|
|
10542
|
+
}
|
|
10543
|
+
}
|
|
10544
|
+
getOutput() {
|
|
10545
|
+
return {
|
|
10546
|
+
newTraces: this.solvedUnroutedTraces,
|
|
10547
|
+
allTracesMerged: [
|
|
10548
|
+
...this.alreadySolvedTraces,
|
|
10549
|
+
...this.solvedUnroutedTraces
|
|
10550
|
+
]
|
|
10551
|
+
};
|
|
10552
|
+
}
|
|
10553
|
+
visualize() {
|
|
10554
|
+
const graphics = visualizeInputProblem(this.inputProblem);
|
|
10555
|
+
for (const trace of this.solvedUnroutedTraces) {
|
|
10556
|
+
graphics.lines.push({
|
|
10557
|
+
points: trace.tracePath,
|
|
10558
|
+
strokeColor: "blue"
|
|
10559
|
+
});
|
|
10560
|
+
}
|
|
10561
|
+
return graphics;
|
|
10562
|
+
}
|
|
10563
|
+
};
|
|
10564
|
+
|
|
10040
10565
|
// lib/solvers/SchematicTracePipelineSolver/SchematicTracePipelineSolver.ts
|
|
10041
10566
|
function definePipelineStep(solverName, solverClass, getConstructorParams, opts = {}) {
|
|
10042
10567
|
return {
|
|
@@ -10052,6 +10577,7 @@ var SchematicTracePipelineSolver = class extends BaseSolver {
|
|
|
10052
10577
|
// guidelinesSolver?: GuidelinesSolver
|
|
10053
10578
|
schematicTraceLinesSolver;
|
|
10054
10579
|
longDistancePairSolver;
|
|
10580
|
+
unroutedTraceRecoverySolver;
|
|
10055
10581
|
traceOverlapShiftSolver;
|
|
10056
10582
|
netLabelPlacementSolver;
|
|
10057
10583
|
labelMergingSolver;
|
|
@@ -10122,13 +10648,24 @@ var SchematicTracePipelineSolver = class extends BaseSolver {
|
|
|
10122
10648
|
}
|
|
10123
10649
|
}
|
|
10124
10650
|
),
|
|
10651
|
+
definePipelineStep(
|
|
10652
|
+
"unroutedTraceRecoverySolver",
|
|
10653
|
+
UnroutedTraceRecoverySolver,
|
|
10654
|
+
(instance) => [
|
|
10655
|
+
{
|
|
10656
|
+
inputProblem: instance.inputProblem,
|
|
10657
|
+
failedConnectionPairs: instance.schematicTraceLinesSolver.failedConnectionPairs,
|
|
10658
|
+
alreadySolvedTraces: instance.longDistancePairSolver.getOutput().allTracesMerged
|
|
10659
|
+
}
|
|
10660
|
+
]
|
|
10661
|
+
),
|
|
10125
10662
|
definePipelineStep(
|
|
10126
10663
|
"traceOverlapShiftSolver",
|
|
10127
10664
|
TraceOverlapShiftSolver,
|
|
10128
10665
|
() => [
|
|
10129
10666
|
{
|
|
10130
10667
|
inputProblem: this.inputProblem,
|
|
10131
|
-
inputTracePaths: this.
|
|
10668
|
+
inputTracePaths: this.unroutedTraceRecoverySolver?.getOutput().allTracesMerged,
|
|
10132
10669
|
globalConnMap: this.mspConnectionPairSolver.globalConnMap
|
|
10133
10670
|
}
|
|
10134
10671
|
],
|
|
@@ -10144,7 +10681,7 @@ var SchematicTracePipelineSolver = class extends BaseSolver {
|
|
|
10144
10681
|
{
|
|
10145
10682
|
inputProblem: this.inputProblem,
|
|
10146
10683
|
inputTraceMap: this.traceOverlapShiftSolver?.correctedTraceMap ?? Object.fromEntries(
|
|
10147
|
-
this.
|
|
10684
|
+
this.unroutedTraceRecoverySolver.getOutput().allTracesMerged.map(
|
|
10148
10685
|
(p) => [p.mspPairId, p]
|
|
10149
10686
|
)
|
|
10150
10687
|
)
|
|
@@ -10160,7 +10697,7 @@ var SchematicTracePipelineSolver = class extends BaseSolver {
|
|
|
10160
10697
|
TraceLabelOverlapAvoidanceSolver,
|
|
10161
10698
|
(instance) => {
|
|
10162
10699
|
const traceMap = instance.traceOverlapShiftSolver?.correctedTraceMap ?? Object.fromEntries(
|
|
10163
|
-
instance.
|
|
10700
|
+
instance.unroutedTraceRecoverySolver.getOutput().allTracesMerged.map((p) => [p.mspPairId, p])
|
|
10164
10701
|
);
|
|
10165
10702
|
const traces = Object.values(traceMap);
|
|
10166
10703
|
const netLabelPlacements = instance.netLabelPlacementSolver.netLabelPlacements;
|