@tscircuit/schematic-trace-solver 0.0.63 → 0.0.65
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 +5 -0
- package/dist/index.js +208 -143
- package/lib/solvers/AvailableNetOrientationSolver/AvailableNetOrientationSolver.ts +51 -36
- package/lib/solvers/AvailableNetOrientationSolver/geometry.ts +13 -0
- package/lib/solvers/NetLabelTraceCollisionSolver/NetLabelTraceCollisionSolver.ts +9 -13
- package/lib/solvers/TraceOverlapShiftSolver/TraceOverlapIssueSolver/TraceOverlapIssueSolver.ts +89 -6
- package/lib/solvers/TraceOverlapShiftSolver/TraceOverlapShiftSolver.ts +1 -0
- package/package.json +1 -1
- package/tests/examples/__snapshots__/example34.snap.svg +23 -19
- package/tests/examples/example34.test.ts +8 -0
- package/tests/fixtures/traceLabelCollisions.ts +42 -0
- package/tests/repros/__snapshots__/netlabel-connector-through-rail-label.snap.svg +273 -0
- package/tests/repros/__snapshots__/trace-overlap-box-resistor.snap.svg +113 -0
- package/tests/repros/assets/repro-netlabel-connector-through-label.input.json +139 -0
- package/tests/repros/assets/repro126-trace-overlap-box-resistor.input.json +74 -0
- package/tests/repros/netlabel-connector-through-rail-label.test.ts +19 -0
- package/tests/repros/trace-overlap-box-resistor.test.ts +14 -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 EPS11 = 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) < -EPS11) 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) < -EPS11) 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) < EPS11 || Math.abs(p1.y - p2.y) < EPS11) {
|
|
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 EPS11 = 1e-9;
|
|
854
|
+
const samePoint = (p, q) => Math.abs(p.x - q.x) < EPS11 && Math.abs(p.y - q.y) < EPS11;
|
|
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: EPS11 = 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) < EPS11;
|
|
1059
|
+
const isHorizontal3 = Math.abs(start.y - end.y) < EPS11;
|
|
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) {
|
|
@@ -1103,15 +1103,18 @@ var applyJogToTerminalSegment = ({
|
|
|
1103
1103
|
};
|
|
1104
1104
|
|
|
1105
1105
|
// lib/solvers/TraceOverlapShiftSolver/TraceOverlapIssueSolver/TraceOverlapIssueSolver.ts
|
|
1106
|
+
var EPS4 = 1e-6;
|
|
1106
1107
|
var TraceOverlapIssueSolver = class extends BaseSolver {
|
|
1107
1108
|
overlappingTraceSegments;
|
|
1108
1109
|
traceNetIslands;
|
|
1110
|
+
obstacleRects;
|
|
1109
1111
|
SHIFT_DISTANCE = 0.1;
|
|
1110
1112
|
correctedTraceMap = {};
|
|
1111
1113
|
constructor(params) {
|
|
1112
1114
|
super();
|
|
1113
1115
|
this.overlappingTraceSegments = params.overlappingTraceSegments;
|
|
1114
1116
|
this.traceNetIslands = params.traceNetIslands;
|
|
1117
|
+
this.obstacleRects = getObstacleRects(params.inputProblem);
|
|
1115
1118
|
for (const { connNetId, pathsWithOverlap } of this.overlappingTraceSegments) {
|
|
1116
1119
|
for (const {
|
|
1117
1120
|
solvedTracePathIndex,
|
|
@@ -1123,13 +1126,15 @@ var TraceOverlapIssueSolver = class extends BaseSolver {
|
|
|
1123
1126
|
}
|
|
1124
1127
|
}
|
|
1125
1128
|
_step() {
|
|
1126
|
-
const
|
|
1127
|
-
const offsets = this.overlappingTraceSegments.map((_, idx) => {
|
|
1129
|
+
const offsets = this.overlappingTraceSegments.map((group, idx) => {
|
|
1128
1130
|
const n = Math.floor(idx / 2) + 1;
|
|
1129
1131
|
const signed = idx % 2 === 0 ? -n : n;
|
|
1130
|
-
return
|
|
1132
|
+
return this.getObstacleAwareOffset({
|
|
1133
|
+
group,
|
|
1134
|
+
offset: signed * this.SHIFT_DISTANCE
|
|
1135
|
+
});
|
|
1131
1136
|
});
|
|
1132
|
-
const eq = (a, b) => Math.abs(a - b) <
|
|
1137
|
+
const eq = (a, b) => Math.abs(a - b) < EPS4;
|
|
1133
1138
|
const samePoint = (p, q) => !!p && !!q && eq(p.x, q.x) && eq(p.y, q.y);
|
|
1134
1139
|
this.overlappingTraceSegments.forEach((group, gidx) => {
|
|
1135
1140
|
const offset = offsets[gidx];
|
|
@@ -1144,7 +1149,6 @@ var TraceOverlapIssueSolver = class extends BaseSolver {
|
|
|
1144
1149
|
const original = this.traceNetIslands[group.connNetId][pathIdx];
|
|
1145
1150
|
const current = this.correctedTraceMap[original.mspPairId] ?? original;
|
|
1146
1151
|
const pts = current.tracePath.map((p) => ({ ...p }));
|
|
1147
|
-
const segIdxs = Array.from(segIdxSet).sort((a, b) => a - b);
|
|
1148
1152
|
const segIdxsRev = Array.from(segIdxSet).sort((a, b) => a - b).reverse();
|
|
1149
1153
|
const JOG_SIZE = this.SHIFT_DISTANCE;
|
|
1150
1154
|
for (const si of segIdxsRev) {
|
|
@@ -1155,13 +1159,13 @@ var TraceOverlapIssueSolver = class extends BaseSolver {
|
|
|
1155
1159
|
segmentIndex: si,
|
|
1156
1160
|
offset,
|
|
1157
1161
|
JOG_SIZE,
|
|
1158
|
-
EPS:
|
|
1162
|
+
EPS: EPS4
|
|
1159
1163
|
});
|
|
1160
1164
|
} else {
|
|
1161
1165
|
const start = pts[si];
|
|
1162
1166
|
const end = pts[si + 1];
|
|
1163
|
-
const isVertical4 = Math.abs(start.x - end.x) <
|
|
1164
|
-
const isHorizontal3 = Math.abs(start.y - end.y) <
|
|
1167
|
+
const isVertical4 = Math.abs(start.x - end.x) < EPS4;
|
|
1168
|
+
const isHorizontal3 = Math.abs(start.y - end.y) < EPS4;
|
|
1165
1169
|
if (!isVertical4 && !isHorizontal3) continue;
|
|
1166
1170
|
if (isVertical4) {
|
|
1167
1171
|
start.x += offset;
|
|
@@ -1186,6 +1190,53 @@ var TraceOverlapIssueSolver = class extends BaseSolver {
|
|
|
1186
1190
|
});
|
|
1187
1191
|
this.solved = true;
|
|
1188
1192
|
}
|
|
1193
|
+
getObstacleAwareOffset({
|
|
1194
|
+
group,
|
|
1195
|
+
offset
|
|
1196
|
+
}) {
|
|
1197
|
+
const blockingCollisions = this.getBlockingCollisions({ group, offset });
|
|
1198
|
+
if (blockingCollisions.length === 0) return offset;
|
|
1199
|
+
return blockingCollisions.flatMap(({ start, isVertical: isVertical4, obstacle }) => [
|
|
1200
|
+
(isVertical4 ? obstacle.minX - start.x : obstacle.minY - start.y) - this.SHIFT_DISTANCE,
|
|
1201
|
+
(isVertical4 ? obstacle.maxX - start.x : obstacle.maxY - start.y) + this.SHIFT_DISTANCE
|
|
1202
|
+
]).filter(
|
|
1203
|
+
(candidateOffset) => this.getBlockingCollisions({ group, offset: candidateOffset }).length === 0
|
|
1204
|
+
).sort((a, b) => Math.abs(a - offset) - Math.abs(b - offset))[0] ?? offset;
|
|
1205
|
+
}
|
|
1206
|
+
getBlockingCollisions({
|
|
1207
|
+
group,
|
|
1208
|
+
offset
|
|
1209
|
+
}) {
|
|
1210
|
+
const blockingCollisions = [];
|
|
1211
|
+
for (const {
|
|
1212
|
+
solvedTracePathIndex,
|
|
1213
|
+
traceSegmentIndex
|
|
1214
|
+
} of group.pathsWithOverlap) {
|
|
1215
|
+
const trace = this.traceNetIslands[group.connNetId][solvedTracePathIndex];
|
|
1216
|
+
const start = trace.tracePath[traceSegmentIndex];
|
|
1217
|
+
const end = trace.tracePath[traceSegmentIndex + 1];
|
|
1218
|
+
if (!start || !end) continue;
|
|
1219
|
+
const isVertical4 = Math.abs(start.x - end.x) < EPS4;
|
|
1220
|
+
const isHorizontal3 = Math.abs(start.y - end.y) < EPS4;
|
|
1221
|
+
if (!isVertical4 && !isHorizontal3) continue;
|
|
1222
|
+
const shiftedSegment = isVertical4 ? [
|
|
1223
|
+
{ ...start, x: start.x + offset },
|
|
1224
|
+
{ ...end, x: end.x + offset }
|
|
1225
|
+
] : [
|
|
1226
|
+
{ ...start, y: start.y + offset },
|
|
1227
|
+
{ ...end, y: end.y + offset }
|
|
1228
|
+
];
|
|
1229
|
+
const collision = findFirstCollision(shiftedSegment, this.obstacleRects);
|
|
1230
|
+
if (collision) {
|
|
1231
|
+
blockingCollisions.push({
|
|
1232
|
+
start,
|
|
1233
|
+
isVertical: isVertical4,
|
|
1234
|
+
obstacle: collision.rect
|
|
1235
|
+
});
|
|
1236
|
+
}
|
|
1237
|
+
}
|
|
1238
|
+
return blockingCollisions;
|
|
1239
|
+
}
|
|
1189
1240
|
visualize() {
|
|
1190
1241
|
const graphics = {
|
|
1191
1242
|
lines: [],
|
|
@@ -1258,7 +1309,7 @@ var TraceOverlapShiftSolver = class extends BaseSolver {
|
|
|
1258
1309
|
return islands;
|
|
1259
1310
|
}
|
|
1260
1311
|
findNextOverlapIssue() {
|
|
1261
|
-
const
|
|
1312
|
+
const EPS11 = 2e-3;
|
|
1262
1313
|
const netIds = Object.keys(this.traceNetIslands);
|
|
1263
1314
|
for (let i = 0; i < netIds.length; i++) {
|
|
1264
1315
|
for (let j = i + 1; j < netIds.length; j++) {
|
|
@@ -1276,7 +1327,7 @@ var TraceOverlapShiftSolver = class extends BaseSolver {
|
|
|
1276
1327
|
const minB = Math.min(b1, b2);
|
|
1277
1328
|
const maxB = Math.max(b1, b2);
|
|
1278
1329
|
const overlap = Math.min(maxA, maxB) - Math.max(minA, minB);
|
|
1279
|
-
return overlap >
|
|
1330
|
+
return overlap > EPS11;
|
|
1280
1331
|
};
|
|
1281
1332
|
for (let pa = 0; pa < pathsA.length; pa++) {
|
|
1282
1333
|
const pathA = pathsA[pa];
|
|
@@ -1284,8 +1335,8 @@ var TraceOverlapShiftSolver = class extends BaseSolver {
|
|
|
1284
1335
|
for (let sa = 0; sa < ptsA.length - 1; sa++) {
|
|
1285
1336
|
const a1 = ptsA[sa];
|
|
1286
1337
|
const a2 = ptsA[sa + 1];
|
|
1287
|
-
const aVert = Math.abs(a1.x - a2.x) <
|
|
1288
|
-
const aHorz = Math.abs(a1.y - a2.y) <
|
|
1338
|
+
const aVert = Math.abs(a1.x - a2.x) < EPS11;
|
|
1339
|
+
const aHorz = Math.abs(a1.y - a2.y) < EPS11;
|
|
1289
1340
|
if (!aVert && !aHorz) continue;
|
|
1290
1341
|
for (let pb = 0; pb < pathsB.length; pb++) {
|
|
1291
1342
|
const pathB = pathsB[pb];
|
|
@@ -1293,11 +1344,11 @@ var TraceOverlapShiftSolver = class extends BaseSolver {
|
|
|
1293
1344
|
for (let sb = 0; sb < ptsB.length - 1; sb++) {
|
|
1294
1345
|
const b1 = ptsB[sb];
|
|
1295
1346
|
const b2 = ptsB[sb + 1];
|
|
1296
|
-
const bVert = Math.abs(b1.x - b2.x) <
|
|
1297
|
-
const bHorz = Math.abs(b1.y - b2.y) <
|
|
1347
|
+
const bVert = Math.abs(b1.x - b2.x) < EPS11;
|
|
1348
|
+
const bHorz = Math.abs(b1.y - b2.y) < EPS11;
|
|
1298
1349
|
if (!bVert && !bHorz) continue;
|
|
1299
1350
|
if (aVert && bVert) {
|
|
1300
|
-
if (Math.abs(a1.x - b1.x) <
|
|
1351
|
+
if (Math.abs(a1.x - b1.x) < EPS11) {
|
|
1301
1352
|
if (overlaps1D(a1.y, a2.y, b1.y, b2.y)) {
|
|
1302
1353
|
const keyA = `${pa}:${sa}`;
|
|
1303
1354
|
const keyB = `${pb}:${sb}`;
|
|
@@ -1318,7 +1369,7 @@ var TraceOverlapShiftSolver = class extends BaseSolver {
|
|
|
1318
1369
|
}
|
|
1319
1370
|
}
|
|
1320
1371
|
} else if (aHorz && bHorz) {
|
|
1321
|
-
if (Math.abs(a1.y - b1.y) <
|
|
1372
|
+
if (Math.abs(a1.y - b1.y) < EPS11) {
|
|
1322
1373
|
if (overlaps1D(a1.x, a2.x, b1.x, b2.x)) {
|
|
1323
1374
|
const keyA = `${pa}:${sa}`;
|
|
1324
1375
|
const keyB = `${pb}:${sb}`;
|
|
@@ -1356,14 +1407,14 @@ var TraceOverlapShiftSolver = class extends BaseSolver {
|
|
|
1356
1407
|
return null;
|
|
1357
1408
|
}
|
|
1358
1409
|
findNextDiagonalSegment() {
|
|
1359
|
-
const
|
|
1410
|
+
const EPS11 = 2e-3;
|
|
1360
1411
|
for (const mspPairId in this.correctedTraceMap) {
|
|
1361
1412
|
const tracePath = this.correctedTraceMap[mspPairId].tracePath;
|
|
1362
1413
|
for (let i = 0; i < tracePath.length - 1; i++) {
|
|
1363
1414
|
const p1 = tracePath[i];
|
|
1364
1415
|
const p2 = tracePath[i + 1];
|
|
1365
|
-
const isHorizontal3 = Math.abs(p1.y - p2.y) <
|
|
1366
|
-
const isVertical4 = Math.abs(p1.x - p2.x) <
|
|
1416
|
+
const isHorizontal3 = Math.abs(p1.y - p2.y) < EPS11;
|
|
1417
|
+
const isVertical4 = Math.abs(p1.x - p2.x) < EPS11;
|
|
1367
1418
|
if (!isHorizontal3 && !isVertical4) {
|
|
1368
1419
|
return { mspPairId, tracePath, i, p1, p2 };
|
|
1369
1420
|
}
|
|
@@ -1377,13 +1428,13 @@ var TraceOverlapShiftSolver = class extends BaseSolver {
|
|
|
1377
1428
|
return false;
|
|
1378
1429
|
}
|
|
1379
1430
|
const { mspPairId, tracePath, i, p1, p2 } = diagonalInfo;
|
|
1380
|
-
const
|
|
1431
|
+
const EPS11 = 2e-3;
|
|
1381
1432
|
const p0 = i > 0 ? tracePath[i - 1] : null;
|
|
1382
1433
|
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) <
|
|
1434
|
+
const prevIsVertical = p0 ? Math.abs(p0.x - p1.x) < EPS11 : false;
|
|
1435
|
+
const prevIsHorizontal = p0 ? Math.abs(p0.y - p1.y) < EPS11 : false;
|
|
1436
|
+
const nextIsVertical = p3 ? Math.abs(p2.x - p3.x) < EPS11 : false;
|
|
1437
|
+
const nextIsHorizontal = p3 ? Math.abs(p2.y - p3.y) < EPS11 : false;
|
|
1387
1438
|
const elbow1 = { x: p1.x, y: p2.y };
|
|
1388
1439
|
const elbow2 = { x: p2.x, y: p1.y };
|
|
1389
1440
|
let score1 = 0;
|
|
@@ -1428,6 +1479,7 @@ var TraceOverlapShiftSolver = class extends BaseSolver {
|
|
|
1428
1479
|
}
|
|
1429
1480
|
const { overlappingTraceSegments } = overlapIssue;
|
|
1430
1481
|
this.activeSubSolver = new TraceOverlapIssueSolver({
|
|
1482
|
+
inputProblem: this.inputProblem,
|
|
1431
1483
|
overlappingTraceSegments,
|
|
1432
1484
|
traceNetIslands: this.traceNetIslands
|
|
1433
1485
|
});
|
|
@@ -1548,24 +1600,24 @@ function getRectBounds(center, w, h) {
|
|
|
1548
1600
|
}
|
|
1549
1601
|
|
|
1550
1602
|
// lib/solvers/NetLabelPlacementSolver/SingleNetLabelPlacementSolver/collisions.ts
|
|
1551
|
-
function segmentIntersectsRect2(p1, p2, rect,
|
|
1552
|
-
const isVert = Math.abs(p1.x - p2.x) <
|
|
1553
|
-
const isHorz = Math.abs(p1.y - p2.y) <
|
|
1603
|
+
function segmentIntersectsRect2(p1, p2, rect, EPS11 = 1e-9) {
|
|
1604
|
+
const isVert = Math.abs(p1.x - p2.x) < EPS11;
|
|
1605
|
+
const isHorz = Math.abs(p1.y - p2.y) < EPS11;
|
|
1554
1606
|
if (!isVert && !isHorz) return false;
|
|
1555
1607
|
if (isVert) {
|
|
1556
1608
|
const x = p1.x;
|
|
1557
|
-
if (x < rect.minX -
|
|
1609
|
+
if (x < rect.minX - EPS11 || x > rect.maxX + EPS11) return false;
|
|
1558
1610
|
const segMinY = Math.min(p1.y, p2.y);
|
|
1559
1611
|
const segMaxY = Math.max(p1.y, p2.y);
|
|
1560
1612
|
const overlap = Math.min(segMaxY, rect.maxY) - Math.max(segMinY, rect.minY);
|
|
1561
|
-
return overlap >
|
|
1613
|
+
return overlap > EPS11;
|
|
1562
1614
|
} else {
|
|
1563
1615
|
const y = p1.y;
|
|
1564
|
-
if (y < rect.minY -
|
|
1616
|
+
if (y < rect.minY - EPS11 || y > rect.maxY + EPS11) return false;
|
|
1565
1617
|
const segMinX = Math.min(p1.x, p2.x);
|
|
1566
1618
|
const segMaxX = Math.max(p1.x, p2.x);
|
|
1567
1619
|
const overlap = Math.min(segMaxX, rect.maxX) - Math.max(segMinX, rect.minX);
|
|
1568
|
-
return overlap >
|
|
1620
|
+
return overlap > EPS11;
|
|
1569
1621
|
}
|
|
1570
1622
|
}
|
|
1571
1623
|
function rectIntersectsAnyTrace(bounds, inputTraceMap, hostPathId, hostSegIndex) {
|
|
@@ -1949,14 +2001,14 @@ var SingleNetLabelPlacementSolver = class extends BaseSolver {
|
|
|
1949
2001
|
};
|
|
1950
2002
|
let bestCandidate = null;
|
|
1951
2003
|
let bestScore = -Infinity;
|
|
1952
|
-
const
|
|
2004
|
+
const EPS11 = 1e-6;
|
|
1953
2005
|
for (const curr of tracesToScan) {
|
|
1954
2006
|
const pts = curr.tracePath.slice();
|
|
1955
2007
|
for (let si = 0; si < pts.length - 1; si++) {
|
|
1956
2008
|
const a = pts[si];
|
|
1957
2009
|
const b = pts[si + 1];
|
|
1958
|
-
const isH = Math.abs(a.y - b.y) <
|
|
1959
|
-
const isV = Math.abs(a.x - b.x) <
|
|
2010
|
+
const isH = Math.abs(a.y - b.y) < EPS11;
|
|
2011
|
+
const isV = Math.abs(a.x - b.x) < EPS11;
|
|
1960
2012
|
if (!isH && !isV) continue;
|
|
1961
2013
|
const segmentAllowed = isH ? ["y+", "y-"] : ["x+", "x-"];
|
|
1962
2014
|
const candidateOrients = orientations.filter(
|
|
@@ -4172,8 +4224,8 @@ var findIntersectionsWithObstacles = (p1, p2, obstacles) => {
|
|
|
4172
4224
|
};
|
|
4173
4225
|
|
|
4174
4226
|
// lib/solvers/TraceCleanupSolver/sub-solver/generateLShapeRerouteCandidates.ts
|
|
4175
|
-
var
|
|
4176
|
-
var isVertical2 = (a, b, eps =
|
|
4227
|
+
var EPS5 = 1e-6;
|
|
4228
|
+
var isVertical2 = (a, b, eps = EPS5) => Math.abs(a.x - b.x) < eps;
|
|
4177
4229
|
var generateLShapeRerouteCandidates = ({
|
|
4178
4230
|
lShape,
|
|
4179
4231
|
rectangle,
|
|
@@ -4186,7 +4238,7 @@ var generateLShapeRerouteCandidates = ({
|
|
|
4186
4238
|
let c2;
|
|
4187
4239
|
let i1_padded = interactionPoint1;
|
|
4188
4240
|
let i2_padded = interactionPoint2;
|
|
4189
|
-
if (Math.abs(p2.x - x) <
|
|
4241
|
+
if (Math.abs(p2.x - x) < EPS5 && Math.abs(p2.y - (y + height)) < EPS5) {
|
|
4190
4242
|
c2 = { x: x + width + padding, y: y - padding };
|
|
4191
4243
|
if (isVertical2(p1, p2)) {
|
|
4192
4244
|
i1_padded = { x: interactionPoint1.x, y: interactionPoint1.y - padding };
|
|
@@ -4198,7 +4250,7 @@ var generateLShapeRerouteCandidates = ({
|
|
|
4198
4250
|
} else {
|
|
4199
4251
|
i2_padded = { x: interactionPoint2.x + padding, y: interactionPoint2.y };
|
|
4200
4252
|
}
|
|
4201
|
-
} else if (Math.abs(p2.x - (x + width)) <
|
|
4253
|
+
} else if (Math.abs(p2.x - (x + width)) < EPS5 && Math.abs(p2.y - (y + height)) < EPS5) {
|
|
4202
4254
|
c2 = { x: x - padding, y: y - padding };
|
|
4203
4255
|
if (isVertical2(p1, p2)) {
|
|
4204
4256
|
i1_padded = { x: interactionPoint1.x, y: interactionPoint1.y - padding };
|
|
@@ -4210,7 +4262,7 @@ var generateLShapeRerouteCandidates = ({
|
|
|
4210
4262
|
} else {
|
|
4211
4263
|
i2_padded = { x: interactionPoint2.x - padding, y: interactionPoint2.y };
|
|
4212
4264
|
}
|
|
4213
|
-
} else if (Math.abs(p2.x - x) <
|
|
4265
|
+
} else if (Math.abs(p2.x - x) < EPS5 && Math.abs(p2.y - y) < EPS5) {
|
|
4214
4266
|
c2 = { x: x + width + padding, y: y + height + padding };
|
|
4215
4267
|
if (isVertical2(p1, p2)) {
|
|
4216
4268
|
i1_padded = { x: interactionPoint1.x, y: interactionPoint1.y + padding };
|
|
@@ -4222,7 +4274,7 @@ var generateLShapeRerouteCandidates = ({
|
|
|
4222
4274
|
} else {
|
|
4223
4275
|
i2_padded = { x: interactionPoint2.x + padding, y: interactionPoint2.y };
|
|
4224
4276
|
}
|
|
4225
|
-
} else if (Math.abs(p2.x - (x + width)) <
|
|
4277
|
+
} else if (Math.abs(p2.x - (x + width)) < EPS5 && Math.abs(p2.y - y) < EPS5) {
|
|
4226
4278
|
c2 = { x: x - padding, y: y + height + padding };
|
|
4227
4279
|
if (isVertical2(p1, p2)) {
|
|
4228
4280
|
i1_padded = { x: interactionPoint1.x, y: interactionPoint1.y + padding };
|
|
@@ -4667,9 +4719,9 @@ var UntangleTraceSubsolver = class extends BaseSolver {
|
|
|
4667
4719
|
};
|
|
4668
4720
|
|
|
4669
4721
|
// lib/solvers/TraceCleanupSolver/is4PointRectangle.ts
|
|
4670
|
-
var
|
|
4671
|
-
var sameX = (a, b) => Math.abs(a.x - b.x) <=
|
|
4672
|
-
var sameY = (a, b) => Math.abs(a.y - b.y) <=
|
|
4722
|
+
var EPS6 = 1e-6;
|
|
4723
|
+
var sameX = (a, b) => Math.abs(a.x - b.x) <= EPS6;
|
|
4724
|
+
var sameY = (a, b) => Math.abs(a.y - b.y) <= EPS6;
|
|
4673
4725
|
var is4PointRectangle = (path) => {
|
|
4674
4726
|
if (path.length !== 4) return false;
|
|
4675
4727
|
const [p0, p1, p2, p3] = path;
|
|
@@ -4803,7 +4855,7 @@ var TraceCleanupSolver = class extends BaseSolver {
|
|
|
4803
4855
|
};
|
|
4804
4856
|
|
|
4805
4857
|
// lib/solvers/Example28Solver/types.ts
|
|
4806
|
-
var
|
|
4858
|
+
var EPS7 = 1e-9;
|
|
4807
4859
|
|
|
4808
4860
|
// lib/solvers/Example28Solver/geometry.ts
|
|
4809
4861
|
var getPathKey = (path) => path.map((point) => `${point.x},${point.y}`).join(";");
|
|
@@ -4815,10 +4867,10 @@ var getPathLength = (path) => {
|
|
|
4815
4867
|
return length;
|
|
4816
4868
|
};
|
|
4817
4869
|
var getDistance = (a, b) => Math.abs(a.x - b.x) + Math.abs(a.y - b.y);
|
|
4818
|
-
var isAxisAlignedSegment = (start, end) => Math.abs(start.x - end.x) <
|
|
4819
|
-
var getSegmentOrientation = (start, end) => Math.abs(start.y - end.y) <
|
|
4870
|
+
var isAxisAlignedSegment = (start, end) => Math.abs(start.x - end.x) < EPS7 || Math.abs(start.y - end.y) < EPS7;
|
|
4871
|
+
var getSegmentOrientation = (start, end) => Math.abs(start.y - end.y) < EPS7 ? "horizontal" : "vertical";
|
|
4820
4872
|
var projectPointToSegment = (point, start, end) => {
|
|
4821
|
-
if (Math.abs(start.x - end.x) <
|
|
4873
|
+
if (Math.abs(start.x - end.x) < EPS7) {
|
|
4822
4874
|
return {
|
|
4823
4875
|
x: start.x,
|
|
4824
4876
|
y: Math.min(
|
|
@@ -4827,7 +4879,7 @@ var projectPointToSegment = (point, start, end) => {
|
|
|
4827
4879
|
)
|
|
4828
4880
|
};
|
|
4829
4881
|
}
|
|
4830
|
-
if (Math.abs(start.y - end.y) <
|
|
4882
|
+
if (Math.abs(start.y - end.y) < EPS7) {
|
|
4831
4883
|
return {
|
|
4832
4884
|
x: Math.min(
|
|
4833
4885
|
Math.max(point.x, Math.min(start.x, end.x)),
|
|
@@ -4870,9 +4922,9 @@ var findSegmentContainingPoint = (path, point) => {
|
|
|
4870
4922
|
};
|
|
4871
4923
|
var isPointWithinSegmentPrimaryRange = (point, segment) => {
|
|
4872
4924
|
if (segment.orientation === "horizontal") {
|
|
4873
|
-
return point.x >= Math.min(segment.start.x, segment.end.x) -
|
|
4925
|
+
return point.x >= Math.min(segment.start.x, segment.end.x) - EPS7 && point.x <= Math.max(segment.start.x, segment.end.x) + EPS7;
|
|
4874
4926
|
}
|
|
4875
|
-
return point.y >= Math.min(segment.start.y, segment.end.y) -
|
|
4927
|
+
return point.y >= Math.min(segment.start.y, segment.end.y) - EPS7 && point.y <= Math.max(segment.start.y, segment.end.y) + EPS7;
|
|
4876
4928
|
};
|
|
4877
4929
|
var findPreferredReroutedSegment = (path, originalSegmentIndex, originalSegmentCount, orientation, anchorPoint) => {
|
|
4878
4930
|
const matchingSegments = getSegments(path).filter(
|
|
@@ -4900,18 +4952,18 @@ var projectPointToPath = (point, path) => {
|
|
|
4900
4952
|
return bestPoint;
|
|
4901
4953
|
};
|
|
4902
4954
|
var segmentsIntersect = (a1, a2, b1, b2) => {
|
|
4903
|
-
const aVertical = Math.abs(a1.x - a2.x) <
|
|
4904
|
-
const bVertical = Math.abs(b1.x - b2.x) <
|
|
4905
|
-
const between = (value, p1, p2) => value >= Math.min(p1, p2) -
|
|
4955
|
+
const aVertical = Math.abs(a1.x - a2.x) < EPS7;
|
|
4956
|
+
const bVertical = Math.abs(b1.x - b2.x) < EPS7;
|
|
4957
|
+
const between = (value, p1, p2) => value >= Math.min(p1, p2) - EPS7 && value <= Math.max(p1, p2) + EPS7;
|
|
4906
4958
|
if (aVertical && bVertical) {
|
|
4907
|
-
if (Math.abs(a1.x - b1.x) >
|
|
4959
|
+
if (Math.abs(a1.x - b1.x) > EPS7) return false;
|
|
4908
4960
|
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));
|
|
4909
|
-
return overlap >
|
|
4961
|
+
return overlap > EPS7;
|
|
4910
4962
|
}
|
|
4911
4963
|
if (!aVertical && !bVertical) {
|
|
4912
|
-
if (Math.abs(a1.y - b1.y) >
|
|
4964
|
+
if (Math.abs(a1.y - b1.y) > EPS7) return false;
|
|
4913
4965
|
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));
|
|
4914
|
-
return overlap >
|
|
4966
|
+
return overlap > EPS7;
|
|
4915
4967
|
}
|
|
4916
4968
|
const verticalA = aVertical ? a1 : b1;
|
|
4917
4969
|
const verticalB = aVertical ? a2 : b2;
|
|
@@ -4943,13 +4995,13 @@ var isPathCollidingWithChipInterior = (path, chipObstacles) => {
|
|
|
4943
4995
|
return false;
|
|
4944
4996
|
};
|
|
4945
4997
|
var segmentRunsAlongRectBoundary = (start, end, rect) => {
|
|
4946
|
-
const isVertical4 = Math.abs(start.x - end.x) <
|
|
4947
|
-
const isHorizontal3 = Math.abs(start.y - end.y) <
|
|
4998
|
+
const isVertical4 = Math.abs(start.x - end.x) < EPS7;
|
|
4999
|
+
const isHorizontal3 = Math.abs(start.y - end.y) < EPS7;
|
|
4948
5000
|
if (isVertical4) {
|
|
4949
|
-
return Math.abs(start.x - rect.minX) <
|
|
5001
|
+
return Math.abs(start.x - rect.minX) < EPS7 || Math.abs(start.x - rect.maxX) < EPS7;
|
|
4950
5002
|
}
|
|
4951
5003
|
if (isHorizontal3) {
|
|
4952
|
-
return Math.abs(start.y - rect.minY) <
|
|
5004
|
+
return Math.abs(start.y - rect.minY) < EPS7 || Math.abs(start.y - rect.maxY) < EPS7;
|
|
4953
5005
|
}
|
|
4954
5006
|
return false;
|
|
4955
5007
|
};
|
|
@@ -5573,16 +5625,16 @@ var Example28Solver = class extends BaseSolver {
|
|
|
5573
5625
|
// lib/solvers/AvailableNetOrientationSolver/constants.ts
|
|
5574
5626
|
var LABEL_SEARCH_STEP = 0.05;
|
|
5575
5627
|
var WICK_CLEARANCE = 1e-3;
|
|
5576
|
-
var
|
|
5577
|
-
var TRACE_BOUNDARY_TOLERANCE = WICK_CLEARANCE +
|
|
5628
|
+
var EPS8 = 1e-9;
|
|
5629
|
+
var TRACE_BOUNDARY_TOLERANCE = WICK_CLEARANCE + EPS8;
|
|
5578
5630
|
var CANDIDATE_SELECTED_COLOR2 = "blue";
|
|
5579
5631
|
var CANDIDATE_REJECTED_COLOR2 = "red";
|
|
5580
5632
|
|
|
5581
5633
|
// lib/solvers/AvailableNetOrientationSolver/geometry.ts
|
|
5582
5634
|
var isYOrientation = (orientation) => orientation === "y+" || orientation === "y-";
|
|
5583
5635
|
var isXOrientation = (orientation) => orientation === "x+" || orientation === "x-";
|
|
5584
|
-
var rectsOverlap = (a, b) => Math.min(a.maxX, b.maxX) - Math.max(a.minX, b.minX) >
|
|
5585
|
-
var rangesOverlap = (minA, maxA, minB, maxB) => Math.min(maxA, maxB) - Math.max(minA, minB) >
|
|
5636
|
+
var rectsOverlap = (a, b) => Math.min(a.maxX, b.maxX) - Math.max(a.minX, b.minX) > EPS8 && Math.min(a.maxY, b.maxY) - Math.max(a.minY, b.minY) > EPS8;
|
|
5637
|
+
var rangesOverlap = (minA, maxA, minB, maxB) => Math.min(maxA, maxB) - Math.max(minA, minB) > EPS8;
|
|
5586
5638
|
var traceCrossesBoundsInterior = (bounds, traceMap) => {
|
|
5587
5639
|
for (const trace of Object.values(traceMap)) {
|
|
5588
5640
|
const points = trace.tracePath;
|
|
@@ -5605,7 +5657,7 @@ var segmentCrossesBoundsInterior = (p1, p2, bounds) => {
|
|
|
5605
5657
|
return false;
|
|
5606
5658
|
}
|
|
5607
5659
|
if (sameX2(p1, p2)) {
|
|
5608
|
-
if (p1.x <= interiorBounds.minX +
|
|
5660
|
+
if (p1.x <= interiorBounds.minX + EPS8 || p1.x >= interiorBounds.maxX - EPS8) {
|
|
5609
5661
|
return false;
|
|
5610
5662
|
}
|
|
5611
5663
|
return rangesOverlap(
|
|
@@ -5616,7 +5668,7 @@ var segmentCrossesBoundsInterior = (p1, p2, bounds) => {
|
|
|
5616
5668
|
);
|
|
5617
5669
|
}
|
|
5618
5670
|
if (sameY2(p1, p2)) {
|
|
5619
|
-
if (p1.y <= interiorBounds.minY +
|
|
5671
|
+
if (p1.y <= interiorBounds.minY + EPS8 || p1.y >= interiorBounds.maxY - EPS8) {
|
|
5620
5672
|
return false;
|
|
5621
5673
|
}
|
|
5622
5674
|
return rangesOverlap(
|
|
@@ -5636,6 +5688,14 @@ var tracePathCrossesAnyBounds = (tracePath, bounds) => {
|
|
|
5636
5688
|
}
|
|
5637
5689
|
return false;
|
|
5638
5690
|
};
|
|
5691
|
+
var tracePathIntersectsBounds = (tracePath, bounds) => {
|
|
5692
|
+
for (let i = 0; i < tracePath.length - 1; i++) {
|
|
5693
|
+
if (segmentIntersectsRect2(tracePath[i], tracePath[i + 1], bounds)) {
|
|
5694
|
+
return true;
|
|
5695
|
+
}
|
|
5696
|
+
}
|
|
5697
|
+
return false;
|
|
5698
|
+
};
|
|
5639
5699
|
var tracePathCrossesAnyTrace = (tracePath, traceMap) => {
|
|
5640
5700
|
for (const trace of Object.values(traceMap)) {
|
|
5641
5701
|
const points = trace.tracePath;
|
|
@@ -5656,10 +5716,10 @@ var tracePathCrossesAnyTrace = (tracePath, traceMap) => {
|
|
|
5656
5716
|
};
|
|
5657
5717
|
var segmentsStrictlyCross = (a1, a2, b1, b2) => {
|
|
5658
5718
|
if (sameX2(a1, a2) && sameY2(b1, b2)) {
|
|
5659
|
-
return a1.x > Math.min(b1.x, b2.x) +
|
|
5719
|
+
return a1.x > Math.min(b1.x, b2.x) + EPS8 && a1.x < Math.max(b1.x, b2.x) - EPS8 && b1.y > Math.min(a1.y, a2.y) + EPS8 && b1.y < Math.max(a1.y, a2.y) - EPS8;
|
|
5660
5720
|
}
|
|
5661
5721
|
if (sameY2(a1, a2) && sameX2(b1, b2)) {
|
|
5662
|
-
return b1.x > Math.min(a1.x, a2.x) +
|
|
5722
|
+
return b1.x > Math.min(a1.x, a2.x) + EPS8 && b1.x < Math.max(a1.x, a2.x) - EPS8 && a1.y > Math.min(b1.y, b2.y) + EPS8 && a1.y < Math.max(b1.y, b2.y) - EPS8;
|
|
5663
5723
|
}
|
|
5664
5724
|
return false;
|
|
5665
5725
|
};
|
|
@@ -5691,8 +5751,8 @@ var simplifyOrthogonalPath = (path) => {
|
|
|
5691
5751
|
return simplified;
|
|
5692
5752
|
};
|
|
5693
5753
|
var pointsEqual = (a, b) => sameX2(a, b) && sameY2(a, b);
|
|
5694
|
-
var sameX2 = (a, b) => Math.abs(a.x - b.x) <=
|
|
5695
|
-
var sameY2 = (a, b) => Math.abs(a.y - b.y) <=
|
|
5754
|
+
var sameX2 = (a, b) => Math.abs(a.x - b.x) <= EPS8;
|
|
5755
|
+
var sameY2 = (a, b) => Math.abs(a.y - b.y) <= EPS8;
|
|
5696
5756
|
var getMaxSearchDistance = (inputProblem) => {
|
|
5697
5757
|
const maxChipWidth = Math.max(
|
|
5698
5758
|
...inputProblem.chips.map((chip) => chip.width),
|
|
@@ -5900,28 +5960,7 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
|
|
|
5900
5960
|
this.addConnectorTrace(label, candidate, labelIndex);
|
|
5901
5961
|
}
|
|
5902
5962
|
addConnectorTrace(label, candidate, labelIndex) {
|
|
5903
|
-
|
|
5904
|
-
if (candidate.phase === "lateral-shift") {
|
|
5905
|
-
const orientDir = dir(candidate.orientation);
|
|
5906
|
-
const kickedSource = {
|
|
5907
|
-
x: label.anchorPoint.x - orientDir.x * LABEL_SEARCH_STEP,
|
|
5908
|
-
y: label.anchorPoint.y - orientDir.y * LABEL_SEARCH_STEP
|
|
5909
|
-
};
|
|
5910
|
-
tracePath = simplifyOrthogonalPath([
|
|
5911
|
-
label.anchorPoint,
|
|
5912
|
-
...getConnectorTracePath(
|
|
5913
|
-
kickedSource,
|
|
5914
|
-
candidate.anchorPoint,
|
|
5915
|
-
candidate.orientation
|
|
5916
|
-
)
|
|
5917
|
-
]);
|
|
5918
|
-
} else {
|
|
5919
|
-
tracePath = getConnectorTracePath(
|
|
5920
|
-
label.anchorPoint,
|
|
5921
|
-
candidate.anchorPoint,
|
|
5922
|
-
candidate.orientation
|
|
5923
|
-
);
|
|
5924
|
-
}
|
|
5963
|
+
const tracePath = this.getCandidateConnectorTrace(label, candidate);
|
|
5925
5964
|
if (tracePath.length < 2) return;
|
|
5926
5965
|
const mspPairId = `available-net-orientation-${labelIndex}-${label.netId ?? label.globalConnNetId}`;
|
|
5927
5966
|
const connectorTrace = {
|
|
@@ -6001,7 +6040,7 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
|
|
|
6001
6040
|
);
|
|
6002
6041
|
const maxSearchDistance = this.getSearchDistanceLimit(label, orientation);
|
|
6003
6042
|
const maxOutwardDistance = outwardDirection.x === 0 && outwardDirection.y === 0 ? 0 : this.maxSearchDistance;
|
|
6004
|
-
for (let outwardDistance = 0; outwardDistance <= maxOutwardDistance +
|
|
6043
|
+
for (let outwardDistance = 0; outwardDistance <= maxOutwardDistance + EPS8; outwardDistance += LABEL_SEARCH_STEP) {
|
|
6005
6044
|
const baseAnchor = {
|
|
6006
6045
|
x: initialBaseAnchor.x + outwardDirection.x * outwardDistance,
|
|
6007
6046
|
y: initialBaseAnchor.y + outwardDirection.y * outwardDistance
|
|
@@ -6074,7 +6113,7 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
|
|
|
6074
6113
|
outwardDistance,
|
|
6075
6114
|
phase = "shift"
|
|
6076
6115
|
} = params;
|
|
6077
|
-
for (let distance3 = LABEL_SEARCH_STEP; distance3 <= maxSearchDistance +
|
|
6116
|
+
for (let distance3 = LABEL_SEARCH_STEP; distance3 <= maxSearchDistance + EPS8; distance3 += LABEL_SEARCH_STEP) {
|
|
6078
6117
|
const anchorPoint = {
|
|
6079
6118
|
x: baseAnchor.x + direction.x * distance3,
|
|
6080
6119
|
y: baseAnchor.y + direction.y * distance3
|
|
@@ -6104,9 +6143,36 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
|
|
|
6104
6143
|
distance: distance3,
|
|
6105
6144
|
outwardDistance,
|
|
6106
6145
|
selected: false,
|
|
6107
|
-
status: this.getCandidateStatus(
|
|
6146
|
+
status: this.getCandidateStatus({
|
|
6147
|
+
candidate,
|
|
6148
|
+
label,
|
|
6149
|
+
labelIndex,
|
|
6150
|
+
phase
|
|
6151
|
+
})
|
|
6108
6152
|
};
|
|
6109
6153
|
}
|
|
6154
|
+
getCandidateConnectorTrace(label, candidate) {
|
|
6155
|
+
if (candidate.phase === "lateral-shift") {
|
|
6156
|
+
const orientDir = dir(candidate.orientation);
|
|
6157
|
+
const kickedSource = {
|
|
6158
|
+
x: label.anchorPoint.x - orientDir.x * LABEL_SEARCH_STEP,
|
|
6159
|
+
y: label.anchorPoint.y - orientDir.y * LABEL_SEARCH_STEP
|
|
6160
|
+
};
|
|
6161
|
+
return simplifyOrthogonalPath([
|
|
6162
|
+
label.anchorPoint,
|
|
6163
|
+
...getConnectorTracePath(
|
|
6164
|
+
kickedSource,
|
|
6165
|
+
candidate.anchorPoint,
|
|
6166
|
+
candidate.orientation
|
|
6167
|
+
)
|
|
6168
|
+
]);
|
|
6169
|
+
}
|
|
6170
|
+
return getConnectorTracePath(
|
|
6171
|
+
label.anchorPoint,
|
|
6172
|
+
candidate.anchorPoint,
|
|
6173
|
+
candidate.orientation
|
|
6174
|
+
);
|
|
6175
|
+
}
|
|
6110
6176
|
getSearchStartAnchor(label, orientation) {
|
|
6111
6177
|
const anchorPoint = this.getWickOffsetAnchor(label.anchorPoint, orientation);
|
|
6112
6178
|
const { width, height } = getDimsForOrientation({
|
|
@@ -6226,17 +6292,18 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
|
|
|
6226
6292
|
(nc) => nc.pinIds.some((pid) => label.pinIds.includes(pid))
|
|
6227
6293
|
)?.netLabelHeight;
|
|
6228
6294
|
}
|
|
6229
|
-
getCandidateStatus(
|
|
6295
|
+
getCandidateStatus(params) {
|
|
6296
|
+
const { candidate, label, labelIndex, phase } = params;
|
|
6230
6297
|
const boundsStatus = this.getBoundsStatus(
|
|
6231
6298
|
getRectBounds(candidate.center, candidate.width, candidate.height),
|
|
6232
6299
|
labelIndex
|
|
6233
6300
|
);
|
|
6234
6301
|
if (boundsStatus !== "valid") return boundsStatus;
|
|
6235
|
-
const connectorTrace =
|
|
6236
|
-
|
|
6237
|
-
candidate.
|
|
6238
|
-
|
|
6239
|
-
);
|
|
6302
|
+
const connectorTrace = this.getCandidateConnectorTrace(label, {
|
|
6303
|
+
anchorPoint: candidate.anchorPoint,
|
|
6304
|
+
orientation: candidate.orientation,
|
|
6305
|
+
phase
|
|
6306
|
+
});
|
|
6240
6307
|
if (tracePathCrossesAnyTrace(connectorTrace, this.traceMap)) {
|
|
6241
6308
|
return "trace-collision";
|
|
6242
6309
|
}
|
|
@@ -6248,7 +6315,7 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
|
|
|
6248
6315
|
for (let i = 0; i < this.outputNetLabelPlacements.length; i++) {
|
|
6249
6316
|
if (i === labelIndex) continue;
|
|
6250
6317
|
const otherLabel = this.outputNetLabelPlacements[i];
|
|
6251
|
-
if (
|
|
6318
|
+
if (tracePathIntersectsBounds(
|
|
6252
6319
|
connectorTrace,
|
|
6253
6320
|
getRectBounds(otherLabel.center, otherLabel.width, otherLabel.height)
|
|
6254
6321
|
)) {
|
|
@@ -6284,8 +6351,8 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
|
|
|
6284
6351
|
sharesChipBoundary(bounds) {
|
|
6285
6352
|
for (const chip of this.chipObstacleSpatialIndex.chips) {
|
|
6286
6353
|
const chipBounds = chip.bounds;
|
|
6287
|
-
const adjacentToVerticalSide = Math.abs(bounds.minX - chipBounds.maxX) <= WICK_CLEARANCE +
|
|
6288
|
-
const adjacentToHorizontalSide = Math.abs(bounds.minY - chipBounds.maxY) <= WICK_CLEARANCE +
|
|
6354
|
+
const adjacentToVerticalSide = Math.abs(bounds.minX - chipBounds.maxX) <= WICK_CLEARANCE + EPS8 || Math.abs(bounds.maxX - chipBounds.minX) <= WICK_CLEARANCE + EPS8;
|
|
6355
|
+
const adjacentToHorizontalSide = Math.abs(bounds.minY - chipBounds.maxY) <= WICK_CLEARANCE + EPS8 || Math.abs(bounds.maxY - chipBounds.minY) <= WICK_CLEARANCE + EPS8;
|
|
6289
6356
|
if (adjacentToVerticalSide && rangesOverlap(
|
|
6290
6357
|
bounds.minY,
|
|
6291
6358
|
bounds.maxY,
|
|
@@ -6333,7 +6400,7 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
|
|
|
6333
6400
|
let nearestDistance = Number.POSITIVE_INFINITY;
|
|
6334
6401
|
for (const chip of this.chipObstacleSpatialIndex.chips) {
|
|
6335
6402
|
const bounds = chip.bounds;
|
|
6336
|
-
if (point.x < bounds.minX -
|
|
6403
|
+
if (point.x < bounds.minX - EPS8 || point.x > bounds.maxX + EPS8 || point.y < bounds.minY - EPS8 || point.y > bounds.maxY + EPS8) {
|
|
6337
6404
|
continue;
|
|
6338
6405
|
}
|
|
6339
6406
|
for (const [side, distance3] of getSideDistances(point, bounds)) {
|
|
@@ -6350,8 +6417,8 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
|
|
|
6350
6417
|
let nearestDistanceSq = Number.POSITIVE_INFINITY;
|
|
6351
6418
|
for (const chip of this.chipObstacleSpatialIndex.chips) {
|
|
6352
6419
|
const bounds = chip.bounds;
|
|
6353
|
-
const dx = point.x < bounds.minX -
|
|
6354
|
-
const dy = point.y < bounds.minY -
|
|
6420
|
+
const dx = point.x < bounds.minX - EPS8 ? bounds.minX - point.x : point.x > bounds.maxX + EPS8 ? point.x - bounds.maxX : 0;
|
|
6421
|
+
const dy = point.y < bounds.minY - EPS8 ? bounds.minY - point.y : point.y > bounds.maxY + EPS8 ? point.y - bounds.maxY : 0;
|
|
6355
6422
|
if (dx === 0 && dy === 0) continue;
|
|
6356
6423
|
const distanceSq = dx ** 2 + dy ** 2;
|
|
6357
6424
|
if (distanceSq >= nearestDistanceSq) continue;
|
|
@@ -6390,9 +6457,9 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
|
|
|
6390
6457
|
};
|
|
6391
6458
|
|
|
6392
6459
|
// lib/solvers/VccNetLabelCornerPlacementSolver/geometry.ts
|
|
6393
|
-
var
|
|
6460
|
+
var EPS9 = 1e-6;
|
|
6394
6461
|
var isTraceLine = (trace) => getUniquePinCount(trace.pinIds) >= 2;
|
|
6395
|
-
var rectsOverlap2 = (a, b) => Math.min(a.maxX, b.maxX) - Math.max(a.minX, b.minX) >
|
|
6462
|
+
var rectsOverlap2 = (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;
|
|
6396
6463
|
var getTraceCorners = (path) => {
|
|
6397
6464
|
const corners = [];
|
|
6398
6465
|
for (let i = 1; i < path.length - 1; i++) {
|
|
@@ -6416,11 +6483,11 @@ var getUniquePinCount = (pinIds) => new Set(pinIds).size;
|
|
|
6416
6483
|
var isTraceCorner = (a, b, c) => getSegmentOrientation2(a, b) !== getSegmentOrientation2(b, c);
|
|
6417
6484
|
var isPointOnSegment = (point, start, end) => {
|
|
6418
6485
|
if (getSegmentOrientation2(start, end) === "horizontal") {
|
|
6419
|
-
return Math.abs(point.y - start.y) <=
|
|
6486
|
+
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;
|
|
6420
6487
|
}
|
|
6421
|
-
return Math.abs(point.x - start.x) <=
|
|
6488
|
+
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;
|
|
6422
6489
|
};
|
|
6423
|
-
var getSegmentOrientation2 = (a, b) => Math.abs(a.y - b.y) <=
|
|
6490
|
+
var getSegmentOrientation2 = (a, b) => Math.abs(a.y - b.y) <= EPS9 ? "horizontal" : "vertical";
|
|
6424
6491
|
|
|
6425
6492
|
// lib/solvers/VccNetLabelCornerPlacementSolver/visualize.ts
|
|
6426
6493
|
var CANDIDATE_SELECTED_COLOR3 = "blue";
|
|
@@ -6698,11 +6765,11 @@ var VccNetLabelCornerPlacementSolver = class extends BaseSolver {
|
|
|
6698
6765
|
};
|
|
6699
6766
|
|
|
6700
6767
|
// lib/solvers/TraceAnchoredNetLabelOverlapSolver/geometry.ts
|
|
6701
|
-
var
|
|
6768
|
+
var EPS10 = 1e-6;
|
|
6702
6769
|
var TRACE_BOUNDARY_TOLERANCE2 = 1e-6;
|
|
6703
6770
|
var getLabelBounds = (label) => getRectBounds(label.center, label.width, label.height);
|
|
6704
|
-
var rectsOverlap3 = (a, b) => Math.min(a.maxX, b.maxX) - Math.max(a.minX, b.minX) >
|
|
6705
|
-
var rectsTouchOrOverlap = (a, b) => Math.min(a.maxX, b.maxX) - Math.max(a.minX, b.minX) >= -
|
|
6771
|
+
var rectsOverlap3 = (a, b) => Math.min(a.maxX, b.maxX) - Math.max(a.minX, b.minX) > EPS10 && Math.min(a.maxY, b.maxY) - Math.max(a.minY, b.minY) > EPS10;
|
|
6772
|
+
var rectsTouchOrOverlap = (a, b) => Math.min(a.maxX, b.maxX) - Math.max(a.minX, b.minX) >= -EPS10 && Math.min(a.maxY, b.maxY) - Math.max(a.minY, b.minY) >= -EPS10;
|
|
6706
6773
|
var traceCrossesBoundsInterior2 = (bounds, traces) => {
|
|
6707
6774
|
for (const trace of traces) {
|
|
6708
6775
|
const points = trace.tracePath;
|
|
@@ -6748,7 +6815,7 @@ var getPointAtTraceDistance = (trace, distance3) => {
|
|
|
6748
6815
|
const end = trace.tracePath[i + 1];
|
|
6749
6816
|
const segmentLength = getManhattanDistance(start, end);
|
|
6750
6817
|
const nextDistance = pathDistance + segmentLength;
|
|
6751
|
-
if (distance3 <= nextDistance +
|
|
6818
|
+
if (distance3 <= nextDistance + EPS10) {
|
|
6752
6819
|
const offset = Math.max(
|
|
6753
6820
|
0,
|
|
6754
6821
|
Math.min(segmentLength, distance3 - pathDistance)
|
|
@@ -6787,7 +6854,7 @@ var segmentCrossesBoundsInterior2 = (start, end, bounds) => {
|
|
|
6787
6854
|
return false;
|
|
6788
6855
|
}
|
|
6789
6856
|
if (isVertical3(start, end)) {
|
|
6790
|
-
if (start.x <= interior.minX +
|
|
6857
|
+
if (start.x <= interior.minX + EPS10 || start.x >= interior.maxX - EPS10) {
|
|
6791
6858
|
return false;
|
|
6792
6859
|
}
|
|
6793
6860
|
return rangesOverlap2(
|
|
@@ -6798,7 +6865,7 @@ var segmentCrossesBoundsInterior2 = (start, end, bounds) => {
|
|
|
6798
6865
|
);
|
|
6799
6866
|
}
|
|
6800
6867
|
if (isHorizontal2(start, end)) {
|
|
6801
|
-
if (start.y <= interior.minY +
|
|
6868
|
+
if (start.y <= interior.minY + EPS10 || start.y >= interior.maxY - EPS10) {
|
|
6802
6869
|
return false;
|
|
6803
6870
|
}
|
|
6804
6871
|
return rangesOverlap2(
|
|
@@ -6812,10 +6879,10 @@ var segmentCrossesBoundsInterior2 = (start, end, bounds) => {
|
|
|
6812
6879
|
};
|
|
6813
6880
|
var isPointOnSegment2 = (point, start, end) => {
|
|
6814
6881
|
if (isHorizontal2(start, end)) {
|
|
6815
|
-
return Math.abs(point.y - start.y) <=
|
|
6882
|
+
return Math.abs(point.y - start.y) <= EPS10 && point.x >= Math.min(start.x, end.x) - EPS10 && point.x <= Math.max(start.x, end.x) + EPS10;
|
|
6816
6883
|
}
|
|
6817
6884
|
if (isVertical3(start, end)) {
|
|
6818
|
-
return Math.abs(point.x - start.x) <=
|
|
6885
|
+
return Math.abs(point.x - start.x) <= EPS10 && point.y >= Math.min(start.y, end.y) - EPS10 && point.y <= Math.max(start.y, end.y) + EPS10;
|
|
6819
6886
|
}
|
|
6820
6887
|
return false;
|
|
6821
6888
|
};
|
|
@@ -6823,9 +6890,9 @@ var getSegmentDirection = (start, end) => ({
|
|
|
6823
6890
|
x: isVertical3(start, end) ? 0 : Math.sign(end.x - start.x),
|
|
6824
6891
|
y: isHorizontal2(start, end) ? 0 : Math.sign(end.y - start.y)
|
|
6825
6892
|
});
|
|
6826
|
-
var isHorizontal2 = (start, end) => Math.abs(start.y - end.y) <=
|
|
6827
|
-
var isVertical3 = (start, end) => Math.abs(start.x - end.x) <=
|
|
6828
|
-
var rangesOverlap2 = (minA, maxA, minB, maxB) => Math.min(maxA, maxB) - Math.max(minA, minB) >
|
|
6893
|
+
var isHorizontal2 = (start, end) => Math.abs(start.y - end.y) <= EPS10;
|
|
6894
|
+
var isVertical3 = (start, end) => Math.abs(start.x - end.x) <= EPS10;
|
|
6895
|
+
var rangesOverlap2 = (minA, maxA, minB, maxB) => Math.min(maxA, maxB) - Math.max(minA, minB) > EPS10;
|
|
6829
6896
|
var getUniquePinCount2 = (pinIds) => new Set(pinIds).size;
|
|
6830
6897
|
|
|
6831
6898
|
// lib/solvers/TraceAnchoredNetLabelOverlapSolver/candidates.ts
|
|
@@ -6882,7 +6949,7 @@ var getCandidateDistances = (traceLength, vertexDistances) => {
|
|
|
6882
6949
|
for (const distance3 of vertexDistances) {
|
|
6883
6950
|
distances.add(roundDistance(distance3));
|
|
6884
6951
|
}
|
|
6885
|
-
return [...distances].filter((distance3) => distance3 >= -
|
|
6952
|
+
return [...distances].filter((distance3) => distance3 >= -EPS10 && distance3 <= traceLength + EPS10).sort((a, b) => a - b);
|
|
6886
6953
|
};
|
|
6887
6954
|
var getOrientationsForPoint = (params) => {
|
|
6888
6955
|
const { inputProblem, label, point, orientationConstraint } = params;
|
|
@@ -6991,13 +7058,13 @@ var getOutwardOrientationOptions = (point, chipBounds) => {
|
|
|
6991
7058
|
};
|
|
6992
7059
|
var getOutwardAxisOption = (params) => {
|
|
6993
7060
|
const { value, min, max, center, positiveOrientation, negativeOrientation } = params;
|
|
6994
|
-
if (value > max +
|
|
7061
|
+
if (value > max + EPS10) {
|
|
6995
7062
|
return {
|
|
6996
7063
|
orientation: positiveOrientation,
|
|
6997
7064
|
outwardScore: 1 + value - max
|
|
6998
7065
|
};
|
|
6999
7066
|
}
|
|
7000
|
-
if (value < min -
|
|
7067
|
+
if (value < min - EPS10) {
|
|
7001
7068
|
return {
|
|
7002
7069
|
orientation: negativeOrientation,
|
|
7003
7070
|
outwardScore: 1 + min - value
|
|
@@ -7008,7 +7075,7 @@ var getOutwardAxisOption = (params) => {
|
|
|
7008
7075
|
outwardScore: getNormalizedCenterDistance(value, center, max - min)
|
|
7009
7076
|
};
|
|
7010
7077
|
};
|
|
7011
|
-
var getNormalizedCenterDistance = (value, center, span) => Math.abs(value - center) / Math.max(
|
|
7078
|
+
var getNormalizedCenterDistance = (value, center, span) => Math.abs(value - center) / Math.max(EPS10, span / 2);
|
|
7012
7079
|
var ALL_ORIENTATIONS = ["x+", "x-", "y+", "y-"];
|
|
7013
7080
|
var getFlippedOrientation = (orientation) => {
|
|
7014
7081
|
switch (orientation) {
|
|
@@ -7103,7 +7170,7 @@ var normalizeFacingDirection = (value) => {
|
|
|
7103
7170
|
var dedupeStrings = (values) => [
|
|
7104
7171
|
...new Set(values.filter((value) => value !== void 0))
|
|
7105
7172
|
];
|
|
7106
|
-
var isSamePlacement = (label, point, orientation) => Math.abs(point.x - label.anchorPoint.x) <=
|
|
7173
|
+
var isSamePlacement = (label, point, orientation) => Math.abs(point.x - label.anchorPoint.x) <= EPS10 && Math.abs(point.y - label.anchorPoint.y) <= EPS10 && orientation === label.orientation;
|
|
7107
7174
|
|
|
7108
7175
|
// lib/solvers/TraceAnchoredNetLabelOverlapSolver/visualize.ts
|
|
7109
7176
|
var CANDIDATE_SELECTED_COLOR4 = "blue";
|
|
@@ -7491,16 +7558,14 @@ function buildMergedObstacleLabel(seedLabel, allLabels) {
|
|
|
7491
7558
|
height: h
|
|
7492
7559
|
};
|
|
7493
7560
|
}
|
|
7494
|
-
function
|
|
7561
|
+
function detectTraceLabelOverlaps(traces, labels) {
|
|
7495
7562
|
const overlaps = [];
|
|
7496
7563
|
for (const trace of traces) {
|
|
7497
7564
|
for (const label of labels) {
|
|
7498
7565
|
if (trace.globalConnNetId === label.globalConnNetId) continue;
|
|
7499
7566
|
const bounds = getRectBounds(label.center, label.width, label.height);
|
|
7500
7567
|
const path = trace.tracePath;
|
|
7501
|
-
|
|
7502
|
-
const innerEnd = path.length - 2;
|
|
7503
|
-
for (let i = innerStart; i < innerEnd; i++) {
|
|
7568
|
+
for (let i = 0; i < path.length - 1; i++) {
|
|
7504
7569
|
if (segmentIntersectsRect2(path[i], path[i + 1], bounds)) {
|
|
7505
7570
|
overlaps.push({ trace, label });
|
|
7506
7571
|
break;
|
|
@@ -7566,7 +7631,7 @@ var NetLabelTraceCollisionSolver = class extends BaseSolver {
|
|
|
7566
7631
|
}
|
|
7567
7632
|
return;
|
|
7568
7633
|
}
|
|
7569
|
-
const overlaps =
|
|
7634
|
+
const overlaps = detectTraceLabelOverlaps(
|
|
7570
7635
|
this.outputTraces,
|
|
7571
7636
|
this.outputNetLabelPlacements
|
|
7572
7637
|
);
|