@tscircuit/schematic-trace-solver 0.0.107 → 0.0.108
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 -2
- package/dist/index.js +285 -212
- 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/package.json +1 -1
- 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/repros/__snapshots__/repro-tps61222-trace-intersection.snap.svg +63 -220
- 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/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 };
|
|
@@ -630,6 +630,25 @@ function getRectBounds(center, w, h) {
|
|
|
630
630
|
};
|
|
631
631
|
}
|
|
632
632
|
|
|
633
|
+
// lib/utils/textBoxBounds.ts
|
|
634
|
+
function getTextBoxBounds(textBox, padding = {}) {
|
|
635
|
+
return {
|
|
636
|
+
minX: textBox.center.x - textBox.width / 2 - (padding.minX ?? 0),
|
|
637
|
+
minY: textBox.center.y - textBox.height / 2 - (padding.minY ?? 0),
|
|
638
|
+
maxX: textBox.center.x + textBox.width / 2 + (padding.maxX ?? 0),
|
|
639
|
+
maxY: textBox.center.y + textBox.height / 2 + (padding.maxY ?? 0)
|
|
640
|
+
};
|
|
641
|
+
}
|
|
642
|
+
function boundsOverlap(a, b, eps = 1e-9) {
|
|
643
|
+
return a.minX < b.maxX - eps && a.maxX > b.minX + eps && a.minY < b.maxY - eps && a.maxY > b.minY + eps;
|
|
644
|
+
}
|
|
645
|
+
function rectIntersectsAnyTextBox(bounds, inputProblem) {
|
|
646
|
+
for (const textBox of inputProblem.textBoxes ?? []) {
|
|
647
|
+
if (boundsOverlap(bounds, getTextBoxBounds(textBox))) return true;
|
|
648
|
+
}
|
|
649
|
+
return false;
|
|
650
|
+
}
|
|
651
|
+
|
|
633
652
|
// lib/solvers/SchematicTraceLinesSolver/SchematicTraceSingleLineSolver2/calculateDirectShortPath.ts
|
|
634
653
|
import { calculateElbow } from "calculate-elbow";
|
|
635
654
|
var MAX_SHORT_TRACE_DISTANCE = 0.15;
|
|
@@ -875,12 +894,8 @@ var candidateMidsFromSet = (axis, colliding, collisionRects, aabb, opts = {}) =>
|
|
|
875
894
|
}
|
|
876
895
|
};
|
|
877
896
|
|
|
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
|
-
};
|
|
897
|
+
// lib/solvers/SchematicTraceLinesSolver/SchematicTraceSingleLineSolver2/pathOps.ts
|
|
898
|
+
var EPS3 = 1e-9;
|
|
884
899
|
var hasOnlyNonzeroOrthogonalSegments = (path) => path.every((point, index) => {
|
|
885
900
|
const nextPoint = path[index + 1];
|
|
886
901
|
if (!nextPoint) return true;
|
|
@@ -889,57 +904,6 @@ var hasOnlyNonzeroOrthogonalSegments = (path) => path.every((point, index) => {
|
|
|
889
904
|
}
|
|
890
905
|
return Math.abs(point.x - nextPoint.x) + Math.abs(point.y - nextPoint.y) > 0;
|
|
891
906
|
});
|
|
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
907
|
var shiftSegmentOrth = (pts, segIndex, axis, newCoord, eps = EPS3) => {
|
|
944
908
|
if (segIndex < 0 || segIndex >= pts.length - 1) {
|
|
945
909
|
return null;
|
|
@@ -1001,6 +965,121 @@ var pathKey = (pts, decimals = 6) => {
|
|
|
1001
965
|
return key;
|
|
1002
966
|
};
|
|
1003
967
|
|
|
968
|
+
// lib/solvers/SchematicTraceLinesSolver/SchematicTraceSingleLineSolver2/generateEndpointCollisionDetours.ts
|
|
969
|
+
var getSegmentAxis = (start, end) => {
|
|
970
|
+
if (isVertical(start, end)) return "x";
|
|
971
|
+
if (isHorizontal(start, end)) return "y";
|
|
972
|
+
return null;
|
|
973
|
+
};
|
|
974
|
+
var generateEndpointCollisionDetours = ({
|
|
975
|
+
path,
|
|
976
|
+
collidingSegmentIndex,
|
|
977
|
+
obstacle
|
|
978
|
+
}) => {
|
|
979
|
+
if (path.length < 3 || path.length > 4) return [];
|
|
980
|
+
const lastSegmentIndex = path.length - 2;
|
|
981
|
+
if (collidingSegmentIndex !== 0 && collidingSegmentIndex !== lastSegmentIndex) {
|
|
982
|
+
return [];
|
|
983
|
+
}
|
|
984
|
+
const shouldReverse = collidingSegmentIndex === lastSegmentIndex;
|
|
985
|
+
const orderedPath = shouldReverse ? [...path].reverse() : path;
|
|
986
|
+
const [start, corner, end] = orderedPath;
|
|
987
|
+
const firstSegmentAxis = getSegmentAxis(start, corner);
|
|
988
|
+
const secondSegmentAxis = getSegmentAxis(corner, end);
|
|
989
|
+
if (!firstSegmentAxis || !secondSegmentAxis) return [];
|
|
990
|
+
if (firstSegmentAxis === secondSegmentAxis) return [];
|
|
991
|
+
const escapeCoordinates = [
|
|
992
|
+
...midBetweenPointAndRect(secondSegmentAxis, start, obstacle),
|
|
993
|
+
...midBetweenPointAndRect(secondSegmentAxis, end, obstacle)
|
|
994
|
+
];
|
|
995
|
+
const detourCoordinates = [
|
|
996
|
+
...midBetweenPointAndRect(firstSegmentAxis, start, obstacle),
|
|
997
|
+
...midBetweenPointAndRect(firstSegmentAxis, end, obstacle)
|
|
998
|
+
];
|
|
999
|
+
const detours = [];
|
|
1000
|
+
for (const escapeCoordinate of [...new Set(escapeCoordinates)]) {
|
|
1001
|
+
for (const detourCoordinate of [...new Set(detourCoordinates)]) {
|
|
1002
|
+
const orderedDetourPrefix = firstSegmentAxis === "y" ? [
|
|
1003
|
+
start,
|
|
1004
|
+
{ x: escapeCoordinate, y: start.y },
|
|
1005
|
+
{ x: escapeCoordinate, y: detourCoordinate },
|
|
1006
|
+
{ x: end.x, y: detourCoordinate },
|
|
1007
|
+
end
|
|
1008
|
+
] : [
|
|
1009
|
+
start,
|
|
1010
|
+
{ x: start.x, y: escapeCoordinate },
|
|
1011
|
+
{ x: detourCoordinate, y: escapeCoordinate },
|
|
1012
|
+
{ x: detourCoordinate, y: end.y },
|
|
1013
|
+
end
|
|
1014
|
+
];
|
|
1015
|
+
const orderedDetour = [...orderedDetourPrefix, ...orderedPath.slice(3)];
|
|
1016
|
+
const detour = shouldReverse ? orderedDetour.reverse() : orderedDetour;
|
|
1017
|
+
if (hasOnlyNonzeroOrthogonalSegments(detour)) detours.push(detour);
|
|
1018
|
+
}
|
|
1019
|
+
}
|
|
1020
|
+
return detours;
|
|
1021
|
+
};
|
|
1022
|
+
|
|
1023
|
+
// lib/solvers/SchematicTraceLinesSolver/SchematicTraceSingleLineSolver2/generateInternalSegmentCollisionDetours.ts
|
|
1024
|
+
var EPS4 = 1e-9;
|
|
1025
|
+
var DEFAULT_CLEARANCE = 0.2;
|
|
1026
|
+
var isStrictlyBetween = (value, a, b) => value > Math.min(a, b) + EPS4 && value < Math.max(a, b) - EPS4;
|
|
1027
|
+
var generateInternalSegmentCollisionDetours = ({
|
|
1028
|
+
path,
|
|
1029
|
+
collidingSegmentIndex,
|
|
1030
|
+
obstacle,
|
|
1031
|
+
clearance = DEFAULT_CLEARANCE
|
|
1032
|
+
}) => {
|
|
1033
|
+
if (collidingSegmentIndex <= 0 || collidingSegmentIndex >= path.length - 2) {
|
|
1034
|
+
return [];
|
|
1035
|
+
}
|
|
1036
|
+
const start = path[collidingSegmentIndex];
|
|
1037
|
+
const end = path[collidingSegmentIndex + 1];
|
|
1038
|
+
const detourPoints = [];
|
|
1039
|
+
if (isHorizontal(start, end)) {
|
|
1040
|
+
const movingRight = start.x < end.x;
|
|
1041
|
+
const entryX = movingRight ? obstacle.minX - clearance : obstacle.maxX + clearance;
|
|
1042
|
+
const exitX = movingRight ? obstacle.maxX + clearance : obstacle.minX - clearance;
|
|
1043
|
+
if (!isStrictlyBetween(entryX, start.x, end.x) || !isStrictlyBetween(exitX, start.x, end.x)) {
|
|
1044
|
+
return [];
|
|
1045
|
+
}
|
|
1046
|
+
for (const detourY of [
|
|
1047
|
+
obstacle.minY - clearance,
|
|
1048
|
+
obstacle.maxY + clearance
|
|
1049
|
+
]) {
|
|
1050
|
+
detourPoints.push([
|
|
1051
|
+
{ x: entryX, y: start.y },
|
|
1052
|
+
{ x: entryX, y: detourY },
|
|
1053
|
+
{ x: exitX, y: detourY },
|
|
1054
|
+
{ x: exitX, y: end.y }
|
|
1055
|
+
]);
|
|
1056
|
+
}
|
|
1057
|
+
} else if (isVertical(start, end)) {
|
|
1058
|
+
const movingUp = start.y < end.y;
|
|
1059
|
+
const entryY = movingUp ? obstacle.minY - clearance : obstacle.maxY + clearance;
|
|
1060
|
+
const exitY = movingUp ? obstacle.maxY + clearance : obstacle.minY - clearance;
|
|
1061
|
+
if (!isStrictlyBetween(entryY, start.y, end.y) || !isStrictlyBetween(exitY, start.y, end.y)) {
|
|
1062
|
+
return [];
|
|
1063
|
+
}
|
|
1064
|
+
for (const detourX of [
|
|
1065
|
+
obstacle.minX - clearance,
|
|
1066
|
+
obstacle.maxX + clearance
|
|
1067
|
+
]) {
|
|
1068
|
+
detourPoints.push([
|
|
1069
|
+
{ x: start.x, y: entryY },
|
|
1070
|
+
{ x: detourX, y: entryY },
|
|
1071
|
+
{ x: detourX, y: exitY },
|
|
1072
|
+
{ x: end.x, y: exitY }
|
|
1073
|
+
]);
|
|
1074
|
+
}
|
|
1075
|
+
}
|
|
1076
|
+
return detourPoints.map((points) => [
|
|
1077
|
+
...path.slice(0, collidingSegmentIndex + 1),
|
|
1078
|
+
...points,
|
|
1079
|
+
...path.slice(collidingSegmentIndex + 1)
|
|
1080
|
+
]).filter(hasOnlyNonzeroOrthogonalSegments);
|
|
1081
|
+
};
|
|
1082
|
+
|
|
1004
1083
|
// lib/solvers/GuidelinesSolver/getInputChipBounds.ts
|
|
1005
1084
|
function getInputChipBounds(chip) {
|
|
1006
1085
|
const halfWidth = chip.width / 2;
|
|
@@ -1013,26 +1092,8 @@ function getInputChipBounds(chip) {
|
|
|
1013
1092
|
};
|
|
1014
1093
|
}
|
|
1015
1094
|
|
|
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
1095
|
// lib/solvers/SchematicTraceLinesSolver/SchematicTraceSingleLineSolver2/rect.ts
|
|
1096
|
+
var isTextBoxObstacle = (obstacle) => obstacle.kind === "text_box";
|
|
1036
1097
|
var chipToRect = (chip) => {
|
|
1037
1098
|
const b = getInputChipBounds(chip);
|
|
1038
1099
|
return { kind: "chip", chipId: chip.chipId, ...b };
|
|
@@ -1096,13 +1157,11 @@ var SchematicTraceSingleLineSolver2 = class extends BaseSolver {
|
|
|
1096
1157
|
this.obstacles = getObstacleRects(this.inputProblem, {
|
|
1097
1158
|
textBoxPadding: this.getTextBoxPaddingForConnectionPair()
|
|
1098
1159
|
});
|
|
1099
|
-
this.textObstacles = new Set(
|
|
1100
|
-
this.obstacles.filter((r) => r.kind === "text_box")
|
|
1101
|
-
);
|
|
1160
|
+
this.textObstacles = new Set(this.obstacles.filter(isTextBoxObstacle));
|
|
1102
1161
|
const endpointChipIds = new Set(this.pins.map((pin) => pin.chipId));
|
|
1103
1162
|
this.endpointTextObstacles = new Set(
|
|
1104
|
-
endpointChipIds.size > 1 ? this.obstacles.filter(
|
|
1105
|
-
(
|
|
1163
|
+
endpointChipIds.size > 1 ? this.obstacles.filter(isTextBoxObstacle).filter(
|
|
1164
|
+
(obstacle) => obstacle.textBox.chipId !== void 0 && endpointChipIds.has(obstacle.textBox.chipId)
|
|
1106
1165
|
) : []
|
|
1107
1166
|
);
|
|
1108
1167
|
const [pin1, pin2] = this.pins;
|
|
@@ -1290,7 +1349,10 @@ var SchematicTraceSingleLineSolver2 = class extends BaseSolver {
|
|
|
1290
1349
|
path[adjacentEndpointSegIndex + 1]
|
|
1291
1350
|
)) {
|
|
1292
1351
|
for (const textObstacle of this.endpointTextObstacles) {
|
|
1293
|
-
|
|
1352
|
+
const textBounds = getTextBoxBounds(textObstacle.textBox);
|
|
1353
|
+
if (!segmentIntersectsRect(segmentStart, segmentEnd, textBounds)) {
|
|
1354
|
+
excludedRects.add(textObstacle);
|
|
1355
|
+
}
|
|
1294
1356
|
}
|
|
1295
1357
|
}
|
|
1296
1358
|
return excludedRects;
|
|
@@ -1299,8 +1361,8 @@ var SchematicTraceSingleLineSolver2 = class extends BaseSolver {
|
|
|
1299
1361
|
if (!collision) {
|
|
1300
1362
|
const first = path[0];
|
|
1301
1363
|
const last = path[path.length - 1];
|
|
1302
|
-
const
|
|
1303
|
-
const samePoint = (p, q) => Math.abs(p.x - q.x) <
|
|
1364
|
+
const EPS13 = 1e-9;
|
|
1365
|
+
const samePoint = (p, q) => Math.abs(p.x - q.x) < EPS13 && Math.abs(p.y - q.y) < EPS13;
|
|
1304
1366
|
if (samePoint(first, { x: PA.x, y: PA.y }) && samePoint(last, { x: PB.x, y: PB.y })) {
|
|
1305
1367
|
this.solvedTracePath = path;
|
|
1306
1368
|
this.solved = true;
|
|
@@ -1373,14 +1435,7 @@ var SchematicTraceSingleLineSolver2 = class extends BaseSolver {
|
|
|
1373
1435
|
candidates.push(...mids);
|
|
1374
1436
|
}
|
|
1375
1437
|
const newStates = [];
|
|
1376
|
-
const
|
|
1377
|
-
const newPath = shiftSegmentOrth(
|
|
1378
|
-
path,
|
|
1379
|
-
candidateSegIndex,
|
|
1380
|
-
candidateAxis,
|
|
1381
|
-
coord
|
|
1382
|
-
);
|
|
1383
|
-
if (!newPath) return;
|
|
1438
|
+
const addPathCandidate = (newPath) => {
|
|
1384
1439
|
const key = pathKey(newPath);
|
|
1385
1440
|
if (this.visited.has(key)) return;
|
|
1386
1441
|
this.visited.add(key);
|
|
@@ -1393,10 +1448,28 @@ var SchematicTraceSingleLineSolver2 = class extends BaseSolver {
|
|
|
1393
1448
|
pinBandPenalty: this.getPinBandPenalty(newPath)
|
|
1394
1449
|
});
|
|
1395
1450
|
};
|
|
1451
|
+
const addShiftedCandidate = (candidateSegIndex, candidateAxis, coord) => {
|
|
1452
|
+
const newPath = shiftSegmentOrth(
|
|
1453
|
+
path,
|
|
1454
|
+
candidateSegIndex,
|
|
1455
|
+
candidateAxis,
|
|
1456
|
+
coord
|
|
1457
|
+
);
|
|
1458
|
+
if (newPath) addPathCandidate(newPath);
|
|
1459
|
+
};
|
|
1460
|
+
const lastSegIndex = path.length - 2;
|
|
1461
|
+
if (this.connectionPair === void 0 && rect.kind === "text_box" && this.endpointTextObstacles.has(rect) && !collisionRects.has(rect) && originalSegIndex > 0 && originalSegIndex < lastSegIndex) {
|
|
1462
|
+
for (const detour of generateInternalSegmentCollisionDetours({
|
|
1463
|
+
path,
|
|
1464
|
+
collidingSegmentIndex: originalSegIndex,
|
|
1465
|
+
obstacle: rect
|
|
1466
|
+
})) {
|
|
1467
|
+
addPathCandidate(detour);
|
|
1468
|
+
}
|
|
1469
|
+
}
|
|
1396
1470
|
for (const coord of candidates) {
|
|
1397
1471
|
addShiftedCandidate(segIndex, axis, coord);
|
|
1398
1472
|
}
|
|
1399
|
-
const lastSegIndex = path.length - 2;
|
|
1400
1473
|
const adjacentSegmentIndexes = originalSegIndex === 1 ? [2] : originalSegIndex === lastSegIndex - 1 ? [lastSegIndex - 2] : [];
|
|
1401
1474
|
for (const adjacentSegIndex of adjacentSegmentIndexes) {
|
|
1402
1475
|
if (adjacentSegIndex < 0 || adjacentSegIndex >= lastSegIndex) continue;
|
|
@@ -1573,13 +1646,13 @@ var applyJogToTerminalSegment = ({
|
|
|
1573
1646
|
segmentIndex: si,
|
|
1574
1647
|
offset,
|
|
1575
1648
|
JOG_SIZE,
|
|
1576
|
-
EPS:
|
|
1649
|
+
EPS: EPS13 = 1e-6
|
|
1577
1650
|
}) => {
|
|
1578
1651
|
if (si !== 0 && si !== pts.length - 2) return;
|
|
1579
1652
|
const start = pts[si];
|
|
1580
1653
|
const end = pts[si + 1];
|
|
1581
|
-
const isVertical5 = Math.abs(start.x - end.x) <
|
|
1582
|
-
const isHorizontal4 = Math.abs(start.y - end.y) <
|
|
1654
|
+
const isVertical5 = Math.abs(start.x - end.x) < EPS13;
|
|
1655
|
+
const isHorizontal4 = Math.abs(start.y - end.y) < EPS13;
|
|
1583
1656
|
if (!isVertical5 && !isHorizontal4) return;
|
|
1584
1657
|
const segDir = isVertical5 ? end.y > start.y ? 1 : -1 : end.x > start.x ? 1 : -1;
|
|
1585
1658
|
if (pts.length === 2) {
|
|
@@ -1652,7 +1725,7 @@ var applyJogToTerminalSegment = ({
|
|
|
1652
1725
|
};
|
|
1653
1726
|
|
|
1654
1727
|
// lib/solvers/TraceOverlapShiftSolver/TraceOverlapIssueSolver/TraceOverlapIssueSolver.ts
|
|
1655
|
-
var
|
|
1728
|
+
var EPS5 = 1e-6;
|
|
1656
1729
|
var TraceOverlapIssueSolver = class extends BaseSolver {
|
|
1657
1730
|
overlappingTraceSegments;
|
|
1658
1731
|
interactionKind;
|
|
@@ -1741,7 +1814,7 @@ var TraceOverlapIssueSolver = class extends BaseSolver {
|
|
|
1741
1814
|
}
|
|
1742
1815
|
applyOffsets(offsets) {
|
|
1743
1816
|
const correctedTraceMap = { ...this.correctedTraceMap };
|
|
1744
|
-
const eq = (a, b) => Math.abs(a - b) <
|
|
1817
|
+
const eq = (a, b) => Math.abs(a - b) < EPS5;
|
|
1745
1818
|
const samePoint = (p, q) => !!p && !!q && eq(p.x, q.x) && eq(p.y, q.y);
|
|
1746
1819
|
this.overlappingTraceSegments.forEach((group, groupIndex) => {
|
|
1747
1820
|
const offset = offsets[groupIndex];
|
|
@@ -1763,9 +1836,9 @@ var TraceOverlapIssueSolver = class extends BaseSolver {
|
|
|
1763
1836
|
const start = pts[si];
|
|
1764
1837
|
const end = pts[si + 1];
|
|
1765
1838
|
if (!start || !end) continue;
|
|
1766
|
-
if (Math.abs(start.x - end.x) <
|
|
1839
|
+
if (Math.abs(start.x - end.x) < EPS5) {
|
|
1767
1840
|
segmentAxes.set(si, "vertical");
|
|
1768
|
-
} else if (Math.abs(start.y - end.y) <
|
|
1841
|
+
} else if (Math.abs(start.y - end.y) < EPS5) {
|
|
1769
1842
|
segmentAxes.set(si, "horizontal");
|
|
1770
1843
|
}
|
|
1771
1844
|
}
|
|
@@ -1780,7 +1853,7 @@ var TraceOverlapIssueSolver = class extends BaseSolver {
|
|
|
1780
1853
|
segmentIndex: si,
|
|
1781
1854
|
offset,
|
|
1782
1855
|
JOG_SIZE,
|
|
1783
|
-
EPS:
|
|
1856
|
+
EPS: EPS5
|
|
1784
1857
|
});
|
|
1785
1858
|
} else {
|
|
1786
1859
|
const start = pts[si];
|
|
@@ -1867,7 +1940,7 @@ var TraceOverlapIssueSolver = class extends BaseSolver {
|
|
|
1867
1940
|
max = obstacle.maxY;
|
|
1868
1941
|
}
|
|
1869
1942
|
const next = orig + candidateOffset;
|
|
1870
|
-
return orig <= min +
|
|
1943
|
+
return orig <= min + EPS5 && next >= max - EPS5 || orig >= max - EPS5 && next <= min + EPS5;
|
|
1871
1944
|
});
|
|
1872
1945
|
const edges = blockingCollisions.map(({ start, isVertical: isVertical5, obstacle }) => {
|
|
1873
1946
|
if (isVertical5) {
|
|
@@ -1904,8 +1977,8 @@ var TraceOverlapIssueSolver = class extends BaseSolver {
|
|
|
1904
1977
|
const start = trace.tracePath[traceSegmentIndex];
|
|
1905
1978
|
const end = trace.tracePath[traceSegmentIndex + 1];
|
|
1906
1979
|
if (!start || !end) continue;
|
|
1907
|
-
const isVertical5 = Math.abs(start.x - end.x) <
|
|
1908
|
-
const isHorizontal4 = Math.abs(start.y - end.y) <
|
|
1980
|
+
const isVertical5 = Math.abs(start.x - end.x) < EPS5;
|
|
1981
|
+
const isHorizontal4 = Math.abs(start.y - end.y) < EPS5;
|
|
1909
1982
|
if (!isVertical5 && !isHorizontal4) continue;
|
|
1910
1983
|
const shiftedSegment = isVertical5 ? [
|
|
1911
1984
|
{ ...start, x: start.x + offset },
|
|
@@ -1997,7 +2070,7 @@ var TraceOverlapShiftSolver = class extends BaseSolver {
|
|
|
1997
2070
|
return islands;
|
|
1998
2071
|
}
|
|
1999
2072
|
findNextOverlapIssue() {
|
|
2000
|
-
const
|
|
2073
|
+
const EPS13 = 2e-3;
|
|
2001
2074
|
const netIds = Object.keys(this.traceNetIslands);
|
|
2002
2075
|
for (let i = 0; i < netIds.length; i++) {
|
|
2003
2076
|
for (let j = i + 1; j < netIds.length; j++) {
|
|
@@ -2024,7 +2097,7 @@ var TraceOverlapShiftSolver = class extends BaseSolver {
|
|
|
2024
2097
|
segmentBIndex,
|
|
2025
2098
|
rangeOverlap
|
|
2026
2099
|
}) => {
|
|
2027
|
-
if (rangeOverlap >
|
|
2100
|
+
if (rangeOverlap > EPS13) {
|
|
2028
2101
|
const keyA = `${pathAIndex}:${segmentAIndex}`;
|
|
2029
2102
|
const keyB = `${pathBIndex}:${segmentBIndex}`;
|
|
2030
2103
|
if (!seenA.has(keyA)) {
|
|
@@ -2043,7 +2116,7 @@ var TraceOverlapShiftSolver = class extends BaseSolver {
|
|
|
2043
2116
|
}
|
|
2044
2117
|
return;
|
|
2045
2118
|
}
|
|
2046
|
-
if (rangeOverlap < -
|
|
2119
|
+
if (rangeOverlap < -EPS13) return;
|
|
2047
2120
|
const pathA = pathsA[pathAIndex].tracePath;
|
|
2048
2121
|
const pathB = pathsB[pathBIndex].tracePath;
|
|
2049
2122
|
const segmentAStart = pathA[segmentAIndex];
|
|
@@ -2066,8 +2139,8 @@ var TraceOverlapShiftSolver = class extends BaseSolver {
|
|
|
2066
2139
|
for (let sa = 0; sa < ptsA.length - 1; sa++) {
|
|
2067
2140
|
const a1 = ptsA[sa];
|
|
2068
2141
|
const a2 = ptsA[sa + 1];
|
|
2069
|
-
const aVert = Math.abs(a1.x - a2.x) <
|
|
2070
|
-
const aHorz = Math.abs(a1.y - a2.y) <
|
|
2142
|
+
const aVert = Math.abs(a1.x - a2.x) < EPS13;
|
|
2143
|
+
const aHorz = Math.abs(a1.y - a2.y) < EPS13;
|
|
2071
2144
|
if (!aVert && !aHorz) continue;
|
|
2072
2145
|
for (let pb = 0; pb < pathsB.length; pb++) {
|
|
2073
2146
|
const pathB = pathsB[pb];
|
|
@@ -2075,11 +2148,11 @@ var TraceOverlapShiftSolver = class extends BaseSolver {
|
|
|
2075
2148
|
for (let sb = 0; sb < ptsB.length - 1; sb++) {
|
|
2076
2149
|
const b1 = ptsB[sb];
|
|
2077
2150
|
const b2 = ptsB[sb + 1];
|
|
2078
|
-
const bVert = Math.abs(b1.x - b2.x) <
|
|
2079
|
-
const bHorz = Math.abs(b1.y - b2.y) <
|
|
2151
|
+
const bVert = Math.abs(b1.x - b2.x) < EPS13;
|
|
2152
|
+
const bHorz = Math.abs(b1.y - b2.y) < EPS13;
|
|
2080
2153
|
if (!bVert && !bHorz) continue;
|
|
2081
2154
|
if (aVert && bVert) {
|
|
2082
|
-
if (Math.abs(a1.x - b1.x) <
|
|
2155
|
+
if (Math.abs(a1.x - b1.x) < EPS13) {
|
|
2083
2156
|
recordCollinearInteraction({
|
|
2084
2157
|
pathAIndex: pa,
|
|
2085
2158
|
segmentAIndex: sa,
|
|
@@ -2089,7 +2162,7 @@ var TraceOverlapShiftSolver = class extends BaseSolver {
|
|
|
2089
2162
|
});
|
|
2090
2163
|
}
|
|
2091
2164
|
} else if (aHorz && bHorz) {
|
|
2092
|
-
if (Math.abs(a1.y - b1.y) <
|
|
2165
|
+
if (Math.abs(a1.y - b1.y) < EPS13) {
|
|
2093
2166
|
recordCollinearInteraction({
|
|
2094
2167
|
pathAIndex: pa,
|
|
2095
2168
|
segmentAIndex: sa,
|
|
@@ -2145,14 +2218,14 @@ var TraceOverlapShiftSolver = class extends BaseSolver {
|
|
|
2145
2218
|
return null;
|
|
2146
2219
|
}
|
|
2147
2220
|
findNextDiagonalSegment() {
|
|
2148
|
-
const
|
|
2221
|
+
const EPS13 = 2e-3;
|
|
2149
2222
|
for (const mspPairId in this.correctedTraceMap) {
|
|
2150
2223
|
const tracePath = this.correctedTraceMap[mspPairId].tracePath;
|
|
2151
2224
|
for (let i = 0; i < tracePath.length - 1; i++) {
|
|
2152
2225
|
const p1 = tracePath[i];
|
|
2153
2226
|
const p2 = tracePath[i + 1];
|
|
2154
|
-
const isHorizontal4 = Math.abs(p1.y - p2.y) <
|
|
2155
|
-
const isVertical5 = Math.abs(p1.x - p2.x) <
|
|
2227
|
+
const isHorizontal4 = Math.abs(p1.y - p2.y) < EPS13;
|
|
2228
|
+
const isVertical5 = Math.abs(p1.x - p2.x) < EPS13;
|
|
2156
2229
|
if (!isHorizontal4 && !isVertical5) {
|
|
2157
2230
|
return { mspPairId, tracePath, i, p1, p2 };
|
|
2158
2231
|
}
|
|
@@ -2166,13 +2239,13 @@ var TraceOverlapShiftSolver = class extends BaseSolver {
|
|
|
2166
2239
|
return false;
|
|
2167
2240
|
}
|
|
2168
2241
|
const { mspPairId, tracePath, i, p1, p2 } = diagonalInfo;
|
|
2169
|
-
const
|
|
2242
|
+
const EPS13 = 2e-3;
|
|
2170
2243
|
const p0 = i > 0 ? tracePath[i - 1] : null;
|
|
2171
2244
|
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) <
|
|
2245
|
+
const prevIsVertical = p0 ? Math.abs(p0.x - p1.x) < EPS13 : false;
|
|
2246
|
+
const prevIsHorizontal = p0 ? Math.abs(p0.y - p1.y) < EPS13 : false;
|
|
2247
|
+
const nextIsVertical = p3 ? Math.abs(p2.x - p3.x) < EPS13 : false;
|
|
2248
|
+
const nextIsHorizontal = p3 ? Math.abs(p2.y - p3.y) < EPS13 : false;
|
|
2176
2249
|
const elbow1 = { x: p1.x, y: p2.y };
|
|
2177
2250
|
const elbow2 = { x: p2.x, y: p1.y };
|
|
2178
2251
|
let score1 = 0;
|
|
@@ -2299,24 +2372,24 @@ var ChipObstacleSpatialIndex = class {
|
|
|
2299
2372
|
};
|
|
2300
2373
|
|
|
2301
2374
|
// 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) <
|
|
2375
|
+
function segmentIntersectsRect2(p1, p2, rect, EPS13 = 1e-9) {
|
|
2376
|
+
const isVert = Math.abs(p1.x - p2.x) < EPS13;
|
|
2377
|
+
const isHorz = Math.abs(p1.y - p2.y) < EPS13;
|
|
2305
2378
|
if (!isVert && !isHorz) return false;
|
|
2306
2379
|
if (isVert) {
|
|
2307
2380
|
const x = p1.x;
|
|
2308
|
-
if (x < rect.minX -
|
|
2381
|
+
if (x < rect.minX - EPS13 || x > rect.maxX + EPS13) return false;
|
|
2309
2382
|
const segMinY = Math.min(p1.y, p2.y);
|
|
2310
2383
|
const segMaxY = Math.max(p1.y, p2.y);
|
|
2311
2384
|
const overlap = Math.min(segMaxY, rect.maxY) - Math.max(segMinY, rect.minY);
|
|
2312
|
-
return overlap >
|
|
2385
|
+
return overlap > EPS13;
|
|
2313
2386
|
} else {
|
|
2314
2387
|
const y = p1.y;
|
|
2315
|
-
if (y < rect.minY -
|
|
2388
|
+
if (y < rect.minY - EPS13 || y > rect.maxY + EPS13) return false;
|
|
2316
2389
|
const segMinX = Math.min(p1.x, p2.x);
|
|
2317
2390
|
const segMaxX = Math.max(p1.x, p2.x);
|
|
2318
2391
|
const overlap = Math.min(segMaxX, rect.maxX) - Math.max(segMinX, rect.minX);
|
|
2319
|
-
return overlap >
|
|
2392
|
+
return overlap > EPS13;
|
|
2320
2393
|
}
|
|
2321
2394
|
}
|
|
2322
2395
|
function rectIntersectsAnyTrace(bounds, inputTraceMap, hostPathId, hostSegIndex) {
|
|
@@ -2713,14 +2786,14 @@ var SingleNetLabelPlacementSolver = class extends BaseSolver {
|
|
|
2713
2786
|
};
|
|
2714
2787
|
let bestCandidate = null;
|
|
2715
2788
|
let bestScore = -Infinity;
|
|
2716
|
-
const
|
|
2789
|
+
const EPS13 = 1e-6;
|
|
2717
2790
|
for (const curr of tracesToScan) {
|
|
2718
2791
|
const pts = curr.tracePath.slice();
|
|
2719
2792
|
for (let si = 0; si < pts.length - 1; si++) {
|
|
2720
2793
|
const a = pts[si];
|
|
2721
2794
|
const b = pts[si + 1];
|
|
2722
|
-
const isH = Math.abs(a.y - b.y) <
|
|
2723
|
-
const isV = Math.abs(a.x - b.x) <
|
|
2795
|
+
const isH = Math.abs(a.y - b.y) < EPS13;
|
|
2796
|
+
const isV = Math.abs(a.x - b.x) < EPS13;
|
|
2724
2797
|
if (!isH && !isV) continue;
|
|
2725
2798
|
const segmentAllowed = isH ? ["y+", "y-"] : ["x+", "x-"];
|
|
2726
2799
|
const candidateOrients = orientations.filter(
|
|
@@ -5123,9 +5196,9 @@ var moveRailSegments = (trace, segments, coordinate) => {
|
|
|
5123
5196
|
};
|
|
5124
5197
|
|
|
5125
5198
|
// lib/solvers/RailNetLabelCornerPlacementSolver/geometry.ts
|
|
5126
|
-
var
|
|
5199
|
+
var EPS6 = 1e-6;
|
|
5127
5200
|
var isTraceLine = (trace) => getUniquePinCount(trace.pinIds) >= 2;
|
|
5128
|
-
var rectsOverlap = (a, b) => Math.min(a.maxX, b.maxX) - Math.max(a.minX, b.minX) >
|
|
5201
|
+
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
5202
|
var getTraceCorners = (path) => {
|
|
5130
5203
|
const corners = [];
|
|
5131
5204
|
for (let i = 1; i < path.length - 1; i++) {
|
|
@@ -5149,11 +5222,11 @@ var getUniquePinCount = (pinIds) => new Set(pinIds).size;
|
|
|
5149
5222
|
var isTraceCorner = (a, b, c) => getSegmentOrientation(a, b) !== getSegmentOrientation(b, c);
|
|
5150
5223
|
var isPointOnSegment = (point, start, end) => {
|
|
5151
5224
|
if (getSegmentOrientation(start, end) === "horizontal") {
|
|
5152
|
-
return Math.abs(point.y - start.y) <=
|
|
5225
|
+
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
5226
|
}
|
|
5154
|
-
return Math.abs(point.x - start.x) <=
|
|
5227
|
+
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
5228
|
};
|
|
5156
|
-
var getSegmentOrientation = (a, b) => Math.abs(a.y - b.y) <=
|
|
5229
|
+
var getSegmentOrientation = (a, b) => Math.abs(a.y - b.y) <= EPS6 ? "horizontal" : "vertical";
|
|
5157
5230
|
|
|
5158
5231
|
// lib/solvers/TraceCleanupSolver/sameNetRailAlignment/preservesLabelAnchors.ts
|
|
5159
5232
|
var getAnchoredTraceIds = (label, traces) => new Set(
|
|
@@ -5169,17 +5242,17 @@ var preservesLabelAnchors = (labels, before, after) => labels.every((label) => {
|
|
|
5169
5242
|
});
|
|
5170
5243
|
|
|
5171
5244
|
// lib/solvers/Example28Solver/types.ts
|
|
5172
|
-
var
|
|
5245
|
+
var EPS7 = 1e-9;
|
|
5173
5246
|
|
|
5174
5247
|
// lib/solvers/Example28Solver/segmentRunsAlongRectBoundary.ts
|
|
5175
5248
|
var segmentRunsAlongRectBoundary = (start, end, rect) => {
|
|
5176
|
-
const isVertical5 = Math.abs(start.x - end.x) <
|
|
5177
|
-
const isHorizontal4 = Math.abs(start.y - end.y) <
|
|
5249
|
+
const isVertical5 = Math.abs(start.x - end.x) < EPS7;
|
|
5250
|
+
const isHorizontal4 = Math.abs(start.y - end.y) < EPS7;
|
|
5178
5251
|
if (isVertical5) {
|
|
5179
|
-
return Math.abs(start.x - rect.minX) <
|
|
5252
|
+
return Math.abs(start.x - rect.minX) < EPS7 || Math.abs(start.x - rect.maxX) < EPS7;
|
|
5180
5253
|
}
|
|
5181
5254
|
if (isHorizontal4) {
|
|
5182
|
-
return Math.abs(start.y - rect.minY) <
|
|
5255
|
+
return Math.abs(start.y - rect.minY) < EPS7 || Math.abs(start.y - rect.maxY) < EPS7;
|
|
5183
5256
|
}
|
|
5184
5257
|
return false;
|
|
5185
5258
|
};
|
|
@@ -5194,10 +5267,10 @@ var getPathLength = (path) => {
|
|
|
5194
5267
|
return length;
|
|
5195
5268
|
};
|
|
5196
5269
|
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) <
|
|
5270
|
+
var isAxisAlignedSegment = (start, end) => Math.abs(start.x - end.x) < EPS7 || Math.abs(start.y - end.y) < EPS7;
|
|
5271
|
+
var getSegmentOrientation2 = (start, end) => Math.abs(start.y - end.y) < EPS7 ? "horizontal" : "vertical";
|
|
5199
5272
|
var projectPointToSegment = (point, start, end) => {
|
|
5200
|
-
if (Math.abs(start.x - end.x) <
|
|
5273
|
+
if (Math.abs(start.x - end.x) < EPS7) {
|
|
5201
5274
|
return {
|
|
5202
5275
|
x: start.x,
|
|
5203
5276
|
y: Math.min(
|
|
@@ -5206,7 +5279,7 @@ var projectPointToSegment = (point, start, end) => {
|
|
|
5206
5279
|
)
|
|
5207
5280
|
};
|
|
5208
5281
|
}
|
|
5209
|
-
if (Math.abs(start.y - end.y) <
|
|
5282
|
+
if (Math.abs(start.y - end.y) < EPS7) {
|
|
5210
5283
|
return {
|
|
5211
5284
|
x: Math.min(
|
|
5212
5285
|
Math.max(point.x, Math.min(start.x, end.x)),
|
|
@@ -5249,9 +5322,9 @@ var findSegmentContainingPoint = (path, point) => {
|
|
|
5249
5322
|
};
|
|
5250
5323
|
var isPointWithinSegmentPrimaryRange = (point, segment) => {
|
|
5251
5324
|
if (segment.orientation === "horizontal") {
|
|
5252
|
-
return point.x >= Math.min(segment.start.x, segment.end.x) -
|
|
5325
|
+
return point.x >= Math.min(segment.start.x, segment.end.x) - EPS7 && point.x <= Math.max(segment.start.x, segment.end.x) + EPS7;
|
|
5253
5326
|
}
|
|
5254
|
-
return point.y >= Math.min(segment.start.y, segment.end.y) -
|
|
5327
|
+
return point.y >= Math.min(segment.start.y, segment.end.y) - EPS7 && point.y <= Math.max(segment.start.y, segment.end.y) + EPS7;
|
|
5255
5328
|
};
|
|
5256
5329
|
var findPreferredReroutedSegment = (path, originalSegmentIndex, originalSegmentCount, orientation, anchorPoint) => {
|
|
5257
5330
|
const matchingSegments = getSegments(path).filter(
|
|
@@ -5279,18 +5352,18 @@ var projectPointToPath = (point, path) => {
|
|
|
5279
5352
|
return bestPoint;
|
|
5280
5353
|
};
|
|
5281
5354
|
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) -
|
|
5355
|
+
const aVertical = Math.abs(a1.x - a2.x) < EPS7;
|
|
5356
|
+
const bVertical = Math.abs(b1.x - b2.x) < EPS7;
|
|
5357
|
+
const between = (value, p1, p2) => value >= Math.min(p1, p2) - EPS7 && value <= Math.max(p1, p2) + EPS7;
|
|
5285
5358
|
if (aVertical && bVertical) {
|
|
5286
|
-
if (Math.abs(a1.x - b1.x) >
|
|
5359
|
+
if (Math.abs(a1.x - b1.x) > EPS7) return false;
|
|
5287
5360
|
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 >
|
|
5361
|
+
return overlap > EPS7;
|
|
5289
5362
|
}
|
|
5290
5363
|
if (!aVertical && !bVertical) {
|
|
5291
|
-
if (Math.abs(a1.y - b1.y) >
|
|
5364
|
+
if (Math.abs(a1.y - b1.y) > EPS7) return false;
|
|
5292
5365
|
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 >
|
|
5366
|
+
return overlap > EPS7;
|
|
5294
5367
|
}
|
|
5295
5368
|
const verticalA = aVertical ? a1 : b1;
|
|
5296
5369
|
const verticalB = aVertical ? a2 : b2;
|
|
@@ -5652,7 +5725,7 @@ var getTraceObstacles = (allTraces, excludeTraceId) => {
|
|
|
5652
5725
|
|
|
5653
5726
|
// lib/solvers/TraceCleanupSolver/sub-solver/findIntersectionsWithObstacles.ts
|
|
5654
5727
|
import { getSegmentIntersection } from "@tscircuit/math-utils/line-intersections";
|
|
5655
|
-
var
|
|
5728
|
+
var EPS8 = 1e-6;
|
|
5656
5729
|
var findIntersectionsWithObstacles = (p1, p2, obstacles) => {
|
|
5657
5730
|
const intersections = [];
|
|
5658
5731
|
for (const obstacle of obstacles) {
|
|
@@ -5671,17 +5744,17 @@ var findIntersectionsWithObstacles = (p1, p2, obstacles) => {
|
|
|
5671
5744
|
}
|
|
5672
5745
|
return intersections;
|
|
5673
5746
|
};
|
|
5674
|
-
var isSamePoint = (first, second) => Math.abs(first.x - second.x) <
|
|
5747
|
+
var isSamePoint = (first, second) => Math.abs(first.x - second.x) < EPS8 && Math.abs(first.y - second.y) < EPS8;
|
|
5675
5748
|
var findPerpendicularPathCrossings = (path, otherPath) => {
|
|
5676
5749
|
const crossings = [];
|
|
5677
5750
|
for (let pathSegmentIndex = 1; pathSegmentIndex < path.length - 2; pathSegmentIndex++) {
|
|
5678
5751
|
const start = path[pathSegmentIndex];
|
|
5679
5752
|
const end = path[pathSegmentIndex + 1];
|
|
5680
|
-
const isVertical5 = Math.abs(start.x - end.x) <
|
|
5753
|
+
const isVertical5 = Math.abs(start.x - end.x) < EPS8;
|
|
5681
5754
|
for (let otherPathSegmentIndex = 1; otherPathSegmentIndex < otherPath.length - 2; otherPathSegmentIndex++) {
|
|
5682
5755
|
const otherStart = otherPath[otherPathSegmentIndex];
|
|
5683
5756
|
const otherEnd = otherPath[otherPathSegmentIndex + 1];
|
|
5684
|
-
const otherIsVertical = Math.abs(otherStart.x - otherEnd.x) <
|
|
5757
|
+
const otherIsVertical = Math.abs(otherStart.x - otherEnd.x) < EPS8;
|
|
5685
5758
|
if (isVertical5 === otherIsVertical) continue;
|
|
5686
5759
|
const intersection = getSegmentIntersection(
|
|
5687
5760
|
start,
|
|
@@ -5701,8 +5774,8 @@ var findPerpendicularPathCrossings = (path, otherPath) => {
|
|
|
5701
5774
|
};
|
|
5702
5775
|
|
|
5703
5776
|
// lib/solvers/TraceCleanupSolver/sub-solver/generateLShapeRerouteCandidates.ts
|
|
5704
|
-
var
|
|
5705
|
-
var isVertical3 = (a, b, eps =
|
|
5777
|
+
var EPS9 = 1e-6;
|
|
5778
|
+
var isVertical3 = (a, b, eps = EPS9) => Math.abs(a.x - b.x) < eps;
|
|
5706
5779
|
var generateLShapeRerouteCandidates = ({
|
|
5707
5780
|
lShape,
|
|
5708
5781
|
rectangle,
|
|
@@ -5715,7 +5788,7 @@ var generateLShapeRerouteCandidates = ({
|
|
|
5715
5788
|
let c2;
|
|
5716
5789
|
let i1_padded = interactionPoint1;
|
|
5717
5790
|
let i2_padded = interactionPoint2;
|
|
5718
|
-
if (Math.abs(p2.x - x) <
|
|
5791
|
+
if (Math.abs(p2.x - x) < EPS9 && Math.abs(p2.y - (y + height)) < EPS9) {
|
|
5719
5792
|
c2 = { x: x + width + padding, y: y - padding };
|
|
5720
5793
|
if (isVertical3(p1, p2)) {
|
|
5721
5794
|
i1_padded = { x: interactionPoint1.x, y: interactionPoint1.y - padding };
|
|
@@ -5727,7 +5800,7 @@ var generateLShapeRerouteCandidates = ({
|
|
|
5727
5800
|
} else {
|
|
5728
5801
|
i2_padded = { x: interactionPoint2.x + padding, y: interactionPoint2.y };
|
|
5729
5802
|
}
|
|
5730
|
-
} else if (Math.abs(p2.x - (x + width)) <
|
|
5803
|
+
} else if (Math.abs(p2.x - (x + width)) < EPS9 && Math.abs(p2.y - (y + height)) < EPS9) {
|
|
5731
5804
|
c2 = { x: x - padding, y: y - padding };
|
|
5732
5805
|
if (isVertical3(p1, p2)) {
|
|
5733
5806
|
i1_padded = { x: interactionPoint1.x, y: interactionPoint1.y - padding };
|
|
@@ -5739,7 +5812,7 @@ var generateLShapeRerouteCandidates = ({
|
|
|
5739
5812
|
} else {
|
|
5740
5813
|
i2_padded = { x: interactionPoint2.x - padding, y: interactionPoint2.y };
|
|
5741
5814
|
}
|
|
5742
|
-
} else if (Math.abs(p2.x - x) <
|
|
5815
|
+
} else if (Math.abs(p2.x - x) < EPS9 && Math.abs(p2.y - y) < EPS9) {
|
|
5743
5816
|
c2 = { x: x + width + padding, y: y + height + padding };
|
|
5744
5817
|
if (isVertical3(p1, p2)) {
|
|
5745
5818
|
i1_padded = { x: interactionPoint1.x, y: interactionPoint1.y + padding };
|
|
@@ -5751,7 +5824,7 @@ var generateLShapeRerouteCandidates = ({
|
|
|
5751
5824
|
} else {
|
|
5752
5825
|
i2_padded = { x: interactionPoint2.x + padding, y: interactionPoint2.y };
|
|
5753
5826
|
}
|
|
5754
|
-
} else if (Math.abs(p2.x - (x + width)) <
|
|
5827
|
+
} else if (Math.abs(p2.x - (x + width)) < EPS9 && Math.abs(p2.y - y) < EPS9) {
|
|
5755
5828
|
c2 = { x: x - padding, y: y + height + padding };
|
|
5756
5829
|
if (isVertical3(p1, p2)) {
|
|
5757
5830
|
i1_padded = { x: interactionPoint1.x, y: interactionPoint1.y + padding };
|
|
@@ -5779,7 +5852,7 @@ var generatePerpendicularTraceDetours = ({
|
|
|
5779
5852
|
const buildDetours = (path, index) => {
|
|
5780
5853
|
const start = path[index];
|
|
5781
5854
|
const end = path[index + 1];
|
|
5782
|
-
const movingAxis = Math.abs(start.x - end.x) <
|
|
5855
|
+
const movingAxis = Math.abs(start.x - end.x) < EPS9 ? "y" : "x";
|
|
5783
5856
|
const detourAxis = movingAxis === "x" ? "y" : "x";
|
|
5784
5857
|
const gate = obstacleStart[movingAxis] + Math.sign(start[movingAxis] - obstacleStart[movingAxis]) * clearance;
|
|
5785
5858
|
const obstacleRange = [obstacleStart[detourAxis], obstacleEnd[detourAxis]];
|
|
@@ -6377,9 +6450,9 @@ var UntangleTraceSubsolver = class extends BaseSolver {
|
|
|
6377
6450
|
};
|
|
6378
6451
|
|
|
6379
6452
|
// 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) <=
|
|
6453
|
+
var EPS10 = 1e-6;
|
|
6454
|
+
var sameX = (a, b) => Math.abs(a.x - b.x) <= EPS10;
|
|
6455
|
+
var sameY = (a, b) => Math.abs(a.y - b.y) <= EPS10;
|
|
6383
6456
|
var is4PointRectangle = (path) => {
|
|
6384
6457
|
if (path.length !== 4) return false;
|
|
6385
6458
|
const [p0, p1, p2, p3] = path;
|
|
@@ -6654,7 +6727,7 @@ var doesPathRunAlongChipBoundary = (path, chipObstacles) => {
|
|
|
6654
6727
|
const end = path[i + 1];
|
|
6655
6728
|
for (const obstacle of chipObstacles) {
|
|
6656
6729
|
if (!segmentRunsAlongRectBoundary(start, end, obstacle)) continue;
|
|
6657
|
-
if (getSegmentOverlapWithRectSpan(start, end, obstacle) >
|
|
6730
|
+
if (getSegmentOverlapWithRectSpan(start, end, obstacle) > EPS7) {
|
|
6658
6731
|
return true;
|
|
6659
6732
|
}
|
|
6660
6733
|
}
|
|
@@ -6669,13 +6742,13 @@ var getChipBoundaryOverlap = (path, chipObstacles) => {
|
|
|
6669
6742
|
for (const obstacle of chipObstacles) {
|
|
6670
6743
|
if (!segmentRunsAlongRectBoundary(start, end, obstacle)) continue;
|
|
6671
6744
|
const overlap = getSegmentOverlapWithRectSpan(start, end, obstacle);
|
|
6672
|
-
if (overlap >
|
|
6745
|
+
if (overlap > EPS7) total += overlap;
|
|
6673
6746
|
}
|
|
6674
6747
|
}
|
|
6675
6748
|
return total;
|
|
6676
6749
|
};
|
|
6677
6750
|
var getSegmentOverlapWithRectSpan = (start, end, rect) => {
|
|
6678
|
-
const isVertical5 = Math.abs(start.x - end.x) <
|
|
6751
|
+
const isVertical5 = Math.abs(start.x - end.x) < EPS7;
|
|
6679
6752
|
if (isVertical5) {
|
|
6680
6753
|
return Math.min(Math.max(start.y, end.y), rect.maxY) - Math.max(Math.min(start.y, end.y), rect.minY);
|
|
6681
6754
|
}
|
|
@@ -7439,16 +7512,16 @@ var createPortOnlyLabelConnectorTrace = ({
|
|
|
7439
7512
|
// lib/solvers/AvailableNetOrientationSolver/constants.ts
|
|
7440
7513
|
var LABEL_SEARCH_STEP = 0.05;
|
|
7441
7514
|
var WICK_CLEARANCE = 1e-3;
|
|
7442
|
-
var
|
|
7443
|
-
var TRACE_BOUNDARY_TOLERANCE = WICK_CLEARANCE +
|
|
7515
|
+
var EPS11 = 1e-9;
|
|
7516
|
+
var TRACE_BOUNDARY_TOLERANCE = WICK_CLEARANCE + EPS11;
|
|
7444
7517
|
var CANDIDATE_SELECTED_COLOR2 = "blue";
|
|
7445
7518
|
var CANDIDATE_REJECTED_COLOR2 = "red";
|
|
7446
7519
|
|
|
7447
7520
|
// lib/solvers/AvailableNetOrientationSolver/geometry.ts
|
|
7448
7521
|
var isYOrientation = (orientation) => orientation === "y+" || orientation === "y-";
|
|
7449
7522
|
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) >
|
|
7523
|
+
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;
|
|
7524
|
+
var rangesOverlap = (minA, maxA, minB, maxB) => Math.min(maxA, maxB) - Math.max(minA, minB) > EPS11;
|
|
7452
7525
|
var traceCrossesBoundsInterior = (bounds, traceMap) => {
|
|
7453
7526
|
for (const trace of Object.values(traceMap)) {
|
|
7454
7527
|
const points = trace.tracePath;
|
|
@@ -7471,7 +7544,7 @@ var segmentCrossesBoundsInterior = (p1, p2, bounds) => {
|
|
|
7471
7544
|
return false;
|
|
7472
7545
|
}
|
|
7473
7546
|
if (sameX2(p1, p2)) {
|
|
7474
|
-
if (p1.x <= interiorBounds.minX +
|
|
7547
|
+
if (p1.x <= interiorBounds.minX + EPS11 || p1.x >= interiorBounds.maxX - EPS11) {
|
|
7475
7548
|
return false;
|
|
7476
7549
|
}
|
|
7477
7550
|
return rangesOverlap(
|
|
@@ -7482,7 +7555,7 @@ var segmentCrossesBoundsInterior = (p1, p2, bounds) => {
|
|
|
7482
7555
|
);
|
|
7483
7556
|
}
|
|
7484
7557
|
if (sameY2(p1, p2)) {
|
|
7485
|
-
if (p1.y <= interiorBounds.minY +
|
|
7558
|
+
if (p1.y <= interiorBounds.minY + EPS11 || p1.y >= interiorBounds.maxY - EPS11) {
|
|
7486
7559
|
return false;
|
|
7487
7560
|
}
|
|
7488
7561
|
return rangesOverlap(
|
|
@@ -7538,8 +7611,8 @@ var simplifyOrthogonalPath = (path) => {
|
|
|
7538
7611
|
return simplified;
|
|
7539
7612
|
};
|
|
7540
7613
|
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) <=
|
|
7614
|
+
var sameX2 = (a, b) => Math.abs(a.x - b.x) <= EPS11;
|
|
7615
|
+
var sameY2 = (a, b) => Math.abs(a.y - b.y) <= EPS11;
|
|
7543
7616
|
var getMaxSearchDistance = (inputProblem) => {
|
|
7544
7617
|
const maxChipWidth = Math.max(
|
|
7545
7618
|
...inputProblem.chips.map((chip) => chip.width),
|
|
@@ -7794,11 +7867,11 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
|
|
|
7794
7867
|
if (trace.globalConnNetId !== label.globalConnNetId) return false;
|
|
7795
7868
|
const path = trace.tracePath;
|
|
7796
7869
|
return path.some((point, pointIndex) => {
|
|
7797
|
-
if (Math.abs(point.x - label.anchorPoint.x) >
|
|
7870
|
+
if (Math.abs(point.x - label.anchorPoint.x) > EPS11 || Math.abs(point.y - label.anchorPoint.y) > EPS11) {
|
|
7798
7871
|
return false;
|
|
7799
7872
|
}
|
|
7800
7873
|
return [path[pointIndex - 1], path[pointIndex + 1]].some(
|
|
7801
|
-
(neighbor) => neighbor && Math.abs(neighbor.x - point.x) <=
|
|
7874
|
+
(neighbor) => neighbor && Math.abs(neighbor.x - point.x) <= EPS11 && (neighbor.y - point.y) * direction.y > EPS11
|
|
7802
7875
|
);
|
|
7803
7876
|
});
|
|
7804
7877
|
});
|
|
@@ -7877,7 +7950,7 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
|
|
|
7877
7950
|
);
|
|
7878
7951
|
const maxSearchDistance = this.getSearchDistanceLimit(label, orientation);
|
|
7879
7952
|
const maxOutwardDistance = outwardDirection.x === 0 && outwardDirection.y === 0 ? 0 : this.maxSearchDistance;
|
|
7880
|
-
for (let outwardDistance = 0; outwardDistance <= maxOutwardDistance +
|
|
7953
|
+
for (let outwardDistance = 0; outwardDistance <= maxOutwardDistance + EPS11; outwardDistance += LABEL_SEARCH_STEP) {
|
|
7881
7954
|
const baseAnchor = {
|
|
7882
7955
|
x: initialBaseAnchor.x + outwardDirection.x * outwardDistance,
|
|
7883
7956
|
y: initialBaseAnchor.y + outwardDirection.y * outwardDistance
|
|
@@ -7951,7 +8024,7 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
|
|
|
7951
8024
|
phase = "shift",
|
|
7952
8025
|
stopOnTraceCollision = true
|
|
7953
8026
|
} = params;
|
|
7954
|
-
for (let distance4 = LABEL_SEARCH_STEP; distance4 <= maxSearchDistance +
|
|
8027
|
+
for (let distance4 = LABEL_SEARCH_STEP; distance4 <= maxSearchDistance + EPS11; distance4 += LABEL_SEARCH_STEP) {
|
|
7955
8028
|
const anchorPoint = {
|
|
7956
8029
|
x: baseAnchor.x + direction.x * distance4,
|
|
7957
8030
|
y: baseAnchor.y + direction.y * distance4
|
|
@@ -8188,9 +8261,9 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
|
|
|
8188
8261
|
const { anchorPoint, orientation } = candidate;
|
|
8189
8262
|
const chipBounds = chip.bounds;
|
|
8190
8263
|
if (isYOrientation(orientation)) {
|
|
8191
|
-
return anchorPoint.x < chipBounds.minX -
|
|
8264
|
+
return anchorPoint.x < chipBounds.minX - EPS11 || anchorPoint.x > chipBounds.maxX + EPS11;
|
|
8192
8265
|
}
|
|
8193
|
-
return anchorPoint.y < chipBounds.minY -
|
|
8266
|
+
return anchorPoint.y < chipBounds.minY - EPS11 || anchorPoint.y > chipBounds.maxY + EPS11;
|
|
8194
8267
|
});
|
|
8195
8268
|
}
|
|
8196
8269
|
getBoundsStatus(candidateBoundsCheck) {
|
|
@@ -8264,8 +8337,8 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
|
|
|
8264
8337
|
sharesChipBoundary(bounds) {
|
|
8265
8338
|
for (const chip of this.chipObstacleSpatialIndex.chips) {
|
|
8266
8339
|
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 +
|
|
8340
|
+
const adjacentToVerticalSide = Math.abs(bounds.minX - chipBounds.maxX) <= WICK_CLEARANCE + EPS11 || Math.abs(bounds.maxX - chipBounds.minX) <= WICK_CLEARANCE + EPS11;
|
|
8341
|
+
const adjacentToHorizontalSide = Math.abs(bounds.minY - chipBounds.maxY) <= WICK_CLEARANCE + EPS11 || Math.abs(bounds.maxY - chipBounds.minY) <= WICK_CLEARANCE + EPS11;
|
|
8269
8342
|
if (adjacentToVerticalSide && rangesOverlap(
|
|
8270
8343
|
bounds.minY,
|
|
8271
8344
|
bounds.maxY,
|
|
@@ -8313,7 +8386,7 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
|
|
|
8313
8386
|
let nearestDistance = Number.POSITIVE_INFINITY;
|
|
8314
8387
|
for (const chip of this.chipObstacleSpatialIndex.chips) {
|
|
8315
8388
|
const bounds = chip.bounds;
|
|
8316
|
-
if (point.x < bounds.minX -
|
|
8389
|
+
if (point.x < bounds.minX - EPS11 || point.x > bounds.maxX + EPS11 || point.y < bounds.minY - EPS11 || point.y > bounds.maxY + EPS11) {
|
|
8317
8390
|
continue;
|
|
8318
8391
|
}
|
|
8319
8392
|
for (const [side, distance4] of getSideDistances(point, bounds)) {
|
|
@@ -8330,8 +8403,8 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
|
|
|
8330
8403
|
let nearestDistanceSq = Number.POSITIVE_INFINITY;
|
|
8331
8404
|
for (const chip of this.chipObstacleSpatialIndex.chips) {
|
|
8332
8405
|
const bounds = chip.bounds;
|
|
8333
|
-
const dx = point.x < bounds.minX -
|
|
8334
|
-
const dy = point.y < bounds.minY -
|
|
8406
|
+
const dx = point.x < bounds.minX - EPS11 ? bounds.minX - point.x : point.x > bounds.maxX + EPS11 ? point.x - bounds.maxX : 0;
|
|
8407
|
+
const dy = point.y < bounds.minY - EPS11 ? bounds.minY - point.y : point.y > bounds.maxY + EPS11 ? point.y - bounds.maxY : 0;
|
|
8335
8408
|
if (dx === 0 && dy === 0) continue;
|
|
8336
8409
|
const distanceSq = dx ** 2 + dy ** 2;
|
|
8337
8410
|
if (distanceSq >= nearestDistanceSq) continue;
|
|
@@ -8615,8 +8688,8 @@ var RailNetLabelCornerPlacementSolver = class extends BaseSolver {
|
|
|
8615
8688
|
if (seenCornerKeys.has(key)) continue;
|
|
8616
8689
|
seenCornerKeys.add(key);
|
|
8617
8690
|
const pinAligned = pins.some((pin) => {
|
|
8618
|
-
if (isVertical5) return Math.abs(pin.x - anchorPoint.x) <
|
|
8619
|
-
return Math.abs(pin.y - anchorPoint.y) <
|
|
8691
|
+
if (isVertical5) return Math.abs(pin.x - anchorPoint.x) < EPS6;
|
|
8692
|
+
return Math.abs(pin.y - anchorPoint.y) < EPS6;
|
|
8620
8693
|
});
|
|
8621
8694
|
if (!pinAligned) continue;
|
|
8622
8695
|
candidates.push({
|
|
@@ -8709,11 +8782,11 @@ var getOrientationConstraint = (inputProblem, label) => {
|
|
|
8709
8782
|
};
|
|
8710
8783
|
|
|
8711
8784
|
// lib/solvers/TraceAnchoredNetLabelOverlapSolver/geometry.ts
|
|
8712
|
-
var
|
|
8785
|
+
var EPS12 = 1e-6;
|
|
8713
8786
|
var TRACE_BOUNDARY_TOLERANCE2 = 1e-6;
|
|
8714
8787
|
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) >= -
|
|
8788
|
+
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;
|
|
8789
|
+
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
8790
|
var traceCrossesBoundsInterior2 = (bounds, traces) => {
|
|
8718
8791
|
for (const trace of traces) {
|
|
8719
8792
|
const points = trace.tracePath;
|
|
@@ -8759,7 +8832,7 @@ var getPointAtTraceDistance = (trace, distance4) => {
|
|
|
8759
8832
|
const end = trace.tracePath[i + 1];
|
|
8760
8833
|
const segmentLength = getManhattanDistance(start, end);
|
|
8761
8834
|
const nextDistance = pathDistance + segmentLength;
|
|
8762
|
-
if (distance4 <= nextDistance +
|
|
8835
|
+
if (distance4 <= nextDistance + EPS12) {
|
|
8763
8836
|
const offset = Math.max(
|
|
8764
8837
|
0,
|
|
8765
8838
|
Math.min(segmentLength, distance4 - pathDistance)
|
|
@@ -8798,7 +8871,7 @@ var segmentCrossesBoundsInterior2 = (start, end, bounds) => {
|
|
|
8798
8871
|
return false;
|
|
8799
8872
|
}
|
|
8800
8873
|
if (isVertical4(start, end)) {
|
|
8801
|
-
if (start.x <= interior.minX +
|
|
8874
|
+
if (start.x <= interior.minX + EPS12 || start.x >= interior.maxX - EPS12) {
|
|
8802
8875
|
return false;
|
|
8803
8876
|
}
|
|
8804
8877
|
return rangesOverlap2(
|
|
@@ -8809,7 +8882,7 @@ var segmentCrossesBoundsInterior2 = (start, end, bounds) => {
|
|
|
8809
8882
|
);
|
|
8810
8883
|
}
|
|
8811
8884
|
if (isHorizontal3(start, end)) {
|
|
8812
|
-
if (start.y <= interior.minY +
|
|
8885
|
+
if (start.y <= interior.minY + EPS12 || start.y >= interior.maxY - EPS12) {
|
|
8813
8886
|
return false;
|
|
8814
8887
|
}
|
|
8815
8888
|
return rangesOverlap2(
|
|
@@ -8823,10 +8896,10 @@ var segmentCrossesBoundsInterior2 = (start, end, bounds) => {
|
|
|
8823
8896
|
};
|
|
8824
8897
|
var isPointOnSegment2 = (point, start, end) => {
|
|
8825
8898
|
if (isHorizontal3(start, end)) {
|
|
8826
|
-
return Math.abs(point.y - start.y) <=
|
|
8899
|
+
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
8900
|
}
|
|
8828
8901
|
if (isVertical4(start, end)) {
|
|
8829
|
-
return Math.abs(point.x - start.x) <=
|
|
8902
|
+
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
8903
|
}
|
|
8831
8904
|
return false;
|
|
8832
8905
|
};
|
|
@@ -8834,9 +8907,9 @@ var getSegmentDirection = (start, end) => ({
|
|
|
8834
8907
|
x: isVertical4(start, end) ? 0 : Math.sign(end.x - start.x),
|
|
8835
8908
|
y: isHorizontal3(start, end) ? 0 : Math.sign(end.y - start.y)
|
|
8836
8909
|
});
|
|
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) >
|
|
8910
|
+
var isHorizontal3 = (start, end) => Math.abs(start.y - end.y) <= EPS12;
|
|
8911
|
+
var isVertical4 = (start, end) => Math.abs(start.x - end.x) <= EPS12;
|
|
8912
|
+
var rangesOverlap2 = (minA, maxA, minB, maxB) => Math.min(maxA, maxB) - Math.max(minA, minB) > EPS12;
|
|
8840
8913
|
var getUniquePinCount2 = (pinIds) => new Set(pinIds).size;
|
|
8841
8914
|
|
|
8842
8915
|
// lib/solvers/TraceAnchoredNetLabelOverlapSolver/candidates.ts
|
|
@@ -8893,7 +8966,7 @@ var getCandidateDistances = (traceLength, vertexDistances) => {
|
|
|
8893
8966
|
for (const distance4 of vertexDistances) {
|
|
8894
8967
|
distances.add(roundDistance(distance4));
|
|
8895
8968
|
}
|
|
8896
|
-
return [...distances].filter((distance4) => distance4 >= -
|
|
8969
|
+
return [...distances].filter((distance4) => distance4 >= -EPS12 && distance4 <= traceLength + EPS12).sort((a, b) => a - b);
|
|
8897
8970
|
};
|
|
8898
8971
|
var getOrientationsForPoint = (params) => {
|
|
8899
8972
|
const { inputProblem, label, point, orientationConstraint } = params;
|
|
@@ -8982,13 +9055,13 @@ var getOutwardOrientationOptions = (point, chipBounds) => {
|
|
|
8982
9055
|
};
|
|
8983
9056
|
var getOutwardAxisOption = (params) => {
|
|
8984
9057
|
const { value, min, max, center, positiveOrientation, negativeOrientation } = params;
|
|
8985
|
-
if (value > max +
|
|
9058
|
+
if (value > max + EPS12) {
|
|
8986
9059
|
return {
|
|
8987
9060
|
orientation: positiveOrientation,
|
|
8988
9061
|
outwardScore: 1 + value - max
|
|
8989
9062
|
};
|
|
8990
9063
|
}
|
|
8991
|
-
if (value < min -
|
|
9064
|
+
if (value < min - EPS12) {
|
|
8992
9065
|
return {
|
|
8993
9066
|
orientation: negativeOrientation,
|
|
8994
9067
|
outwardScore: 1 + min - value
|
|
@@ -8999,7 +9072,7 @@ var getOutwardAxisOption = (params) => {
|
|
|
8999
9072
|
outwardScore: getNormalizedCenterDistance(value, center, max - min)
|
|
9000
9073
|
};
|
|
9001
9074
|
};
|
|
9002
|
-
var getNormalizedCenterDistance = (value, center, span) => Math.abs(value - center) / Math.max(
|
|
9075
|
+
var getNormalizedCenterDistance = (value, center, span) => Math.abs(value - center) / Math.max(EPS12, span / 2);
|
|
9003
9076
|
var ALL_ORIENTATIONS = ["x+", "x-", "y+", "y-"];
|
|
9004
9077
|
var getFlippedOrientation = (orientation) => {
|
|
9005
9078
|
switch (orientation) {
|
|
@@ -9072,7 +9145,7 @@ var getNetLabelHeight = (inputProblem, label) => {
|
|
|
9072
9145
|
)?.netLabelHeight;
|
|
9073
9146
|
};
|
|
9074
9147
|
var roundDistance = (distance4) => Number(distance4.toFixed(6));
|
|
9075
|
-
var isSamePlacement = (label, point, orientation) => Math.abs(point.x - label.anchorPoint.x) <=
|
|
9148
|
+
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
9149
|
|
|
9077
9150
|
// lib/solvers/TraceAnchoredNetLabelOverlapSolver/visualize.ts
|
|
9078
9151
|
var CANDIDATE_SELECTED_COLOR4 = "blue";
|