@tscircuit/schematic-trace-solver 0.0.177 → 0.0.178

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
@@ -325,19 +325,19 @@ var doesPairCrossRestrictedCenterLines = (params) => {
325
325
  chipMap
326
326
  });
327
327
  if (restrictedCenterLines.size === 0) return false;
328
- const EPS16 = 1e-9;
328
+ const EPS17 = 1e-9;
329
329
  const crossesSegment = (a, b) => {
330
330
  for (const [, rcl] of restrictedCenterLines) {
331
331
  if (rcl.axes.has("x") && typeof rcl.x === "number") {
332
- if ((a.x - rcl.x) * (b.x - rcl.x) < -EPS16) return true;
332
+ if ((a.x - rcl.x) * (b.x - rcl.x) < -EPS17) return true;
333
333
  }
334
334
  if (rcl.axes.has("y") && typeof rcl.y === "number") {
335
- if ((a.y - rcl.y) * (b.y - rcl.y) < -EPS16) return true;
335
+ if ((a.y - rcl.y) * (b.y - rcl.y) < -EPS17) return true;
336
336
  }
337
337
  }
338
338
  return false;
339
339
  };
340
- if (Math.abs(p1.x - p2.x) < EPS16 || Math.abs(p1.y - p2.y) < EPS16) {
340
+ if (Math.abs(p1.x - p2.x) < EPS17 || Math.abs(p1.y - p2.y) < EPS17) {
341
341
  return crossesSegment({ x: p1.x, y: p1.y }, { x: p2.x, y: p2.y });
342
342
  }
343
343
  const elbowHV = { x: p2.x, y: p1.y };
@@ -1581,8 +1581,8 @@ var SchematicTraceSingleLineSolver2 = class extends BaseSolver {
1581
1581
  if (!collision) {
1582
1582
  const first = path[0];
1583
1583
  const last = path[path.length - 1];
1584
- const EPS16 = 1e-9;
1585
- const samePoint = (p, q) => Math.abs(p.x - q.x) < EPS16 && Math.abs(p.y - q.y) < EPS16;
1584
+ const EPS17 = 1e-9;
1585
+ const samePoint = (p, q) => Math.abs(p.x - q.x) < EPS17 && Math.abs(p.y - q.y) < EPS17;
1586
1586
  if (samePoint(first, { x: PA.x, y: PA.y }) && samePoint(last, { x: PB.x, y: PB.y })) {
1587
1587
  this.solvedTracePath = path;
1588
1588
  this.solved = true;
@@ -1893,13 +1893,13 @@ var applyJogToTerminalSegment = ({
1893
1893
  segmentIndex: si,
1894
1894
  offset,
1895
1895
  JOG_SIZE,
1896
- EPS: EPS16 = 1e-6
1896
+ EPS: EPS17 = 1e-6
1897
1897
  }) => {
1898
1898
  if (si !== 0 && si !== pts.length - 2) return;
1899
1899
  const start = pts[si];
1900
1900
  const end = pts[si + 1];
1901
- const isVertical6 = Math.abs(start.x - end.x) < EPS16;
1902
- const isHorizontal5 = Math.abs(start.y - end.y) < EPS16;
1901
+ const isVertical6 = Math.abs(start.x - end.x) < EPS17;
1902
+ const isHorizontal5 = Math.abs(start.y - end.y) < EPS17;
1903
1903
  if (!isVertical6 && !isHorizontal5) return;
1904
1904
  const segDir = isVertical6 ? end.y > start.y ? 1 : -1 : end.x > start.x ? 1 : -1;
1905
1905
  if (pts.length === 2) {
@@ -2333,7 +2333,7 @@ var TraceOverlapShiftSolver = class extends BaseSolver {
2333
2333
  return islands;
2334
2334
  }
2335
2335
  findNextOverlapIssue() {
2336
- const EPS16 = 2e-3;
2336
+ const EPS17 = 2e-3;
2337
2337
  const netIds = Object.keys(this.traceNetIslands);
2338
2338
  for (let i = 0; i < netIds.length; i++) {
2339
2339
  for (let j = i + 1; j < netIds.length; j++) {
@@ -2360,7 +2360,7 @@ var TraceOverlapShiftSolver = class extends BaseSolver {
2360
2360
  segmentBIndex,
2361
2361
  rangeOverlap
2362
2362
  }) => {
2363
- if (rangeOverlap > EPS16) {
2363
+ if (rangeOverlap > EPS17) {
2364
2364
  const keyA = `${pathAIndex}:${segmentAIndex}`;
2365
2365
  const keyB = `${pathBIndex}:${segmentBIndex}`;
2366
2366
  if (!seenA.has(keyA)) {
@@ -2379,7 +2379,7 @@ var TraceOverlapShiftSolver = class extends BaseSolver {
2379
2379
  }
2380
2380
  return;
2381
2381
  }
2382
- if (rangeOverlap < -EPS16) return;
2382
+ if (rangeOverlap < -EPS17) return;
2383
2383
  const pathA = pathsA[pathAIndex].tracePath;
2384
2384
  const pathB = pathsB[pathBIndex].tracePath;
2385
2385
  const segmentAStart = pathA[segmentAIndex];
@@ -2402,8 +2402,8 @@ var TraceOverlapShiftSolver = class extends BaseSolver {
2402
2402
  for (let sa = 0; sa < ptsA.length - 1; sa++) {
2403
2403
  const a1 = ptsA[sa];
2404
2404
  const a2 = ptsA[sa + 1];
2405
- const aVert = Math.abs(a1.x - a2.x) < EPS16;
2406
- const aHorz = Math.abs(a1.y - a2.y) < EPS16;
2405
+ const aVert = Math.abs(a1.x - a2.x) < EPS17;
2406
+ const aHorz = Math.abs(a1.y - a2.y) < EPS17;
2407
2407
  if (!aVert && !aHorz) continue;
2408
2408
  for (let pb = 0; pb < pathsB.length; pb++) {
2409
2409
  const pathB = pathsB[pb];
@@ -2414,11 +2414,11 @@ var TraceOverlapShiftSolver = class extends BaseSolver {
2414
2414
  for (let sb = 0; sb < ptsB.length - 1; sb++) {
2415
2415
  const b1 = ptsB[sb];
2416
2416
  const b2 = ptsB[sb + 1];
2417
- const bVert = Math.abs(b1.x - b2.x) < EPS16;
2418
- const bHorz = Math.abs(b1.y - b2.y) < EPS16;
2417
+ const bVert = Math.abs(b1.x - b2.x) < EPS17;
2418
+ const bHorz = Math.abs(b1.y - b2.y) < EPS17;
2419
2419
  if (!bVert && !bHorz) continue;
2420
2420
  if (aVert && bVert) {
2421
- if (Math.abs(a1.x - b1.x) < EPS16) {
2421
+ if (Math.abs(a1.x - b1.x) < EPS17) {
2422
2422
  recordCollinearInteraction({
2423
2423
  pathAIndex: pa,
2424
2424
  segmentAIndex: sa,
@@ -2428,7 +2428,7 @@ var TraceOverlapShiftSolver = class extends BaseSolver {
2428
2428
  });
2429
2429
  }
2430
2430
  } else if (aHorz && bHorz) {
2431
- if (Math.abs(a1.y - b1.y) < EPS16) {
2431
+ if (Math.abs(a1.y - b1.y) < EPS17) {
2432
2432
  recordCollinearInteraction({
2433
2433
  pathAIndex: pa,
2434
2434
  segmentAIndex: sa,
@@ -2484,14 +2484,14 @@ var TraceOverlapShiftSolver = class extends BaseSolver {
2484
2484
  return null;
2485
2485
  }
2486
2486
  findNextDiagonalSegment() {
2487
- const EPS16 = 2e-3;
2487
+ const EPS17 = 2e-3;
2488
2488
  for (const mspPairId in this.correctedTraceMap) {
2489
2489
  const tracePath = this.correctedTraceMap[mspPairId].tracePath;
2490
2490
  for (let i = 0; i < tracePath.length - 1; i++) {
2491
2491
  const p1 = tracePath[i];
2492
2492
  const p2 = tracePath[i + 1];
2493
- const isHorizontal5 = Math.abs(p1.y - p2.y) < EPS16;
2494
- const isVertical6 = Math.abs(p1.x - p2.x) < EPS16;
2493
+ const isHorizontal5 = Math.abs(p1.y - p2.y) < EPS17;
2494
+ const isVertical6 = Math.abs(p1.x - p2.x) < EPS17;
2495
2495
  if (!isHorizontal5 && !isVertical6) {
2496
2496
  return { mspPairId, tracePath, i, p1, p2 };
2497
2497
  }
@@ -2505,13 +2505,13 @@ var TraceOverlapShiftSolver = class extends BaseSolver {
2505
2505
  return false;
2506
2506
  }
2507
2507
  const { mspPairId, tracePath, i, p1, p2 } = diagonalInfo;
2508
- const EPS16 = 2e-3;
2508
+ const EPS17 = 2e-3;
2509
2509
  const p0 = i > 0 ? tracePath[i - 1] : null;
2510
2510
  const p3 = i + 2 < tracePath.length ? tracePath[i + 2] : null;
2511
- const prevIsVertical = p0 ? Math.abs(p0.x - p1.x) < EPS16 : false;
2512
- const prevIsHorizontal = p0 ? Math.abs(p0.y - p1.y) < EPS16 : false;
2513
- const nextIsVertical = p3 ? Math.abs(p2.x - p3.x) < EPS16 : false;
2514
- const nextIsHorizontal = p3 ? Math.abs(p2.y - p3.y) < EPS16 : false;
2511
+ const prevIsVertical = p0 ? Math.abs(p0.x - p1.x) < EPS17 : false;
2512
+ const prevIsHorizontal = p0 ? Math.abs(p0.y - p1.y) < EPS17 : false;
2513
+ const nextIsVertical = p3 ? Math.abs(p2.x - p3.x) < EPS17 : false;
2514
+ const nextIsHorizontal = p3 ? Math.abs(p2.y - p3.y) < EPS17 : false;
2515
2515
  const elbow1 = { x: p1.x, y: p2.y };
2516
2516
  const elbow2 = { x: p2.x, y: p1.y };
2517
2517
  let score1 = 0;
@@ -2673,24 +2673,24 @@ var ChipObstacleSpatialIndex = class {
2673
2673
  };
2674
2674
 
2675
2675
  // lib/solvers/NetLabelPlacementSolver/SingleNetLabelPlacementSolver/collisions.ts
2676
- function segmentIntersectsRect2(p1, p2, rect, EPS16 = 1e-9) {
2677
- const isVert = Math.abs(p1.x - p2.x) < EPS16;
2678
- const isHorz = Math.abs(p1.y - p2.y) < EPS16;
2676
+ function segmentIntersectsRect2(p1, p2, rect, EPS17 = 1e-9) {
2677
+ const isVert = Math.abs(p1.x - p2.x) < EPS17;
2678
+ const isHorz = Math.abs(p1.y - p2.y) < EPS17;
2679
2679
  if (!isVert && !isHorz) return false;
2680
2680
  if (isVert) {
2681
2681
  const x = p1.x;
2682
- if (x < rect.minX - EPS16 || x > rect.maxX + EPS16) return false;
2682
+ if (x < rect.minX - EPS17 || x > rect.maxX + EPS17) return false;
2683
2683
  const segMinY = Math.min(p1.y, p2.y);
2684
2684
  const segMaxY = Math.max(p1.y, p2.y);
2685
2685
  const overlap = Math.min(segMaxY, rect.maxY) - Math.max(segMinY, rect.minY);
2686
- return overlap > EPS16;
2686
+ return overlap > EPS17;
2687
2687
  } else {
2688
2688
  const y = p1.y;
2689
- if (y < rect.minY - EPS16 || y > rect.maxY + EPS16) return false;
2689
+ if (y < rect.minY - EPS17 || y > rect.maxY + EPS17) return false;
2690
2690
  const segMinX = Math.min(p1.x, p2.x);
2691
2691
  const segMaxX = Math.max(p1.x, p2.x);
2692
2692
  const overlap = Math.min(segMaxX, rect.maxX) - Math.max(segMinX, rect.minX);
2693
- return overlap > EPS16;
2693
+ return overlap > EPS17;
2694
2694
  }
2695
2695
  }
2696
2696
  function rectIntersectsAnyTrace(bounds, inputTraceMap, hostPathId, hostSegIndex) {
@@ -3089,14 +3089,14 @@ var SingleNetLabelPlacementSolver = class extends BaseSolver {
3089
3089
  };
3090
3090
  let bestCandidate = null;
3091
3091
  let bestScore = -Infinity;
3092
- const EPS16 = 1e-6;
3092
+ const EPS17 = 1e-6;
3093
3093
  for (const curr of tracesToScan) {
3094
3094
  const pts = curr.tracePath.slice();
3095
3095
  for (let si = 0; si < pts.length - 1; si++) {
3096
3096
  const a = pts[si];
3097
3097
  const b = pts[si + 1];
3098
- const isH = Math.abs(a.y - b.y) < EPS16;
3099
- const isV = Math.abs(a.x - b.x) < EPS16;
3098
+ const isH = Math.abs(a.y - b.y) < EPS17;
3099
+ const isV = Math.abs(a.x - b.x) < EPS17;
3100
3100
  if (!isH && !isV) continue;
3101
3101
  const segmentAllowed = isH ? ["y+", "y-"] : ["x+", "x-"];
3102
3102
  const candidateOrients = orientations.filter(
@@ -6619,13 +6619,17 @@ var findIntersectionsWithObstacles = (p1, p2, obstacles) => {
6619
6619
  return intersections;
6620
6620
  };
6621
6621
  var isSamePoint = (first, second) => Math.abs(first.x - second.x) < EPS9 && Math.abs(first.y - second.y) < EPS9;
6622
- var findPerpendicularPathCrossings = (path, otherPath) => {
6622
+ var findPerpendicularPathCrossings = (path, otherPath, options = {}) => {
6623
6623
  const crossings = [];
6624
- for (let pathSegmentIndex = 1; pathSegmentIndex < path.length - 2; pathSegmentIndex++) {
6624
+ const firstPathSegmentIndex = options.includeTerminalSegments ? 0 : 1;
6625
+ const lastPathSegmentIndex = options.includeTerminalSegments ? path.length - 1 : path.length - 2;
6626
+ const firstOtherPathSegmentIndex = options.includeTerminalSegments ? 0 : 1;
6627
+ const lastOtherPathSegmentIndex = options.includeTerminalSegments ? otherPath.length - 1 : otherPath.length - 2;
6628
+ for (let pathSegmentIndex = firstPathSegmentIndex; pathSegmentIndex < lastPathSegmentIndex; pathSegmentIndex++) {
6625
6629
  const start = path[pathSegmentIndex];
6626
6630
  const end = path[pathSegmentIndex + 1];
6627
6631
  const isVertical6 = Math.abs(start.x - end.x) < EPS9;
6628
- for (let otherPathSegmentIndex = 1; otherPathSegmentIndex < otherPath.length - 2; otherPathSegmentIndex++) {
6632
+ for (let otherPathSegmentIndex = firstOtherPathSegmentIndex; otherPathSegmentIndex < lastOtherPathSegmentIndex; otherPathSegmentIndex++) {
6629
6633
  const otherStart = otherPath[otherPathSegmentIndex];
6630
6634
  const otherEnd = otherPath[otherPathSegmentIndex + 1];
6631
6635
  const otherIsVertical = Math.abs(otherStart.x - otherEnd.x) < EPS9;
@@ -6765,6 +6769,7 @@ var generatePerpendicularTraceDetours = ({
6765
6769
  segmentIndex,
6766
6770
  obstacleStart,
6767
6771
  obstacleEnd,
6772
+ obstacleBounds,
6768
6773
  chipBounds,
6769
6774
  clearance
6770
6775
  }) => {
@@ -6773,18 +6778,34 @@ var generatePerpendicularTraceDetours = ({
6773
6778
  const end = path[index + 1];
6774
6779
  const movingAxis = Math.abs(start.x - end.x) < EPS10 ? "y" : "x";
6775
6780
  const detourAxis = movingAxis === "x" ? "y" : "x";
6776
- const gate = obstacleStart[movingAxis] + Math.sign(start[movingAxis] - obstacleStart[movingAxis]) * clearance;
6777
- const obstacleRange = [obstacleStart[detourAxis], obstacleEnd[detourAxis]];
6781
+ const bounds = obstacleBounds ?? {
6782
+ minX: Math.min(obstacleStart.x, obstacleEnd.x),
6783
+ minY: Math.min(obstacleStart.y, obstacleEnd.y),
6784
+ maxX: Math.max(obstacleStart.x, obstacleEnd.x),
6785
+ maxY: Math.max(obstacleStart.y, obstacleEnd.y)
6786
+ };
6787
+ const movingLowBound = movingAxis === "x" ? "minX" : "minY";
6788
+ const movingHighBound = movingAxis === "x" ? "maxX" : "maxY";
6789
+ let gate = obstacleStart[movingAxis] + Math.sign(start[movingAxis] - obstacleStart[movingAxis]) * clearance;
6790
+ if (obstacleBounds) {
6791
+ const startSide = start[movingAxis] < (bounds[movingLowBound] + bounds[movingHighBound]) / 2 ? -1 : 1;
6792
+ gate = bounds[startSide < 0 ? movingLowBound : movingHighBound] + startSide * clearance;
6793
+ }
6778
6794
  const lowBound = detourAxis === "x" ? "minX" : "minY";
6779
6795
  const highBound = detourAxis === "x" ? "maxX" : "maxY";
6796
+ const minDetour = bounds[lowBound] - clearance;
6797
+ const maxDetour = bounds[highBound] + clearance;
6798
+ const nextAnchor = obstacleBounds ? path[index + 2] : void 0;
6799
+ const balancedDetour = nextAnchor ? nextAnchor[detourAxis] < minDetour ? (nextAnchor[detourAxis] + minDetour) / 2 : nextAnchor[detourAxis] > maxDetour ? (nextAnchor[detourAxis] + maxDetour) / 2 : void 0 : void 0;
6780
6800
  const detourCoordinates = [
6781
- Math.min(...obstacleRange) - clearance,
6782
- Math.max(...obstacleRange) + clearance,
6783
- ...chipBounds.flatMap((bounds) => [
6784
- bounds[lowBound] - clearance,
6785
- bounds[highBound] + clearance
6801
+ balancedDetour,
6802
+ minDetour,
6803
+ maxDetour,
6804
+ ...chipBounds.flatMap((bounds2) => [
6805
+ bounds2[lowBound] - clearance,
6806
+ bounds2[highBound] + clearance
6786
6807
  ])
6787
- ];
6808
+ ].filter((coordinate) => coordinate !== void 0);
6788
6809
  return [...new Set(detourCoordinates)].map(
6789
6810
  (detour) => simplifyPath([
6790
6811
  ...path.slice(0, index + 1),
@@ -7391,6 +7412,126 @@ var is4PointRectangle = (path) => {
7391
7412
  return isHVHC || isVHVC;
7392
7413
  };
7393
7414
 
7415
+ // lib/solvers/TraceCleanupSolver/rerouteGeneratedNetLabelConnectorCrossings.ts
7416
+ var EPS12 = 1e-6;
7417
+ var getConnectorObstacleBounds = (connector, segmentIndex, labels) => {
7418
+ const start = connector.tracePath[segmentIndex];
7419
+ const end = connector.tracePath[segmentIndex + 1];
7420
+ const bounds = {
7421
+ minX: Math.min(start.x, end.x),
7422
+ minY: Math.min(start.y, end.y),
7423
+ maxX: Math.max(start.x, end.x),
7424
+ maxY: Math.max(start.y, end.y)
7425
+ };
7426
+ for (const label of labels) {
7427
+ if (label.globalConnNetId !== connector.globalConnNetId) continue;
7428
+ if (!label.pinIds.every((pinId) => connector.pinIds.includes(pinId)))
7429
+ continue;
7430
+ if (!tracePathContainsPoint(connector.tracePath, label.anchorPoint))
7431
+ continue;
7432
+ const labelBounds = getRectBounds(label.center, label.width, label.height);
7433
+ bounds.minX = Math.min(bounds.minX, labelBounds.minX);
7434
+ bounds.minY = Math.min(bounds.minY, labelBounds.minY);
7435
+ bounds.maxX = Math.max(bounds.maxX, labelBounds.maxX);
7436
+ bounds.maxY = Math.max(bounds.maxY, labelBounds.maxY);
7437
+ }
7438
+ return bounds;
7439
+ };
7440
+ var getEligibleConnectorCrossings = (traces, connectorTraceIds, eligibleTraceIds) => {
7441
+ const crossings = [];
7442
+ for (const connector of traces) {
7443
+ if (!connectorTraceIds.has(connector.mspPairId)) continue;
7444
+ for (let traceIndex = 0; traceIndex < traces.length; traceIndex++) {
7445
+ const trace = traces[traceIndex];
7446
+ if (trace.mspPairId === connector.mspPairId) continue;
7447
+ if (connectorTraceIds.has(trace.mspPairId)) continue;
7448
+ if (trace.globalConnNetId === connector.globalConnNetId) continue;
7449
+ if (eligibleTraceIds && !eligibleTraceIds.has(trace.mspPairId)) continue;
7450
+ for (const crossing of findPerpendicularPathCrossings(
7451
+ trace.tracePath,
7452
+ connector.tracePath,
7453
+ { includeTerminalSegments: true }
7454
+ )) {
7455
+ crossings.push({
7456
+ traceIndex,
7457
+ connector,
7458
+ connectorSegmentIndex: crossing.otherPathSegmentIndex,
7459
+ traceSegmentIndex: crossing.pathSegmentIndex
7460
+ });
7461
+ }
7462
+ }
7463
+ }
7464
+ return crossings;
7465
+ };
7466
+ var rerouteGeneratedNetLabelConnectorCrossings = ({
7467
+ inputProblem,
7468
+ traces,
7469
+ netLabelPlacements,
7470
+ mergedLabelNetIdMap,
7471
+ clearance,
7472
+ eligibleTraceIds,
7473
+ connectorTraceIds
7474
+ }) => {
7475
+ const outputTraces = [...traces];
7476
+ const componentAndTextObstacles = getObstacleRects(inputProblem).filter(
7477
+ (obstacle) => obstacle.kind === "chip" || obstacle.kind === "text_box"
7478
+ );
7479
+ let reroutedTraceCount = 0;
7480
+ while (true) {
7481
+ const candidates = getEligibleConnectorCrossings(
7482
+ outputTraces,
7483
+ connectorTraceIds,
7484
+ eligibleTraceIds
7485
+ ).flatMap((crossing) => {
7486
+ const trace = outputTraces[crossing.traceIndex];
7487
+ const obstacleBounds = getConnectorObstacleBounds(
7488
+ crossing.connector,
7489
+ crossing.connectorSegmentIndex,
7490
+ netLabelPlacements
7491
+ );
7492
+ const foreignTraces = outputTraces.filter(
7493
+ (otherTrace) => otherTrace.mspPairId !== trace.mspPairId && otherTrace.globalConnNetId !== trace.globalConnNetId
7494
+ );
7495
+ const foreignLabelBounds = netLabelPlacements.filter((label) => {
7496
+ const mergedNetIds = mergedLabelNetIdMap[label.globalConnNetId];
7497
+ return mergedNetIds ? !mergedNetIds.has(trace.globalConnNetId) : label.globalConnNetId !== trace.globalConnNetId;
7498
+ }).map((label) => getRectBounds(label.center, label.width, label.height));
7499
+ return generatePerpendicularTraceDetours({
7500
+ trace,
7501
+ segmentIndex: crossing.traceSegmentIndex,
7502
+ obstacleStart: crossing.connector.tracePath[crossing.connectorSegmentIndex],
7503
+ obstacleEnd: crossing.connector.tracePath[crossing.connectorSegmentIndex + 1],
7504
+ obstacleBounds,
7505
+ chipBounds: [],
7506
+ clearance
7507
+ }).filter(
7508
+ (candidate) => getPathLength2(candidate.path) <= getPathLength2(trace.tracePath) + EPS12 && countTurns(candidate.path) <= countTurns(trace.tracePath) + 2 && !isPathCollidingWithObstacles(
7509
+ candidate.path,
7510
+ componentAndTextObstacles
7511
+ ) && !hasCollisionsWithLabels(candidate.path, foreignLabelBounds) && !isPathColliding(candidate.path, foreignTraces, trace.mspPairId).isColliding && !doesPathCoincideWithTraces(candidate.path, foreignTraces)
7512
+ ).map((candidate) => ({
7513
+ ...candidate,
7514
+ traceIndex: crossing.traceIndex
7515
+ }));
7516
+ });
7517
+ candidates.sort((first, second) => {
7518
+ const lengthDifference = getPathLength2(first.path) - getPathLength2(second.path);
7519
+ return Math.abs(lengthDifference) > EPS12 ? lengthDifference : countTurns(first.path) - countTurns(second.path);
7520
+ });
7521
+ const bestCandidate = candidates[0];
7522
+ if (!bestCandidate) break;
7523
+ outputTraces[bestCandidate.traceIndex] = {
7524
+ ...outputTraces[bestCandidate.traceIndex],
7525
+ tracePath: bestCandidate.path
7526
+ };
7527
+ reroutedTraceCount++;
7528
+ }
7529
+ return {
7530
+ traces: outputTraces,
7531
+ reroutedTraceCount
7532
+ };
7533
+ };
7534
+
7394
7535
  // lib/solvers/TraceCleanupSolver/TraceCleanupSolver.ts
7395
7536
  var DEFAULT_OPERATIONS = [
7396
7537
  "untangling_traces",
@@ -7442,6 +7583,9 @@ var TraceCleanupSolver = class extends BaseSolver {
7442
7583
  case "untangling_traces":
7443
7584
  this._runUntangleTracesStep();
7444
7585
  break;
7586
+ case "rerouting_generated_net_label_connector_crossings":
7587
+ this._runGeneratedNetLabelConnectorCrossingRerouteStep();
7588
+ break;
7445
7589
  case "minimizing_turns":
7446
7590
  this._runMinimizeTurnsStep();
7447
7591
  break;
@@ -7465,6 +7609,23 @@ var TraceCleanupSolver = class extends BaseSolver {
7465
7609
  allTraces: Array.from(this.tracesMap.values())
7466
7610
  });
7467
7611
  }
7612
+ _runGeneratedNetLabelConnectorCrossingRerouteStep() {
7613
+ const result = rerouteGeneratedNetLabelConnectorCrossings({
7614
+ inputProblem: this.input.inputProblem,
7615
+ traces: this.outputTraces,
7616
+ netLabelPlacements: this.input.allLabelPlacements,
7617
+ mergedLabelNetIdMap: this.input.mergedLabelNetIdMap,
7618
+ clearance: this.input.paddingBuffer,
7619
+ eligibleTraceIds: this.input.eligibleTraceIds,
7620
+ connectorTraceIds: this.input.netLabelConnectorTraceIds ?? /* @__PURE__ */ new Set()
7621
+ });
7622
+ this.outputTraces = result.traces;
7623
+ this.tracesMap = new Map(
7624
+ this.outputTraces.map((trace) => [trace.mspPairId, trace])
7625
+ );
7626
+ this.stats.reroutedGeneratedConnectorCrossingTraceCount = result.reroutedTraceCount;
7627
+ this._advancePipeline();
7628
+ }
7468
7629
  _runMinimizeTurnsStep() {
7469
7630
  if (this.traceIdQueue.length === 0) {
7470
7631
  this._advancePipeline();
@@ -8502,16 +8663,16 @@ var createPortOnlyLabelConnectorTrace = ({
8502
8663
  var LABEL_SEARCH_STEP = 0.05;
8503
8664
  var MAX_RECORDED_CANDIDATES = 2e3;
8504
8665
  var WICK_CLEARANCE = 1e-3;
8505
- var EPS12 = 1e-9;
8506
- var TRACE_BOUNDARY_TOLERANCE = WICK_CLEARANCE + EPS12;
8666
+ var EPS13 = 1e-9;
8667
+ var TRACE_BOUNDARY_TOLERANCE = WICK_CLEARANCE + EPS13;
8507
8668
  var CANDIDATE_SELECTED_COLOR2 = "blue";
8508
8669
  var CANDIDATE_REJECTED_COLOR2 = "red";
8509
8670
 
8510
8671
  // lib/solvers/AvailableNetOrientationSolver/geometry.ts
8511
8672
  var isYOrientation = (orientation) => orientation === "y+" || orientation === "y-";
8512
8673
  var isXOrientation = (orientation) => orientation === "x+" || orientation === "x-";
8513
- var rectsOverlap2 = (a, b) => Math.min(a.maxX, b.maxX) - Math.max(a.minX, b.minX) > EPS12 && Math.min(a.maxY, b.maxY) - Math.max(a.minY, b.minY) > EPS12;
8514
- var rangesOverlap = (minA, maxA, minB, maxB) => Math.min(maxA, maxB) - Math.max(minA, minB) > EPS12;
8674
+ var rectsOverlap2 = (a, b) => Math.min(a.maxX, b.maxX) - Math.max(a.minX, b.minX) > EPS13 && Math.min(a.maxY, b.maxY) - Math.max(a.minY, b.minY) > EPS13;
8675
+ var rangesOverlap = (minA, maxA, minB, maxB) => Math.min(maxA, maxB) - Math.max(minA, minB) > EPS13;
8515
8676
  var traceCrossesBoundsInterior = (bounds, traceMap) => {
8516
8677
  for (const trace of Object.values(traceMap)) {
8517
8678
  const points = trace.tracePath;
@@ -8534,7 +8695,7 @@ var segmentCrossesBoundsInterior = (p1, p2, bounds) => {
8534
8695
  return false;
8535
8696
  }
8536
8697
  if (sameX2(p1, p2)) {
8537
- if (p1.x <= interiorBounds.minX + EPS12 || p1.x >= interiorBounds.maxX - EPS12) {
8698
+ if (p1.x <= interiorBounds.minX + EPS13 || p1.x >= interiorBounds.maxX - EPS13) {
8538
8699
  return false;
8539
8700
  }
8540
8701
  return rangesOverlap(
@@ -8545,7 +8706,7 @@ var segmentCrossesBoundsInterior = (p1, p2, bounds) => {
8545
8706
  );
8546
8707
  }
8547
8708
  if (sameY2(p1, p2)) {
8548
- if (p1.y <= interiorBounds.minY + EPS12 || p1.y >= interiorBounds.maxY - EPS12) {
8709
+ if (p1.y <= interiorBounds.minY + EPS13 || p1.y >= interiorBounds.maxY - EPS13) {
8549
8710
  return false;
8550
8711
  }
8551
8712
  return rangesOverlap(
@@ -8593,8 +8754,8 @@ var simplifyOrthogonalPath = (path) => {
8593
8754
  return simplified;
8594
8755
  };
8595
8756
  var pointsEqual2 = (a, b) => sameX2(a, b) && sameY2(a, b);
8596
- var sameX2 = (a, b) => Math.abs(a.x - b.x) <= EPS12;
8597
- var sameY2 = (a, b) => Math.abs(a.y - b.y) <= EPS12;
8757
+ var sameX2 = (a, b) => Math.abs(a.x - b.x) <= EPS13;
8758
+ var sameY2 = (a, b) => Math.abs(a.y - b.y) <= EPS13;
8598
8759
  var getMaxSearchDistance = (inputProblem) => {
8599
8760
  const maxChipWidth = Math.max(
8600
8761
  ...inputProblem.chips.map((chip) => chip.width),
@@ -8753,7 +8914,7 @@ var AvailableNetOrientationObstacleIndex = class {
8753
8914
  }
8754
8915
  getTraceSegmentsInBounds(bounds) {
8755
8916
  if (!this.traceSegmentIndex) return [];
8756
- const searchBounds = getPaddedBounds(bounds, EPS12);
8917
+ const searchBounds = getPaddedBounds(bounds, EPS13);
8757
8918
  return this.traceSegmentIndex.search(
8758
8919
  searchBounds.minX,
8759
8920
  searchBounds.minY,
@@ -8766,7 +8927,7 @@ var AvailableNetOrientationObstacleIndex = class {
8766
8927
  for (let pointIndex = 0; pointIndex < tracePath.length - 1; pointIndex++) {
8767
8928
  const segmentBounds = getPaddedBounds(
8768
8929
  getSegmentBounds(tracePath[pointIndex], tracePath[pointIndex + 1]),
8769
- EPS12
8930
+ EPS13
8770
8931
  );
8771
8932
  for (const labelIndex of this.getLabelIndicesInBounds(segmentBounds)) {
8772
8933
  labelIndices.add(labelIndex);
@@ -8779,7 +8940,7 @@ var AvailableNetOrientationObstacleIndex = class {
8779
8940
  const start = tracePath[pointIndex];
8780
8941
  const end = tracePath[pointIndex + 1];
8781
8942
  const nearbyChips = this.chipObstacleSpatialIndex.getChipsInBounds(
8782
- getPaddedBounds(getSegmentBounds(start, end), EPS12)
8943
+ getPaddedBounds(getSegmentBounds(start, end), EPS13)
8783
8944
  );
8784
8945
  for (const chip of nearbyChips) {
8785
8946
  if (segmentCrossesBoundsInterior(start, end, chip.bounds)) return true;
@@ -8926,7 +9087,8 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
8926
9087
  getOutput() {
8927
9088
  return {
8928
9089
  traces: this.traces,
8929
- netLabelPlacements: this.outputNetLabelPlacements
9090
+ netLabelPlacements: this.outputNetLabelPlacements,
9091
+ netLabelConnectorTraceIds: this.netLabelConnectorTraceIds
8930
9092
  };
8931
9093
  }
8932
9094
  getProcessableLabelIndices() {
@@ -9247,7 +9409,7 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
9247
9409
  index,
9248
9410
  pin: this.pinMap[otherLabel.pinIds[0]]
9249
9411
  })).filter(
9250
- ({ index, pin: otherPin }) => this.crowdedPortOnlyLabelIndices.has(index) && otherPin?.chipId === pin.chipId && otherPin.x > pin.x + EPS12
9412
+ ({ index, pin: otherPin }) => this.crowdedPortOnlyLabelIndices.has(index) && otherPin?.chipId === pin.chipId && otherPin.x > pin.x + EPS13
9251
9413
  ).sort((a, b) => a.pin.x - b.pin.x)[0]?.pin;
9252
9414
  if (orientation === "y-" && nextPinToRight) return null;
9253
9415
  const anchorX = orientation === "y-" ? Math.max(
@@ -9280,7 +9442,7 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
9280
9442
  const centeredAnchorY = hasUpFacingStack ? (lowestUpFacingLabelY + highestUpFacingLabelY) / 2 : stackedAnchorY;
9281
9443
  const anchorYs = orientation === "y-" ? [centeredAnchorY, stackedAnchorY] : [stackedAnchorY];
9282
9444
  for (const anchorY of anchorYs) {
9283
- if (anchorY - label.anchorPoint.y > this.maxSearchDistance + EPS12) {
9445
+ if (anchorY - label.anchorPoint.y > this.maxSearchDistance + EPS13) {
9284
9446
  continue;
9285
9447
  }
9286
9448
  const candidate = this.createCandidate(
@@ -9309,11 +9471,11 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
9309
9471
  if (trace.globalConnNetId !== label.globalConnNetId) return false;
9310
9472
  const path = trace.tracePath;
9311
9473
  return path.some((point, pointIndex) => {
9312
- if (Math.abs(point.x - label.anchorPoint.x) > EPS12 || Math.abs(point.y - label.anchorPoint.y) > EPS12) {
9474
+ if (Math.abs(point.x - label.anchorPoint.x) > EPS13 || Math.abs(point.y - label.anchorPoint.y) > EPS13) {
9313
9475
  return false;
9314
9476
  }
9315
9477
  return [path[pointIndex - 1], path[pointIndex + 1]].some(
9316
- (neighbor) => neighbor && Math.abs(neighbor.x - point.x) <= EPS12 && (neighbor.y - point.y) * direction.y > EPS12
9478
+ (neighbor) => neighbor && Math.abs(neighbor.x - point.x) <= EPS13 && (neighbor.y - point.y) * direction.y > EPS13
9317
9479
  );
9318
9480
  });
9319
9481
  });
@@ -9403,7 +9565,7 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
9403
9565
  orientation
9404
9566
  );
9405
9567
  if (outwardDirection.x === 0 && outwardDirection.y === 0) continue;
9406
- for (let distance7 = LABEL_SEARCH_STEP; distance7 <= this.maxSearchDistance + EPS12; distance7 += LABEL_SEARCH_STEP) {
9568
+ for (let distance7 = LABEL_SEARCH_STEP; distance7 <= this.maxSearchDistance + EPS13; distance7 += LABEL_SEARCH_STEP) {
9407
9569
  const anchorPoint = {
9408
9570
  x: connectorSource.x + outwardDirection.x * distance7,
9409
9571
  y: connectorSource.y + outwardDirection.y * distance7
@@ -9481,7 +9643,7 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
9481
9643
  const furthestRowPoints = points.filter(
9482
9644
  (point) => Math.abs(
9483
9645
  point.x * direction.x + point.y * direction.y - furthestAlong
9484
- ) <= EPS12
9646
+ ) <= EPS13
9485
9647
  );
9486
9648
  const directHostPinIds = new Set(
9487
9649
  [...directHostTraceIds].flatMap(
@@ -9502,7 +9664,7 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
9502
9664
  preferNearestBendOnOutwardRow: adjacentTraces.some(
9503
9665
  (trace) => furthestRowPoints.some(
9504
9666
  (point) => trace.tracePath.some(
9505
- (tracePoint) => Math.abs(tracePoint.x - point.x) <= EPS12 && Math.abs(tracePoint.y - point.y) <= EPS12
9667
+ (tracePoint) => Math.abs(tracePoint.x - point.x) <= EPS13 && Math.abs(tracePoint.y - point.y) <= EPS13
9506
9668
  )
9507
9669
  )
9508
9670
  )
@@ -9514,7 +9676,7 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
9514
9676
  for (let i = 0; i < otherTrace.tracePath.length - 1; i++) {
9515
9677
  const start = otherTrace.tracePath[i];
9516
9678
  const end = otherTrace.tracePath[i + 1];
9517
- if (Math.abs(start.x - end.x) <= EPS12 && Math.abs(start.y - end.y) > EPS12) {
9679
+ if (Math.abs(start.x - end.x) <= EPS13 && Math.abs(start.y - end.y) > EPS13) {
9518
9680
  verticalRailXs.add(start.x);
9519
9681
  }
9520
9682
  }
@@ -9522,7 +9684,7 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
9522
9684
  for (let i = 0; i < trace.tracePath.length - 1; i++) {
9523
9685
  const start = trace.tracePath[i];
9524
9686
  const end = trace.tracePath[i + 1];
9525
- if (Math.abs(start.x - end.x) <= EPS12 && Math.abs(start.y - end.y) > EPS12 && [...verticalRailXs].some((x) => Math.abs(x - start.x) <= EPS12)) {
9687
+ if (Math.abs(start.x - end.x) <= EPS13 && Math.abs(start.y - end.y) > EPS13 && [...verticalRailXs].some((x) => Math.abs(x - start.x) <= EPS13)) {
9526
9688
  return true;
9527
9689
  }
9528
9690
  }
@@ -9541,7 +9703,7 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
9541
9703
  );
9542
9704
  const maxSearchDistance = this.getSearchDistanceLimit(label, orientation);
9543
9705
  const maxOutwardDistance = outwardDirection.x === 0 && outwardDirection.y === 0 ? 0 : this.maxSearchDistance;
9544
- for (let outwardDistance = 0; outwardDistance <= maxOutwardDistance + EPS12; outwardDistance += LABEL_SEARCH_STEP) {
9706
+ for (let outwardDistance = 0; outwardDistance <= maxOutwardDistance + EPS13; outwardDistance += LABEL_SEARCH_STEP) {
9545
9707
  const baseAnchor = {
9546
9708
  x: initialBaseAnchor.x + outwardDirection.x * outwardDistance,
9547
9709
  y: initialBaseAnchor.y + outwardDirection.y * outwardDistance
@@ -9617,7 +9779,7 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
9617
9779
  connectorSource,
9618
9780
  startDistance = LABEL_SEARCH_STEP
9619
9781
  } = params;
9620
- for (let distance7 = startDistance; distance7 <= maxSearchDistance + EPS12; distance7 += LABEL_SEARCH_STEP) {
9782
+ for (let distance7 = startDistance; distance7 <= maxSearchDistance + EPS13; distance7 += LABEL_SEARCH_STEP) {
9621
9783
  const anchorPoint = {
9622
9784
  x: baseAnchor.x + direction.x * distance7,
9623
9785
  y: baseAnchor.y + direction.y * distance7
@@ -9946,9 +10108,9 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
9946
10108
  const { anchorPoint, orientation } = candidate;
9947
10109
  const chipBounds = chip.bounds;
9948
10110
  if (isYOrientation(orientation)) {
9949
- return anchorPoint.x < chipBounds.minX - EPS12 || anchorPoint.x > chipBounds.maxX + EPS12;
10111
+ return anchorPoint.x < chipBounds.minX - EPS13 || anchorPoint.x > chipBounds.maxX + EPS13;
9950
10112
  }
9951
- return anchorPoint.y < chipBounds.minY - EPS12 || anchorPoint.y > chipBounds.maxY + EPS12;
10113
+ return anchorPoint.y < chipBounds.minY - EPS13 || anchorPoint.y > chipBounds.maxY + EPS13;
9952
10114
  });
9953
10115
  }
9954
10116
  staysOutsideConnectedPinRow(params) {
@@ -9956,9 +10118,9 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
9956
10118
  const pin = this.pinMap[label.pinIds[0]];
9957
10119
  if (!pin || !isYOrientation(candidate.orientation)) return false;
9958
10120
  if (candidate.anchorPoint.x < pin.x) {
9959
- return bounds.maxX <= pin.x + CONNECTED_PIN_ROW_OVERLAP_TOLERANCE + EPS12;
10121
+ return bounds.maxX <= pin.x + CONNECTED_PIN_ROW_OVERLAP_TOLERANCE + EPS13;
9960
10122
  }
9961
- return bounds.minX >= pin.x - CONNECTED_PIN_ROW_OVERLAP_TOLERANCE - EPS12;
10123
+ return bounds.minX >= pin.x - CONNECTED_PIN_ROW_OVERLAP_TOLERANCE - EPS13;
9962
10124
  }
9963
10125
  getBoundsStatus(candidateBoundsCheck) {
9964
10126
  const { bounds, labelIndex, label, ignoreChipCollisions } = candidateBoundsCheck;
@@ -10039,14 +10201,14 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
10039
10201
  candidate.width,
10040
10202
  candidate.height
10041
10203
  );
10042
- if (labelBounds.minY < chip.bounds.minY - EPS12 || labelBounds.maxY > chip.bounds.maxY + EPS12) {
10204
+ if (labelBounds.minY < chip.bounds.minY - EPS13 || labelBounds.maxY > chip.bounds.maxY + EPS13) {
10043
10205
  return false;
10044
10206
  }
10045
- if (candidate.anchorPoint.x >= chip.bounds.minX - EPS12 && candidate.anchorPoint.x <= chip.bounds.maxX + EPS12) {
10207
+ if (candidate.anchorPoint.x >= chip.bounds.minX - EPS13 && candidate.anchorPoint.x <= chip.bounds.maxX + EPS13) {
10046
10208
  return false;
10047
10209
  }
10048
10210
  return chip.pins.every(
10049
- (pin) => label.pinIds.includes(pin.pinId) || pin.y <= labelBounds.minY + EPS12 || pin.y >= labelBounds.maxY - EPS12
10211
+ (pin) => label.pinIds.includes(pin.pinId) || pin.y <= labelBounds.minY + EPS13 || pin.y >= labelBounds.maxY - EPS13
10050
10212
  );
10051
10213
  }
10052
10214
  getTextBlockedMultiPinRailTraces(label, orientation) {
@@ -10073,20 +10235,20 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
10073
10235
  const pins = [...connectedPinIds].map((pinId) => this.pinMap[pinId]);
10074
10236
  const direction = dir(orientation);
10075
10237
  const pinX = pins[0].x;
10076
- if (pins.some((pin) => Math.abs(pin.x - pinX) > EPS12)) return null;
10077
- const sidePins = this.inputProblem.chips.find((chip) => chip.chipId === componentId).pins.filter((pin) => Math.abs(pin.x - pinX) <= EPS12);
10238
+ if (pins.some((pin) => Math.abs(pin.x - pinX) > EPS13)) return null;
10239
+ const sidePins = this.inputProblem.chips.find((chip) => chip.chipId === componentId).pins.filter((pin) => Math.abs(pin.x - pinX) <= EPS13);
10078
10240
  const minY = Math.min(...pins.map((pin) => pin.y));
10079
10241
  const maxY = Math.max(...pins.map((pin) => pin.y));
10080
10242
  if (sidePins.some(
10081
- (pin) => pin.y >= minY - EPS12 && pin.y <= maxY + EPS12 && !connectedPinIds.has(pin.pinId)
10082
- ) || orientation === "y-" && minY > Math.min(...sidePins.map((pin) => pin.y)) + EPS12 || orientation === "y+" && maxY < Math.max(...sidePins.map((pin) => pin.y)) - EPS12) {
10243
+ (pin) => pin.y >= minY - EPS13 && pin.y <= maxY + EPS13 && !connectedPinIds.has(pin.pinId)
10244
+ ) || orientation === "y-" && minY > Math.min(...sidePins.map((pin) => pin.y)) + EPS13 || orientation === "y+" && maxY < Math.max(...sidePins.map((pin) => pin.y)) - EPS13) {
10083
10245
  return null;
10084
10246
  }
10085
10247
  const outerPinPosition = Math.max(
10086
10248
  ...pins.map((pin) => pin.x * direction.x + pin.y * direction.y)
10087
10249
  );
10088
10250
  const blockedByText = (this.inputProblem.textBoxes ?? []).some(
10089
- (textBox) => textBox.chipId === componentId && textBox.center.x * direction.x + textBox.center.y * direction.y > outerPinPosition + EPS12
10251
+ (textBox) => textBox.chipId === componentId && textBox.center.x * direction.x + textBox.center.y * direction.y > outerPinPosition + EPS13
10090
10252
  );
10091
10253
  return blockedByText ? [...connectedTraces] : null;
10092
10254
  }
@@ -10102,7 +10264,7 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
10102
10264
  ...new Set(
10103
10265
  localTraces.flatMap((trace) => trace.tracePath.map((point) => point.x))
10104
10266
  )
10105
- ].filter((x) => Math.abs(x - pinX) > EPS12).sort((a, b) => Math.abs(a - pinX) - Math.abs(b - pinX));
10267
+ ].filter((x) => Math.abs(x - pinX) > EPS13).sort((a, b) => Math.abs(a - pinX) - Math.abs(b - pinX));
10106
10268
  for (const x of railXs) {
10107
10269
  const connectorSource = { x, y: connectorY };
10108
10270
  if (!Object.values(this.traceMap).some(
@@ -10165,8 +10327,8 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
10165
10327
  if (!chip) return null;
10166
10328
  const sides = new Set(
10167
10329
  pins.map((pin) => {
10168
- if (Math.abs(pin.x - chip.bounds.minX) <= EPS12) return "left";
10169
- if (Math.abs(pin.x - chip.bounds.maxX) <= EPS12) return "right";
10330
+ if (Math.abs(pin.x - chip.bounds.minX) <= EPS13) return "left";
10331
+ if (Math.abs(pin.x - chip.bounds.maxX) <= EPS13) return "right";
10170
10332
  return null;
10171
10333
  })
10172
10334
  );
@@ -10205,16 +10367,16 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
10205
10367
  }
10206
10368
  sharesChipBoundary(bounds) {
10207
10369
  const boundarySearchBounds = {
10208
- minX: bounds.minX - WICK_CLEARANCE - EPS12,
10209
- minY: bounds.minY - WICK_CLEARANCE - EPS12,
10210
- maxX: bounds.maxX + WICK_CLEARANCE + EPS12,
10211
- maxY: bounds.maxY + WICK_CLEARANCE + EPS12
10370
+ minX: bounds.minX - WICK_CLEARANCE - EPS13,
10371
+ minY: bounds.minY - WICK_CLEARANCE - EPS13,
10372
+ maxX: bounds.maxX + WICK_CLEARANCE + EPS13,
10373
+ maxY: bounds.maxY + WICK_CLEARANCE + EPS13
10212
10374
  };
10213
10375
  const nearbyChips = this.chipObstacleSpatialIndex.getChipsInBounds(boundarySearchBounds);
10214
10376
  for (const chip of nearbyChips) {
10215
10377
  const chipBounds = chip.bounds;
10216
- const adjacentToVerticalSide = Math.abs(bounds.minX - chipBounds.maxX) <= WICK_CLEARANCE + EPS12 || Math.abs(bounds.maxX - chipBounds.minX) <= WICK_CLEARANCE + EPS12;
10217
- const adjacentToHorizontalSide = Math.abs(bounds.minY - chipBounds.maxY) <= WICK_CLEARANCE + EPS12 || Math.abs(bounds.maxY - chipBounds.minY) <= WICK_CLEARANCE + EPS12;
10378
+ const adjacentToVerticalSide = Math.abs(bounds.minX - chipBounds.maxX) <= WICK_CLEARANCE + EPS13 || Math.abs(bounds.maxX - chipBounds.minX) <= WICK_CLEARANCE + EPS13;
10379
+ const adjacentToHorizontalSide = Math.abs(bounds.minY - chipBounds.maxY) <= WICK_CLEARANCE + EPS13 || Math.abs(bounds.maxY - chipBounds.minY) <= WICK_CLEARANCE + EPS13;
10218
10380
  if (adjacentToVerticalSide && rangesOverlap(
10219
10381
  bounds.minY,
10220
10382
  bounds.maxY,
@@ -10276,7 +10438,7 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
10276
10438
  let nearestDistance = Number.POSITIVE_INFINITY;
10277
10439
  for (const chip of this.chipObstacleSpatialIndex.chips) {
10278
10440
  const bounds = chip.bounds;
10279
- if (point.x < bounds.minX - EPS12 || point.x > bounds.maxX + EPS12 || point.y < bounds.minY - EPS12 || point.y > bounds.maxY + EPS12) {
10441
+ if (point.x < bounds.minX - EPS13 || point.x > bounds.maxX + EPS13 || point.y < bounds.minY - EPS13 || point.y > bounds.maxY + EPS13) {
10280
10442
  continue;
10281
10443
  }
10282
10444
  for (const [side, distance7] of getSideDistances(point, bounds)) {
@@ -10293,8 +10455,8 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
10293
10455
  let nearestDistanceSq = Number.POSITIVE_INFINITY;
10294
10456
  for (const chip of this.chipObstacleSpatialIndex.chips) {
10295
10457
  const bounds = chip.bounds;
10296
- const dx = point.x < bounds.minX - EPS12 ? bounds.minX - point.x : point.x > bounds.maxX + EPS12 ? point.x - bounds.maxX : 0;
10297
- const dy = point.y < bounds.minY - EPS12 ? bounds.minY - point.y : point.y > bounds.maxY + EPS12 ? point.y - bounds.maxY : 0;
10458
+ const dx = point.x < bounds.minX - EPS13 ? bounds.minX - point.x : point.x > bounds.maxX + EPS13 ? point.x - bounds.maxX : 0;
10459
+ const dy = point.y < bounds.minY - EPS13 ? bounds.minY - point.y : point.y > bounds.maxY + EPS13 ? point.y - bounds.maxY : 0;
10298
10460
  if (dx === 0 && dy === 0) continue;
10299
10461
  const distanceSq = dx ** 2 + dy ** 2;
10300
10462
  if (distanceSq >= nearestDistanceSq) continue;
@@ -10854,11 +11016,11 @@ var getOrientationConstraint = (inputProblem, label) => {
10854
11016
  };
10855
11017
 
10856
11018
  // lib/solvers/TraceAnchoredNetLabelOverlapSolver/geometry.ts
10857
- var EPS13 = 1e-6;
11019
+ var EPS14 = 1e-6;
10858
11020
  var TRACE_BOUNDARY_TOLERANCE2 = 1e-6;
10859
11021
  var getLabelBounds = (label) => getRectBounds(label.center, label.width, label.height);
10860
- var rectsOverlap3 = (a, b) => Math.min(a.maxX, b.maxX) - Math.max(a.minX, b.minX) > EPS13 && Math.min(a.maxY, b.maxY) - Math.max(a.minY, b.minY) > EPS13;
10861
- var rectsTouchOrOverlap = (a, b) => Math.min(a.maxX, b.maxX) - Math.max(a.minX, b.minX) >= -EPS13 && Math.min(a.maxY, b.maxY) - Math.max(a.minY, b.minY) >= -EPS13;
11022
+ var rectsOverlap3 = (a, b) => Math.min(a.maxX, b.maxX) - Math.max(a.minX, b.minX) > EPS14 && Math.min(a.maxY, b.maxY) - Math.max(a.minY, b.minY) > EPS14;
11023
+ var rectsTouchOrOverlap = (a, b) => Math.min(a.maxX, b.maxX) - Math.max(a.minX, b.minX) >= -EPS14 && Math.min(a.maxY, b.maxY) - Math.max(a.minY, b.minY) >= -EPS14;
10862
11024
  var traceCrossesBoundsInterior2 = (bounds, traces) => {
10863
11025
  for (const trace of traces) {
10864
11026
  const points = trace.tracePath;
@@ -10904,7 +11066,7 @@ var getPointAtTraceDistance = (trace, distance7) => {
10904
11066
  const end = trace.tracePath[i + 1];
10905
11067
  const segmentLength = getManhattanDistance(start, end);
10906
11068
  const nextDistance = pathDistance + segmentLength;
10907
- if (distance7 <= nextDistance + EPS13) {
11069
+ if (distance7 <= nextDistance + EPS14) {
10908
11070
  const offset = Math.max(
10909
11071
  0,
10910
11072
  Math.min(segmentLength, distance7 - pathDistance)
@@ -10943,7 +11105,7 @@ var segmentCrossesBoundsInterior2 = (start, end, bounds) => {
10943
11105
  return false;
10944
11106
  }
10945
11107
  if (isVertical4(start, end)) {
10946
- if (start.x <= interior.minX + EPS13 || start.x >= interior.maxX - EPS13) {
11108
+ if (start.x <= interior.minX + EPS14 || start.x >= interior.maxX - EPS14) {
10947
11109
  return false;
10948
11110
  }
10949
11111
  return rangesOverlap2(
@@ -10954,7 +11116,7 @@ var segmentCrossesBoundsInterior2 = (start, end, bounds) => {
10954
11116
  );
10955
11117
  }
10956
11118
  if (isHorizontal3(start, end)) {
10957
- if (start.y <= interior.minY + EPS13 || start.y >= interior.maxY - EPS13) {
11119
+ if (start.y <= interior.minY + EPS14 || start.y >= interior.maxY - EPS14) {
10958
11120
  return false;
10959
11121
  }
10960
11122
  return rangesOverlap2(
@@ -10968,10 +11130,10 @@ var segmentCrossesBoundsInterior2 = (start, end, bounds) => {
10968
11130
  };
10969
11131
  var isPointOnSegment2 = (point, start, end) => {
10970
11132
  if (isHorizontal3(start, end)) {
10971
- return Math.abs(point.y - start.y) <= EPS13 && point.x >= Math.min(start.x, end.x) - EPS13 && point.x <= Math.max(start.x, end.x) + EPS13;
11133
+ return Math.abs(point.y - start.y) <= EPS14 && point.x >= Math.min(start.x, end.x) - EPS14 && point.x <= Math.max(start.x, end.x) + EPS14;
10972
11134
  }
10973
11135
  if (isVertical4(start, end)) {
10974
- return Math.abs(point.x - start.x) <= EPS13 && point.y >= Math.min(start.y, end.y) - EPS13 && point.y <= Math.max(start.y, end.y) + EPS13;
11136
+ return Math.abs(point.x - start.x) <= EPS14 && point.y >= Math.min(start.y, end.y) - EPS14 && point.y <= Math.max(start.y, end.y) + EPS14;
10975
11137
  }
10976
11138
  return false;
10977
11139
  };
@@ -10979,9 +11141,9 @@ var getSegmentDirection = (start, end) => ({
10979
11141
  x: isVertical4(start, end) ? 0 : Math.sign(end.x - start.x),
10980
11142
  y: isHorizontal3(start, end) ? 0 : Math.sign(end.y - start.y)
10981
11143
  });
10982
- var isHorizontal3 = (start, end) => Math.abs(start.y - end.y) <= EPS13;
10983
- var isVertical4 = (start, end) => Math.abs(start.x - end.x) <= EPS13;
10984
- var rangesOverlap2 = (minA, maxA, minB, maxB) => Math.min(maxA, maxB) - Math.max(minA, minB) > EPS13;
11144
+ var isHorizontal3 = (start, end) => Math.abs(start.y - end.y) <= EPS14;
11145
+ var isVertical4 = (start, end) => Math.abs(start.x - end.x) <= EPS14;
11146
+ var rangesOverlap2 = (minA, maxA, minB, maxB) => Math.min(maxA, maxB) - Math.max(minA, minB) > EPS14;
10985
11147
  var getUniquePinCount2 = (pinIds) => new Set(pinIds).size;
10986
11148
 
10987
11149
  // lib/solvers/TraceAnchoredNetLabelOverlapSolver/candidates.ts
@@ -11038,7 +11200,7 @@ var getCandidateDistances = (traceLength, vertexDistances) => {
11038
11200
  for (const distance7 of vertexDistances) {
11039
11201
  distances.add(roundDistance(distance7));
11040
11202
  }
11041
- return [...distances].filter((distance7) => distance7 >= -EPS13 && distance7 <= traceLength + EPS13).sort((a, b) => a - b);
11203
+ return [...distances].filter((distance7) => distance7 >= -EPS14 && distance7 <= traceLength + EPS14).sort((a, b) => a - b);
11042
11204
  };
11043
11205
  var getOrientationsForPoint = (params) => {
11044
11206
  const { inputProblem, label, point, orientationConstraint } = params;
@@ -11127,13 +11289,13 @@ var getOutwardOrientationOptions = (point, chipBounds) => {
11127
11289
  };
11128
11290
  var getOutwardAxisOption = (params) => {
11129
11291
  const { value, min, max, center, positiveOrientation, negativeOrientation } = params;
11130
- if (value > max + EPS13) {
11292
+ if (value > max + EPS14) {
11131
11293
  return {
11132
11294
  orientation: positiveOrientation,
11133
11295
  outwardScore: 1 + value - max
11134
11296
  };
11135
11297
  }
11136
- if (value < min - EPS13) {
11298
+ if (value < min - EPS14) {
11137
11299
  return {
11138
11300
  orientation: negativeOrientation,
11139
11301
  outwardScore: 1 + min - value
@@ -11144,7 +11306,7 @@ var getOutwardAxisOption = (params) => {
11144
11306
  outwardScore: getNormalizedCenterDistance(value, center, max - min)
11145
11307
  };
11146
11308
  };
11147
- var getNormalizedCenterDistance = (value, center, span) => Math.abs(value - center) / Math.max(EPS13, span / 2);
11309
+ var getNormalizedCenterDistance = (value, center, span) => Math.abs(value - center) / Math.max(EPS14, span / 2);
11148
11310
  var ALL_ORIENTATIONS = ["x+", "x-", "y+", "y-"];
11149
11311
  var getFlippedOrientation = (orientation) => {
11150
11312
  switch (orientation) {
@@ -11212,7 +11374,7 @@ var getNetLabelHeight = (inputProblem, label) => {
11212
11374
  )?.netLabelHeight;
11213
11375
  };
11214
11376
  var roundDistance = (distance7) => Number(distance7.toFixed(6));
11215
- var isSamePlacement = (label, point, orientation) => Math.abs(point.x - label.anchorPoint.x) <= EPS13 && Math.abs(point.y - label.anchorPoint.y) <= EPS13 && orientation === label.orientation;
11377
+ var isSamePlacement = (label, point, orientation) => Math.abs(point.x - label.anchorPoint.x) <= EPS14 && Math.abs(point.y - label.anchorPoint.y) <= EPS14 && orientation === label.orientation;
11216
11378
 
11217
11379
  // lib/solvers/TraceAnchoredNetLabelOverlapSolver/visualize.ts
11218
11380
  var CANDIDATE_SELECTED_COLOR4 = "blue";
@@ -15032,15 +15194,15 @@ var pathIntersectsRenderedLabel = (path, label) => {
15032
15194
  };
15033
15195
 
15034
15196
  // lib/solvers/InlineNetLabelSolver/restoreReroutesAroundSupersededLabels.ts
15035
- var EPS14 = 1e-6;
15197
+ var EPS15 = 1e-6;
15036
15198
  var getPathLength5 = (path) => path.slice(1).reduce((length, point, pointIndex) => {
15037
15199
  const previousPoint = path[pointIndex];
15038
15200
  return length + Math.abs(point.x - previousPoint.x) + Math.abs(point.y - previousPoint.y);
15039
15201
  }, 0);
15040
15202
  var pathsEqual = (first, second) => first.length === second.length && first.every(
15041
- (point, index) => Math.abs(point.x - second[index].x) <= EPS14 && Math.abs(point.y - second[index].y) <= EPS14
15203
+ (point, index) => Math.abs(point.x - second[index].x) <= EPS15 && Math.abs(point.y - second[index].y) <= EPS15
15042
15204
  );
15043
- var isStrictlySimpler = (candidate, current) => candidate.length < current.length && getPathLength5(candidate) <= getPathLength5(current) + EPS14;
15205
+ var isStrictlySimpler = (candidate, current) => candidate.length < current.length && getPathLength5(candidate) <= getPathLength5(current) + EPS15;
15044
15206
  var getIntersectionKeys = (path, otherPath) => {
15045
15207
  const intersections = /* @__PURE__ */ new Set();
15046
15208
  for (let pathIndex = 0; pathIndex < path.length - 1; pathIndex++) {
@@ -16095,12 +16257,12 @@ var getTraceRecoveryConnectivityMaps = (inputProblem) => {
16095
16257
  };
16096
16258
 
16097
16259
  // lib/solvers/NetLabelToTraceSolver/reduceTraceCrossings.ts
16098
- var EPS15 = 1e-9;
16099
- var isHorizontal4 = (start, end) => Math.abs(start.y - end.y) < EPS15;
16100
- var isVertical5 = (start, end) => Math.abs(start.x - end.x) < EPS15;
16260
+ var EPS16 = 1e-9;
16261
+ var isHorizontal4 = (start, end) => Math.abs(start.y - end.y) < EPS16;
16262
+ var isVertical5 = (start, end) => Math.abs(start.x - end.x) < EPS16;
16101
16263
  var compactConsecutivePoints = (path) => path.filter((point, index) => {
16102
16264
  const previousPoint = path[index - 1];
16103
- return !previousPoint || Math.abs(point.x - previousPoint.x) >= EPS15 || Math.abs(point.y - previousPoint.y) >= EPS15;
16265
+ return !previousPoint || Math.abs(point.x - previousPoint.x) >= EPS16 || Math.abs(point.y - previousPoint.y) >= EPS16;
16104
16266
  });
16105
16267
  var isValidOrthogonalPath = (path) => {
16106
16268
  if (path.length < 2 || !path.every((point, index) => {
@@ -16138,7 +16300,7 @@ var getEndpointAlignedSegmentCandidates = (tracePath) => {
16138
16300
  }
16139
16301
  const alignedCoordinates = segmentIsVertical ? [previousPoint.x, nextPoint.x] : [previousPoint.y, nextPoint.y];
16140
16302
  for (const alignedCoordinate of alignedCoordinates) {
16141
- if (Math.abs(alignedCoordinate - (segmentIsVertical ? start.x : start.y)) < EPS15) {
16303
+ if (Math.abs(alignedCoordinate - (segmentIsVertical ? start.x : start.y)) < EPS16) {
16142
16304
  continue;
16143
16305
  }
16144
16306
  const candidate = tracePath.map((point) => ({ ...point }));
@@ -16914,10 +17076,14 @@ var SchematicTracePipelineSolver = class extends BaseSolver {
16914
17076
  allLabelPlacements: collisionOutput.netLabelPlacements,
16915
17077
  mergedLabelNetIdMap: labelMergingOutput.mergedLabelNetIdMap,
16916
17078
  paddingBuffer: 0.1,
16917
- operations: ["aligning_same_net_rails"],
17079
+ operations: [
17080
+ "rerouting_generated_net_label_connector_crossings",
17081
+ "aligning_same_net_rails"
17082
+ ],
16918
17083
  eligibleTraceIds: new Set(
16919
17084
  instance.traceCleanupSolver.getOutput().traces.map((trace) => trace.mspPairId)
16920
- )
17085
+ ),
17086
+ netLabelConnectorTraceIds: instance.availableNetOrientationSolver.netLabelConnectorTraceIds
16921
17087
  }
16922
17088
  ];
16923
17089
  }