@tscircuit/schematic-trace-solver 0.0.57 → 0.0.61
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 +15 -1
- package/dist/index.js +367 -136
- package/lib/solvers/AvailableNetOrientationSolver/AvailableNetOrientationSolver.ts +150 -14
- package/lib/solvers/AvailableNetOrientationSolver/geometry.ts +1 -1
- package/lib/solvers/AvailableNetOrientationSolver/types.ts +1 -1
- package/lib/solvers/Example28Solver/reroute.ts +137 -17
- package/lib/solvers/Example28Solver/types.ts +1 -0
- package/lib/solvers/NetLabelPlacementSolver/NetLabelPlacementSolver.ts +32 -10
- package/lib/solvers/TraceAnchoredNetLabelOverlapSolver/candidates.ts +17 -5
- package/lib/solvers/TraceCleanupSolver/is4PointRectangle.ts +7 -2
- package/lib/types/InputProblem.ts +1 -0
- package/package.json +1 -1
- package/site/examples/example35.page.tsx +4 -0
- package/site/examples/example36.page.tsx +4 -0
- package/site/examples/example37.page.tsx +4 -0
- package/site/examples/example38.page.tsx +4 -0
- package/tests/assets/example35.json +127 -0
- package/tests/assets/example36.json +124 -0
- package/tests/assets/example37.json +173 -0
- package/tests/assets/example38.json +32 -0
- package/tests/examples/__snapshots__/example04.snap.svg +16 -17
- package/tests/examples/__snapshots__/example35.snap.svg +177 -0
- package/tests/examples/__snapshots__/example36.snap.svg +160 -0
- package/tests/examples/__snapshots__/example37.snap.svg +320 -0
- package/tests/examples/__snapshots__/example38.snap.svg +77 -0
- package/tests/examples/example35.test.ts +12 -0
- package/tests/examples/example36.test.ts +12 -0
- package/tests/examples/example37.test.ts +12 -0
- package/tests/examples/example38.test.ts +12 -0
package/dist/index.js
CHANGED
|
@@ -271,19 +271,19 @@ var doesPairCrossRestrictedCenterLines = (params) => {
|
|
|
271
271
|
chipMap
|
|
272
272
|
});
|
|
273
273
|
if (restrictedCenterLines.size === 0) return false;
|
|
274
|
-
const
|
|
274
|
+
const EPS10 = 1e-9;
|
|
275
275
|
const crossesSegment = (a, b) => {
|
|
276
276
|
for (const [, rcl] of restrictedCenterLines) {
|
|
277
277
|
if (rcl.axes.has("x") && typeof rcl.x === "number") {
|
|
278
|
-
if ((a.x - rcl.x) * (b.x - rcl.x) < -
|
|
278
|
+
if ((a.x - rcl.x) * (b.x - rcl.x) < -EPS10) return true;
|
|
279
279
|
}
|
|
280
280
|
if (rcl.axes.has("y") && typeof rcl.y === "number") {
|
|
281
|
-
if ((a.y - rcl.y) * (b.y - rcl.y) < -
|
|
281
|
+
if ((a.y - rcl.y) * (b.y - rcl.y) < -EPS10) return true;
|
|
282
282
|
}
|
|
283
283
|
}
|
|
284
284
|
return false;
|
|
285
285
|
};
|
|
286
|
-
if (Math.abs(p1.x - p2.x) <
|
|
286
|
+
if (Math.abs(p1.x - p2.x) < EPS10 || Math.abs(p1.y - p2.y) < EPS10) {
|
|
287
287
|
return crossesSegment({ x: p1.x, y: p1.y }, { x: p2.x, y: p2.y });
|
|
288
288
|
}
|
|
289
289
|
const elbowHV = { x: p2.x, y: p1.y };
|
|
@@ -850,8 +850,8 @@ var SchematicTraceSingleLineSolver2 = class extends BaseSolver {
|
|
|
850
850
|
if (!collision) {
|
|
851
851
|
const first = path[0];
|
|
852
852
|
const last = path[path.length - 1];
|
|
853
|
-
const
|
|
854
|
-
const samePoint = (p, q) => Math.abs(p.x - q.x) <
|
|
853
|
+
const EPS10 = 1e-9;
|
|
854
|
+
const samePoint = (p, q) => Math.abs(p.x - q.x) < EPS10 && Math.abs(p.y - q.y) < EPS10;
|
|
855
855
|
if (samePoint(first, { x: PA.x, y: PA.y }) && samePoint(last, { x: PB.x, y: PB.y })) {
|
|
856
856
|
this.solvedTracePath = path;
|
|
857
857
|
this.solved = true;
|
|
@@ -1050,13 +1050,13 @@ var applyJogToTerminalSegment = ({
|
|
|
1050
1050
|
segmentIndex: si,
|
|
1051
1051
|
offset,
|
|
1052
1052
|
JOG_SIZE,
|
|
1053
|
-
EPS:
|
|
1053
|
+
EPS: EPS10 = 1e-6
|
|
1054
1054
|
}) => {
|
|
1055
1055
|
if (si !== 0 && si !== pts.length - 2) return;
|
|
1056
1056
|
const start = pts[si];
|
|
1057
1057
|
const end = pts[si + 1];
|
|
1058
|
-
const isVertical4 = Math.abs(start.x - end.x) <
|
|
1059
|
-
const isHorizontal3 = Math.abs(start.y - end.y) <
|
|
1058
|
+
const isVertical4 = Math.abs(start.x - end.x) < EPS10;
|
|
1059
|
+
const isHorizontal3 = Math.abs(start.y - end.y) < EPS10;
|
|
1060
1060
|
if (!isVertical4 && !isHorizontal3) return;
|
|
1061
1061
|
const segDir = isVertical4 ? end.y > start.y ? 1 : -1 : end.x > start.x ? 1 : -1;
|
|
1062
1062
|
if (si === 0) {
|
|
@@ -1123,13 +1123,13 @@ var TraceOverlapIssueSolver = class extends BaseSolver {
|
|
|
1123
1123
|
}
|
|
1124
1124
|
}
|
|
1125
1125
|
_step() {
|
|
1126
|
-
const
|
|
1126
|
+
const EPS10 = 1e-6;
|
|
1127
1127
|
const offsets = this.overlappingTraceSegments.map((_, idx) => {
|
|
1128
1128
|
const n = Math.floor(idx / 2) + 1;
|
|
1129
1129
|
const signed = idx % 2 === 0 ? -n : n;
|
|
1130
1130
|
return signed * this.SHIFT_DISTANCE;
|
|
1131
1131
|
});
|
|
1132
|
-
const eq = (a, b) => Math.abs(a - b) <
|
|
1132
|
+
const eq = (a, b) => Math.abs(a - b) < EPS10;
|
|
1133
1133
|
const samePoint = (p, q) => !!p && !!q && eq(p.x, q.x) && eq(p.y, q.y);
|
|
1134
1134
|
this.overlappingTraceSegments.forEach((group, gidx) => {
|
|
1135
1135
|
const offset = offsets[gidx];
|
|
@@ -1155,13 +1155,13 @@ var TraceOverlapIssueSolver = class extends BaseSolver {
|
|
|
1155
1155
|
segmentIndex: si,
|
|
1156
1156
|
offset,
|
|
1157
1157
|
JOG_SIZE,
|
|
1158
|
-
EPS:
|
|
1158
|
+
EPS: EPS10
|
|
1159
1159
|
});
|
|
1160
1160
|
} else {
|
|
1161
1161
|
const start = pts[si];
|
|
1162
1162
|
const end = pts[si + 1];
|
|
1163
|
-
const isVertical4 = Math.abs(start.x - end.x) <
|
|
1164
|
-
const isHorizontal3 = Math.abs(start.y - end.y) <
|
|
1163
|
+
const isVertical4 = Math.abs(start.x - end.x) < EPS10;
|
|
1164
|
+
const isHorizontal3 = Math.abs(start.y - end.y) < EPS10;
|
|
1165
1165
|
if (!isVertical4 && !isHorizontal3) continue;
|
|
1166
1166
|
if (isVertical4) {
|
|
1167
1167
|
start.x += offset;
|
|
@@ -1258,7 +1258,7 @@ var TraceOverlapShiftSolver = class extends BaseSolver {
|
|
|
1258
1258
|
return islands;
|
|
1259
1259
|
}
|
|
1260
1260
|
findNextOverlapIssue() {
|
|
1261
|
-
const
|
|
1261
|
+
const EPS10 = 2e-3;
|
|
1262
1262
|
const netIds = Object.keys(this.traceNetIslands);
|
|
1263
1263
|
for (let i = 0; i < netIds.length; i++) {
|
|
1264
1264
|
for (let j = i + 1; j < netIds.length; j++) {
|
|
@@ -1276,7 +1276,7 @@ var TraceOverlapShiftSolver = class extends BaseSolver {
|
|
|
1276
1276
|
const minB = Math.min(b1, b2);
|
|
1277
1277
|
const maxB = Math.max(b1, b2);
|
|
1278
1278
|
const overlap = Math.min(maxA, maxB) - Math.max(minA, minB);
|
|
1279
|
-
return overlap >
|
|
1279
|
+
return overlap > EPS10;
|
|
1280
1280
|
};
|
|
1281
1281
|
for (let pa = 0; pa < pathsA.length; pa++) {
|
|
1282
1282
|
const pathA = pathsA[pa];
|
|
@@ -1284,8 +1284,8 @@ var TraceOverlapShiftSolver = class extends BaseSolver {
|
|
|
1284
1284
|
for (let sa = 0; sa < ptsA.length - 1; sa++) {
|
|
1285
1285
|
const a1 = ptsA[sa];
|
|
1286
1286
|
const a2 = ptsA[sa + 1];
|
|
1287
|
-
const aVert = Math.abs(a1.x - a2.x) <
|
|
1288
|
-
const aHorz = Math.abs(a1.y - a2.y) <
|
|
1287
|
+
const aVert = Math.abs(a1.x - a2.x) < EPS10;
|
|
1288
|
+
const aHorz = Math.abs(a1.y - a2.y) < EPS10;
|
|
1289
1289
|
if (!aVert && !aHorz) continue;
|
|
1290
1290
|
for (let pb = 0; pb < pathsB.length; pb++) {
|
|
1291
1291
|
const pathB = pathsB[pb];
|
|
@@ -1293,11 +1293,11 @@ var TraceOverlapShiftSolver = class extends BaseSolver {
|
|
|
1293
1293
|
for (let sb = 0; sb < ptsB.length - 1; sb++) {
|
|
1294
1294
|
const b1 = ptsB[sb];
|
|
1295
1295
|
const b2 = ptsB[sb + 1];
|
|
1296
|
-
const bVert = Math.abs(b1.x - b2.x) <
|
|
1297
|
-
const bHorz = Math.abs(b1.y - b2.y) <
|
|
1296
|
+
const bVert = Math.abs(b1.x - b2.x) < EPS10;
|
|
1297
|
+
const bHorz = Math.abs(b1.y - b2.y) < EPS10;
|
|
1298
1298
|
if (!bVert && !bHorz) continue;
|
|
1299
1299
|
if (aVert && bVert) {
|
|
1300
|
-
if (Math.abs(a1.x - b1.x) <
|
|
1300
|
+
if (Math.abs(a1.x - b1.x) < EPS10) {
|
|
1301
1301
|
if (overlaps1D(a1.y, a2.y, b1.y, b2.y)) {
|
|
1302
1302
|
const keyA = `${pa}:${sa}`;
|
|
1303
1303
|
const keyB = `${pb}:${sb}`;
|
|
@@ -1318,7 +1318,7 @@ var TraceOverlapShiftSolver = class extends BaseSolver {
|
|
|
1318
1318
|
}
|
|
1319
1319
|
}
|
|
1320
1320
|
} else if (aHorz && bHorz) {
|
|
1321
|
-
if (Math.abs(a1.y - b1.y) <
|
|
1321
|
+
if (Math.abs(a1.y - b1.y) < EPS10) {
|
|
1322
1322
|
if (overlaps1D(a1.x, a2.x, b1.x, b2.x)) {
|
|
1323
1323
|
const keyA = `${pa}:${sa}`;
|
|
1324
1324
|
const keyB = `${pb}:${sb}`;
|
|
@@ -1356,14 +1356,14 @@ var TraceOverlapShiftSolver = class extends BaseSolver {
|
|
|
1356
1356
|
return null;
|
|
1357
1357
|
}
|
|
1358
1358
|
findNextDiagonalSegment() {
|
|
1359
|
-
const
|
|
1359
|
+
const EPS10 = 2e-3;
|
|
1360
1360
|
for (const mspPairId in this.correctedTraceMap) {
|
|
1361
1361
|
const tracePath = this.correctedTraceMap[mspPairId].tracePath;
|
|
1362
1362
|
for (let i = 0; i < tracePath.length - 1; i++) {
|
|
1363
1363
|
const p1 = tracePath[i];
|
|
1364
1364
|
const p2 = tracePath[i + 1];
|
|
1365
|
-
const isHorizontal3 = Math.abs(p1.y - p2.y) <
|
|
1366
|
-
const isVertical4 = Math.abs(p1.x - p2.x) <
|
|
1365
|
+
const isHorizontal3 = Math.abs(p1.y - p2.y) < EPS10;
|
|
1366
|
+
const isVertical4 = Math.abs(p1.x - p2.x) < EPS10;
|
|
1367
1367
|
if (!isHorizontal3 && !isVertical4) {
|
|
1368
1368
|
return { mspPairId, tracePath, i, p1, p2 };
|
|
1369
1369
|
}
|
|
@@ -1377,13 +1377,13 @@ var TraceOverlapShiftSolver = class extends BaseSolver {
|
|
|
1377
1377
|
return false;
|
|
1378
1378
|
}
|
|
1379
1379
|
const { mspPairId, tracePath, i, p1, p2 } = diagonalInfo;
|
|
1380
|
-
const
|
|
1380
|
+
const EPS10 = 2e-3;
|
|
1381
1381
|
const p0 = i > 0 ? tracePath[i - 1] : null;
|
|
1382
1382
|
const p3 = i + 2 < tracePath.length ? tracePath[i + 2] : null;
|
|
1383
|
-
const prevIsVertical = p0 ? Math.abs(p0.x - p1.x) <
|
|
1384
|
-
const prevIsHorizontal = p0 ? Math.abs(p0.y - p1.y) <
|
|
1385
|
-
const nextIsVertical = p3 ? Math.abs(p2.x - p3.x) <
|
|
1386
|
-
const nextIsHorizontal = p3 ? Math.abs(p2.y - p3.y) <
|
|
1383
|
+
const prevIsVertical = p0 ? Math.abs(p0.x - p1.x) < EPS10 : false;
|
|
1384
|
+
const prevIsHorizontal = p0 ? Math.abs(p0.y - p1.y) < EPS10 : false;
|
|
1385
|
+
const nextIsVertical = p3 ? Math.abs(p2.x - p3.x) < EPS10 : false;
|
|
1386
|
+
const nextIsHorizontal = p3 ? Math.abs(p2.y - p3.y) < EPS10 : false;
|
|
1387
1387
|
const elbow1 = { x: p1.x, y: p2.y };
|
|
1388
1388
|
const elbow2 = { x: p2.x, y: p1.y };
|
|
1389
1389
|
let score1 = 0;
|
|
@@ -1547,24 +1547,24 @@ function getRectBounds(center, w, h) {
|
|
|
1547
1547
|
}
|
|
1548
1548
|
|
|
1549
1549
|
// lib/solvers/NetLabelPlacementSolver/SingleNetLabelPlacementSolver/collisions.ts
|
|
1550
|
-
function segmentIntersectsRect2(p1, p2, rect,
|
|
1551
|
-
const isVert = Math.abs(p1.x - p2.x) <
|
|
1552
|
-
const isHorz = Math.abs(p1.y - p2.y) <
|
|
1550
|
+
function segmentIntersectsRect2(p1, p2, rect, EPS10 = 1e-9) {
|
|
1551
|
+
const isVert = Math.abs(p1.x - p2.x) < EPS10;
|
|
1552
|
+
const isHorz = Math.abs(p1.y - p2.y) < EPS10;
|
|
1553
1553
|
if (!isVert && !isHorz) return false;
|
|
1554
1554
|
if (isVert) {
|
|
1555
1555
|
const x = p1.x;
|
|
1556
|
-
if (x < rect.minX -
|
|
1556
|
+
if (x < rect.minX - EPS10 || x > rect.maxX + EPS10) return false;
|
|
1557
1557
|
const segMinY = Math.min(p1.y, p2.y);
|
|
1558
1558
|
const segMaxY = Math.max(p1.y, p2.y);
|
|
1559
1559
|
const overlap = Math.min(segMaxY, rect.maxY) - Math.max(segMinY, rect.minY);
|
|
1560
|
-
return overlap >
|
|
1560
|
+
return overlap > EPS10;
|
|
1561
1561
|
} else {
|
|
1562
1562
|
const y = p1.y;
|
|
1563
|
-
if (y < rect.minY -
|
|
1563
|
+
if (y < rect.minY - EPS10 || y > rect.maxY + EPS10) return false;
|
|
1564
1564
|
const segMinX = Math.min(p1.x, p2.x);
|
|
1565
1565
|
const segMaxX = Math.max(p1.x, p2.x);
|
|
1566
1566
|
const overlap = Math.min(segMaxX, rect.maxX) - Math.max(segMinX, rect.minX);
|
|
1567
|
-
return overlap >
|
|
1567
|
+
return overlap > EPS10;
|
|
1568
1568
|
}
|
|
1569
1569
|
}
|
|
1570
1570
|
function rectIntersectsAnyTrace(bounds, inputTraceMap, hostPathId, hostSegIndex) {
|
|
@@ -1942,14 +1942,14 @@ var SingleNetLabelPlacementSolver = class extends BaseSolver {
|
|
|
1942
1942
|
};
|
|
1943
1943
|
let bestCandidate = null;
|
|
1944
1944
|
let bestScore = -Infinity;
|
|
1945
|
-
const
|
|
1945
|
+
const EPS10 = 1e-6;
|
|
1946
1946
|
for (const curr of tracesToScan) {
|
|
1947
1947
|
const pts = curr.tracePath.slice();
|
|
1948
1948
|
for (let si = 0; si < pts.length - 1; si++) {
|
|
1949
1949
|
const a = pts[si];
|
|
1950
1950
|
const b = pts[si + 1];
|
|
1951
|
-
const isH = Math.abs(a.y - b.y) <
|
|
1952
|
-
const isV = Math.abs(a.x - b.x) <
|
|
1951
|
+
const isH = Math.abs(a.y - b.y) < EPS10;
|
|
1952
|
+
const isV = Math.abs(a.x - b.x) < EPS10;
|
|
1953
1953
|
if (!isH && !isV) continue;
|
|
1954
1954
|
const segmentAllowed = isH ? ["y+", "y-"] : ["x+", "x-"];
|
|
1955
1955
|
const candidateOrients = orientations.filter(
|
|
@@ -2227,6 +2227,29 @@ var NetLabelPlacementSolver = class extends BaseSolver {
|
|
|
2227
2227
|
}
|
|
2228
2228
|
return groups;
|
|
2229
2229
|
}
|
|
2230
|
+
getNetLabelWidthForGroup(group) {
|
|
2231
|
+
if (group.netId) {
|
|
2232
|
+
const ncWidth = this.inputProblem.netConnections.find(
|
|
2233
|
+
(nc) => nc.netId === group.netId
|
|
2234
|
+
)?.netLabelWidth;
|
|
2235
|
+
if (ncWidth !== void 0) return ncWidth;
|
|
2236
|
+
const dcWidthByNetId = this.inputProblem.directConnections.find(
|
|
2237
|
+
(dc) => dc.netId === group.netId
|
|
2238
|
+
)?.netLabelWidth;
|
|
2239
|
+
if (dcWidthByNetId !== void 0) return dcWidthByNetId;
|
|
2240
|
+
}
|
|
2241
|
+
const pinIds = group.overlappingTraces?.pins.map((p) => p.pinId) ?? [];
|
|
2242
|
+
if (group.portOnlyPinId) {
|
|
2243
|
+
pinIds.push(group.portOnlyPinId);
|
|
2244
|
+
}
|
|
2245
|
+
const dcWidthByPinId = this.inputProblem.directConnections.find(
|
|
2246
|
+
(dc) => dc.pinIds.some((pid) => pinIds.includes(pid))
|
|
2247
|
+
)?.netLabelWidth;
|
|
2248
|
+
if (dcWidthByPinId !== void 0) return dcWidthByPinId;
|
|
2249
|
+
return this.inputProblem.netConnections.find(
|
|
2250
|
+
(nc) => nc.pinIds.some((pid) => pinIds.includes(pid))
|
|
2251
|
+
)?.netLabelWidth;
|
|
2252
|
+
}
|
|
2230
2253
|
_step() {
|
|
2231
2254
|
if (this.activeSubSolver?.solved) {
|
|
2232
2255
|
this.netLabelPlacements.push(this.activeSubSolver.netLabelPlacement);
|
|
@@ -2241,9 +2264,7 @@ var NetLabelPlacementSolver = class extends BaseSolver {
|
|
|
2241
2264
|
const isAlreadyFull = currOrients.length === 4 && fullOrients.every((o) => currOrients.includes(o));
|
|
2242
2265
|
if (!this.triedAnyOrientationFallbackForCurrentGroup && !isAlreadyFull && this.currentGroup) {
|
|
2243
2266
|
this.triedAnyOrientationFallbackForCurrentGroup = true;
|
|
2244
|
-
const netLabelWidth2 = this.
|
|
2245
|
-
(nc) => nc.netId === this.currentGroup.netId
|
|
2246
|
-
)?.netLabelWidth : void 0;
|
|
2267
|
+
const netLabelWidth2 = this.getNetLabelWidthForGroup(this.currentGroup);
|
|
2247
2268
|
this.activeSubSolver = new SingleNetLabelPlacementSolver({
|
|
2248
2269
|
inputProblem: this.inputProblem,
|
|
2249
2270
|
inputTraceMap: this.inputTraceMap,
|
|
@@ -2269,9 +2290,7 @@ var NetLabelPlacementSolver = class extends BaseSolver {
|
|
|
2269
2290
|
const netId = nextOverlappingSameNetTraceGroup.netId ?? nextOverlappingSameNetTraceGroup.globalConnNetId;
|
|
2270
2291
|
this.currentGroup = nextOverlappingSameNetTraceGroup;
|
|
2271
2292
|
this.triedAnyOrientationFallbackForCurrentGroup = false;
|
|
2272
|
-
const netLabelWidth = this.
|
|
2273
|
-
(nc) => nc.netId === this.currentGroup.netId
|
|
2274
|
-
)?.netLabelWidth : void 0;
|
|
2293
|
+
const netLabelWidth = this.getNetLabelWidthForGroup(this.currentGroup);
|
|
2275
2294
|
this.activeSubSolver = new SingleNetLabelPlacementSolver({
|
|
2276
2295
|
inputProblem: this.inputProblem,
|
|
2277
2296
|
inputTraceMap: this.inputTraceMap,
|
|
@@ -4621,11 +4640,14 @@ var UntangleTraceSubsolver = class extends BaseSolver {
|
|
|
4621
4640
|
};
|
|
4622
4641
|
|
|
4623
4642
|
// lib/solvers/TraceCleanupSolver/is4PointRectangle.ts
|
|
4643
|
+
var EPS5 = 1e-6;
|
|
4644
|
+
var sameX = (a, b) => Math.abs(a.x - b.x) <= EPS5;
|
|
4645
|
+
var sameY = (a, b) => Math.abs(a.y - b.y) <= EPS5;
|
|
4624
4646
|
var is4PointRectangle = (path) => {
|
|
4625
4647
|
if (path.length !== 4) return false;
|
|
4626
4648
|
const [p0, p1, p2, p3] = path;
|
|
4627
|
-
const isHVHC = p0
|
|
4628
|
-
const isVHVC = p0
|
|
4649
|
+
const isHVHC = sameY(p0, p1) && sameX(p1, p2) && sameY(p2, p3) && sameX(p0, p3);
|
|
4650
|
+
const isVHVC = sameX(p0, p1) && sameY(p1, p2) && sameX(p2, p3) && sameY(p0, p3);
|
|
4629
4651
|
return isHVHC || isVHVC;
|
|
4630
4652
|
};
|
|
4631
4653
|
|
|
@@ -4754,7 +4776,7 @@ var TraceCleanupSolver = class extends BaseSolver {
|
|
|
4754
4776
|
};
|
|
4755
4777
|
|
|
4756
4778
|
// lib/solvers/Example28Solver/types.ts
|
|
4757
|
-
var
|
|
4779
|
+
var EPS6 = 1e-9;
|
|
4758
4780
|
|
|
4759
4781
|
// lib/solvers/Example28Solver/geometry.ts
|
|
4760
4782
|
var getPathKey = (path) => path.map((point) => `${point.x},${point.y}`).join(";");
|
|
@@ -4766,10 +4788,10 @@ var getPathLength = (path) => {
|
|
|
4766
4788
|
return length;
|
|
4767
4789
|
};
|
|
4768
4790
|
var getDistance = (a, b) => Math.abs(a.x - b.x) + Math.abs(a.y - b.y);
|
|
4769
|
-
var isAxisAlignedSegment = (start, end) => Math.abs(start.x - end.x) <
|
|
4770
|
-
var getSegmentOrientation = (start, end) => Math.abs(start.y - end.y) <
|
|
4791
|
+
var isAxisAlignedSegment = (start, end) => Math.abs(start.x - end.x) < EPS6 || Math.abs(start.y - end.y) < EPS6;
|
|
4792
|
+
var getSegmentOrientation = (start, end) => Math.abs(start.y - end.y) < EPS6 ? "horizontal" : "vertical";
|
|
4771
4793
|
var projectPointToSegment = (point, start, end) => {
|
|
4772
|
-
if (Math.abs(start.x - end.x) <
|
|
4794
|
+
if (Math.abs(start.x - end.x) < EPS6) {
|
|
4773
4795
|
return {
|
|
4774
4796
|
x: start.x,
|
|
4775
4797
|
y: Math.min(
|
|
@@ -4778,7 +4800,7 @@ var projectPointToSegment = (point, start, end) => {
|
|
|
4778
4800
|
)
|
|
4779
4801
|
};
|
|
4780
4802
|
}
|
|
4781
|
-
if (Math.abs(start.y - end.y) <
|
|
4803
|
+
if (Math.abs(start.y - end.y) < EPS6) {
|
|
4782
4804
|
return {
|
|
4783
4805
|
x: Math.min(
|
|
4784
4806
|
Math.max(point.x, Math.min(start.x, end.x)),
|
|
@@ -4821,9 +4843,9 @@ var findSegmentContainingPoint = (path, point) => {
|
|
|
4821
4843
|
};
|
|
4822
4844
|
var isPointWithinSegmentPrimaryRange = (point, segment) => {
|
|
4823
4845
|
if (segment.orientation === "horizontal") {
|
|
4824
|
-
return point.x >= Math.min(segment.start.x, segment.end.x) -
|
|
4846
|
+
return point.x >= Math.min(segment.start.x, segment.end.x) - EPS6 && point.x <= Math.max(segment.start.x, segment.end.x) + EPS6;
|
|
4825
4847
|
}
|
|
4826
|
-
return point.y >= Math.min(segment.start.y, segment.end.y) -
|
|
4848
|
+
return point.y >= Math.min(segment.start.y, segment.end.y) - EPS6 && point.y <= Math.max(segment.start.y, segment.end.y) + EPS6;
|
|
4827
4849
|
};
|
|
4828
4850
|
var findPreferredReroutedSegment = (path, originalSegmentIndex, originalSegmentCount, orientation, anchorPoint) => {
|
|
4829
4851
|
const matchingSegments = getSegments(path).filter(
|
|
@@ -4851,18 +4873,18 @@ var projectPointToPath = (point, path) => {
|
|
|
4851
4873
|
return bestPoint;
|
|
4852
4874
|
};
|
|
4853
4875
|
var segmentsIntersect = (a1, a2, b1, b2) => {
|
|
4854
|
-
const aVertical = Math.abs(a1.x - a2.x) <
|
|
4855
|
-
const bVertical = Math.abs(b1.x - b2.x) <
|
|
4856
|
-
const between = (value, p1, p2) => value >= Math.min(p1, p2) -
|
|
4876
|
+
const aVertical = Math.abs(a1.x - a2.x) < EPS6;
|
|
4877
|
+
const bVertical = Math.abs(b1.x - b2.x) < EPS6;
|
|
4878
|
+
const between = (value, p1, p2) => value >= Math.min(p1, p2) - EPS6 && value <= Math.max(p1, p2) + EPS6;
|
|
4857
4879
|
if (aVertical && bVertical) {
|
|
4858
|
-
if (Math.abs(a1.x - b1.x) >
|
|
4880
|
+
if (Math.abs(a1.x - b1.x) > EPS6) return false;
|
|
4859
4881
|
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));
|
|
4860
|
-
return overlap >
|
|
4882
|
+
return overlap > EPS6;
|
|
4861
4883
|
}
|
|
4862
4884
|
if (!aVertical && !bVertical) {
|
|
4863
|
-
if (Math.abs(a1.y - b1.y) >
|
|
4885
|
+
if (Math.abs(a1.y - b1.y) > EPS6) return false;
|
|
4864
4886
|
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));
|
|
4865
|
-
return overlap >
|
|
4887
|
+
return overlap > EPS6;
|
|
4866
4888
|
}
|
|
4867
4889
|
const verticalA = aVertical ? a1 : b1;
|
|
4868
4890
|
const verticalB = aVertical ? a2 : b2;
|
|
@@ -4894,13 +4916,13 @@ var isPathCollidingWithChipInterior = (path, chipObstacles) => {
|
|
|
4894
4916
|
return false;
|
|
4895
4917
|
};
|
|
4896
4918
|
var segmentRunsAlongRectBoundary = (start, end, rect) => {
|
|
4897
|
-
const isVertical4 = Math.abs(start.x - end.x) <
|
|
4898
|
-
const isHorizontal3 = Math.abs(start.y - end.y) <
|
|
4919
|
+
const isVertical4 = Math.abs(start.x - end.x) < EPS6;
|
|
4920
|
+
const isHorizontal3 = Math.abs(start.y - end.y) < EPS6;
|
|
4899
4921
|
if (isVertical4) {
|
|
4900
|
-
return Math.abs(start.x - rect.minX) <
|
|
4922
|
+
return Math.abs(start.x - rect.minX) < EPS6 || Math.abs(start.x - rect.maxX) < EPS6;
|
|
4901
4923
|
}
|
|
4902
4924
|
if (isHorizontal3) {
|
|
4903
|
-
return Math.abs(start.y - rect.minY) <
|
|
4925
|
+
return Math.abs(start.y - rect.minY) < EPS6 || Math.abs(start.y - rect.maxY) < EPS6;
|
|
4904
4926
|
}
|
|
4905
4927
|
return false;
|
|
4906
4928
|
};
|
|
@@ -5008,9 +5030,37 @@ var generateRerouteCandidateResults = ({
|
|
|
5008
5030
|
outputNetLabelPlacements,
|
|
5009
5031
|
chipObstacles
|
|
5010
5032
|
}) => {
|
|
5011
|
-
const rawCandidates = generateCandidatePaths(trace, label, inputProblem);
|
|
5012
5033
|
const seen = /* @__PURE__ */ new Set();
|
|
5013
5034
|
const candidateResults = [];
|
|
5035
|
+
const horizontalSegmentPushCandidate = generateHorizontalSegmentPushCandidate(
|
|
5036
|
+
trace,
|
|
5037
|
+
label
|
|
5038
|
+
);
|
|
5039
|
+
if (horizontalSegmentPushCandidate) {
|
|
5040
|
+
candidateResults.push(
|
|
5041
|
+
createCandidateResult({
|
|
5042
|
+
trace,
|
|
5043
|
+
obstacleLabel: label,
|
|
5044
|
+
path: horizontalSegmentPushCandidate,
|
|
5045
|
+
seen,
|
|
5046
|
+
outputTraces,
|
|
5047
|
+
outputNetLabelPlacements,
|
|
5048
|
+
chipObstacles,
|
|
5049
|
+
usesHorizontalSegmentPush: true
|
|
5050
|
+
})
|
|
5051
|
+
);
|
|
5052
|
+
}
|
|
5053
|
+
const rawCandidates = [
|
|
5054
|
+
...generateLabelHugCandidates(trace, label),
|
|
5055
|
+
...generateRerouteCandidates({
|
|
5056
|
+
trace,
|
|
5057
|
+
label,
|
|
5058
|
+
problem: inputProblem,
|
|
5059
|
+
paddingBuffer: LABEL_SIDE_CLEARANCE,
|
|
5060
|
+
detourCount: 0
|
|
5061
|
+
}),
|
|
5062
|
+
...generateEndpointDetourCandidates(trace, label)
|
|
5063
|
+
];
|
|
5014
5064
|
for (const rawCandidate of rawCandidates) {
|
|
5015
5065
|
candidateResults.push(
|
|
5016
5066
|
createCandidateResult({
|
|
@@ -5026,17 +5076,6 @@ var generateRerouteCandidateResults = ({
|
|
|
5026
5076
|
}
|
|
5027
5077
|
return candidateResults;
|
|
5028
5078
|
};
|
|
5029
|
-
var generateCandidatePaths = (trace, label, inputProblem) => [
|
|
5030
|
-
...generateLabelHugCandidates(trace, label),
|
|
5031
|
-
...generateRerouteCandidates({
|
|
5032
|
-
trace,
|
|
5033
|
-
label,
|
|
5034
|
-
problem: inputProblem,
|
|
5035
|
-
paddingBuffer: LABEL_SIDE_CLEARANCE,
|
|
5036
|
-
detourCount: 0
|
|
5037
|
-
}),
|
|
5038
|
-
...generateEndpointDetourCandidates(trace, label)
|
|
5039
|
-
];
|
|
5040
5079
|
var createCandidateResult = ({
|
|
5041
5080
|
trace,
|
|
5042
5081
|
obstacleLabel,
|
|
@@ -5044,13 +5083,15 @@ var createCandidateResult = ({
|
|
|
5044
5083
|
seen,
|
|
5045
5084
|
outputTraces,
|
|
5046
5085
|
outputNetLabelPlacements,
|
|
5047
|
-
chipObstacles
|
|
5086
|
+
chipObstacles,
|
|
5087
|
+
usesHorizontalSegmentPush
|
|
5048
5088
|
}) => {
|
|
5049
5089
|
const key = getPathKey(path);
|
|
5050
5090
|
if (seen.has(key)) {
|
|
5051
5091
|
return {
|
|
5052
5092
|
path,
|
|
5053
5093
|
status: "duplicate",
|
|
5094
|
+
usesHorizontalSegmentPush,
|
|
5054
5095
|
selected: false
|
|
5055
5096
|
};
|
|
5056
5097
|
}
|
|
@@ -5059,6 +5100,7 @@ var createCandidateResult = ({
|
|
|
5059
5100
|
return {
|
|
5060
5101
|
path,
|
|
5061
5102
|
status: "chip-collision",
|
|
5103
|
+
usesHorizontalSegmentPush,
|
|
5062
5104
|
selected: false
|
|
5063
5105
|
};
|
|
5064
5106
|
}
|
|
@@ -5072,6 +5114,7 @@ var createCandidateResult = ({
|
|
|
5072
5114
|
outputNetLabelPlacements
|
|
5073
5115
|
}),
|
|
5074
5116
|
status: "valid",
|
|
5117
|
+
usesHorizontalSegmentPush,
|
|
5075
5118
|
selected: false
|
|
5076
5119
|
};
|
|
5077
5120
|
};
|
|
@@ -5148,6 +5191,12 @@ var selectBestReroutePath = ({
|
|
|
5148
5191
|
outputNetLabelPlacements,
|
|
5149
5192
|
candidateResults
|
|
5150
5193
|
}) => {
|
|
5194
|
+
for (const candidate of candidateResults) {
|
|
5195
|
+
if (!candidate.usesHorizontalSegmentPush) continue;
|
|
5196
|
+
if (candidate.status !== "valid") continue;
|
|
5197
|
+
if (!candidate.score) continue;
|
|
5198
|
+
return candidate.path;
|
|
5199
|
+
}
|
|
5151
5200
|
let bestPath = null;
|
|
5152
5201
|
let bestScore = scoreTracePath({
|
|
5153
5202
|
trace,
|
|
@@ -5164,6 +5213,71 @@ var selectBestReroutePath = ({
|
|
|
5164
5213
|
}
|
|
5165
5214
|
return bestPath;
|
|
5166
5215
|
};
|
|
5216
|
+
var generateHorizontalSegmentPushCandidate = (trace, label) => {
|
|
5217
|
+
const labelDirection = dir(label.orientation);
|
|
5218
|
+
if (labelDirection.x === 0) return null;
|
|
5219
|
+
const path = trace.tracePath;
|
|
5220
|
+
const bounds = getRectBounds(label.center, label.width, label.height);
|
|
5221
|
+
const collidingVerticalSegmentIndex = path.findIndex((start, index) => {
|
|
5222
|
+
const end = path[index + 1];
|
|
5223
|
+
if (!end) return false;
|
|
5224
|
+
if (Math.abs(start.x - end.x) >= 1e-9) return false;
|
|
5225
|
+
return segmentIntersectsRect2(start, end, bounds);
|
|
5226
|
+
});
|
|
5227
|
+
if (collidingVerticalSegmentIndex <= 0 || collidingVerticalSegmentIndex >= path.length - 2) {
|
|
5228
|
+
return null;
|
|
5229
|
+
}
|
|
5230
|
+
const previousAnchor = path[collidingVerticalSegmentIndex - 1];
|
|
5231
|
+
const verticalStart = path[collidingVerticalSegmentIndex];
|
|
5232
|
+
const verticalEnd = path[collidingVerticalSegmentIndex + 1];
|
|
5233
|
+
const nextAnchor = path[collidingVerticalSegmentIndex + 2];
|
|
5234
|
+
if (Math.abs(previousAnchor.y - verticalStart.y) >= 1e-9 || Math.abs(verticalEnd.y - nextAnchor.y) >= 1e-9) {
|
|
5235
|
+
return null;
|
|
5236
|
+
}
|
|
5237
|
+
let segmentPushX = bounds.minX - LABEL_SIDE_CLEARANCE;
|
|
5238
|
+
if (labelDirection.x > 0) {
|
|
5239
|
+
segmentPushX = bounds.maxX + LABEL_SIDE_CLEARANCE;
|
|
5240
|
+
}
|
|
5241
|
+
const segmentPushStartY = getClearedHorizontalY({
|
|
5242
|
+
start: previousAnchor,
|
|
5243
|
+
end: { x: segmentPushX, y: verticalStart.y },
|
|
5244
|
+
labelBounds: bounds
|
|
5245
|
+
});
|
|
5246
|
+
const segmentPushEndY = getClearedHorizontalY({
|
|
5247
|
+
start: { x: segmentPushX, y: verticalEnd.y },
|
|
5248
|
+
end: nextAnchor,
|
|
5249
|
+
labelBounds: bounds
|
|
5250
|
+
});
|
|
5251
|
+
const segmentPushPath = [
|
|
5252
|
+
...path.slice(0, collidingVerticalSegmentIndex - 1),
|
|
5253
|
+
previousAnchor
|
|
5254
|
+
];
|
|
5255
|
+
if (Math.abs(previousAnchor.y - segmentPushStartY) >= 1e-9) {
|
|
5256
|
+
segmentPushPath.push({ x: previousAnchor.x, y: segmentPushStartY });
|
|
5257
|
+
}
|
|
5258
|
+
segmentPushPath.push({ x: segmentPushX, y: segmentPushStartY });
|
|
5259
|
+
segmentPushPath.push({ x: segmentPushX, y: segmentPushEndY });
|
|
5260
|
+
if (Math.abs(nextAnchor.y - segmentPushEndY) >= 1e-9) {
|
|
5261
|
+
segmentPushPath.push({ x: nextAnchor.x, y: segmentPushEndY });
|
|
5262
|
+
}
|
|
5263
|
+
segmentPushPath.push(
|
|
5264
|
+
nextAnchor,
|
|
5265
|
+
...path.slice(collidingVerticalSegmentIndex + 3)
|
|
5266
|
+
);
|
|
5267
|
+
return simplifyPath(segmentPushPath);
|
|
5268
|
+
};
|
|
5269
|
+
var getClearedHorizontalY = ({
|
|
5270
|
+
start,
|
|
5271
|
+
end,
|
|
5272
|
+
labelBounds
|
|
5273
|
+
}) => {
|
|
5274
|
+
if (!segmentIntersectsRect2(start, end, labelBounds)) return start.y;
|
|
5275
|
+
const labelCenterY = (labelBounds.minY + labelBounds.maxY) / 2;
|
|
5276
|
+
if (start.y >= labelCenterY) {
|
|
5277
|
+
return labelBounds.maxY + LABEL_HUG_CLEARANCE;
|
|
5278
|
+
}
|
|
5279
|
+
return labelBounds.minY - LABEL_HUG_CLEARANCE;
|
|
5280
|
+
};
|
|
5167
5281
|
var markSelectedCandidate = (candidateResults, bestPath) => {
|
|
5168
5282
|
if (!bestPath) return;
|
|
5169
5283
|
for (const candidate of candidateResults) {
|
|
@@ -5432,16 +5546,16 @@ var Example28Solver = class extends BaseSolver {
|
|
|
5432
5546
|
// lib/solvers/AvailableNetOrientationSolver/constants.ts
|
|
5433
5547
|
var LABEL_SEARCH_STEP = 0.05;
|
|
5434
5548
|
var WICK_CLEARANCE = 1e-3;
|
|
5435
|
-
var
|
|
5436
|
-
var TRACE_BOUNDARY_TOLERANCE = WICK_CLEARANCE +
|
|
5549
|
+
var EPS7 = 1e-9;
|
|
5550
|
+
var TRACE_BOUNDARY_TOLERANCE = WICK_CLEARANCE + EPS7;
|
|
5437
5551
|
var CANDIDATE_SELECTED_COLOR2 = "blue";
|
|
5438
5552
|
var CANDIDATE_REJECTED_COLOR2 = "red";
|
|
5439
5553
|
|
|
5440
5554
|
// lib/solvers/AvailableNetOrientationSolver/geometry.ts
|
|
5441
5555
|
var isYOrientation = (orientation) => orientation === "y+" || orientation === "y-";
|
|
5442
5556
|
var isXOrientation = (orientation) => orientation === "x+" || orientation === "x-";
|
|
5443
|
-
var rectsOverlap = (a, b) => Math.min(a.maxX, b.maxX) - Math.max(a.minX, b.minX) >
|
|
5444
|
-
var rangesOverlap = (minA, maxA, minB, maxB) => Math.min(maxA, maxB) - Math.max(minA, minB) >
|
|
5557
|
+
var rectsOverlap = (a, b) => Math.min(a.maxX, b.maxX) - Math.max(a.minX, b.minX) > EPS7 && Math.min(a.maxY, b.maxY) - Math.max(a.minY, b.minY) > EPS7;
|
|
5558
|
+
var rangesOverlap = (minA, maxA, minB, maxB) => Math.min(maxA, maxB) - Math.max(minA, minB) > EPS7;
|
|
5445
5559
|
var traceCrossesBoundsInterior = (bounds, traceMap) => {
|
|
5446
5560
|
for (const trace of Object.values(traceMap)) {
|
|
5447
5561
|
const points = trace.tracePath;
|
|
@@ -5463,8 +5577,8 @@ var segmentCrossesBoundsInterior = (p1, p2, bounds) => {
|
|
|
5463
5577
|
if (interiorBounds.minX >= interiorBounds.maxX || interiorBounds.minY >= interiorBounds.maxY) {
|
|
5464
5578
|
return false;
|
|
5465
5579
|
}
|
|
5466
|
-
if (
|
|
5467
|
-
if (p1.x <= interiorBounds.minX +
|
|
5580
|
+
if (sameX2(p1, p2)) {
|
|
5581
|
+
if (p1.x <= interiorBounds.minX + EPS7 || p1.x >= interiorBounds.maxX - EPS7) {
|
|
5468
5582
|
return false;
|
|
5469
5583
|
}
|
|
5470
5584
|
return rangesOverlap(
|
|
@@ -5474,8 +5588,8 @@ var segmentCrossesBoundsInterior = (p1, p2, bounds) => {
|
|
|
5474
5588
|
interiorBounds.maxY
|
|
5475
5589
|
);
|
|
5476
5590
|
}
|
|
5477
|
-
if (
|
|
5478
|
-
if (p1.y <= interiorBounds.minY +
|
|
5591
|
+
if (sameY2(p1, p2)) {
|
|
5592
|
+
if (p1.y <= interiorBounds.minY + EPS7 || p1.y >= interiorBounds.maxY - EPS7) {
|
|
5479
5593
|
return false;
|
|
5480
5594
|
}
|
|
5481
5595
|
return rangesOverlap(
|
|
@@ -5514,11 +5628,11 @@ var tracePathCrossesAnyTrace = (tracePath, traceMap) => {
|
|
|
5514
5628
|
return false;
|
|
5515
5629
|
};
|
|
5516
5630
|
var segmentsStrictlyCross = (a1, a2, b1, b2) => {
|
|
5517
|
-
if (
|
|
5518
|
-
return a1.x > Math.min(b1.x, b2.x) +
|
|
5631
|
+
if (sameX2(a1, a2) && sameY2(b1, b2)) {
|
|
5632
|
+
return a1.x > Math.min(b1.x, b2.x) + EPS7 && a1.x < Math.max(b1.x, b2.x) - EPS7 && b1.y > Math.min(a1.y, a2.y) + EPS7 && b1.y < Math.max(a1.y, a2.y) - EPS7;
|
|
5519
5633
|
}
|
|
5520
|
-
if (
|
|
5521
|
-
return b1.x > Math.min(a1.x, a2.x) +
|
|
5634
|
+
if (sameY2(a1, a2) && sameX2(b1, b2)) {
|
|
5635
|
+
return b1.x > Math.min(a1.x, a2.x) + EPS7 && b1.x < Math.max(a1.x, a2.x) - EPS7 && a1.y > Math.min(b1.y, b2.y) + EPS7 && a1.y < Math.max(b1.y, b2.y) - EPS7;
|
|
5522
5636
|
}
|
|
5523
5637
|
return false;
|
|
5524
5638
|
};
|
|
@@ -5541,7 +5655,7 @@ var simplifyOrthogonalPath = (path) => {
|
|
|
5541
5655
|
const prev = simplified[simplified.length - 1];
|
|
5542
5656
|
const point = deduped[i];
|
|
5543
5657
|
const next = deduped[i + 1];
|
|
5544
|
-
if (
|
|
5658
|
+
if (sameX2(prev, point) && sameX2(point, next) || sameY2(prev, point) && sameY2(point, next)) {
|
|
5545
5659
|
continue;
|
|
5546
5660
|
}
|
|
5547
5661
|
simplified.push(point);
|
|
@@ -5549,9 +5663,9 @@ var simplifyOrthogonalPath = (path) => {
|
|
|
5549
5663
|
simplified.push(deduped[deduped.length - 1]);
|
|
5550
5664
|
return simplified;
|
|
5551
5665
|
};
|
|
5552
|
-
var pointsEqual = (a, b) =>
|
|
5553
|
-
var
|
|
5554
|
-
var
|
|
5666
|
+
var pointsEqual = (a, b) => sameX2(a, b) && sameY2(a, b);
|
|
5667
|
+
var sameX2 = (a, b) => Math.abs(a.x - b.x) <= EPS7;
|
|
5668
|
+
var sameY2 = (a, b) => Math.abs(a.y - b.y) <= EPS7;
|
|
5555
5669
|
var getMaxSearchDistance = (inputProblem) => {
|
|
5556
5670
|
const maxChipWidth = Math.max(
|
|
5557
5671
|
...inputProblem.chips.map((chip) => chip.width),
|
|
@@ -5759,11 +5873,28 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
|
|
|
5759
5873
|
this.addConnectorTrace(label, candidate, labelIndex);
|
|
5760
5874
|
}
|
|
5761
5875
|
addConnectorTrace(label, candidate, labelIndex) {
|
|
5762
|
-
|
|
5763
|
-
|
|
5764
|
-
candidate.
|
|
5765
|
-
|
|
5766
|
-
|
|
5876
|
+
let tracePath;
|
|
5877
|
+
if (candidate.phase === "lateral-shift") {
|
|
5878
|
+
const orientDir = dir(candidate.orientation);
|
|
5879
|
+
const kickedSource = {
|
|
5880
|
+
x: label.anchorPoint.x - orientDir.x * LABEL_SEARCH_STEP,
|
|
5881
|
+
y: label.anchorPoint.y - orientDir.y * LABEL_SEARCH_STEP
|
|
5882
|
+
};
|
|
5883
|
+
tracePath = simplifyOrthogonalPath([
|
|
5884
|
+
label.anchorPoint,
|
|
5885
|
+
...getConnectorTracePath(
|
|
5886
|
+
kickedSource,
|
|
5887
|
+
candidate.anchorPoint,
|
|
5888
|
+
candidate.orientation
|
|
5889
|
+
)
|
|
5890
|
+
]);
|
|
5891
|
+
} else {
|
|
5892
|
+
tracePath = getConnectorTracePath(
|
|
5893
|
+
label.anchorPoint,
|
|
5894
|
+
candidate.anchorPoint,
|
|
5895
|
+
candidate.orientation
|
|
5896
|
+
);
|
|
5897
|
+
}
|
|
5767
5898
|
if (tracePath.length < 2) return;
|
|
5768
5899
|
const mspPairId = `available-net-orientation-${labelIndex}-${label.netId ?? label.globalConnNetId}`;
|
|
5769
5900
|
const connectorTrace = {
|
|
@@ -5796,7 +5927,18 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
|
|
|
5796
5927
|
labelIndex,
|
|
5797
5928
|
orientations
|
|
5798
5929
|
);
|
|
5799
|
-
|
|
5930
|
+
if (rotatedCandidate) return rotatedCandidate;
|
|
5931
|
+
const shiftedCandidate = this.findValidShiftedCandidate(
|
|
5932
|
+
label,
|
|
5933
|
+
orientations[0],
|
|
5934
|
+
labelIndex
|
|
5935
|
+
);
|
|
5936
|
+
if (shiftedCandidate) return shiftedCandidate;
|
|
5937
|
+
return this.findValidLateralShiftedCandidate(
|
|
5938
|
+
label,
|
|
5939
|
+
orientations[0],
|
|
5940
|
+
labelIndex
|
|
5941
|
+
);
|
|
5800
5942
|
}
|
|
5801
5943
|
findValidRotatedCandidate(label, labelIndex, orientations) {
|
|
5802
5944
|
for (const orientation of orientations) {
|
|
@@ -5832,7 +5974,7 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
|
|
|
5832
5974
|
);
|
|
5833
5975
|
const maxSearchDistance = this.getSearchDistanceLimit(label, orientation);
|
|
5834
5976
|
const maxOutwardDistance = outwardDirection.x === 0 && outwardDirection.y === 0 ? 0 : this.maxSearchDistance;
|
|
5835
|
-
for (let outwardDistance = 0; outwardDistance <= maxOutwardDistance +
|
|
5977
|
+
for (let outwardDistance = 0; outwardDistance <= maxOutwardDistance + EPS7; outwardDistance += LABEL_SEARCH_STEP) {
|
|
5836
5978
|
const baseAnchor = {
|
|
5837
5979
|
x: initialBaseAnchor.x + outwardDirection.x * outwardDistance,
|
|
5838
5980
|
y: initialBaseAnchor.y + outwardDirection.y * outwardDistance
|
|
@@ -5850,6 +5992,50 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
|
|
|
5850
5992
|
}
|
|
5851
5993
|
return null;
|
|
5852
5994
|
}
|
|
5995
|
+
/**
|
|
5996
|
+
* When all candidates fail for the current (unshifted) position, try
|
|
5997
|
+
* shifting the label anchor laterally — x for y-orientations, y for
|
|
5998
|
+
* x-orientations — and re-attempting the required orientation.
|
|
5999
|
+
*
|
|
6000
|
+
* Offsets are tried in alternating sign order:
|
|
6001
|
+
* -1·step, +1·step, -2·step, +2·step, …
|
|
6002
|
+
* so the nearest escape routes are tested first.
|
|
6003
|
+
*/
|
|
6004
|
+
findValidLateralShiftedCandidate(label, orientation, labelIndex) {
|
|
6005
|
+
const direction = dir(orientation);
|
|
6006
|
+
const initialBaseAnchor = this.getSearchStartAnchor(label, orientation);
|
|
6007
|
+
const lateralDir = {
|
|
6008
|
+
x: isYOrientation(orientation) ? 1 : 0,
|
|
6009
|
+
y: isXOrientation(orientation) ? 1 : 0
|
|
6010
|
+
};
|
|
6011
|
+
const maxSteps = Math.ceil(this.maxSearchDistance / LABEL_SEARCH_STEP);
|
|
6012
|
+
for (let step = 1; step <= maxSteps; step++) {
|
|
6013
|
+
for (const sign of [-1, 1]) {
|
|
6014
|
+
const lateralOffset = sign * step * LABEL_SEARCH_STEP;
|
|
6015
|
+
const baseAnchor = {
|
|
6016
|
+
x: initialBaseAnchor.x + lateralDir.x * lateralOffset,
|
|
6017
|
+
y: initialBaseAnchor.y + lateralDir.y * lateralOffset
|
|
6018
|
+
};
|
|
6019
|
+
const maxSearchDistance = this.getLateralColumnMaxDistance(
|
|
6020
|
+
label,
|
|
6021
|
+
orientation,
|
|
6022
|
+
baseAnchor
|
|
6023
|
+
);
|
|
6024
|
+
const candidate = this.findValidCandidateInShiftColumn({
|
|
6025
|
+
label,
|
|
6026
|
+
labelIndex,
|
|
6027
|
+
orientation,
|
|
6028
|
+
direction,
|
|
6029
|
+
baseAnchor,
|
|
6030
|
+
maxSearchDistance,
|
|
6031
|
+
outwardDistance: lateralOffset,
|
|
6032
|
+
phase: "lateral-shift"
|
|
6033
|
+
});
|
|
6034
|
+
if (candidate) return candidate;
|
|
6035
|
+
}
|
|
6036
|
+
}
|
|
6037
|
+
return null;
|
|
6038
|
+
}
|
|
5853
6039
|
findValidCandidateInShiftColumn(params) {
|
|
5854
6040
|
const {
|
|
5855
6041
|
label,
|
|
@@ -5858,9 +6044,10 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
|
|
|
5858
6044
|
direction,
|
|
5859
6045
|
baseAnchor,
|
|
5860
6046
|
maxSearchDistance,
|
|
5861
|
-
outwardDistance
|
|
6047
|
+
outwardDistance,
|
|
6048
|
+
phase = "shift"
|
|
5862
6049
|
} = params;
|
|
5863
|
-
for (let distance3 = LABEL_SEARCH_STEP; distance3 <= maxSearchDistance +
|
|
6050
|
+
for (let distance3 = LABEL_SEARCH_STEP; distance3 <= maxSearchDistance + EPS7; distance3 += LABEL_SEARCH_STEP) {
|
|
5864
6051
|
const anchorPoint = {
|
|
5865
6052
|
x: baseAnchor.x + direction.x * distance3,
|
|
5866
6053
|
y: baseAnchor.y + direction.y * distance3
|
|
@@ -5870,7 +6057,7 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
|
|
|
5870
6057
|
candidate,
|
|
5871
6058
|
label,
|
|
5872
6059
|
labelIndex,
|
|
5873
|
-
|
|
6060
|
+
phase,
|
|
5874
6061
|
distance3,
|
|
5875
6062
|
outwardDistance
|
|
5876
6063
|
);
|
|
@@ -5951,6 +6138,21 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
|
|
|
5951
6138
|
const labelLength = orientation === "y+" || orientation === "y-" ? height : width;
|
|
5952
6139
|
return Math.min(this.maxSearchDistance, labelLength * 2);
|
|
5953
6140
|
}
|
|
6141
|
+
getLateralColumnMaxDistance(label, orientation, baseAnchor) {
|
|
6142
|
+
const chipId = label.pinIds.map((pid) => this.pinMap[pid]?.chipId).find(Boolean);
|
|
6143
|
+
const chip = chipId ? this.chipObstacleSpatialIndex.chips.find((c) => c.chipId === chipId) : null;
|
|
6144
|
+
if (chip) {
|
|
6145
|
+
if (orientation === "y-")
|
|
6146
|
+
return Math.max(0, baseAnchor.y - chip.bounds.minY);
|
|
6147
|
+
if (orientation === "y+")
|
|
6148
|
+
return Math.max(0, chip.bounds.maxY - baseAnchor.y);
|
|
6149
|
+
if (orientation === "x-")
|
|
6150
|
+
return Math.max(0, baseAnchor.x - chip.bounds.minX);
|
|
6151
|
+
if (orientation === "x+")
|
|
6152
|
+
return Math.max(0, chip.bounds.maxX - baseAnchor.x);
|
|
6153
|
+
}
|
|
6154
|
+
return this.getSearchDistanceLimit(label, orientation);
|
|
6155
|
+
}
|
|
5954
6156
|
createCandidate(label, anchorPoint, orientation) {
|
|
5955
6157
|
const { width, height } = getDimsForOrientation({
|
|
5956
6158
|
orientation,
|
|
@@ -5965,9 +6167,22 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
|
|
|
5965
6167
|
};
|
|
5966
6168
|
}
|
|
5967
6169
|
getNetLabelWidth(label) {
|
|
5968
|
-
if (
|
|
6170
|
+
if (label.netId) {
|
|
6171
|
+
const ncWidth = this.inputProblem.netConnections.find(
|
|
6172
|
+
(connection) => connection.netId === label.netId
|
|
6173
|
+
)?.netLabelWidth;
|
|
6174
|
+
if (ncWidth !== void 0) return ncWidth;
|
|
6175
|
+
const dcWidthByNetId = this.inputProblem.directConnections.find(
|
|
6176
|
+
(dc) => dc.netId === label.netId
|
|
6177
|
+
)?.netLabelWidth;
|
|
6178
|
+
if (dcWidthByNetId !== void 0) return dcWidthByNetId;
|
|
6179
|
+
}
|
|
6180
|
+
const dcWidthByPinId = this.inputProblem.directConnections.find(
|
|
6181
|
+
(dc) => dc.pinIds.some((pid) => label.pinIds.includes(pid))
|
|
6182
|
+
)?.netLabelWidth;
|
|
6183
|
+
if (dcWidthByPinId !== void 0) return dcWidthByPinId;
|
|
5969
6184
|
return this.inputProblem.netConnections.find(
|
|
5970
|
-
(
|
|
6185
|
+
(nc) => nc.pinIds.some((pid) => label.pinIds.includes(pid))
|
|
5971
6186
|
)?.netLabelWidth;
|
|
5972
6187
|
}
|
|
5973
6188
|
getCandidateStatus(candidate, label, labelIndex) {
|
|
@@ -5984,6 +6199,11 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
|
|
|
5984
6199
|
if (tracePathCrossesAnyTrace(connectorTrace, this.traceMap)) {
|
|
5985
6200
|
return "trace-collision";
|
|
5986
6201
|
}
|
|
6202
|
+
for (const chip of this.chipObstacleSpatialIndex.chips) {
|
|
6203
|
+
if (tracePathCrossesAnyBounds(connectorTrace, chip.bounds)) {
|
|
6204
|
+
return "chip-collision";
|
|
6205
|
+
}
|
|
6206
|
+
}
|
|
5987
6207
|
for (let i = 0; i < this.outputNetLabelPlacements.length; i++) {
|
|
5988
6208
|
if (i === labelIndex) continue;
|
|
5989
6209
|
const otherLabel = this.outputNetLabelPlacements[i];
|
|
@@ -6023,8 +6243,8 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
|
|
|
6023
6243
|
sharesChipBoundary(bounds) {
|
|
6024
6244
|
for (const chip of this.chipObstacleSpatialIndex.chips) {
|
|
6025
6245
|
const chipBounds = chip.bounds;
|
|
6026
|
-
const adjacentToVerticalSide = Math.abs(bounds.minX - chipBounds.maxX) <= WICK_CLEARANCE +
|
|
6027
|
-
const adjacentToHorizontalSide = Math.abs(bounds.minY - chipBounds.maxY) <= WICK_CLEARANCE +
|
|
6246
|
+
const adjacentToVerticalSide = Math.abs(bounds.minX - chipBounds.maxX) <= WICK_CLEARANCE + EPS7 || Math.abs(bounds.maxX - chipBounds.minX) <= WICK_CLEARANCE + EPS7;
|
|
6247
|
+
const adjacentToHorizontalSide = Math.abs(bounds.minY - chipBounds.maxY) <= WICK_CLEARANCE + EPS7 || Math.abs(bounds.maxY - chipBounds.minY) <= WICK_CLEARANCE + EPS7;
|
|
6028
6248
|
if (adjacentToVerticalSide && rangesOverlap(
|
|
6029
6249
|
bounds.minY,
|
|
6030
6250
|
bounds.maxY,
|
|
@@ -6072,7 +6292,7 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
|
|
|
6072
6292
|
let nearestDistance = Number.POSITIVE_INFINITY;
|
|
6073
6293
|
for (const chip of this.chipObstacleSpatialIndex.chips) {
|
|
6074
6294
|
const bounds = chip.bounds;
|
|
6075
|
-
if (point.x < bounds.minX -
|
|
6295
|
+
if (point.x < bounds.minX - EPS7 || point.x > bounds.maxX + EPS7 || point.y < bounds.minY - EPS7 || point.y > bounds.maxY + EPS7) {
|
|
6076
6296
|
continue;
|
|
6077
6297
|
}
|
|
6078
6298
|
for (const [side, distance3] of getSideDistances(point, bounds)) {
|
|
@@ -6089,8 +6309,8 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
|
|
|
6089
6309
|
let nearestDistanceSq = Number.POSITIVE_INFINITY;
|
|
6090
6310
|
for (const chip of this.chipObstacleSpatialIndex.chips) {
|
|
6091
6311
|
const bounds = chip.bounds;
|
|
6092
|
-
const dx = point.x < bounds.minX -
|
|
6093
|
-
const dy = point.y < bounds.minY -
|
|
6312
|
+
const dx = point.x < bounds.minX - EPS7 ? bounds.minX - point.x : point.x > bounds.maxX + EPS7 ? point.x - bounds.maxX : 0;
|
|
6313
|
+
const dy = point.y < bounds.minY - EPS7 ? bounds.minY - point.y : point.y > bounds.maxY + EPS7 ? point.y - bounds.maxY : 0;
|
|
6094
6314
|
if (dx === 0 && dy === 0) continue;
|
|
6095
6315
|
const distanceSq = dx ** 2 + dy ** 2;
|
|
6096
6316
|
if (distanceSq >= nearestDistanceSq) continue;
|
|
@@ -6129,9 +6349,9 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
|
|
|
6129
6349
|
};
|
|
6130
6350
|
|
|
6131
6351
|
// lib/solvers/VccNetLabelCornerPlacementSolver/geometry.ts
|
|
6132
|
-
var
|
|
6352
|
+
var EPS8 = 1e-6;
|
|
6133
6353
|
var isTraceLine = (trace) => getUniquePinCount(trace.pinIds) >= 2;
|
|
6134
|
-
var rectsOverlap2 = (a, b) => Math.min(a.maxX, b.maxX) - Math.max(a.minX, b.minX) >
|
|
6354
|
+
var rectsOverlap2 = (a, b) => Math.min(a.maxX, b.maxX) - Math.max(a.minX, b.minX) > EPS8 && Math.min(a.maxY, b.maxY) - Math.max(a.minY, b.minY) > EPS8;
|
|
6135
6355
|
var getTraceCorners = (path) => {
|
|
6136
6356
|
const corners = [];
|
|
6137
6357
|
for (let i = 1; i < path.length - 1; i++) {
|
|
@@ -6155,11 +6375,11 @@ var getUniquePinCount = (pinIds) => new Set(pinIds).size;
|
|
|
6155
6375
|
var isTraceCorner = (a, b, c) => getSegmentOrientation2(a, b) !== getSegmentOrientation2(b, c);
|
|
6156
6376
|
var isPointOnSegment = (point, start, end) => {
|
|
6157
6377
|
if (getSegmentOrientation2(start, end) === "horizontal") {
|
|
6158
|
-
return Math.abs(point.y - start.y) <=
|
|
6378
|
+
return Math.abs(point.y - start.y) <= EPS8 && point.x >= Math.min(start.x, end.x) - EPS8 && point.x <= Math.max(start.x, end.x) + EPS8;
|
|
6159
6379
|
}
|
|
6160
|
-
return Math.abs(point.x - start.x) <=
|
|
6380
|
+
return Math.abs(point.x - start.x) <= EPS8 && point.y >= Math.min(start.y, end.y) - EPS8 && point.y <= Math.max(start.y, end.y) + EPS8;
|
|
6161
6381
|
};
|
|
6162
|
-
var getSegmentOrientation2 = (a, b) => Math.abs(a.y - b.y) <=
|
|
6382
|
+
var getSegmentOrientation2 = (a, b) => Math.abs(a.y - b.y) <= EPS8 ? "horizontal" : "vertical";
|
|
6163
6383
|
|
|
6164
6384
|
// lib/solvers/VccNetLabelCornerPlacementSolver/visualize.ts
|
|
6165
6385
|
var CANDIDATE_SELECTED_COLOR3 = "blue";
|
|
@@ -6437,11 +6657,11 @@ var VccNetLabelCornerPlacementSolver = class extends BaseSolver {
|
|
|
6437
6657
|
};
|
|
6438
6658
|
|
|
6439
6659
|
// lib/solvers/TraceAnchoredNetLabelOverlapSolver/geometry.ts
|
|
6440
|
-
var
|
|
6660
|
+
var EPS9 = 1e-6;
|
|
6441
6661
|
var TRACE_BOUNDARY_TOLERANCE2 = 1e-6;
|
|
6442
6662
|
var getLabelBounds = (label) => getRectBounds(label.center, label.width, label.height);
|
|
6443
|
-
var rectsOverlap3 = (a, b) => Math.min(a.maxX, b.maxX) - Math.max(a.minX, b.minX) >
|
|
6444
|
-
var rectsTouchOrOverlap = (a, b) => Math.min(a.maxX, b.maxX) - Math.max(a.minX, b.minX) >= -
|
|
6663
|
+
var rectsOverlap3 = (a, b) => Math.min(a.maxX, b.maxX) - Math.max(a.minX, b.minX) > EPS9 && Math.min(a.maxY, b.maxY) - Math.max(a.minY, b.minY) > EPS9;
|
|
6664
|
+
var rectsTouchOrOverlap = (a, b) => Math.min(a.maxX, b.maxX) - Math.max(a.minX, b.minX) >= -EPS9 && Math.min(a.maxY, b.maxY) - Math.max(a.minY, b.minY) >= -EPS9;
|
|
6445
6665
|
var traceCrossesBoundsInterior2 = (bounds, traces) => {
|
|
6446
6666
|
for (const trace of traces) {
|
|
6447
6667
|
const points = trace.tracePath;
|
|
@@ -6487,7 +6707,7 @@ var getPointAtTraceDistance = (trace, distance3) => {
|
|
|
6487
6707
|
const end = trace.tracePath[i + 1];
|
|
6488
6708
|
const segmentLength = getManhattanDistance(start, end);
|
|
6489
6709
|
const nextDistance = pathDistance + segmentLength;
|
|
6490
|
-
if (distance3 <= nextDistance +
|
|
6710
|
+
if (distance3 <= nextDistance + EPS9) {
|
|
6491
6711
|
const offset = Math.max(
|
|
6492
6712
|
0,
|
|
6493
6713
|
Math.min(segmentLength, distance3 - pathDistance)
|
|
@@ -6526,7 +6746,7 @@ var segmentCrossesBoundsInterior2 = (start, end, bounds) => {
|
|
|
6526
6746
|
return false;
|
|
6527
6747
|
}
|
|
6528
6748
|
if (isVertical3(start, end)) {
|
|
6529
|
-
if (start.x <= interior.minX +
|
|
6749
|
+
if (start.x <= interior.minX + EPS9 || start.x >= interior.maxX - EPS9) {
|
|
6530
6750
|
return false;
|
|
6531
6751
|
}
|
|
6532
6752
|
return rangesOverlap2(
|
|
@@ -6537,7 +6757,7 @@ var segmentCrossesBoundsInterior2 = (start, end, bounds) => {
|
|
|
6537
6757
|
);
|
|
6538
6758
|
}
|
|
6539
6759
|
if (isHorizontal2(start, end)) {
|
|
6540
|
-
if (start.y <= interior.minY +
|
|
6760
|
+
if (start.y <= interior.minY + EPS9 || start.y >= interior.maxY - EPS9) {
|
|
6541
6761
|
return false;
|
|
6542
6762
|
}
|
|
6543
6763
|
return rangesOverlap2(
|
|
@@ -6551,10 +6771,10 @@ var segmentCrossesBoundsInterior2 = (start, end, bounds) => {
|
|
|
6551
6771
|
};
|
|
6552
6772
|
var isPointOnSegment2 = (point, start, end) => {
|
|
6553
6773
|
if (isHorizontal2(start, end)) {
|
|
6554
|
-
return Math.abs(point.y - start.y) <=
|
|
6774
|
+
return Math.abs(point.y - start.y) <= EPS9 && point.x >= Math.min(start.x, end.x) - EPS9 && point.x <= Math.max(start.x, end.x) + EPS9;
|
|
6555
6775
|
}
|
|
6556
6776
|
if (isVertical3(start, end)) {
|
|
6557
|
-
return Math.abs(point.x - start.x) <=
|
|
6777
|
+
return Math.abs(point.x - start.x) <= EPS9 && point.y >= Math.min(start.y, end.y) - EPS9 && point.y <= Math.max(start.y, end.y) + EPS9;
|
|
6558
6778
|
}
|
|
6559
6779
|
return false;
|
|
6560
6780
|
};
|
|
@@ -6562,9 +6782,9 @@ var getSegmentDirection = (start, end) => ({
|
|
|
6562
6782
|
x: isVertical3(start, end) ? 0 : Math.sign(end.x - start.x),
|
|
6563
6783
|
y: isHorizontal2(start, end) ? 0 : Math.sign(end.y - start.y)
|
|
6564
6784
|
});
|
|
6565
|
-
var isHorizontal2 = (start, end) => Math.abs(start.y - end.y) <=
|
|
6566
|
-
var isVertical3 = (start, end) => Math.abs(start.x - end.x) <=
|
|
6567
|
-
var rangesOverlap2 = (minA, maxA, minB, maxB) => Math.min(maxA, maxB) - Math.max(minA, minB) >
|
|
6785
|
+
var isHorizontal2 = (start, end) => Math.abs(start.y - end.y) <= EPS9;
|
|
6786
|
+
var isVertical3 = (start, end) => Math.abs(start.x - end.x) <= EPS9;
|
|
6787
|
+
var rangesOverlap2 = (minA, maxA, minB, maxB) => Math.min(maxA, maxB) - Math.max(minA, minB) > EPS9;
|
|
6568
6788
|
var getUniquePinCount2 = (pinIds) => new Set(pinIds).size;
|
|
6569
6789
|
|
|
6570
6790
|
// lib/solvers/TraceAnchoredNetLabelOverlapSolver/candidates.ts
|
|
@@ -6619,7 +6839,7 @@ var getCandidateDistances = (traceLength, vertexDistances) => {
|
|
|
6619
6839
|
for (const distance3 of vertexDistances) {
|
|
6620
6840
|
distances.add(roundDistance(distance3));
|
|
6621
6841
|
}
|
|
6622
|
-
return [...distances].filter((distance3) => distance3 >= -
|
|
6842
|
+
return [...distances].filter((distance3) => distance3 >= -EPS9 && distance3 <= traceLength + EPS9).sort((a, b) => a - b);
|
|
6623
6843
|
};
|
|
6624
6844
|
var getOrientationsForPoint = (params) => {
|
|
6625
6845
|
const { inputProblem, label, point, orientationConstraint } = params;
|
|
@@ -6726,13 +6946,13 @@ var getOutwardOrientationOptions = (point, chipBounds) => {
|
|
|
6726
6946
|
};
|
|
6727
6947
|
var getOutwardAxisOption = (params) => {
|
|
6728
6948
|
const { value, min, max, center, positiveOrientation, negativeOrientation } = params;
|
|
6729
|
-
if (value > max +
|
|
6949
|
+
if (value > max + EPS9) {
|
|
6730
6950
|
return {
|
|
6731
6951
|
orientation: positiveOrientation,
|
|
6732
6952
|
outwardScore: 1 + value - max
|
|
6733
6953
|
};
|
|
6734
6954
|
}
|
|
6735
|
-
if (value < min -
|
|
6955
|
+
if (value < min - EPS9) {
|
|
6736
6956
|
return {
|
|
6737
6957
|
orientation: negativeOrientation,
|
|
6738
6958
|
outwardScore: 1 + min - value
|
|
@@ -6743,7 +6963,7 @@ var getOutwardAxisOption = (params) => {
|
|
|
6743
6963
|
outwardScore: getNormalizedCenterDistance(value, center, max - min)
|
|
6744
6964
|
};
|
|
6745
6965
|
};
|
|
6746
|
-
var getNormalizedCenterDistance = (value, center, span) => Math.abs(value - center) / Math.max(
|
|
6966
|
+
var getNormalizedCenterDistance = (value, center, span) => Math.abs(value - center) / Math.max(EPS9, span / 2);
|
|
6747
6967
|
var ALL_ORIENTATIONS = ["x+", "x-", "y+", "y-"];
|
|
6748
6968
|
var getFlippedOrientation = (orientation) => {
|
|
6749
6969
|
switch (orientation) {
|
|
@@ -6789,11 +7009,22 @@ var getChipBounds = (inputProblem) => {
|
|
|
6789
7009
|
};
|
|
6790
7010
|
};
|
|
6791
7011
|
var getNetLabelWidth = (inputProblem, label) => {
|
|
6792
|
-
const
|
|
7012
|
+
const ncWidthByNetId = inputProblem.netConnections.find(
|
|
6793
7013
|
(connection) => connection.netId === label.netId
|
|
6794
7014
|
)?.netLabelWidth;
|
|
6795
|
-
if (
|
|
6796
|
-
|
|
7015
|
+
if (ncWidthByNetId !== void 0) return ncWidthByNetId;
|
|
7016
|
+
const dcWidth = inputProblem.directConnections.find(
|
|
7017
|
+
(dc) => dc.pinIds.some((pid) => label.pinIds.includes(pid))
|
|
7018
|
+
)?.netLabelWidth;
|
|
7019
|
+
if (dcWidth !== void 0) return dcWidth;
|
|
7020
|
+
const ncWidthByPinId = inputProblem.netConnections.find(
|
|
7021
|
+
(nc) => nc.pinIds.some((pid) => label.pinIds.includes(pid))
|
|
7022
|
+
)?.netLabelWidth;
|
|
7023
|
+
if (ncWidthByPinId !== void 0) return ncWidthByPinId;
|
|
7024
|
+
if (label.orientation === "y+" || label.orientation === "y-") {
|
|
7025
|
+
return label.height;
|
|
7026
|
+
}
|
|
7027
|
+
return label.width;
|
|
6797
7028
|
};
|
|
6798
7029
|
var roundDistance = (distance3) => Number(distance3.toFixed(6));
|
|
6799
7030
|
var dedupeOrientations = (orientations) => [
|
|
@@ -6818,7 +7049,7 @@ var normalizeFacingDirection = (value) => {
|
|
|
6818
7049
|
var dedupeStrings = (values) => [
|
|
6819
7050
|
...new Set(values.filter((value) => value !== void 0))
|
|
6820
7051
|
];
|
|
6821
|
-
var isSamePlacement = (label, point, orientation) => Math.abs(point.x - label.anchorPoint.x) <=
|
|
7052
|
+
var isSamePlacement = (label, point, orientation) => Math.abs(point.x - label.anchorPoint.x) <= EPS9 && Math.abs(point.y - label.anchorPoint.y) <= EPS9 && orientation === label.orientation;
|
|
6822
7053
|
|
|
6823
7054
|
// lib/solvers/TraceAnchoredNetLabelOverlapSolver/visualize.ts
|
|
6824
7055
|
var CANDIDATE_SELECTED_COLOR4 = "blue";
|