@tscircuit/schematic-trace-solver 0.0.56 → 0.0.60

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.js CHANGED
@@ -271,19 +271,19 @@ var doesPairCrossRestrictedCenterLines = (params) => {
271
271
  chipMap
272
272
  });
273
273
  if (restrictedCenterLines.size === 0) return false;
274
- const EPS9 = 1e-9;
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) < -EPS9) return true;
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) < -EPS9) return true;
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) < EPS9 || Math.abs(p1.y - p2.y) < EPS9) {
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 EPS9 = 1e-9;
854
- const samePoint = (p, q) => Math.abs(p.x - q.x) < EPS9 && Math.abs(p.y - q.y) < EPS9;
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: EPS9 = 1e-6
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) < EPS9;
1059
- const isHorizontal3 = Math.abs(start.y - end.y) < EPS9;
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 EPS9 = 1e-6;
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) < EPS9;
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: EPS9
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) < EPS9;
1164
- const isHorizontal3 = Math.abs(start.y - end.y) < EPS9;
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 EPS9 = 2e-3;
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 > EPS9;
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) < EPS9;
1288
- const aHorz = Math.abs(a1.y - a2.y) < EPS9;
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) < EPS9;
1297
- const bHorz = Math.abs(b1.y - b2.y) < EPS9;
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) < EPS9) {
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) < EPS9) {
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 EPS9 = 2e-3;
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) < EPS9;
1366
- const isVertical4 = Math.abs(p1.x - p2.x) < EPS9;
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 EPS9 = 2e-3;
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) < EPS9 : false;
1384
- const prevIsHorizontal = p0 ? Math.abs(p0.y - p1.y) < EPS9 : false;
1385
- const nextIsVertical = p3 ? Math.abs(p2.x - p3.x) < EPS9 : false;
1386
- const nextIsHorizontal = p3 ? Math.abs(p2.y - p3.y) < EPS9 : false;
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, EPS9 = 1e-9) {
1551
- const isVert = Math.abs(p1.x - p2.x) < EPS9;
1552
- const isHorz = Math.abs(p1.y - p2.y) < EPS9;
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 - EPS9 || x > rect.maxX + EPS9) return false;
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 > EPS9;
1560
+ return overlap > EPS10;
1561
1561
  } else {
1562
1562
  const y = p1.y;
1563
- if (y < rect.minY - EPS9 || y > rect.maxY + EPS9) return false;
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 > EPS9;
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 EPS9 = 1e-6;
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) < EPS9;
1952
- const isV = Math.abs(a.x - b.x) < EPS9;
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.currentGroup.netId ? this.inputProblem.netConnections.find(
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.currentGroup.netId ? this.inputProblem.netConnections.find(
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.y === p1.y && p1.x === p2.x && p2.y === p3.y && p0.x === p3.x;
4628
- const isVHVC = p0.x === p1.x && p1.y === p2.y && p2.x === p3.x && p0.y === p3.y;
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 EPS5 = 1e-9;
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) < EPS5 || Math.abs(start.y - end.y) < EPS5;
4770
- var getSegmentOrientation = (start, end) => Math.abs(start.y - end.y) < EPS5 ? "horizontal" : "vertical";
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) < EPS5) {
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) < EPS5) {
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) - EPS5 && point.x <= Math.max(segment.start.x, segment.end.x) + EPS5;
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) - EPS5 && point.y <= Math.max(segment.start.y, segment.end.y) + EPS5;
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) < EPS5;
4855
- const bVertical = Math.abs(b1.x - b2.x) < EPS5;
4856
- const between = (value, p1, p2) => value >= Math.min(p1, p2) - EPS5 && value <= Math.max(p1, p2) + EPS5;
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) > EPS5) return false;
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 > EPS5;
4882
+ return overlap > EPS6;
4861
4883
  }
4862
4884
  if (!aVertical && !bVertical) {
4863
- if (Math.abs(a1.y - b1.y) > EPS5) return false;
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 > EPS5;
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) < EPS5;
4898
- const isHorizontal3 = Math.abs(start.y - end.y) < EPS5;
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) < EPS5 || Math.abs(start.x - rect.maxX) < EPS5;
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) < EPS5 || Math.abs(start.y - rect.maxY) < EPS5;
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 EPS6 = 1e-9;
5436
- var TRACE_BOUNDARY_TOLERANCE = WICK_CLEARANCE + EPS6;
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) > EPS6 && Math.min(a.maxY, b.maxY) - Math.max(a.minY, b.minY) > EPS6;
5444
- var rangesOverlap = (minA, maxA, minB, maxB) => Math.min(maxA, maxB) - Math.max(minA, minB) > EPS6;
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 (sameX(p1, p2)) {
5467
- if (p1.x <= interiorBounds.minX + EPS6 || p1.x >= interiorBounds.maxX - EPS6) {
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 (sameY(p1, p2)) {
5478
- if (p1.y <= interiorBounds.minY + EPS6 || p1.y >= interiorBounds.maxY - EPS6) {
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(
@@ -5487,6 +5601,14 @@ var segmentCrossesBoundsInterior = (p1, p2, bounds) => {
5487
5601
  }
5488
5602
  return false;
5489
5603
  };
5604
+ var tracePathCrossesAnyBounds = (tracePath, bounds) => {
5605
+ for (let i = 0; i < tracePath.length - 1; i++) {
5606
+ if (segmentCrossesBoundsInterior(tracePath[i], tracePath[i + 1], bounds)) {
5607
+ return true;
5608
+ }
5609
+ }
5610
+ return false;
5611
+ };
5490
5612
  var tracePathCrossesAnyTrace = (tracePath, traceMap) => {
5491
5613
  for (const trace of Object.values(traceMap)) {
5492
5614
  const points = trace.tracePath;
@@ -5506,11 +5628,11 @@ var tracePathCrossesAnyTrace = (tracePath, traceMap) => {
5506
5628
  return false;
5507
5629
  };
5508
5630
  var segmentsStrictlyCross = (a1, a2, b1, b2) => {
5509
- if (sameX(a1, a2) && sameY(b1, b2)) {
5510
- return a1.x > Math.min(b1.x, b2.x) + EPS6 && a1.x < Math.max(b1.x, b2.x) - EPS6 && b1.y > Math.min(a1.y, a2.y) + EPS6 && b1.y < Math.max(a1.y, a2.y) - EPS6;
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;
5511
5633
  }
5512
- if (sameY(a1, a2) && sameX(b1, b2)) {
5513
- return b1.x > Math.min(a1.x, a2.x) + EPS6 && b1.x < Math.max(a1.x, a2.x) - EPS6 && a1.y > Math.min(b1.y, b2.y) + EPS6 && a1.y < Math.max(b1.y, b2.y) - EPS6;
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;
5514
5636
  }
5515
5637
  return false;
5516
5638
  };
@@ -5533,7 +5655,7 @@ var simplifyOrthogonalPath = (path) => {
5533
5655
  const prev = simplified[simplified.length - 1];
5534
5656
  const point = deduped[i];
5535
5657
  const next = deduped[i + 1];
5536
- if (sameX(prev, point) && sameX(point, next) || sameY(prev, point) && sameY(point, next)) {
5658
+ if (sameX2(prev, point) && sameX2(point, next) || sameY2(prev, point) && sameY2(point, next)) {
5537
5659
  continue;
5538
5660
  }
5539
5661
  simplified.push(point);
@@ -5541,9 +5663,9 @@ var simplifyOrthogonalPath = (path) => {
5541
5663
  simplified.push(deduped[deduped.length - 1]);
5542
5664
  return simplified;
5543
5665
  };
5544
- var pointsEqual = (a, b) => sameX(a, b) && sameY(a, b);
5545
- var sameX = (a, b) => Math.abs(a.x - b.x) <= EPS6;
5546
- var sameY = (a, b) => Math.abs(a.y - b.y) <= EPS6;
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;
5547
5669
  var getMaxSearchDistance = (inputProblem) => {
5548
5670
  const maxChipWidth = Math.max(
5549
5671
  ...inputProblem.chips.map((chip) => chip.width),
@@ -5824,7 +5946,7 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
5824
5946
  );
5825
5947
  const maxSearchDistance = this.getSearchDistanceLimit(label, orientation);
5826
5948
  const maxOutwardDistance = outwardDirection.x === 0 && outwardDirection.y === 0 ? 0 : this.maxSearchDistance;
5827
- for (let outwardDistance = 0; outwardDistance <= maxOutwardDistance + EPS6; outwardDistance += LABEL_SEARCH_STEP) {
5949
+ for (let outwardDistance = 0; outwardDistance <= maxOutwardDistance + EPS7; outwardDistance += LABEL_SEARCH_STEP) {
5828
5950
  const baseAnchor = {
5829
5951
  x: initialBaseAnchor.x + outwardDirection.x * outwardDistance,
5830
5952
  y: initialBaseAnchor.y + outwardDirection.y * outwardDistance
@@ -5852,7 +5974,7 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
5852
5974
  maxSearchDistance,
5853
5975
  outwardDistance
5854
5976
  } = params;
5855
- for (let distance3 = LABEL_SEARCH_STEP; distance3 <= maxSearchDistance + EPS6; distance3 += LABEL_SEARCH_STEP) {
5977
+ for (let distance3 = LABEL_SEARCH_STEP; distance3 <= maxSearchDistance + EPS7; distance3 += LABEL_SEARCH_STEP) {
5856
5978
  const anchorPoint = {
5857
5979
  x: baseAnchor.x + direction.x * distance3,
5858
5980
  y: baseAnchor.y + direction.y * distance3
@@ -5957,9 +6079,22 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
5957
6079
  };
5958
6080
  }
5959
6081
  getNetLabelWidth(label) {
5960
- if (!label.netId) return void 0;
6082
+ if (label.netId) {
6083
+ const ncWidth = this.inputProblem.netConnections.find(
6084
+ (connection) => connection.netId === label.netId
6085
+ )?.netLabelWidth;
6086
+ if (ncWidth !== void 0) return ncWidth;
6087
+ const dcWidthByNetId = this.inputProblem.directConnections.find(
6088
+ (dc) => dc.netId === label.netId
6089
+ )?.netLabelWidth;
6090
+ if (dcWidthByNetId !== void 0) return dcWidthByNetId;
6091
+ }
6092
+ const dcWidthByPinId = this.inputProblem.directConnections.find(
6093
+ (dc) => dc.pinIds.some((pid) => label.pinIds.includes(pid))
6094
+ )?.netLabelWidth;
6095
+ if (dcWidthByPinId !== void 0) return dcWidthByPinId;
5961
6096
  return this.inputProblem.netConnections.find(
5962
- (connection) => connection.netId === label.netId
6097
+ (nc) => nc.pinIds.some((pid) => label.pinIds.includes(pid))
5963
6098
  )?.netLabelWidth;
5964
6099
  }
5965
6100
  getCandidateStatus(candidate, label, labelIndex) {
@@ -5968,16 +6103,24 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
5968
6103
  labelIndex
5969
6104
  );
5970
6105
  if (boundsStatus !== "valid") return boundsStatus;
5971
- if (tracePathCrossesAnyTrace(
5972
- getConnectorTracePath(
5973
- label.anchorPoint,
5974
- candidate.anchorPoint,
5975
- candidate.orientation
5976
- ),
5977
- this.traceMap
5978
- )) {
6106
+ const connectorTrace = getConnectorTracePath(
6107
+ label.anchorPoint,
6108
+ candidate.anchorPoint,
6109
+ candidate.orientation
6110
+ );
6111
+ if (tracePathCrossesAnyTrace(connectorTrace, this.traceMap)) {
5979
6112
  return "trace-collision";
5980
6113
  }
6114
+ for (let i = 0; i < this.outputNetLabelPlacements.length; i++) {
6115
+ if (i === labelIndex) continue;
6116
+ const otherLabel = this.outputNetLabelPlacements[i];
6117
+ if (tracePathCrossesAnyBounds(
6118
+ connectorTrace,
6119
+ getRectBounds(otherLabel.center, otherLabel.width, otherLabel.height)
6120
+ )) {
6121
+ return "netlabel-collision";
6122
+ }
6123
+ }
5981
6124
  return "valid";
5982
6125
  }
5983
6126
  getBoundsStatus(bounds, labelIndex) {
@@ -6007,8 +6150,8 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
6007
6150
  sharesChipBoundary(bounds) {
6008
6151
  for (const chip of this.chipObstacleSpatialIndex.chips) {
6009
6152
  const chipBounds = chip.bounds;
6010
- const adjacentToVerticalSide = Math.abs(bounds.minX - chipBounds.maxX) <= WICK_CLEARANCE + EPS6 || Math.abs(bounds.maxX - chipBounds.minX) <= WICK_CLEARANCE + EPS6;
6011
- const adjacentToHorizontalSide = Math.abs(bounds.minY - chipBounds.maxY) <= WICK_CLEARANCE + EPS6 || Math.abs(bounds.maxY - chipBounds.minY) <= WICK_CLEARANCE + EPS6;
6153
+ const adjacentToVerticalSide = Math.abs(bounds.minX - chipBounds.maxX) <= WICK_CLEARANCE + EPS7 || Math.abs(bounds.maxX - chipBounds.minX) <= WICK_CLEARANCE + EPS7;
6154
+ const adjacentToHorizontalSide = Math.abs(bounds.minY - chipBounds.maxY) <= WICK_CLEARANCE + EPS7 || Math.abs(bounds.maxY - chipBounds.minY) <= WICK_CLEARANCE + EPS7;
6012
6155
  if (adjacentToVerticalSide && rangesOverlap(
6013
6156
  bounds.minY,
6014
6157
  bounds.maxY,
@@ -6056,7 +6199,7 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
6056
6199
  let nearestDistance = Number.POSITIVE_INFINITY;
6057
6200
  for (const chip of this.chipObstacleSpatialIndex.chips) {
6058
6201
  const bounds = chip.bounds;
6059
- if (point.x < bounds.minX - EPS6 || point.x > bounds.maxX + EPS6 || point.y < bounds.minY - EPS6 || point.y > bounds.maxY + EPS6) {
6202
+ if (point.x < bounds.minX - EPS7 || point.x > bounds.maxX + EPS7 || point.y < bounds.minY - EPS7 || point.y > bounds.maxY + EPS7) {
6060
6203
  continue;
6061
6204
  }
6062
6205
  for (const [side, distance3] of getSideDistances(point, bounds)) {
@@ -6073,8 +6216,8 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
6073
6216
  let nearestDistanceSq = Number.POSITIVE_INFINITY;
6074
6217
  for (const chip of this.chipObstacleSpatialIndex.chips) {
6075
6218
  const bounds = chip.bounds;
6076
- const dx = point.x < bounds.minX - EPS6 ? bounds.minX - point.x : point.x > bounds.maxX + EPS6 ? point.x - bounds.maxX : 0;
6077
- const dy = point.y < bounds.minY - EPS6 ? bounds.minY - point.y : point.y > bounds.maxY + EPS6 ? point.y - bounds.maxY : 0;
6219
+ const dx = point.x < bounds.minX - EPS7 ? bounds.minX - point.x : point.x > bounds.maxX + EPS7 ? point.x - bounds.maxX : 0;
6220
+ const dy = point.y < bounds.minY - EPS7 ? bounds.minY - point.y : point.y > bounds.maxY + EPS7 ? point.y - bounds.maxY : 0;
6078
6221
  if (dx === 0 && dy === 0) continue;
6079
6222
  const distanceSq = dx ** 2 + dy ** 2;
6080
6223
  if (distanceSq >= nearestDistanceSq) continue;
@@ -6113,9 +6256,9 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
6113
6256
  };
6114
6257
 
6115
6258
  // lib/solvers/VccNetLabelCornerPlacementSolver/geometry.ts
6116
- var EPS7 = 1e-6;
6259
+ var EPS8 = 1e-6;
6117
6260
  var isTraceLine = (trace) => getUniquePinCount(trace.pinIds) >= 2;
6118
- var rectsOverlap2 = (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;
6261
+ 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;
6119
6262
  var getTraceCorners = (path) => {
6120
6263
  const corners = [];
6121
6264
  for (let i = 1; i < path.length - 1; i++) {
@@ -6139,11 +6282,11 @@ var getUniquePinCount = (pinIds) => new Set(pinIds).size;
6139
6282
  var isTraceCorner = (a, b, c) => getSegmentOrientation2(a, b) !== getSegmentOrientation2(b, c);
6140
6283
  var isPointOnSegment = (point, start, end) => {
6141
6284
  if (getSegmentOrientation2(start, end) === "horizontal") {
6142
- return Math.abs(point.y - start.y) <= EPS7 && point.x >= Math.min(start.x, end.x) - EPS7 && point.x <= Math.max(start.x, end.x) + EPS7;
6285
+ 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;
6143
6286
  }
6144
- return Math.abs(point.x - start.x) <= EPS7 && point.y >= Math.min(start.y, end.y) - EPS7 && point.y <= Math.max(start.y, end.y) + EPS7;
6287
+ 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;
6145
6288
  };
6146
- var getSegmentOrientation2 = (a, b) => Math.abs(a.y - b.y) <= EPS7 ? "horizontal" : "vertical";
6289
+ var getSegmentOrientation2 = (a, b) => Math.abs(a.y - b.y) <= EPS8 ? "horizontal" : "vertical";
6147
6290
 
6148
6291
  // lib/solvers/VccNetLabelCornerPlacementSolver/visualize.ts
6149
6292
  var CANDIDATE_SELECTED_COLOR3 = "blue";
@@ -6421,11 +6564,11 @@ var VccNetLabelCornerPlacementSolver = class extends BaseSolver {
6421
6564
  };
6422
6565
 
6423
6566
  // lib/solvers/TraceAnchoredNetLabelOverlapSolver/geometry.ts
6424
- var EPS8 = 1e-6;
6567
+ var EPS9 = 1e-6;
6425
6568
  var TRACE_BOUNDARY_TOLERANCE2 = 1e-6;
6426
6569
  var getLabelBounds = (label) => getRectBounds(label.center, label.width, label.height);
6427
- var rectsOverlap3 = (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;
6428
- var rectsTouchOrOverlap = (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;
6570
+ 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;
6571
+ 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;
6429
6572
  var traceCrossesBoundsInterior2 = (bounds, traces) => {
6430
6573
  for (const trace of traces) {
6431
6574
  const points = trace.tracePath;
@@ -6471,7 +6614,7 @@ var getPointAtTraceDistance = (trace, distance3) => {
6471
6614
  const end = trace.tracePath[i + 1];
6472
6615
  const segmentLength = getManhattanDistance(start, end);
6473
6616
  const nextDistance = pathDistance + segmentLength;
6474
- if (distance3 <= nextDistance + EPS8) {
6617
+ if (distance3 <= nextDistance + EPS9) {
6475
6618
  const offset = Math.max(
6476
6619
  0,
6477
6620
  Math.min(segmentLength, distance3 - pathDistance)
@@ -6510,7 +6653,7 @@ var segmentCrossesBoundsInterior2 = (start, end, bounds) => {
6510
6653
  return false;
6511
6654
  }
6512
6655
  if (isVertical3(start, end)) {
6513
- if (start.x <= interior.minX + EPS8 || start.x >= interior.maxX - EPS8) {
6656
+ if (start.x <= interior.minX + EPS9 || start.x >= interior.maxX - EPS9) {
6514
6657
  return false;
6515
6658
  }
6516
6659
  return rangesOverlap2(
@@ -6521,7 +6664,7 @@ var segmentCrossesBoundsInterior2 = (start, end, bounds) => {
6521
6664
  );
6522
6665
  }
6523
6666
  if (isHorizontal2(start, end)) {
6524
- if (start.y <= interior.minY + EPS8 || start.y >= interior.maxY - EPS8) {
6667
+ if (start.y <= interior.minY + EPS9 || start.y >= interior.maxY - EPS9) {
6525
6668
  return false;
6526
6669
  }
6527
6670
  return rangesOverlap2(
@@ -6535,10 +6678,10 @@ var segmentCrossesBoundsInterior2 = (start, end, bounds) => {
6535
6678
  };
6536
6679
  var isPointOnSegment2 = (point, start, end) => {
6537
6680
  if (isHorizontal2(start, end)) {
6538
- 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;
6681
+ 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;
6539
6682
  }
6540
6683
  if (isVertical3(start, end)) {
6541
- 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;
6684
+ 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;
6542
6685
  }
6543
6686
  return false;
6544
6687
  };
@@ -6546,9 +6689,9 @@ var getSegmentDirection = (start, end) => ({
6546
6689
  x: isVertical3(start, end) ? 0 : Math.sign(end.x - start.x),
6547
6690
  y: isHorizontal2(start, end) ? 0 : Math.sign(end.y - start.y)
6548
6691
  });
6549
- var isHorizontal2 = (start, end) => Math.abs(start.y - end.y) <= EPS8;
6550
- var isVertical3 = (start, end) => Math.abs(start.x - end.x) <= EPS8;
6551
- var rangesOverlap2 = (minA, maxA, minB, maxB) => Math.min(maxA, maxB) - Math.max(minA, minB) > EPS8;
6692
+ var isHorizontal2 = (start, end) => Math.abs(start.y - end.y) <= EPS9;
6693
+ var isVertical3 = (start, end) => Math.abs(start.x - end.x) <= EPS9;
6694
+ var rangesOverlap2 = (minA, maxA, minB, maxB) => Math.min(maxA, maxB) - Math.max(minA, minB) > EPS9;
6552
6695
  var getUniquePinCount2 = (pinIds) => new Set(pinIds).size;
6553
6696
 
6554
6697
  // lib/solvers/TraceAnchoredNetLabelOverlapSolver/candidates.ts
@@ -6603,7 +6746,7 @@ var getCandidateDistances = (traceLength, vertexDistances) => {
6603
6746
  for (const distance3 of vertexDistances) {
6604
6747
  distances.add(roundDistance(distance3));
6605
6748
  }
6606
- return [...distances].filter((distance3) => distance3 >= -EPS8 && distance3 <= traceLength + EPS8).sort((a, b) => a - b);
6749
+ return [...distances].filter((distance3) => distance3 >= -EPS9 && distance3 <= traceLength + EPS9).sort((a, b) => a - b);
6607
6750
  };
6608
6751
  var getOrientationsForPoint = (params) => {
6609
6752
  const { inputProblem, label, point, orientationConstraint } = params;
@@ -6710,13 +6853,13 @@ var getOutwardOrientationOptions = (point, chipBounds) => {
6710
6853
  };
6711
6854
  var getOutwardAxisOption = (params) => {
6712
6855
  const { value, min, max, center, positiveOrientation, negativeOrientation } = params;
6713
- if (value > max + EPS8) {
6856
+ if (value > max + EPS9) {
6714
6857
  return {
6715
6858
  orientation: positiveOrientation,
6716
6859
  outwardScore: 1 + value - max
6717
6860
  };
6718
6861
  }
6719
- if (value < min - EPS8) {
6862
+ if (value < min - EPS9) {
6720
6863
  return {
6721
6864
  orientation: negativeOrientation,
6722
6865
  outwardScore: 1 + min - value
@@ -6727,7 +6870,7 @@ var getOutwardAxisOption = (params) => {
6727
6870
  outwardScore: getNormalizedCenterDistance(value, center, max - min)
6728
6871
  };
6729
6872
  };
6730
- var getNormalizedCenterDistance = (value, center, span) => Math.abs(value - center) / Math.max(EPS8, span / 2);
6873
+ var getNormalizedCenterDistance = (value, center, span) => Math.abs(value - center) / Math.max(EPS9, span / 2);
6731
6874
  var ALL_ORIENTATIONS = ["x+", "x-", "y+", "y-"];
6732
6875
  var getFlippedOrientation = (orientation) => {
6733
6876
  switch (orientation) {
@@ -6773,11 +6916,22 @@ var getChipBounds = (inputProblem) => {
6773
6916
  };
6774
6917
  };
6775
6918
  var getNetLabelWidth = (inputProblem, label) => {
6776
- const configuredWidth = inputProblem.netConnections.find(
6919
+ const ncWidthByNetId = inputProblem.netConnections.find(
6777
6920
  (connection) => connection.netId === label.netId
6778
6921
  )?.netLabelWidth;
6779
- if (configuredWidth !== void 0) return configuredWidth;
6780
- return label.orientation === "y+" || label.orientation === "y-" ? label.height : label.width;
6922
+ if (ncWidthByNetId !== void 0) return ncWidthByNetId;
6923
+ const dcWidth = inputProblem.directConnections.find(
6924
+ (dc) => dc.pinIds.some((pid) => label.pinIds.includes(pid))
6925
+ )?.netLabelWidth;
6926
+ if (dcWidth !== void 0) return dcWidth;
6927
+ const ncWidthByPinId = inputProblem.netConnections.find(
6928
+ (nc) => nc.pinIds.some((pid) => label.pinIds.includes(pid))
6929
+ )?.netLabelWidth;
6930
+ if (ncWidthByPinId !== void 0) return ncWidthByPinId;
6931
+ if (label.orientation === "y+" || label.orientation === "y-") {
6932
+ return label.height;
6933
+ }
6934
+ return label.width;
6781
6935
  };
6782
6936
  var roundDistance = (distance3) => Number(distance3.toFixed(6));
6783
6937
  var dedupeOrientations = (orientations) => [
@@ -6802,7 +6956,7 @@ var normalizeFacingDirection = (value) => {
6802
6956
  var dedupeStrings = (values) => [
6803
6957
  ...new Set(values.filter((value) => value !== void 0))
6804
6958
  ];
6805
- var isSamePlacement = (label, point, orientation) => Math.abs(point.x - label.anchorPoint.x) <= EPS8 && Math.abs(point.y - label.anchorPoint.y) <= EPS8 && orientation === label.orientation;
6959
+ var isSamePlacement = (label, point, orientation) => Math.abs(point.x - label.anchorPoint.x) <= EPS9 && Math.abs(point.y - label.anchorPoint.y) <= EPS9 && orientation === label.orientation;
6806
6960
 
6807
6961
  // lib/solvers/TraceAnchoredNetLabelOverlapSolver/visualize.ts
6808
6962
  var CANDIDATE_SELECTED_COLOR4 = "blue";