@tscircuit/schematic-trace-solver 0.0.174 → 0.0.176

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.
Files changed (63) hide show
  1. package/dist/index.d.ts +5 -0
  2. package/dist/index.js +759 -91
  3. package/lib/solvers/AvailableNetOrientationSolver/AvailableNetOrientationSolver.ts +5 -1
  4. package/lib/solvers/InlineNetLabelSolver/InlineNetLabelSolver.ts +16 -1
  5. package/lib/solvers/InlineNetLabelSolver/restoreReroutesAroundSupersededLabels.ts +174 -0
  6. package/lib/solvers/NetLabelToTraceSolver/NetLabelToTraceSolver.ts +2 -30
  7. package/lib/solvers/SameNetJunctionAlignmentSolver/SameNetJunctionAlignmentSolver.ts +2 -0
  8. package/lib/solvers/SameNetJunctionAlignmentSolver/alignSameNetJunctions.ts +748 -15
  9. package/lib/solvers/SameNetJunctionAlignmentSolver/findNearestSharedPinExitRail.ts +140 -0
  10. package/lib/solvers/SchematicTracePipelineSolver/SchematicTracePipelineSolver.ts +12 -5
  11. package/lib/utils/doesPathCoincideWithTraces.ts +17 -4
  12. package/lib/utils/pathIntersectsRenderedLabel.ts +33 -0
  13. package/package.json +1 -1
  14. package/site/bug-reports/bug-report-20260901T055358Z.page.tsx +4 -0
  15. package/site/bug-reports/bug-report-20260901T064117Z.page.tsx +4 -0
  16. package/site/bug-reports/bug-report-20260901T134241Z.page.tsx +4 -0
  17. package/tests/bug-reports/bug-report-20260707T134549Z/__snapshots__/bug-report-20260707T134549Z.snap.svg +2 -2
  18. package/tests/bug-reports/bug-report-20260707T134549Z/bug-report-20260707T134549Z.test.ts +9 -0
  19. package/tests/bug-reports/bug-report-20260707T230831Z/__snapshots__/bug-report-20260707T230831Z.snap.svg +2 -2
  20. package/tests/bug-reports/bug-report-20260717T042845Z/__snapshots__/bug-report-20260717T042845Z.snap.svg +2 -2
  21. package/tests/bug-reports/bug-report-20260721T221026Z/__snapshots__/bug-report-20260721T221026Z.snap.svg +2 -2
  22. package/tests/bug-reports/bug-report-20260730T061837Z/__snapshots__/bug-report-20260730T061837Z.snap.svg +2 -2
  23. package/tests/bug-reports/bug-report-20260730T061837Z/bug-report-20260730T061837Z.test.ts +8 -4
  24. package/tests/bug-reports/bug-report-20260804T171919Z/__snapshots__/bug-report-20260804T171919Z.snap.svg +2 -2
  25. package/tests/bug-reports/bug-report-20260805T061316Z/__snapshots__/bug-report-20260805T061316Z.snap.svg +2 -2
  26. package/tests/bug-reports/bug-report-20260806T061548Z/__snapshots__/bug-report-20260806T061548Z.snap.svg +2 -2
  27. package/tests/bug-reports/bug-report-20260825T045913Z/__snapshots__/bug-report-20260825T045913Z.snap.svg +2 -2
  28. package/tests/bug-reports/bug-report-20260826T072956Z/__snapshots__/bug-report-20260826T072956Z.snap.svg +6 -6
  29. package/tests/bug-reports/bug-report-20260901T055358Z/__snapshots__/bug-report-20260901T055358Z.snap.svg +676 -0
  30. package/tests/bug-reports/bug-report-20260901T055358Z/bug-report-20260901T055358Z.json +2467 -0
  31. package/tests/bug-reports/bug-report-20260901T055358Z/bug-report-20260901T055358Z.test.ts +59 -0
  32. package/tests/bug-reports/bug-report-20260901T064117Z/__snapshots__/bug-report-20260901T064117Z.snap.svg +134 -0
  33. package/tests/bug-reports/bug-report-20260901T064117Z/bug-report-20260901T064117Z.json +215 -0
  34. package/tests/bug-reports/bug-report-20260901T064117Z/bug-report-20260901T064117Z.test.ts +12 -0
  35. package/tests/bug-reports/bug-report-20260901T134241Z/__snapshots__/bug-report-20260901T134241Z.snap.svg +115 -0
  36. package/tests/bug-reports/bug-report-20260901T134241Z/bug-report-20260901T134241Z.json +359 -0
  37. package/tests/bug-reports/bug-report-20260901T134241Z/bug-report-20260901T134241Z.test.ts +60 -0
  38. package/tests/examples/__snapshots__/example51.snap.svg +2 -2
  39. package/tests/repros/__snapshots__/board-1273-trace-overlap-cycle.snap.svg +10 -10
  40. package/tests/repros/__snapshots__/board1096-usb-label-overlap-iteration.snap.svg +2 -2
  41. package/tests/repros/__snapshots__/repro-bq25895-cross-net-trace-overlap.snap.svg +2 -2
  42. package/tests/repros/__snapshots__/repro-core-ground-inline-label-fallback.snap.svg +10 -10
  43. package/tests/repros/__snapshots__/repro-example35-minimize-trace-crossing.snap.svg +2 -2
  44. package/tests/repros/__snapshots__/repro-isolated-rs485-isow7841.snap.svg +18 -18
  45. package/tests/repros/__snapshots__/repro-pga300-redundant-ground-traces.snap.svg +18 -18
  46. package/tests/repros/__snapshots__/repro-pmp11282-isolated-dcdc.snap.svg +10 -10
  47. package/tests/repros/__snapshots__/repro-powerbank-3v-system-power.snap.svg +2 -2
  48. package/tests/repros/__snapshots__/repro-ti-power-output-section.snap.svg +2 -2
  49. package/tests/repros/__snapshots__/repro-tida-01389-hbridge.snap.svg +2 -2
  50. package/tests/repros/__snapshots__/repro-tida010076-page02.snap.svg +2 -2
  51. package/tests/repros/__snapshots__/repro-trellis-core-gnd-net-label-overlap.snap.svg +134 -0
  52. package/tests/repros/__snapshots__/repro-wireless-mouse-charger-section.snap.svg +164 -0
  53. package/tests/repros/__snapshots__/repro161-power-section-autolayout.snap.svg +2 -2
  54. package/tests/repros/__snapshots__/repro48-555-timer-vcc-rail-label.snap.svg +2 -2
  55. package/tests/repros/assets/repro-trellis-core-gnd-net-label-overlap.input.json +178 -0
  56. package/tests/repros/assets/repro-wireless-mouse-charger-section.input.json +591 -0
  57. package/tests/repros/repro-isolated-rs485-isow7841.test.ts +4 -1
  58. package/tests/repros/repro-powerbank-3v-system-power.test.ts +24 -0
  59. package/tests/repros/repro-tida-01389-hbridge.test.ts +24 -0
  60. package/tests/repros/repro-trellis-core-gnd-net-label-overlap.test.ts +73 -0
  61. package/tests/repros/repro-wireless-mouse-charger-section.test.ts +16 -0
  62. package/tests/solvers/InlineNetLabelSolver/restore-reroutes-around-superseded-labels.test.ts +186 -0
  63. package/tests/solvers/SameNetJunctionAlignmentSolver/parallel-load-rails.test.ts +1 -0
package/dist/index.js CHANGED
@@ -325,19 +325,19 @@ var doesPairCrossRestrictedCenterLines = (params) => {
325
325
  chipMap
326
326
  });
327
327
  if (restrictedCenterLines.size === 0) return false;
328
- const EPS15 = 1e-9;
328
+ const EPS16 = 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) < -EPS15) return true;
332
+ if ((a.x - rcl.x) * (b.x - rcl.x) < -EPS16) 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) < -EPS15) return true;
335
+ if ((a.y - rcl.y) * (b.y - rcl.y) < -EPS16) return true;
336
336
  }
337
337
  }
338
338
  return false;
339
339
  };
340
- if (Math.abs(p1.x - p2.x) < EPS15 || Math.abs(p1.y - p2.y) < EPS15) {
340
+ if (Math.abs(p1.x - p2.x) < EPS16 || Math.abs(p1.y - p2.y) < EPS16) {
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 };
@@ -1575,8 +1575,8 @@ var SchematicTraceSingleLineSolver2 = class extends BaseSolver {
1575
1575
  if (!collision) {
1576
1576
  const first = path[0];
1577
1577
  const last = path[path.length - 1];
1578
- const EPS15 = 1e-9;
1579
- const samePoint = (p, q) => Math.abs(p.x - q.x) < EPS15 && Math.abs(p.y - q.y) < EPS15;
1578
+ const EPS16 = 1e-9;
1579
+ const samePoint = (p, q) => Math.abs(p.x - q.x) < EPS16 && Math.abs(p.y - q.y) < EPS16;
1580
1580
  if (samePoint(first, { x: PA.x, y: PA.y }) && samePoint(last, { x: PB.x, y: PB.y })) {
1581
1581
  this.solvedTracePath = path;
1582
1582
  this.solved = true;
@@ -1887,13 +1887,13 @@ var applyJogToTerminalSegment = ({
1887
1887
  segmentIndex: si,
1888
1888
  offset,
1889
1889
  JOG_SIZE,
1890
- EPS: EPS15 = 1e-6
1890
+ EPS: EPS16 = 1e-6
1891
1891
  }) => {
1892
1892
  if (si !== 0 && si !== pts.length - 2) return;
1893
1893
  const start = pts[si];
1894
1894
  const end = pts[si + 1];
1895
- const isVertical6 = Math.abs(start.x - end.x) < EPS15;
1896
- const isHorizontal5 = Math.abs(start.y - end.y) < EPS15;
1895
+ const isVertical6 = Math.abs(start.x - end.x) < EPS16;
1896
+ const isHorizontal5 = Math.abs(start.y - end.y) < EPS16;
1897
1897
  if (!isVertical6 && !isHorizontal5) return;
1898
1898
  const segDir = isVertical6 ? end.y > start.y ? 1 : -1 : end.x > start.x ? 1 : -1;
1899
1899
  if (pts.length === 2) {
@@ -2327,7 +2327,7 @@ var TraceOverlapShiftSolver = class extends BaseSolver {
2327
2327
  return islands;
2328
2328
  }
2329
2329
  findNextOverlapIssue() {
2330
- const EPS15 = 2e-3;
2330
+ const EPS16 = 2e-3;
2331
2331
  const netIds = Object.keys(this.traceNetIslands);
2332
2332
  for (let i = 0; i < netIds.length; i++) {
2333
2333
  for (let j = i + 1; j < netIds.length; j++) {
@@ -2354,7 +2354,7 @@ var TraceOverlapShiftSolver = class extends BaseSolver {
2354
2354
  segmentBIndex,
2355
2355
  rangeOverlap
2356
2356
  }) => {
2357
- if (rangeOverlap > EPS15) {
2357
+ if (rangeOverlap > EPS16) {
2358
2358
  const keyA = `${pathAIndex}:${segmentAIndex}`;
2359
2359
  const keyB = `${pathBIndex}:${segmentBIndex}`;
2360
2360
  if (!seenA.has(keyA)) {
@@ -2373,7 +2373,7 @@ var TraceOverlapShiftSolver = class extends BaseSolver {
2373
2373
  }
2374
2374
  return;
2375
2375
  }
2376
- if (rangeOverlap < -EPS15) return;
2376
+ if (rangeOverlap < -EPS16) return;
2377
2377
  const pathA = pathsA[pathAIndex].tracePath;
2378
2378
  const pathB = pathsB[pathBIndex].tracePath;
2379
2379
  const segmentAStart = pathA[segmentAIndex];
@@ -2396,8 +2396,8 @@ var TraceOverlapShiftSolver = class extends BaseSolver {
2396
2396
  for (let sa = 0; sa < ptsA.length - 1; sa++) {
2397
2397
  const a1 = ptsA[sa];
2398
2398
  const a2 = ptsA[sa + 1];
2399
- const aVert = Math.abs(a1.x - a2.x) < EPS15;
2400
- const aHorz = Math.abs(a1.y - a2.y) < EPS15;
2399
+ const aVert = Math.abs(a1.x - a2.x) < EPS16;
2400
+ const aHorz = Math.abs(a1.y - a2.y) < EPS16;
2401
2401
  if (!aVert && !aHorz) continue;
2402
2402
  for (let pb = 0; pb < pathsB.length; pb++) {
2403
2403
  const pathB = pathsB[pb];
@@ -2408,11 +2408,11 @@ var TraceOverlapShiftSolver = class extends BaseSolver {
2408
2408
  for (let sb = 0; sb < ptsB.length - 1; sb++) {
2409
2409
  const b1 = ptsB[sb];
2410
2410
  const b2 = ptsB[sb + 1];
2411
- const bVert = Math.abs(b1.x - b2.x) < EPS15;
2412
- const bHorz = Math.abs(b1.y - b2.y) < EPS15;
2411
+ const bVert = Math.abs(b1.x - b2.x) < EPS16;
2412
+ const bHorz = Math.abs(b1.y - b2.y) < EPS16;
2413
2413
  if (!bVert && !bHorz) continue;
2414
2414
  if (aVert && bVert) {
2415
- if (Math.abs(a1.x - b1.x) < EPS15) {
2415
+ if (Math.abs(a1.x - b1.x) < EPS16) {
2416
2416
  recordCollinearInteraction({
2417
2417
  pathAIndex: pa,
2418
2418
  segmentAIndex: sa,
@@ -2422,7 +2422,7 @@ var TraceOverlapShiftSolver = class extends BaseSolver {
2422
2422
  });
2423
2423
  }
2424
2424
  } else if (aHorz && bHorz) {
2425
- if (Math.abs(a1.y - b1.y) < EPS15) {
2425
+ if (Math.abs(a1.y - b1.y) < EPS16) {
2426
2426
  recordCollinearInteraction({
2427
2427
  pathAIndex: pa,
2428
2428
  segmentAIndex: sa,
@@ -2478,14 +2478,14 @@ var TraceOverlapShiftSolver = class extends BaseSolver {
2478
2478
  return null;
2479
2479
  }
2480
2480
  findNextDiagonalSegment() {
2481
- const EPS15 = 2e-3;
2481
+ const EPS16 = 2e-3;
2482
2482
  for (const mspPairId in this.correctedTraceMap) {
2483
2483
  const tracePath = this.correctedTraceMap[mspPairId].tracePath;
2484
2484
  for (let i = 0; i < tracePath.length - 1; i++) {
2485
2485
  const p1 = tracePath[i];
2486
2486
  const p2 = tracePath[i + 1];
2487
- const isHorizontal5 = Math.abs(p1.y - p2.y) < EPS15;
2488
- const isVertical6 = Math.abs(p1.x - p2.x) < EPS15;
2487
+ const isHorizontal5 = Math.abs(p1.y - p2.y) < EPS16;
2488
+ const isVertical6 = Math.abs(p1.x - p2.x) < EPS16;
2489
2489
  if (!isHorizontal5 && !isVertical6) {
2490
2490
  return { mspPairId, tracePath, i, p1, p2 };
2491
2491
  }
@@ -2499,13 +2499,13 @@ var TraceOverlapShiftSolver = class extends BaseSolver {
2499
2499
  return false;
2500
2500
  }
2501
2501
  const { mspPairId, tracePath, i, p1, p2 } = diagonalInfo;
2502
- const EPS15 = 2e-3;
2502
+ const EPS16 = 2e-3;
2503
2503
  const p0 = i > 0 ? tracePath[i - 1] : null;
2504
2504
  const p3 = i + 2 < tracePath.length ? tracePath[i + 2] : null;
2505
- const prevIsVertical = p0 ? Math.abs(p0.x - p1.x) < EPS15 : false;
2506
- const prevIsHorizontal = p0 ? Math.abs(p0.y - p1.y) < EPS15 : false;
2507
- const nextIsVertical = p3 ? Math.abs(p2.x - p3.x) < EPS15 : false;
2508
- const nextIsHorizontal = p3 ? Math.abs(p2.y - p3.y) < EPS15 : false;
2505
+ const prevIsVertical = p0 ? Math.abs(p0.x - p1.x) < EPS16 : false;
2506
+ const prevIsHorizontal = p0 ? Math.abs(p0.y - p1.y) < EPS16 : false;
2507
+ const nextIsVertical = p3 ? Math.abs(p2.x - p3.x) < EPS16 : false;
2508
+ const nextIsHorizontal = p3 ? Math.abs(p2.y - p3.y) < EPS16 : false;
2509
2509
  const elbow1 = { x: p1.x, y: p2.y };
2510
2510
  const elbow2 = { x: p2.x, y: p1.y };
2511
2511
  let score1 = 0;
@@ -2667,24 +2667,24 @@ var ChipObstacleSpatialIndex = class {
2667
2667
  };
2668
2668
 
2669
2669
  // lib/solvers/NetLabelPlacementSolver/SingleNetLabelPlacementSolver/collisions.ts
2670
- function segmentIntersectsRect2(p1, p2, rect, EPS15 = 1e-9) {
2671
- const isVert = Math.abs(p1.x - p2.x) < EPS15;
2672
- const isHorz = Math.abs(p1.y - p2.y) < EPS15;
2670
+ function segmentIntersectsRect2(p1, p2, rect, EPS16 = 1e-9) {
2671
+ const isVert = Math.abs(p1.x - p2.x) < EPS16;
2672
+ const isHorz = Math.abs(p1.y - p2.y) < EPS16;
2673
2673
  if (!isVert && !isHorz) return false;
2674
2674
  if (isVert) {
2675
2675
  const x = p1.x;
2676
- if (x < rect.minX - EPS15 || x > rect.maxX + EPS15) return false;
2676
+ if (x < rect.minX - EPS16 || x > rect.maxX + EPS16) return false;
2677
2677
  const segMinY = Math.min(p1.y, p2.y);
2678
2678
  const segMaxY = Math.max(p1.y, p2.y);
2679
2679
  const overlap = Math.min(segMaxY, rect.maxY) - Math.max(segMinY, rect.minY);
2680
- return overlap > EPS15;
2680
+ return overlap > EPS16;
2681
2681
  } else {
2682
2682
  const y = p1.y;
2683
- if (y < rect.minY - EPS15 || y > rect.maxY + EPS15) return false;
2683
+ if (y < rect.minY - EPS16 || y > rect.maxY + EPS16) return false;
2684
2684
  const segMinX = Math.min(p1.x, p2.x);
2685
2685
  const segMaxX = Math.max(p1.x, p2.x);
2686
2686
  const overlap = Math.min(segMaxX, rect.maxX) - Math.max(segMinX, rect.minX);
2687
- return overlap > EPS15;
2687
+ return overlap > EPS16;
2688
2688
  }
2689
2689
  }
2690
2690
  function rectIntersectsAnyTrace(bounds, inputTraceMap, hostPathId, hostSegIndex) {
@@ -3083,14 +3083,14 @@ var SingleNetLabelPlacementSolver = class extends BaseSolver {
3083
3083
  };
3084
3084
  let bestCandidate = null;
3085
3085
  let bestScore = -Infinity;
3086
- const EPS15 = 1e-6;
3086
+ const EPS16 = 1e-6;
3087
3087
  for (const curr of tracesToScan) {
3088
3088
  const pts = curr.tracePath.slice();
3089
3089
  for (let si = 0; si < pts.length - 1; si++) {
3090
3090
  const a = pts[si];
3091
3091
  const b = pts[si + 1];
3092
- const isH = Math.abs(a.y - b.y) < EPS15;
3093
- const isV = Math.abs(a.x - b.x) < EPS15;
3092
+ const isH = Math.abs(a.y - b.y) < EPS16;
3093
+ const isV = Math.abs(a.x - b.x) < EPS16;
3094
3094
  if (!isH && !isV) continue;
3095
3095
  const segmentAllowed = isH ? ["y+", "y-"] : ["x+", "x-"];
3096
3096
  const candidateOrients = orientations.filter(
@@ -4171,7 +4171,11 @@ var GEOMETRY_EPS = 1e-6;
4171
4171
  var SCHEMATIC_TRACE_STROKE_WIDTH = 0.02;
4172
4172
  var SCHEMATIC_TRACE_MIN_CENTERLINE_CLEARANCE = SCHEMATIC_TRACE_STROKE_WIDTH + GEOMETRY_EPS;
4173
4173
  var SCHEMATIC_TRACE_MIN_VISUAL_CENTERLINE_CLEARANCE = SCHEMATIC_TRACE_STROKE_WIDTH * 3;
4174
- var doesPathCoincideWithTraces = (path, traces) => {
4174
+ var doesPathCoincideWithTraces = (path, traces) => doesPathCoincideWithPaths(
4175
+ path,
4176
+ traces.map((trace) => trace.tracePath)
4177
+ );
4178
+ var doesPathCoincideWithPaths = (path, otherPaths) => {
4175
4179
  const rangesOverlap1D = (a1, a2, b1, b2) => Math.min(Math.max(a1, a2), Math.max(b1, b2)) - Math.max(Math.min(a1, a2), Math.min(b1, b2)) > COINCIDENT_EPS;
4176
4180
  for (let i = 0; i < path.length - 1; i++) {
4177
4181
  const pathSegStart = path[i];
@@ -4181,10 +4185,10 @@ var doesPathCoincideWithTraces = (path, traces) => {
4181
4185
  if (!isVertical6 && !isHorizontal5) continue;
4182
4186
  const crossAxis = isVertical6 ? "x" : "y";
4183
4187
  const alongAxis = isVertical6 ? "y" : "x";
4184
- for (const trace of traces) {
4185
- for (let j = 0; j < trace.tracePath.length - 1; j++) {
4186
- const traceSegStart = trace.tracePath[j];
4187
- const traceSegEnd = trace.tracePath[j + 1];
4188
+ for (const otherPath of otherPaths) {
4189
+ for (let j = 0; j < otherPath.length - 1; j++) {
4190
+ const traceSegStart = otherPath[j];
4191
+ const traceSegEnd = otherPath[j + 1];
4188
4192
  const isParallel = Math.abs(traceSegStart[crossAxis] - traceSegEnd[crossAxis]) < COINCIDENT_EPS;
4189
4193
  if (!isParallel) continue;
4190
4194
  const isCoincident = Math.abs(pathSegStart[crossAxis] - traceSegStart[crossAxis]) < COINCIDENT_EPS;
@@ -8862,6 +8866,8 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
8862
8866
  inputProblem;
8863
8867
  traces;
8864
8868
  netLabelPlacements;
8869
+ /** Exact provenance for connector traces created by this solver. */
8870
+ netLabelConnectorTraceIds = /* @__PURE__ */ new Set();
8865
8871
  outputNetLabelPlacements;
8866
8872
  queuedLabelIndices = [];
8867
8873
  currentLabelIndex = null;
@@ -9112,6 +9118,7 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
9112
9118
  };
9113
9119
  this.traces.push(connectorTrace);
9114
9120
  this.traceMap[mspPairId] = connectorTrace;
9121
+ this.netLabelConnectorTraceIds.add(mspPairId);
9115
9122
  }
9116
9123
  finish() {
9117
9124
  this.currentLabelIndex = null;
@@ -9434,7 +9441,7 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
9434
9441
  foundConnectedTrace = false;
9435
9442
  for (const trace of Object.values(this.traceMap)) {
9436
9443
  if (connectedTraceIds.has(trace.mspPairId)) continue;
9437
- if (trace.mspPairId.startsWith("available-net-orientation-")) continue;
9444
+ if (this.netLabelConnectorTraceIds.has(trace.mspPairId)) continue;
9438
9445
  if (trace.globalConnNetId !== label.globalConnNetId) continue;
9439
9446
  if (!trace.pinIds.some((pinId) => connectedPinIds.has(pinId)))
9440
9447
  continue;
@@ -12669,11 +12676,99 @@ var pathEntersAnyNetLabel = ({
12669
12676
  return false;
12670
12677
  };
12671
12678
 
12679
+ // lib/solvers/SameNetJunctionAlignmentSolver/findNearestSharedPinExitRail.ts
12680
+ var getPinFacingAxis = (pin) => {
12681
+ if (!pin._facingDirection) return null;
12682
+ return dir(pin._facingDirection).x === 0 ? "y" : "x";
12683
+ };
12684
+ var isCoordinateOnPinFacingSide = ({
12685
+ coordinate,
12686
+ axis,
12687
+ pin
12688
+ }) => {
12689
+ if (!pin._facingDirection) return false;
12690
+ const facingVector = dir(pin._facingDirection);
12691
+ return (coordinate - pin[axis]) * facingVector[axis] > 0;
12692
+ };
12693
+ var getSegmentAxis2 = (start, end) => {
12694
+ if (isHorizontal2(start, end)) return "x";
12695
+ if (isVertical2(start, end)) return "y";
12696
+ return null;
12697
+ };
12698
+ var getAxisAlignedSegments = (path) => {
12699
+ const segments = [];
12700
+ for (let index = 0; index < path.length - 1; index++) {
12701
+ const start = path[index];
12702
+ const end = path[index + 1];
12703
+ const axis = getSegmentAxis2(start, end);
12704
+ if (!axis) continue;
12705
+ const coordinateAxis = axis === "x" ? "y" : "x";
12706
+ segments.push({ start, end, axis, coordinate: start[coordinateAxis] });
12707
+ }
12708
+ return segments;
12709
+ };
12710
+ var getPinExitPoint = ({
12711
+ pin,
12712
+ departureAxis,
12713
+ railCoordinate
12714
+ }) => departureAxis === "x" ? { x: railCoordinate, y: pin.y } : { x: pin.x, y: railCoordinate };
12715
+ var findNearestSharedPinExitRail = ({
12716
+ donorPath,
12717
+ branchDepartureSegment,
12718
+ sharedPin,
12719
+ adjacentPin
12720
+ }) => {
12721
+ const departureAxis = getPinFacingAxis(sharedPin);
12722
+ if (!departureAxis) return null;
12723
+ const railAxis = departureAxis === "x" ? "y" : "x";
12724
+ const branchDeparture = getAxisAlignedSegments(branchDepartureSegment)[0];
12725
+ if (!branchDeparture || branchDeparture.axis !== departureAxis) return null;
12726
+ let nearestRail = null;
12727
+ let nearestDistance = Number.POSITIVE_INFINITY;
12728
+ for (const segment of getAxisAlignedSegments(donorPath)) {
12729
+ if (segment.axis !== railAxis) continue;
12730
+ if (!isCoordinateOnPinFacingSide({
12731
+ coordinate: segment.coordinate,
12732
+ axis: departureAxis,
12733
+ pin: sharedPin
12734
+ })) {
12735
+ continue;
12736
+ }
12737
+ const sharedPinExit = getPinExitPoint({
12738
+ pin: sharedPin,
12739
+ departureAxis,
12740
+ railCoordinate: segment.coordinate
12741
+ });
12742
+ const adjacentPinExit = getPinExitPoint({
12743
+ pin: adjacentPin,
12744
+ departureAxis,
12745
+ railCoordinate: segment.coordinate
12746
+ });
12747
+ if (!tracePathContainsPoint([segment.start, segment.end], sharedPinExit) || !tracePathContainsPoint([segment.start, segment.end], adjacentPinExit) || !tracePathContainsPoint(
12748
+ [branchDeparture.start, branchDeparture.end],
12749
+ sharedPinExit
12750
+ )) {
12751
+ continue;
12752
+ }
12753
+ const distance7 = Math.abs(segment.coordinate - sharedPin[departureAxis]);
12754
+ if (distance7 >= nearestDistance) continue;
12755
+ nearestRail = { segment, sharedPinExit };
12756
+ nearestDistance = distance7;
12757
+ }
12758
+ return nearestRail;
12759
+ };
12760
+
12672
12761
  // lib/solvers/SameNetJunctionAlignmentSolver/alignSameNetJunctions.ts
12673
12762
  var MAX_ALIGNED_LOAD_PIN_OFFSET = 0.2;
12674
12763
  var MAX_SAME_NET_LABEL_BOUNDARY_RAIL_OFFSET = 0.2;
12675
12764
  var MAX_SHARED_PIN_RAIL_OFFSET = 0.05;
12765
+ var MAX_SHARED_ENDPOINT_RAIL_OFFSET = 0.8;
12676
12766
  var MIN_RETURN_STEM_LENGTH = 0.05;
12767
+ var getSegmentAxis3 = (start, end) => {
12768
+ if (isHorizontal2(start, end)) return "x";
12769
+ if (isVertical2(start, end)) return "y";
12770
+ return null;
12771
+ };
12677
12772
  var getSharedPin = ({
12678
12773
  donorTrace,
12679
12774
  branchTrace
@@ -12826,11 +12921,366 @@ var getAlignedBranchPath = ({
12826
12921
  if (branchTrace.pins[0].pinId === sharedPin.pinId) return sharedToOther;
12827
12922
  return [...sharedToOther].reverse();
12828
12923
  };
12924
+ var getAlignedParallelPinExitPath = ({
12925
+ donorTrace,
12926
+ branchTrace
12927
+ }) => {
12928
+ const sharedPin = getSharedPin({ donorTrace, branchTrace });
12929
+ if (!sharedPin) return null;
12930
+ const adjacentPin = getOtherPin({ trace: donorTrace, sharedPin });
12931
+ const targetPin = getOtherPin({ trace: branchTrace, sharedPin });
12932
+ if (!adjacentPin || !targetPin) return null;
12933
+ const facing = sharedPin._facingDirection;
12934
+ const departureAxis = getPinFacingAxis(sharedPin);
12935
+ if (!facing || !departureAxis) return null;
12936
+ const stemAxis = departureAxis === "x" ? "y" : "x";
12937
+ if (adjacentPin.chipId !== sharedPin.chipId || adjacentPin._facingDirection !== facing || !nearlyEqual(adjacentPin[departureAxis], sharedPin[departureAxis]) || getPinFacingAxis(targetPin) !== stemAxis) {
12938
+ return null;
12939
+ }
12940
+ const adjacentPinOffset = Math.abs(
12941
+ adjacentPin[stemAxis] - sharedPin[stemAxis]
12942
+ );
12943
+ if (adjacentPinOffset > MAX_ALIGNED_LOAD_PIN_OFFSET && !nearlyEqual(adjacentPinOffset, MAX_ALIGNED_LOAD_PIN_OFFSET)) {
12944
+ return null;
12945
+ }
12946
+ const branchStartsAtSharedPin = branchTrace.pins[0].pinId === sharedPin.pinId;
12947
+ let sharedToTargetPath = simplifyPath(branchTrace.tracePath);
12948
+ if (!branchStartsAtSharedPin) sharedToTargetPath.reverse();
12949
+ if (sharedToTargetPath.length < 2) return null;
12950
+ const branchDepartureSegment = [
12951
+ sharedToTargetPath[0],
12952
+ sharedToTargetPath[1]
12953
+ ];
12954
+ const sharedExitRail = findNearestSharedPinExitRail({
12955
+ donorPath: donorTrace.tracePath,
12956
+ branchDepartureSegment,
12957
+ sharedPin,
12958
+ adjacentPin
12959
+ });
12960
+ if (!sharedExitRail) return null;
12961
+ const alignedRailCoordinate = adjacentPin[stemAxis];
12962
+ if (!isCoordinateOnPinFacingSide({
12963
+ coordinate: alignedRailCoordinate,
12964
+ axis: stemAxis,
12965
+ pin: targetPin
12966
+ })) {
12967
+ return null;
12968
+ }
12969
+ const alignedStemExit = {
12970
+ ...sharedExitRail.sharedPinExit,
12971
+ [stemAxis]: alignedRailCoordinate
12972
+ };
12973
+ const targetApproach = {
12974
+ x: targetPin.x,
12975
+ y: targetPin.y,
12976
+ [stemAxis]: alignedRailCoordinate
12977
+ };
12978
+ const candidate = simplifyPath([
12979
+ { x: sharedPin.x, y: sharedPin.y },
12980
+ sharedExitRail.sharedPinExit,
12981
+ alignedStemExit,
12982
+ targetApproach,
12983
+ { x: targetPin.x, y: targetPin.y }
12984
+ ]);
12985
+ return branchStartsAtSharedPin ? candidate : candidate.reverse();
12986
+ };
12987
+ var getAlignedSharedEndpointRailPath = ({
12988
+ donorTrace,
12989
+ branchTrace,
12990
+ netLabelConnectorTraceIds
12991
+ }) => {
12992
+ if (netLabelConnectorTraceIds.has(donorTrace.mspPairId) || netLabelConnectorTraceIds.has(branchTrace.mspPairId)) {
12993
+ return null;
12994
+ }
12995
+ const sharedPin = getSharedPin({ donorTrace, branchTrace });
12996
+ if (!sharedPin) return null;
12997
+ const pathFromShared = (trace) => {
12998
+ const path = simplifyPath(trace.tracePath);
12999
+ return trace.pins[0].pinId === sharedPin.pinId ? path : [...path].reverse();
13000
+ };
13001
+ const donorPath = pathFromShared(donorTrace);
13002
+ const branchPath = pathFromShared(branchTrace);
13003
+ if (donorPath.length < 3 || branchPath.length < 4) return null;
13004
+ const donorDepartureAxis = getSegmentAxis3(donorPath[0], donorPath[1]);
13005
+ const branchDepartureAxis = getSegmentAxis3(branchPath[0], branchPath[1]);
13006
+ if (!donorDepartureAxis || donorDepartureAxis !== branchDepartureAxis) {
13007
+ return null;
13008
+ }
13009
+ const donorDeparture = donorPath[1][donorDepartureAxis] - donorPath[0][donorDepartureAxis];
13010
+ const branchDeparture = branchPath[1][branchDepartureAxis] - branchPath[0][branchDepartureAxis];
13011
+ if (Math.sign(donorDeparture) !== Math.sign(branchDeparture)) return null;
13012
+ const donorRailAxis = getSegmentAxis3(donorPath[1], donorPath[2]);
13013
+ const branchRailAxis = getSegmentAxis3(branchPath[1], branchPath[2]);
13014
+ if (!donorRailAxis || donorRailAxis !== branchRailAxis || donorRailAxis === donorDepartureAxis) {
13015
+ return null;
13016
+ }
13017
+ let branchParallelRailCount = 0;
13018
+ for (let index = 1; index < branchPath.length - 2; index++) {
13019
+ if (getSegmentAxis3(branchPath[index], branchPath[index + 1]) === branchRailAxis) {
13020
+ branchParallelRailCount++;
13021
+ }
13022
+ }
13023
+ if (branchParallelRailCount !== 1) return null;
13024
+ const railCoordinateAxis = donorRailAxis === "x" ? "y" : "x";
13025
+ const donorCoordinate = donorPath[1][railCoordinateAxis];
13026
+ const branchCoordinate = branchPath[1][railCoordinateAxis];
13027
+ const railOffset = Math.abs(donorCoordinate - branchCoordinate);
13028
+ if (nearlyEqual(donorCoordinate, branchCoordinate) || railOffset > MAX_SHARED_ENDPOINT_RAIL_OFFSET) {
13029
+ return null;
13030
+ }
13031
+ const donorRange = [
13032
+ donorPath[1][donorRailAxis],
13033
+ donorPath[2][donorRailAxis]
13034
+ ].sort((a, b) => a - b);
13035
+ const branchRange = [
13036
+ branchPath[1][branchRailAxis],
13037
+ branchPath[2][branchRailAxis]
13038
+ ].sort((a, b) => a - b);
13039
+ const railsTouchAfterAlignment = Math.min(donorRange[1], branchRange[1]) >= Math.max(donorRange[0], branchRange[0]) - 1e-6;
13040
+ if (!railsTouchAfterAlignment) return null;
13041
+ const candidateFromShared = simplifyPath(
13042
+ branchPath.map(
13043
+ (point, index) => index === 1 || index === 2 ? { ...point, [railCoordinateAxis]: donorCoordinate } : point
13044
+ )
13045
+ );
13046
+ return branchTrace.pins[0].pinId === sharedPin.pinId ? candidateFromShared : candidateFromShared.reverse();
13047
+ };
13048
+ var getAlignedAttachedLabelConnectorPath = ({
13049
+ donorTrace,
13050
+ connectorTrace,
13051
+ netLabelConnectorTraceIds
13052
+ }) => {
13053
+ if (netLabelConnectorTraceIds.has(donorTrace.mspPairId) || !netLabelConnectorTraceIds.has(connectorTrace.mspPairId)) {
13054
+ return null;
13055
+ }
13056
+ const findCandidate = (connectorPath) => {
13057
+ if (connectorPath.length < 3) return null;
13058
+ const junction = connectorPath[0];
13059
+ const turn = connectorPath[1];
13060
+ const railEnd = connectorPath[2];
13061
+ const departureAxis = getSegmentAxis3(junction, turn);
13062
+ const railAxis = getSegmentAxis3(turn, railEnd);
13063
+ if (!departureAxis || !railAxis || departureAxis === railAxis) return null;
13064
+ const donorSegmentIndex = donorTrace.tracePath.findIndex(
13065
+ (point, index, path) => {
13066
+ const next = path[index + 1];
13067
+ return next && getSegmentAxis3(point, next) === departureAxis && tracePathContainsPoint([point, next], junction) && tracePathContainsPoint([point, next], turn);
13068
+ }
13069
+ );
13070
+ if (donorSegmentIndex < 0) return null;
13071
+ const donorSegmentStart = donorTrace.tracePath[donorSegmentIndex];
13072
+ const donorSegmentEnd = donorTrace.tracePath[donorSegmentIndex + 1];
13073
+ if (nearlyEqual(junction.x, donorSegmentStart.x) && nearlyEqual(junction.y, donorSegmentStart.y) || nearlyEqual(junction.x, donorSegmentEnd.x) && nearlyEqual(junction.y, donorSegmentEnd.y)) {
13074
+ return null;
13075
+ }
13076
+ const adjacentDonorRails = [
13077
+ donorSegmentIndex > 0 ? [donorTrace.tracePath[donorSegmentIndex - 1], donorSegmentStart] : null,
13078
+ donorSegmentIndex + 2 < donorTrace.tracePath.length ? [donorSegmentEnd, donorTrace.tracePath[donorSegmentIndex + 2]] : null
13079
+ ].flatMap(
13080
+ (segment) => segment && getSegmentAxis3(segment[0], segment[1]) === railAxis ? [segment] : []
13081
+ );
13082
+ if (adjacentDonorRails.length === 0) return null;
13083
+ const railCoordinateAxis = railAxis === "x" ? "y" : "x";
13084
+ const connectorRailCoordinate = turn[railCoordinateAxis];
13085
+ const connectorRange = [turn[railAxis], railEnd[railAxis]].sort(
13086
+ (a, b) => a - b
13087
+ );
13088
+ const donorRail = adjacentDonorRails.map((segment) => ({
13089
+ segment,
13090
+ coordinate: segment[0][railCoordinateAxis],
13091
+ offset: Math.abs(
13092
+ segment[0][railCoordinateAxis] - connectorRailCoordinate
13093
+ )
13094
+ })).filter(({ segment, offset }) => {
13095
+ if (offset > MAX_SHARED_ENDPOINT_RAIL_OFFSET) return false;
13096
+ const donorRange = [segment[0][railAxis], segment[1][railAxis]].sort(
13097
+ (a, b) => a - b
13098
+ );
13099
+ const overlapStart = Math.max(donorRange[0], connectorRange[0]);
13100
+ const overlapEnd = Math.min(donorRange[1], connectorRange[1]);
13101
+ return overlapEnd >= overlapStart - 1e-6 && Math.abs(overlapEnd - overlapStart) <= 1e-6;
13102
+ }).sort((a, b) => a.offset - b.offset)[0];
13103
+ if (!donorRail || nearlyEqual(donorRail.offset, 0)) return null;
13104
+ return simplifyPath(
13105
+ connectorPath.map(
13106
+ (point, index) => index === 1 || index === 2 ? { ...point, [railCoordinateAxis]: donorRail.coordinate } : point
13107
+ )
13108
+ );
13109
+ };
13110
+ const forwardPath = simplifyPath(connectorTrace.tracePath);
13111
+ const forwardCandidate = findCandidate(forwardPath);
13112
+ if (forwardCandidate) return forwardCandidate;
13113
+ const reverseCandidate = findCandidate([...forwardPath].reverse());
13114
+ return reverseCandidate ? reverseCandidate.reverse() : null;
13115
+ };
13116
+ var pathsIntersect = (firstPath, secondPath) => {
13117
+ if (firstPath.some((point) => tracePathContainsPoint(secondPath, point)) || secondPath.some((point) => tracePathContainsPoint(firstPath, point))) {
13118
+ return true;
13119
+ }
13120
+ for (let firstIndex = 1; firstIndex < firstPath.length; firstIndex++) {
13121
+ for (let secondIndex = 1; secondIndex < secondPath.length; secondIndex++) {
13122
+ if (getSegmentIntersection3(
13123
+ firstPath[firstIndex - 1],
13124
+ firstPath[firstIndex],
13125
+ secondPath[secondIndex - 1],
13126
+ secondPath[secondIndex]
13127
+ )) {
13128
+ return true;
13129
+ }
13130
+ }
13131
+ }
13132
+ return false;
13133
+ };
13134
+ var preserveAttachedLabelConnectorJunctions = ({
13135
+ originalTrace,
13136
+ candidateTrace,
13137
+ traces,
13138
+ netLabelConnectorTraceIds
13139
+ }) => {
13140
+ let outputTraces = traces.map(
13141
+ (trace) => trace.mspPairId === originalTrace.mspPairId ? candidateTrace : trace
13142
+ );
13143
+ for (const connector of traces) {
13144
+ if (connector.mspPairId === originalTrace.mspPairId || !netLabelConnectorTraceIds.has(connector.mspPairId) || connector.globalConnNetId !== originalTrace.globalConnNetId || !pathsIntersect(originalTrace.tracePath, connector.tracePath) || pathsIntersect(candidateTrace.tracePath, connector.tracePath)) {
13145
+ continue;
13146
+ }
13147
+ const endpointIndex = [0, connector.tracePath.length - 1].find(
13148
+ (index) => tracePathContainsPoint(
13149
+ originalTrace.tracePath,
13150
+ connector.tracePath[index]
13151
+ )
13152
+ );
13153
+ if (endpointIndex === void 0) return null;
13154
+ const originalJunction = connector.tracePath[endpointIndex];
13155
+ const movedJunction = getMovedAnchorPointForReroute(
13156
+ originalJunction,
13157
+ originalTrace.tracePath,
13158
+ candidateTrace.tracePath
13159
+ );
13160
+ if (!movedJunction) return null;
13161
+ const neighborIndex = endpointIndex === 0 ? 1 : endpointIndex - 1;
13162
+ const neighbor = connector.tracePath[neighborIndex];
13163
+ if (!neighbor || getSegmentAxis3(originalJunction, neighbor) !== getSegmentAxis3(movedJunction, neighbor)) {
13164
+ return null;
13165
+ }
13166
+ const movedConnector = {
13167
+ ...connector,
13168
+ tracePath: connector.tracePath.map(
13169
+ (point, index) => index === endpointIndex ? movedJunction : point
13170
+ )
13171
+ };
13172
+ if (!pathsIntersect(candidateTrace.tracePath, movedConnector.tracePath)) {
13173
+ return null;
13174
+ }
13175
+ outputTraces = outputTraces.map(
13176
+ (trace) => trace.mspPairId === connector.mspPairId ? movedConnector : trace
13177
+ );
13178
+ }
13179
+ return outputTraces;
13180
+ };
13181
+ var getPerpendicularPinRail = ({
13182
+ trace,
13183
+ endpointPin
13184
+ }) => {
13185
+ const otherPin = getOtherPin({ trace, sharedPin: endpointPin });
13186
+ if (!otherPin) return null;
13187
+ const startsAtEndpoint = trace.pins[0].pinId === endpointPin.pinId;
13188
+ let endpointToOtherPath = simplifyPath(trace.tracePath);
13189
+ if (!startsAtEndpoint) endpointToOtherPath.reverse();
13190
+ if (endpointToOtherPath.length !== 3) return null;
13191
+ const [endpoint, railPoint, other] = endpointToOtherPath;
13192
+ const endpointFacing = endpointPin._facingDirection;
13193
+ if (endpointFacing === "y+" || endpointFacing === "y-") {
13194
+ if (otherPin._facingDirection !== "x+" && otherPin._facingDirection !== "x-") {
13195
+ return null;
13196
+ }
13197
+ if (!isVertical2(endpoint, railPoint) || !isHorizontal2(railPoint, other) || !railIsOnFacingSide({ railY: railPoint.y, pin: endpointPin })) {
13198
+ return null;
13199
+ }
13200
+ const approachesOtherFromFacingSide2 = otherPin._facingDirection === "x-" ? railPoint.x < otherPin.x : railPoint.x > otherPin.x;
13201
+ return approachesOtherFromFacingSide2 ? { railCoordinate: railPoint.y } : null;
13202
+ }
13203
+ if (endpointFacing !== "x+" && endpointFacing !== "x-") return null;
13204
+ if (otherPin._facingDirection !== "y+" && otherPin._facingDirection !== "y-") {
13205
+ return null;
13206
+ }
13207
+ if (!isHorizontal2(endpoint, railPoint) || !isVertical2(railPoint, other)) {
13208
+ return null;
13209
+ }
13210
+ const railIsOnEndpointFacingSide = endpointFacing === "x+" ? railPoint.x > endpointPin.x : railPoint.x < endpointPin.x;
13211
+ const approachesOtherFromFacingSide = otherPin._facingDirection === "y+" ? railPoint.y > otherPin.y : railPoint.y < otherPin.y;
13212
+ return railIsOnEndpointFacingSide && approachesOtherFromFacingSide ? { railCoordinate: railPoint.x } : null;
13213
+ };
13214
+ var getAlignedPerpendicularEndpointBusPath = ({
13215
+ donorTrace,
13216
+ branchTrace,
13217
+ traces
13218
+ }) => {
13219
+ const sharedPin = getSharedPin({ donorTrace, branchTrace });
13220
+ if (!sharedPin) return null;
13221
+ const returnPin = getOtherPin({ trace: branchTrace, sharedPin });
13222
+ if (!returnPin) return null;
13223
+ const getOtherSameNetTracesAtPin = (pin) => traces.filter(
13224
+ (trace) => trace.mspPairId !== branchTrace.mspPairId && trace.globalConnNetId === branchTrace.globalConnNetId && trace.pinIds.includes(pin.pinId)
13225
+ );
13226
+ const sharedDonorTraces = getOtherSameNetTracesAtPin(sharedPin);
13227
+ const returnDonorTraces = getOtherSameNetTracesAtPin(returnPin);
13228
+ if (sharedDonorTraces.length !== 1 || sharedDonorTraces[0].mspPairId !== donorTrace.mspPairId || returnDonorTraces.length !== 1) {
13229
+ return null;
13230
+ }
13231
+ const sharedRail = getPerpendicularPinRail({
13232
+ trace: donorTrace,
13233
+ endpointPin: sharedPin
13234
+ });
13235
+ if (!sharedRail) return null;
13236
+ const facing = sharedPin._facingDirection;
13237
+ const verticalEndpoints = facing === "y+" || facing === "y-";
13238
+ const horizontalEndpoints = facing === "x+" || facing === "x-";
13239
+ if (!verticalEndpoints && !horizontalEndpoints) return null;
13240
+ if (verticalEndpoints !== (returnPin._facingDirection === "y+" || returnPin._facingDirection === "y-")) {
13241
+ return null;
13242
+ }
13243
+ const branchStartsAtSharedPin = branchTrace.pins[0].pinId === sharedPin.pinId;
13244
+ let sharedToReturnPath = simplifyPath(branchTrace.tracePath);
13245
+ if (!branchStartsAtSharedPin) sharedToReturnPath.reverse();
13246
+ if (sharedToReturnPath.length !== 6) return null;
13247
+ const expectedSegmentOrientations = verticalEndpoints ? ["V", "H", "V", "H", "V"] : ["H", "V", "H", "V", "H"];
13248
+ const actualSegmentOrientations = sharedToReturnPath.slice(1).map(
13249
+ (point, index) => isHorizontal2(sharedToReturnPath[index], point) ? "H" : isVertical2(sharedToReturnPath[index], point) ? "V" : "D"
13250
+ );
13251
+ if (actualSegmentOrientations.some(
13252
+ (orientation, index) => orientation !== expectedSegmentOrientations[index]
13253
+ )) {
13254
+ return null;
13255
+ }
13256
+ const returnRail = getPerpendicularPinRail({
13257
+ trace: returnDonorTraces[0],
13258
+ endpointPin: returnPin
13259
+ });
13260
+ if (!returnRail) return null;
13261
+ const candidate = verticalEndpoints ? simplifyPath([
13262
+ { x: sharedPin.x, y: sharedPin.y },
13263
+ { x: sharedPin.x, y: sharedRail.railCoordinate },
13264
+ { x: sharedToReturnPath[2].x, y: sharedRail.railCoordinate },
13265
+ { x: sharedToReturnPath[3].x, y: returnRail.railCoordinate },
13266
+ { x: returnPin.x, y: returnRail.railCoordinate },
13267
+ { x: returnPin.x, y: returnPin.y }
13268
+ ]) : simplifyPath([
13269
+ { x: sharedPin.x, y: sharedPin.y },
13270
+ { x: sharedRail.railCoordinate, y: sharedPin.y },
13271
+ { x: sharedRail.railCoordinate, y: sharedToReturnPath[2].y },
13272
+ { x: returnRail.railCoordinate, y: sharedToReturnPath[3].y },
13273
+ { x: returnRail.railCoordinate, y: returnPin.y },
13274
+ { x: returnPin.x, y: returnPin.y }
13275
+ ]);
13276
+ return branchStartsAtSharedPin ? candidate : candidate.reverse();
13277
+ };
12829
13278
  var candidateIsClear = ({
12830
13279
  candidateTrace,
12831
13280
  originalTrace,
12832
13281
  traces,
12833
13282
  inputProblem,
13283
+ originalNetLabelPlacements,
12834
13284
  candidateNetLabelPlacements,
12835
13285
  attachedLabelIndexes
12836
13286
  }) => {
@@ -12873,6 +13323,53 @@ var candidateIsClear = ({
12873
13323
  )) {
12874
13324
  return false;
12875
13325
  }
13326
+ const labelHitsTrace = (label, trace) => pathIntersectsAnyNetLabel({
13327
+ path: trace.tracePath,
13328
+ netLabelPlacements: [label]
13329
+ });
13330
+ for (const labelIndex of attachedLabelIndexes) {
13331
+ const originalLabel = originalNetLabelPlacements[labelIndex];
13332
+ const candidateLabel = candidateNetLabelPlacements[labelIndex];
13333
+ const originalBounds = getRectBounds(
13334
+ originalLabel.center,
13335
+ originalLabel.width,
13336
+ originalLabel.height
13337
+ );
13338
+ const candidateBounds = getRectBounds(
13339
+ candidateLabel.center,
13340
+ candidateLabel.width,
13341
+ candidateLabel.height
13342
+ );
13343
+ for (const trace of traces) {
13344
+ if (trace.globalConnNetId === candidateLabel.globalConnNetId) continue;
13345
+ if (labelHitsTrace(candidateLabel, trace) && !labelHitsTrace(originalLabel, trace)) {
13346
+ return false;
13347
+ }
13348
+ }
13349
+ for (const obstacle of obstacles) {
13350
+ if (rectsOverlap(candidateBounds, obstacle) && !rectsOverlap(originalBounds, obstacle)) {
13351
+ return false;
13352
+ }
13353
+ }
13354
+ for (let otherIndex = 0; otherIndex < candidateNetLabelPlacements.length; otherIndex++) {
13355
+ if (otherIndex === labelIndex) continue;
13356
+ const originalOther = originalNetLabelPlacements[otherIndex];
13357
+ const candidateOther = candidateNetLabelPlacements[otherIndex];
13358
+ const originalOtherBounds = getRectBounds(
13359
+ originalOther.center,
13360
+ originalOther.width,
13361
+ originalOther.height
13362
+ );
13363
+ const candidateOtherBounds = getRectBounds(
13364
+ candidateOther.center,
13365
+ candidateOther.width,
13366
+ candidateOther.height
13367
+ );
13368
+ if (rectsOverlap(candidateBounds, candidateOtherBounds) && !rectsOverlap(originalBounds, originalOtherBounds)) {
13369
+ return false;
13370
+ }
13371
+ }
13372
+ }
12876
13373
  const otherNetLabelPlacements = candidateNetLabelPlacements.filter(
12877
13374
  (label) => label.globalConnNetId !== candidateTrace.globalConnNetId
12878
13375
  );
@@ -12956,13 +13453,14 @@ var getAlignedReturnBranchPath = ({
12956
13453
  var alignSameNetJunctions = ({
12957
13454
  inputProblem,
12958
13455
  traces,
12959
- netLabelPlacements
13456
+ netLabelPlacements,
13457
+ netLabelConnectorTraceIds
12960
13458
  }) => {
12961
13459
  let outputTraces = [...traces];
12962
13460
  let outputNetLabelPlacements = [...netLabelPlacements];
12963
13461
  let alignedJunctionCount = 0;
13462
+ const alignedBranchTraceIds = /* @__PURE__ */ new Set();
12964
13463
  for (const alignReturnBranches of [false, true]) {
12965
- const alignedBranchTraceIds = /* @__PURE__ */ new Set();
12966
13464
  const donorTraceIds = traces.map((trace) => trace.mspPairId);
12967
13465
  const pendingDonorTraceIds = new Set(donorTraceIds);
12968
13466
  for (let donorIndex = 0; donorIndex < donorTraceIds.length; donorIndex++) {
@@ -12975,13 +13473,40 @@ var alignSameNetJunctions = ({
12975
13473
  if (alignedBranchTraceIds.has(branchTrace.mspPairId)) continue;
12976
13474
  if (donorTrace.mspPairId === branchTrace.mspPairId) continue;
12977
13475
  if (donorTrace.globalConnNetId !== branchTrace.globalConnNetId) continue;
12978
- const candidatePaths = alignReturnBranches ? [1, 0.5, 0.25].map(
12979
- (returnStemScale) => getAlignedReturnBranchPath({
13476
+ const donorIsLabelConnector = netLabelConnectorTraceIds.has(
13477
+ donorTrace.mspPairId
13478
+ );
13479
+ const branchIsLabelConnector = netLabelConnectorTraceIds.has(
13480
+ branchTrace.mspPairId
13481
+ );
13482
+ const candidatePaths = branchIsLabelConnector ? alignReturnBranches && !donorIsLabelConnector ? [
13483
+ getAlignedAttachedLabelConnectorPath({
13484
+ donorTrace,
13485
+ connectorTrace: branchTrace,
13486
+ netLabelConnectorTraceIds
13487
+ })
13488
+ ] : [] : donorIsLabelConnector ? [] : alignReturnBranches ? [
13489
+ ...[1, 0.5, 0.25].map(
13490
+ (returnStemScale) => getAlignedReturnBranchPath({
13491
+ donorTrace,
13492
+ branchTrace,
13493
+ returnStemScale
13494
+ })
13495
+ ),
13496
+ getAlignedPerpendicularEndpointBusPath({
13497
+ donorTrace,
13498
+ branchTrace,
13499
+ traces: outputTraces
13500
+ }),
13501
+ getAlignedSharedEndpointRailPath({
12980
13502
  donorTrace,
12981
13503
  branchTrace,
12982
- returnStemScale
13504
+ netLabelConnectorTraceIds
12983
13505
  })
12984
- ) : [getAlignedBranchPath({ donorTrace, branchTrace })];
13506
+ ] : [
13507
+ getAlignedBranchPath({ donorTrace, branchTrace }),
13508
+ getAlignedParallelPinExitPath({ donorTrace, branchTrace })
13509
+ ];
12985
13510
  for (const candidatePath of candidatePaths) {
12986
13511
  if (!candidatePath) continue;
12987
13512
  const candidateTrace = { ...branchTrace, tracePath: candidatePath };
@@ -13005,20 +13530,47 @@ var alignSameNetJunctions = ({
13005
13530
  netLabelPlacements: outputNetLabelPlacements,
13006
13531
  attachedLabelIndexes
13007
13532
  });
13533
+ const candidateTraces = preserveAttachedLabelConnectorJunctions({
13534
+ originalTrace: branchTrace,
13535
+ candidateTrace,
13536
+ traces: outputTraces,
13537
+ netLabelConnectorTraceIds
13538
+ });
13539
+ if (!candidateTraces) continue;
13008
13540
  if (!candidateIsClear({
13009
13541
  candidateTrace,
13010
13542
  originalTrace: branchTrace,
13011
- traces: outputTraces,
13543
+ traces: candidateTraces,
13012
13544
  inputProblem,
13545
+ originalNetLabelPlacements: outputNetLabelPlacements,
13013
13546
  candidateNetLabelPlacements,
13014
13547
  attachedLabelIndexes
13015
13548
  })) {
13016
13549
  continue;
13017
13550
  }
13018
- outputTraces = outputTraces.map((trace) => {
13019
- if (trace.mspPairId === branchTrace.mspPairId) return candidateTrace;
13020
- return trace;
13551
+ const movedConnectorsAreClear = candidateTraces.every((trace) => {
13552
+ if (trace.mspPairId === branchTrace.mspPairId || !netLabelConnectorTraceIds.has(trace.mspPairId)) {
13553
+ return true;
13554
+ }
13555
+ const originalConnector = outputTraces.find(
13556
+ (originalTrace) => originalTrace.mspPairId === trace.mspPairId
13557
+ );
13558
+ if (originalConnector.tracePath === trace.tracePath) return true;
13559
+ return candidateIsClear({
13560
+ candidateTrace: trace,
13561
+ originalTrace: originalConnector,
13562
+ traces: candidateTraces,
13563
+ inputProblem,
13564
+ originalNetLabelPlacements: outputNetLabelPlacements,
13565
+ candidateNetLabelPlacements,
13566
+ attachedLabelIndexes: getAttachedLabelIndexes(
13567
+ originalConnector,
13568
+ outputNetLabelPlacements
13569
+ )
13570
+ });
13021
13571
  });
13572
+ if (!movedConnectorsAreClear) continue;
13573
+ outputTraces = candidateTraces;
13022
13574
  outputNetLabelPlacements = candidateNetLabelPlacements;
13023
13575
  alignedBranchTraceIds.add(branchTrace.mspPairId);
13024
13576
  alignedJunctionCount++;
@@ -13830,7 +14382,7 @@ var alignPortOnlyInlineNetLabelStubs = ({
13830
14382
  };
13831
14383
 
13832
14384
  // lib/solvers/InlineNetLabelSolver/getAxisAlignedSegments.ts
13833
- var getAxisAlignedSegments = (path, epsilon = 1e-6) => {
14385
+ var getAxisAlignedSegments2 = (path, epsilon = 1e-6) => {
13834
14386
  const segments = [];
13835
14387
  let runStart = null;
13836
14388
  let runAxis = null;
@@ -14445,6 +14997,131 @@ var pushInlineTerminalLabelsAwayFromAnchoredLabels = ({
14445
14997
  };
14446
14998
  };
14447
14999
 
15000
+ // lib/solvers/InlineNetLabelSolver/restoreReroutesAroundSupersededLabels.ts
15001
+ import { getSegmentIntersection as getSegmentIntersection5 } from "@tscircuit/math-utils/line-intersections";
15002
+
15003
+ // lib/utils/pathIntersectsRenderedLabel.ts
15004
+ import {
15005
+ doesSegmentIntersectRect,
15006
+ getBoundFromCenteredRect
15007
+ } from "@tscircuit/math-utils";
15008
+ var pathIntersectsRenderedLabel = (path, label) => {
15009
+ let width = label.width;
15010
+ let height = label.height;
15011
+ if ("axis" in label && label.axis === "y") {
15012
+ width = label.height;
15013
+ height = label.width;
15014
+ }
15015
+ const bounds = getBoundFromCenteredRect({
15016
+ center: label.center,
15017
+ width,
15018
+ height
15019
+ });
15020
+ for (let pathIndex = 0; pathIndex < path.length - 1; pathIndex++) {
15021
+ if (doesSegmentIntersectRect(path[pathIndex], path[pathIndex + 1], bounds)) {
15022
+ return true;
15023
+ }
15024
+ }
15025
+ return false;
15026
+ };
15027
+
15028
+ // lib/solvers/InlineNetLabelSolver/restoreReroutesAroundSupersededLabels.ts
15029
+ var EPS14 = 1e-6;
15030
+ var getPathLength5 = (path) => path.slice(1).reduce((length, point, pointIndex) => {
15031
+ const previousPoint = path[pointIndex];
15032
+ return length + Math.abs(point.x - previousPoint.x) + Math.abs(point.y - previousPoint.y);
15033
+ }, 0);
15034
+ var pathsEqual = (first, second) => first.length === second.length && first.every(
15035
+ (point, index) => Math.abs(point.x - second[index].x) <= EPS14 && Math.abs(point.y - second[index].y) <= EPS14
15036
+ );
15037
+ var isStrictlySimpler = (candidate, current) => candidate.length < current.length && getPathLength5(candidate) <= getPathLength5(current) + EPS14;
15038
+ var getIntersectionKeys = (path, otherPath) => {
15039
+ const intersections = /* @__PURE__ */ new Set();
15040
+ for (let pathIndex = 0; pathIndex < path.length - 1; pathIndex++) {
15041
+ for (let otherPathIndex = 0; otherPathIndex < otherPath.length - 1; otherPathIndex++) {
15042
+ const point = getSegmentIntersection5(
15043
+ path[pathIndex],
15044
+ path[pathIndex + 1],
15045
+ otherPath[otherPathIndex],
15046
+ otherPath[otherPathIndex + 1]
15047
+ );
15048
+ if (point) {
15049
+ intersections.add(`${point.x.toFixed(6)},${point.y.toFixed(6)}`);
15050
+ }
15051
+ }
15052
+ }
15053
+ return intersections;
15054
+ };
15055
+ var introducesNewCrossings = (candidatePath, currentPath, otherPaths) => otherPaths.some((otherPath) => {
15056
+ const currentIntersections = getIntersectionKeys(currentPath, otherPath);
15057
+ const candidateIntersections = getIntersectionKeys(candidatePath, otherPath);
15058
+ return [...candidateIntersections].some(
15059
+ (intersection) => !currentIntersections.has(intersection)
15060
+ );
15061
+ });
15062
+ var restoreReroutesAroundSupersededLabels = ({
15063
+ inputProblem,
15064
+ traces,
15065
+ netLabelPlacements,
15066
+ inlineNetLabelPlacements,
15067
+ completedReroutes
15068
+ }) => {
15069
+ const outputTraces = [...traces];
15070
+ const supersededLabelGlobalConnNetIds = new Set(
15071
+ inlineNetLabelPlacements.map((placement) => placement.globalConnNetId)
15072
+ );
15073
+ const obstacles = getObstacleRects(inputProblem);
15074
+ let restoredTraceCount = 0;
15075
+ for (const reroute of [...completedReroutes].reverse()) {
15076
+ if (!supersededLabelGlobalConnNetIds.has(reroute.label.globalConnNetId)) {
15077
+ continue;
15078
+ }
15079
+ const traceIndex = outputTraces.findIndex(
15080
+ (trace) => trace.mspPairId === reroute.initialTrace.mspPairId
15081
+ );
15082
+ if (traceIndex < 0) continue;
15083
+ const currentTrace = outputTraces[traceIndex];
15084
+ const currentPath = simplifyPath(currentTrace.tracePath);
15085
+ const recordedReroutePath = simplifyPath(reroute.reroutedTracePath);
15086
+ if (!pathsEqual(currentPath, recordedReroutePath)) continue;
15087
+ const candidatePath = simplifyPath(reroute.initialTrace.tracePath);
15088
+ if (!isStrictlySimpler(candidatePath, currentPath)) continue;
15089
+ const candidateTrace = { ...currentTrace, tracePath: candidatePath };
15090
+ const otherNetTraces = outputTraces.filter(
15091
+ (trace) => trace.mspPairId !== currentTrace.mspPairId && trace.globalConnNetId !== currentTrace.globalConnNetId
15092
+ );
15093
+ const otherNetInlineLabels = inlineNetLabelPlacements.filter(
15094
+ (label) => label.globalConnNetId !== currentTrace.globalConnNetId
15095
+ );
15096
+ const otherNetInlineStubPaths = otherNetInlineLabels.flatMap(
15097
+ (label) => label.stubTracePath ? [[...label.stubTracePath]] : []
15098
+ );
15099
+ if (isPathCollidingWithObstacles(candidatePath, obstacles) || detectTraceLabelOverlap({
15100
+ traces: [candidateTrace],
15101
+ netLabels: netLabelPlacements
15102
+ }).length > 0 || otherNetInlineLabels.some(
15103
+ (label) => pathIntersectsRenderedLabel(candidatePath, label)
15104
+ ) || doesPathCoincideWithTraces(candidatePath, otherNetTraces) || doesPathCoincideWithPaths(candidatePath, otherNetInlineStubPaths) || introducesNewCrossings(
15105
+ candidatePath,
15106
+ currentPath,
15107
+ otherNetTraces.map((trace) => trace.tracePath)
15108
+ ) || introducesNewCrossings(
15109
+ candidatePath,
15110
+ currentPath,
15111
+ otherNetInlineStubPaths
15112
+ ) || !preservesLabelAnchors(
15113
+ netLabelPlacements,
15114
+ [currentTrace],
15115
+ [candidateTrace]
15116
+ )) {
15117
+ continue;
15118
+ }
15119
+ outputTraces[traceIndex] = candidateTrace;
15120
+ restoredTraceCount++;
15121
+ }
15122
+ return { traces: outputTraces, restoredTraceCount };
15123
+ };
15124
+
14448
15125
  // lib/solvers/InlineNetLabelSolver/InlineNetLabelSolver.ts
14449
15126
  var DEFAULT_INLINE_NET_LABEL_HEIGHT = 0.18;
14450
15127
  var INLINE_NET_LABEL_TRACE_MARGIN = 0.05;
@@ -14477,6 +15154,7 @@ var InlineNetLabelSolver = class extends BaseSolver {
14477
15154
  inputProblem;
14478
15155
  traces;
14479
15156
  inputNetLabelPlacements;
15157
+ completedReroutes;
14480
15158
  inlineNetLabelPlacements = [];
14481
15159
  /** Eligible connections still waiting to be processed. */
14482
15160
  queuedConnections;
@@ -14490,6 +15168,7 @@ var InlineNetLabelSolver = class extends BaseSolver {
14490
15168
  this.inputProblem = input.inputProblem;
14491
15169
  this.traces = input.traces;
14492
15170
  this.inputNetLabelPlacements = input.netLabelPlacements;
15171
+ this.completedReroutes = input.completedReroutes ?? [];
14493
15172
  this.globalConnMap = getConnectivityMapsFromInputProblem(
14494
15173
  this.inputProblem
14495
15174
  ).netConnMap;
@@ -14524,7 +15203,8 @@ var InlineNetLabelSolver = class extends BaseSolver {
14524
15203
  {
14525
15204
  inputProblem: this.inputProblem,
14526
15205
  traces: this.traces,
14527
- netLabelPlacements: this.inputNetLabelPlacements
15206
+ netLabelPlacements: this.inputNetLabelPlacements,
15207
+ completedReroutes: this.completedReroutes
14528
15208
  }
14529
15209
  ];
14530
15210
  }
@@ -14840,7 +15520,7 @@ var InlineNetLabelSolver = class extends BaseSolver {
14840
15520
  pinIds,
14841
15521
  ignoredTraceIds = /* @__PURE__ */ new Set()
14842
15522
  }) {
14843
- const segments = getAxisAlignedSegments(trace.tracePath);
15523
+ const segments = getAxisAlignedSegments2(trace.tracePath);
14844
15524
  if (segments.length === 0) return null;
14845
15525
  const height = connection.inlineNetLabelHeight ?? DEFAULT_INLINE_NET_LABEL_HEIGHT;
14846
15526
  const netLabelText = connection.netLabelText?.trim() || void 0;
@@ -15097,9 +15777,17 @@ var InlineNetLabelSolver = class extends BaseSolver {
15097
15777
  if (blockedGlobalConnNetIds.size === 0) {
15098
15778
  this.inlineNetLabelPlacements = activeInlinePlacements;
15099
15779
  this.stats.pushedAnchoredNetLabelCount = pushed.movedLabelCount;
15100
- return {
15780
+ const restored = restoreReroutesAroundSupersededLabels({
15781
+ inputProblem: this.inputProblem,
15101
15782
  traces: pushed.traces,
15102
15783
  netLabelPlacements: pushed.netLabelPlacements,
15784
+ inlineNetLabelPlacements: activeInlinePlacements,
15785
+ completedReroutes: this.completedReroutes
15786
+ });
15787
+ this.stats.restoredSupersededLabelRerouteCount = restored.restoredTraceCount;
15788
+ return {
15789
+ traces: restored.traces,
15790
+ netLabelPlacements: pushed.netLabelPlacements,
15103
15791
  inlineNetLabelPlacements: activeInlinePlacements
15104
15792
  };
15105
15793
  }
@@ -15307,12 +15995,6 @@ var getCollisionLimitedTerminalStubEnd = ({
15307
15995
  return isHorizontal5 ? { x: start.x + direction * availableLength, y: start.y } : { x: start.x, y: start.y + direction * availableLength };
15308
15996
  };
15309
15997
 
15310
- // lib/solvers/NetLabelToTraceSolver/NetLabelToTraceSolver.ts
15311
- import {
15312
- doesSegmentIntersectRect,
15313
- getBoundFromCenteredRect
15314
- } from "@tscircuit/math-utils";
15315
-
15316
15998
  // lib/solvers/NetLabelTraceRecovery/doesTraceRecoveryPathConflict.ts
15317
15999
  import { doSegmentsIntersect as doSegmentsIntersect4 } from "@tscircuit/math-utils";
15318
16000
  var EPSILON = 1e-6;
@@ -15407,12 +16089,12 @@ var getTraceRecoveryConnectivityMaps = (inputProblem) => {
15407
16089
  };
15408
16090
 
15409
16091
  // lib/solvers/NetLabelToTraceSolver/reduceTraceCrossings.ts
15410
- var EPS14 = 1e-9;
15411
- var isHorizontal4 = (start, end) => Math.abs(start.y - end.y) < EPS14;
15412
- var isVertical5 = (start, end) => Math.abs(start.x - end.x) < EPS14;
16092
+ var EPS15 = 1e-9;
16093
+ var isHorizontal4 = (start, end) => Math.abs(start.y - end.y) < EPS15;
16094
+ var isVertical5 = (start, end) => Math.abs(start.x - end.x) < EPS15;
15413
16095
  var compactConsecutivePoints = (path) => path.filter((point, index) => {
15414
16096
  const previousPoint = path[index - 1];
15415
- return !previousPoint || Math.abs(point.x - previousPoint.x) >= EPS14 || Math.abs(point.y - previousPoint.y) >= EPS14;
16097
+ return !previousPoint || Math.abs(point.x - previousPoint.x) >= EPS15 || Math.abs(point.y - previousPoint.y) >= EPS15;
15416
16098
  });
15417
16099
  var isValidOrthogonalPath = (path) => {
15418
16100
  if (path.length < 2 || !path.every((point, index) => {
@@ -15450,7 +16132,7 @@ var getEndpointAlignedSegmentCandidates = (tracePath) => {
15450
16132
  }
15451
16133
  const alignedCoordinates = segmentIsVertical ? [previousPoint.x, nextPoint.x] : [previousPoint.y, nextPoint.y];
15452
16134
  for (const alignedCoordinate of alignedCoordinates) {
15453
- if (Math.abs(alignedCoordinate - (segmentIsVertical ? start.x : start.y)) < EPS14) {
16135
+ if (Math.abs(alignedCoordinate - (segmentIsVertical ? start.x : start.y)) < EPS15) {
15454
16136
  continue;
15455
16137
  }
15456
16138
  const candidate = tracePath.map((point) => ({ ...point }));
@@ -15513,25 +16195,6 @@ var RECOVERED_TRACE_PREFIX = "net-label-to-trace-";
15513
16195
  var MAX_NAMED_NET_RECOVERY_PERPENDICULAR_OFFSET = 0.05;
15514
16196
  var MAX_ROUTED_COMPONENT_RECOVERY_PERPENDICULAR_OFFSET = 0.25;
15515
16197
  var getCanonicalPairKey = (firstPinId, secondPinId) => [firstPinId, secondPinId].sort().join("--");
15516
- var pathIntersectsRenderedLabel = (path, label) => {
15517
- let width = label.width;
15518
- let height = label.height;
15519
- if ("axis" in label && label.axis === "y") {
15520
- width = label.height;
15521
- height = label.width;
15522
- }
15523
- const bounds = getBoundFromCenteredRect({
15524
- center: label.center,
15525
- width,
15526
- height
15527
- });
15528
- for (let pathIndex = 0; pathIndex < path.length - 1; pathIndex++) {
15529
- if (doesSegmentIntersectRect(path[pathIndex], path[pathIndex + 1], bounds)) {
15530
- return true;
15531
- }
15532
- }
15533
- return false;
15534
- };
15535
16198
  var getPerpendicularOffset = (firstPoint, secondPoint) => {
15536
16199
  const xDistance = Math.abs(firstPoint.x - secondPoint.x);
15537
16200
  const yDistance = Math.abs(firstPoint.y - secondPoint.y);
@@ -16174,9 +16837,7 @@ var SchematicTracePipelineSolver = class extends BaseSolver {
16174
16837
  inputTracePaths: instance.availableNetOrientationSolver.traces,
16175
16838
  globalConnMap: instance.mspConnectionPairSolver.globalConnMap,
16176
16839
  traceIdsToShift: new Set(
16177
- instance.availableNetOrientationSolver.traces.filter(
16178
- (trace) => trace.mspPairId.startsWith("available-net-orientation-")
16179
- ).map((trace) => trace.mspPairId)
16840
+ instance.availableNetOrientationSolver.netLabelConnectorTraceIds
16180
16841
  )
16181
16842
  }
16182
16843
  ]
@@ -16335,7 +16996,8 @@ var SchematicTracePipelineSolver = class extends BaseSolver {
16335
16996
  {
16336
16997
  inputProblem: instance.inputProblem,
16337
16998
  traces: instance.netLabelNetLabelCollisionSolver.traces,
16338
- netLabelPlacements: collisionOutput.netLabelPlacements
16999
+ netLabelPlacements: collisionOutput.netLabelPlacements,
17000
+ netLabelConnectorTraceIds: instance.availableNetOrientationSolver.netLabelConnectorTraceIds
16339
17001
  }
16340
17002
  ];
16341
17003
  }
@@ -16345,11 +17007,17 @@ var SchematicTracePipelineSolver = class extends BaseSolver {
16345
17007
  InlineNetLabelSolver,
16346
17008
  (instance) => {
16347
17009
  const junctionOutput = instance.sameNetJunctionAlignmentSolver.getOutput();
17010
+ const completedReroutes = [
17011
+ ...instance.traceLabelOverlapAvoidanceSolver.getOutput().completedReroutes,
17012
+ ...instance.preAlignmentNetLabelTraceCollisionSolver.getOutput().completedReroutes,
17013
+ ...instance.netLabelTraceCollisionSolver.getOutput().completedReroutes
17014
+ ];
16348
17015
  return [
16349
17016
  {
16350
17017
  inputProblem: instance.inputProblem,
16351
17018
  traces: junctionOutput.traces,
16352
- netLabelPlacements: junctionOutput.netLabelPlacements
17019
+ netLabelPlacements: junctionOutput.netLabelPlacements,
17020
+ completedReroutes
16353
17021
  }
16354
17022
  ];
16355
17023
  }