@tscircuit/schematic-trace-solver 0.0.176 → 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 };
@@ -396,6 +396,12 @@ var getGroundConnectionPolicy = (inputProblem) => {
396
396
  );
397
397
  });
398
398
  const areSeparateExplicitGroundIslands = (firstPinId, secondPinId) => {
399
+ const firstChipId = pins.get(firstPinId)?.chip.chipId;
400
+ const secondChipId = pins.get(secondPinId)?.chip.chipId;
401
+ const pinsShareChip = firstChipId !== void 0 && firstChipId === secondChipId;
402
+ if (pinsShareChip && !physicalConnMap.getNetConnectedToId(firstPinId) && !physicalConnMap.getNetConnectedToId(secondPinId)) {
403
+ return false;
404
+ }
399
405
  const firstGlobalNetId = netConnMap.getNetConnectedToId(firstPinId);
400
406
  const secondGlobalNetId = netConnMap.getNetConnectedToId(secondPinId);
401
407
  if (!firstGlobalNetId || firstGlobalNetId !== secondGlobalNetId || !explicitlyWiredGroundNetIds.has(firstGlobalNetId)) {
@@ -1575,8 +1581,8 @@ var SchematicTraceSingleLineSolver2 = class extends BaseSolver {
1575
1581
  if (!collision) {
1576
1582
  const first = path[0];
1577
1583
  const last = path[path.length - 1];
1578
- const EPS16 = 1e-9;
1579
- 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;
1580
1586
  if (samePoint(first, { x: PA.x, y: PA.y }) && samePoint(last, { x: PB.x, y: PB.y })) {
1581
1587
  this.solvedTracePath = path;
1582
1588
  this.solved = true;
@@ -1887,13 +1893,13 @@ var applyJogToTerminalSegment = ({
1887
1893
  segmentIndex: si,
1888
1894
  offset,
1889
1895
  JOG_SIZE,
1890
- EPS: EPS16 = 1e-6
1896
+ EPS: EPS17 = 1e-6
1891
1897
  }) => {
1892
1898
  if (si !== 0 && si !== pts.length - 2) return;
1893
1899
  const start = pts[si];
1894
1900
  const end = pts[si + 1];
1895
- const isVertical6 = Math.abs(start.x - end.x) < EPS16;
1896
- 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;
1897
1903
  if (!isVertical6 && !isHorizontal5) return;
1898
1904
  const segDir = isVertical6 ? end.y > start.y ? 1 : -1 : end.x > start.x ? 1 : -1;
1899
1905
  if (pts.length === 2) {
@@ -2327,7 +2333,7 @@ var TraceOverlapShiftSolver = class extends BaseSolver {
2327
2333
  return islands;
2328
2334
  }
2329
2335
  findNextOverlapIssue() {
2330
- const EPS16 = 2e-3;
2336
+ const EPS17 = 2e-3;
2331
2337
  const netIds = Object.keys(this.traceNetIslands);
2332
2338
  for (let i = 0; i < netIds.length; i++) {
2333
2339
  for (let j = i + 1; j < netIds.length; j++) {
@@ -2354,7 +2360,7 @@ var TraceOverlapShiftSolver = class extends BaseSolver {
2354
2360
  segmentBIndex,
2355
2361
  rangeOverlap
2356
2362
  }) => {
2357
- if (rangeOverlap > EPS16) {
2363
+ if (rangeOverlap > EPS17) {
2358
2364
  const keyA = `${pathAIndex}:${segmentAIndex}`;
2359
2365
  const keyB = `${pathBIndex}:${segmentBIndex}`;
2360
2366
  if (!seenA.has(keyA)) {
@@ -2373,7 +2379,7 @@ var TraceOverlapShiftSolver = class extends BaseSolver {
2373
2379
  }
2374
2380
  return;
2375
2381
  }
2376
- if (rangeOverlap < -EPS16) return;
2382
+ if (rangeOverlap < -EPS17) return;
2377
2383
  const pathA = pathsA[pathAIndex].tracePath;
2378
2384
  const pathB = pathsB[pathBIndex].tracePath;
2379
2385
  const segmentAStart = pathA[segmentAIndex];
@@ -2396,8 +2402,8 @@ var TraceOverlapShiftSolver = class extends BaseSolver {
2396
2402
  for (let sa = 0; sa < ptsA.length - 1; sa++) {
2397
2403
  const a1 = ptsA[sa];
2398
2404
  const a2 = ptsA[sa + 1];
2399
- const aVert = Math.abs(a1.x - a2.x) < EPS16;
2400
- 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;
2401
2407
  if (!aVert && !aHorz) continue;
2402
2408
  for (let pb = 0; pb < pathsB.length; pb++) {
2403
2409
  const pathB = pathsB[pb];
@@ -2408,11 +2414,11 @@ var TraceOverlapShiftSolver = class extends BaseSolver {
2408
2414
  for (let sb = 0; sb < ptsB.length - 1; sb++) {
2409
2415
  const b1 = ptsB[sb];
2410
2416
  const b2 = ptsB[sb + 1];
2411
- const bVert = Math.abs(b1.x - b2.x) < EPS16;
2412
- 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;
2413
2419
  if (!bVert && !bHorz) continue;
2414
2420
  if (aVert && bVert) {
2415
- if (Math.abs(a1.x - b1.x) < EPS16) {
2421
+ if (Math.abs(a1.x - b1.x) < EPS17) {
2416
2422
  recordCollinearInteraction({
2417
2423
  pathAIndex: pa,
2418
2424
  segmentAIndex: sa,
@@ -2422,7 +2428,7 @@ var TraceOverlapShiftSolver = class extends BaseSolver {
2422
2428
  });
2423
2429
  }
2424
2430
  } else if (aHorz && bHorz) {
2425
- if (Math.abs(a1.y - b1.y) < EPS16) {
2431
+ if (Math.abs(a1.y - b1.y) < EPS17) {
2426
2432
  recordCollinearInteraction({
2427
2433
  pathAIndex: pa,
2428
2434
  segmentAIndex: sa,
@@ -2478,14 +2484,14 @@ var TraceOverlapShiftSolver = class extends BaseSolver {
2478
2484
  return null;
2479
2485
  }
2480
2486
  findNextDiagonalSegment() {
2481
- const EPS16 = 2e-3;
2487
+ const EPS17 = 2e-3;
2482
2488
  for (const mspPairId in this.correctedTraceMap) {
2483
2489
  const tracePath = this.correctedTraceMap[mspPairId].tracePath;
2484
2490
  for (let i = 0; i < tracePath.length - 1; i++) {
2485
2491
  const p1 = tracePath[i];
2486
2492
  const p2 = tracePath[i + 1];
2487
- const isHorizontal5 = Math.abs(p1.y - p2.y) < EPS16;
2488
- 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;
2489
2495
  if (!isHorizontal5 && !isVertical6) {
2490
2496
  return { mspPairId, tracePath, i, p1, p2 };
2491
2497
  }
@@ -2499,13 +2505,13 @@ var TraceOverlapShiftSolver = class extends BaseSolver {
2499
2505
  return false;
2500
2506
  }
2501
2507
  const { mspPairId, tracePath, i, p1, p2 } = diagonalInfo;
2502
- const EPS16 = 2e-3;
2508
+ const EPS17 = 2e-3;
2503
2509
  const p0 = i > 0 ? tracePath[i - 1] : null;
2504
2510
  const p3 = i + 2 < tracePath.length ? tracePath[i + 2] : null;
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;
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;
2509
2515
  const elbow1 = { x: p1.x, y: p2.y };
2510
2516
  const elbow2 = { x: p2.x, y: p1.y };
2511
2517
  let score1 = 0;
@@ -2667,24 +2673,24 @@ var ChipObstacleSpatialIndex = class {
2667
2673
  };
2668
2674
 
2669
2675
  // lib/solvers/NetLabelPlacementSolver/SingleNetLabelPlacementSolver/collisions.ts
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;
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;
2673
2679
  if (!isVert && !isHorz) return false;
2674
2680
  if (isVert) {
2675
2681
  const x = p1.x;
2676
- if (x < rect.minX - EPS16 || x > rect.maxX + EPS16) return false;
2682
+ if (x < rect.minX - EPS17 || x > rect.maxX + EPS17) return false;
2677
2683
  const segMinY = Math.min(p1.y, p2.y);
2678
2684
  const segMaxY = Math.max(p1.y, p2.y);
2679
2685
  const overlap = Math.min(segMaxY, rect.maxY) - Math.max(segMinY, rect.minY);
2680
- return overlap > EPS16;
2686
+ return overlap > EPS17;
2681
2687
  } else {
2682
2688
  const y = p1.y;
2683
- if (y < rect.minY - EPS16 || y > rect.maxY + EPS16) return false;
2689
+ if (y < rect.minY - EPS17 || y > rect.maxY + EPS17) return false;
2684
2690
  const segMinX = Math.min(p1.x, p2.x);
2685
2691
  const segMaxX = Math.max(p1.x, p2.x);
2686
2692
  const overlap = Math.min(segMaxX, rect.maxX) - Math.max(segMinX, rect.minX);
2687
- return overlap > EPS16;
2693
+ return overlap > EPS17;
2688
2694
  }
2689
2695
  }
2690
2696
  function rectIntersectsAnyTrace(bounds, inputTraceMap, hostPathId, hostSegIndex) {
@@ -3083,14 +3089,14 @@ var SingleNetLabelPlacementSolver = class extends BaseSolver {
3083
3089
  };
3084
3090
  let bestCandidate = null;
3085
3091
  let bestScore = -Infinity;
3086
- const EPS16 = 1e-6;
3092
+ const EPS17 = 1e-6;
3087
3093
  for (const curr of tracesToScan) {
3088
3094
  const pts = curr.tracePath.slice();
3089
3095
  for (let si = 0; si < pts.length - 1; si++) {
3090
3096
  const a = pts[si];
3091
3097
  const b = pts[si + 1];
3092
- const isH = Math.abs(a.y - b.y) < EPS16;
3093
- 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;
3094
3100
  if (!isH && !isV) continue;
3095
3101
  const segmentAllowed = isH ? ["y+", "y-"] : ["x+", "x-"];
3096
3102
  const candidateOrients = orientations.filter(
@@ -6613,13 +6619,17 @@ var findIntersectionsWithObstacles = (p1, p2, obstacles) => {
6613
6619
  return intersections;
6614
6620
  };
6615
6621
  var isSamePoint = (first, second) => Math.abs(first.x - second.x) < EPS9 && Math.abs(first.y - second.y) < EPS9;
6616
- var findPerpendicularPathCrossings = (path, otherPath) => {
6622
+ var findPerpendicularPathCrossings = (path, otherPath, options = {}) => {
6617
6623
  const crossings = [];
6618
- 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++) {
6619
6629
  const start = path[pathSegmentIndex];
6620
6630
  const end = path[pathSegmentIndex + 1];
6621
6631
  const isVertical6 = Math.abs(start.x - end.x) < EPS9;
6622
- for (let otherPathSegmentIndex = 1; otherPathSegmentIndex < otherPath.length - 2; otherPathSegmentIndex++) {
6632
+ for (let otherPathSegmentIndex = firstOtherPathSegmentIndex; otherPathSegmentIndex < lastOtherPathSegmentIndex; otherPathSegmentIndex++) {
6623
6633
  const otherStart = otherPath[otherPathSegmentIndex];
6624
6634
  const otherEnd = otherPath[otherPathSegmentIndex + 1];
6625
6635
  const otherIsVertical = Math.abs(otherStart.x - otherEnd.x) < EPS9;
@@ -6759,6 +6769,7 @@ var generatePerpendicularTraceDetours = ({
6759
6769
  segmentIndex,
6760
6770
  obstacleStart,
6761
6771
  obstacleEnd,
6772
+ obstacleBounds,
6762
6773
  chipBounds,
6763
6774
  clearance
6764
6775
  }) => {
@@ -6767,18 +6778,34 @@ var generatePerpendicularTraceDetours = ({
6767
6778
  const end = path[index + 1];
6768
6779
  const movingAxis = Math.abs(start.x - end.x) < EPS10 ? "y" : "x";
6769
6780
  const detourAxis = movingAxis === "x" ? "y" : "x";
6770
- const gate = obstacleStart[movingAxis] + Math.sign(start[movingAxis] - obstacleStart[movingAxis]) * clearance;
6771
- 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
+ }
6772
6794
  const lowBound = detourAxis === "x" ? "minX" : "minY";
6773
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;
6774
6800
  const detourCoordinates = [
6775
- Math.min(...obstacleRange) - clearance,
6776
- Math.max(...obstacleRange) + clearance,
6777
- ...chipBounds.flatMap((bounds) => [
6778
- bounds[lowBound] - clearance,
6779
- bounds[highBound] + clearance
6801
+ balancedDetour,
6802
+ minDetour,
6803
+ maxDetour,
6804
+ ...chipBounds.flatMap((bounds2) => [
6805
+ bounds2[lowBound] - clearance,
6806
+ bounds2[highBound] + clearance
6780
6807
  ])
6781
- ];
6808
+ ].filter((coordinate) => coordinate !== void 0);
6782
6809
  return [...new Set(detourCoordinates)].map(
6783
6810
  (detour) => simplifyPath([
6784
6811
  ...path.slice(0, index + 1),
@@ -7385,6 +7412,126 @@ var is4PointRectangle = (path) => {
7385
7412
  return isHVHC || isVHVC;
7386
7413
  };
7387
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
+
7388
7535
  // lib/solvers/TraceCleanupSolver/TraceCleanupSolver.ts
7389
7536
  var DEFAULT_OPERATIONS = [
7390
7537
  "untangling_traces",
@@ -7436,6 +7583,9 @@ var TraceCleanupSolver = class extends BaseSolver {
7436
7583
  case "untangling_traces":
7437
7584
  this._runUntangleTracesStep();
7438
7585
  break;
7586
+ case "rerouting_generated_net_label_connector_crossings":
7587
+ this._runGeneratedNetLabelConnectorCrossingRerouteStep();
7588
+ break;
7439
7589
  case "minimizing_turns":
7440
7590
  this._runMinimizeTurnsStep();
7441
7591
  break;
@@ -7459,6 +7609,23 @@ var TraceCleanupSolver = class extends BaseSolver {
7459
7609
  allTraces: Array.from(this.tracesMap.values())
7460
7610
  });
7461
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
+ }
7462
7629
  _runMinimizeTurnsStep() {
7463
7630
  if (this.traceIdQueue.length === 0) {
7464
7631
  this._advancePipeline();
@@ -8496,16 +8663,16 @@ var createPortOnlyLabelConnectorTrace = ({
8496
8663
  var LABEL_SEARCH_STEP = 0.05;
8497
8664
  var MAX_RECORDED_CANDIDATES = 2e3;
8498
8665
  var WICK_CLEARANCE = 1e-3;
8499
- var EPS12 = 1e-9;
8500
- var TRACE_BOUNDARY_TOLERANCE = WICK_CLEARANCE + EPS12;
8666
+ var EPS13 = 1e-9;
8667
+ var TRACE_BOUNDARY_TOLERANCE = WICK_CLEARANCE + EPS13;
8501
8668
  var CANDIDATE_SELECTED_COLOR2 = "blue";
8502
8669
  var CANDIDATE_REJECTED_COLOR2 = "red";
8503
8670
 
8504
8671
  // lib/solvers/AvailableNetOrientationSolver/geometry.ts
8505
8672
  var isYOrientation = (orientation) => orientation === "y+" || orientation === "y-";
8506
8673
  var isXOrientation = (orientation) => orientation === "x+" || orientation === "x-";
8507
- 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;
8508
- 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;
8509
8676
  var traceCrossesBoundsInterior = (bounds, traceMap) => {
8510
8677
  for (const trace of Object.values(traceMap)) {
8511
8678
  const points = trace.tracePath;
@@ -8528,7 +8695,7 @@ var segmentCrossesBoundsInterior = (p1, p2, bounds) => {
8528
8695
  return false;
8529
8696
  }
8530
8697
  if (sameX2(p1, p2)) {
8531
- if (p1.x <= interiorBounds.minX + EPS12 || p1.x >= interiorBounds.maxX - EPS12) {
8698
+ if (p1.x <= interiorBounds.minX + EPS13 || p1.x >= interiorBounds.maxX - EPS13) {
8532
8699
  return false;
8533
8700
  }
8534
8701
  return rangesOverlap(
@@ -8539,7 +8706,7 @@ var segmentCrossesBoundsInterior = (p1, p2, bounds) => {
8539
8706
  );
8540
8707
  }
8541
8708
  if (sameY2(p1, p2)) {
8542
- if (p1.y <= interiorBounds.minY + EPS12 || p1.y >= interiorBounds.maxY - EPS12) {
8709
+ if (p1.y <= interiorBounds.minY + EPS13 || p1.y >= interiorBounds.maxY - EPS13) {
8543
8710
  return false;
8544
8711
  }
8545
8712
  return rangesOverlap(
@@ -8587,8 +8754,8 @@ var simplifyOrthogonalPath = (path) => {
8587
8754
  return simplified;
8588
8755
  };
8589
8756
  var pointsEqual2 = (a, b) => sameX2(a, b) && sameY2(a, b);
8590
- var sameX2 = (a, b) => Math.abs(a.x - b.x) <= EPS12;
8591
- 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;
8592
8759
  var getMaxSearchDistance = (inputProblem) => {
8593
8760
  const maxChipWidth = Math.max(
8594
8761
  ...inputProblem.chips.map((chip) => chip.width),
@@ -8747,7 +8914,7 @@ var AvailableNetOrientationObstacleIndex = class {
8747
8914
  }
8748
8915
  getTraceSegmentsInBounds(bounds) {
8749
8916
  if (!this.traceSegmentIndex) return [];
8750
- const searchBounds = getPaddedBounds(bounds, EPS12);
8917
+ const searchBounds = getPaddedBounds(bounds, EPS13);
8751
8918
  return this.traceSegmentIndex.search(
8752
8919
  searchBounds.minX,
8753
8920
  searchBounds.minY,
@@ -8760,7 +8927,7 @@ var AvailableNetOrientationObstacleIndex = class {
8760
8927
  for (let pointIndex = 0; pointIndex < tracePath.length - 1; pointIndex++) {
8761
8928
  const segmentBounds = getPaddedBounds(
8762
8929
  getSegmentBounds(tracePath[pointIndex], tracePath[pointIndex + 1]),
8763
- EPS12
8930
+ EPS13
8764
8931
  );
8765
8932
  for (const labelIndex of this.getLabelIndicesInBounds(segmentBounds)) {
8766
8933
  labelIndices.add(labelIndex);
@@ -8773,7 +8940,7 @@ var AvailableNetOrientationObstacleIndex = class {
8773
8940
  const start = tracePath[pointIndex];
8774
8941
  const end = tracePath[pointIndex + 1];
8775
8942
  const nearbyChips = this.chipObstacleSpatialIndex.getChipsInBounds(
8776
- getPaddedBounds(getSegmentBounds(start, end), EPS12)
8943
+ getPaddedBounds(getSegmentBounds(start, end), EPS13)
8777
8944
  );
8778
8945
  for (const chip of nearbyChips) {
8779
8946
  if (segmentCrossesBoundsInterior(start, end, chip.bounds)) return true;
@@ -8920,7 +9087,8 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
8920
9087
  getOutput() {
8921
9088
  return {
8922
9089
  traces: this.traces,
8923
- netLabelPlacements: this.outputNetLabelPlacements
9090
+ netLabelPlacements: this.outputNetLabelPlacements,
9091
+ netLabelConnectorTraceIds: this.netLabelConnectorTraceIds
8924
9092
  };
8925
9093
  }
8926
9094
  getProcessableLabelIndices() {
@@ -9241,7 +9409,7 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
9241
9409
  index,
9242
9410
  pin: this.pinMap[otherLabel.pinIds[0]]
9243
9411
  })).filter(
9244
- ({ 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
9245
9413
  ).sort((a, b) => a.pin.x - b.pin.x)[0]?.pin;
9246
9414
  if (orientation === "y-" && nextPinToRight) return null;
9247
9415
  const anchorX = orientation === "y-" ? Math.max(
@@ -9274,7 +9442,7 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
9274
9442
  const centeredAnchorY = hasUpFacingStack ? (lowestUpFacingLabelY + highestUpFacingLabelY) / 2 : stackedAnchorY;
9275
9443
  const anchorYs = orientation === "y-" ? [centeredAnchorY, stackedAnchorY] : [stackedAnchorY];
9276
9444
  for (const anchorY of anchorYs) {
9277
- if (anchorY - label.anchorPoint.y > this.maxSearchDistance + EPS12) {
9445
+ if (anchorY - label.anchorPoint.y > this.maxSearchDistance + EPS13) {
9278
9446
  continue;
9279
9447
  }
9280
9448
  const candidate = this.createCandidate(
@@ -9303,11 +9471,11 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
9303
9471
  if (trace.globalConnNetId !== label.globalConnNetId) return false;
9304
9472
  const path = trace.tracePath;
9305
9473
  return path.some((point, pointIndex) => {
9306
- 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) {
9307
9475
  return false;
9308
9476
  }
9309
9477
  return [path[pointIndex - 1], path[pointIndex + 1]].some(
9310
- (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
9311
9479
  );
9312
9480
  });
9313
9481
  });
@@ -9397,7 +9565,7 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
9397
9565
  orientation
9398
9566
  );
9399
9567
  if (outwardDirection.x === 0 && outwardDirection.y === 0) continue;
9400
- 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) {
9401
9569
  const anchorPoint = {
9402
9570
  x: connectorSource.x + outwardDirection.x * distance7,
9403
9571
  y: connectorSource.y + outwardDirection.y * distance7
@@ -9475,7 +9643,7 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
9475
9643
  const furthestRowPoints = points.filter(
9476
9644
  (point) => Math.abs(
9477
9645
  point.x * direction.x + point.y * direction.y - furthestAlong
9478
- ) <= EPS12
9646
+ ) <= EPS13
9479
9647
  );
9480
9648
  const directHostPinIds = new Set(
9481
9649
  [...directHostTraceIds].flatMap(
@@ -9496,7 +9664,7 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
9496
9664
  preferNearestBendOnOutwardRow: adjacentTraces.some(
9497
9665
  (trace) => furthestRowPoints.some(
9498
9666
  (point) => trace.tracePath.some(
9499
- (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
9500
9668
  )
9501
9669
  )
9502
9670
  )
@@ -9508,7 +9676,7 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
9508
9676
  for (let i = 0; i < otherTrace.tracePath.length - 1; i++) {
9509
9677
  const start = otherTrace.tracePath[i];
9510
9678
  const end = otherTrace.tracePath[i + 1];
9511
- 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) {
9512
9680
  verticalRailXs.add(start.x);
9513
9681
  }
9514
9682
  }
@@ -9516,7 +9684,7 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
9516
9684
  for (let i = 0; i < trace.tracePath.length - 1; i++) {
9517
9685
  const start = trace.tracePath[i];
9518
9686
  const end = trace.tracePath[i + 1];
9519
- 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)) {
9520
9688
  return true;
9521
9689
  }
9522
9690
  }
@@ -9535,7 +9703,7 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
9535
9703
  );
9536
9704
  const maxSearchDistance = this.getSearchDistanceLimit(label, orientation);
9537
9705
  const maxOutwardDistance = outwardDirection.x === 0 && outwardDirection.y === 0 ? 0 : this.maxSearchDistance;
9538
- for (let outwardDistance = 0; outwardDistance <= maxOutwardDistance + EPS12; outwardDistance += LABEL_SEARCH_STEP) {
9706
+ for (let outwardDistance = 0; outwardDistance <= maxOutwardDistance + EPS13; outwardDistance += LABEL_SEARCH_STEP) {
9539
9707
  const baseAnchor = {
9540
9708
  x: initialBaseAnchor.x + outwardDirection.x * outwardDistance,
9541
9709
  y: initialBaseAnchor.y + outwardDirection.y * outwardDistance
@@ -9611,7 +9779,7 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
9611
9779
  connectorSource,
9612
9780
  startDistance = LABEL_SEARCH_STEP
9613
9781
  } = params;
9614
- for (let distance7 = startDistance; distance7 <= maxSearchDistance + EPS12; distance7 += LABEL_SEARCH_STEP) {
9782
+ for (let distance7 = startDistance; distance7 <= maxSearchDistance + EPS13; distance7 += LABEL_SEARCH_STEP) {
9615
9783
  const anchorPoint = {
9616
9784
  x: baseAnchor.x + direction.x * distance7,
9617
9785
  y: baseAnchor.y + direction.y * distance7
@@ -9940,9 +10108,9 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
9940
10108
  const { anchorPoint, orientation } = candidate;
9941
10109
  const chipBounds = chip.bounds;
9942
10110
  if (isYOrientation(orientation)) {
9943
- return anchorPoint.x < chipBounds.minX - EPS12 || anchorPoint.x > chipBounds.maxX + EPS12;
10111
+ return anchorPoint.x < chipBounds.minX - EPS13 || anchorPoint.x > chipBounds.maxX + EPS13;
9944
10112
  }
9945
- return anchorPoint.y < chipBounds.minY - EPS12 || anchorPoint.y > chipBounds.maxY + EPS12;
10113
+ return anchorPoint.y < chipBounds.minY - EPS13 || anchorPoint.y > chipBounds.maxY + EPS13;
9946
10114
  });
9947
10115
  }
9948
10116
  staysOutsideConnectedPinRow(params) {
@@ -9950,9 +10118,9 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
9950
10118
  const pin = this.pinMap[label.pinIds[0]];
9951
10119
  if (!pin || !isYOrientation(candidate.orientation)) return false;
9952
10120
  if (candidate.anchorPoint.x < pin.x) {
9953
- return bounds.maxX <= pin.x + CONNECTED_PIN_ROW_OVERLAP_TOLERANCE + EPS12;
10121
+ return bounds.maxX <= pin.x + CONNECTED_PIN_ROW_OVERLAP_TOLERANCE + EPS13;
9954
10122
  }
9955
- return bounds.minX >= pin.x - CONNECTED_PIN_ROW_OVERLAP_TOLERANCE - EPS12;
10123
+ return bounds.minX >= pin.x - CONNECTED_PIN_ROW_OVERLAP_TOLERANCE - EPS13;
9956
10124
  }
9957
10125
  getBoundsStatus(candidateBoundsCheck) {
9958
10126
  const { bounds, labelIndex, label, ignoreChipCollisions } = candidateBoundsCheck;
@@ -10033,14 +10201,14 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
10033
10201
  candidate.width,
10034
10202
  candidate.height
10035
10203
  );
10036
- 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) {
10037
10205
  return false;
10038
10206
  }
10039
- 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) {
10040
10208
  return false;
10041
10209
  }
10042
10210
  return chip.pins.every(
10043
- (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
10044
10212
  );
10045
10213
  }
10046
10214
  getTextBlockedMultiPinRailTraces(label, orientation) {
@@ -10067,20 +10235,20 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
10067
10235
  const pins = [...connectedPinIds].map((pinId) => this.pinMap[pinId]);
10068
10236
  const direction = dir(orientation);
10069
10237
  const pinX = pins[0].x;
10070
- if (pins.some((pin) => Math.abs(pin.x - pinX) > EPS12)) return null;
10071
- 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);
10072
10240
  const minY = Math.min(...pins.map((pin) => pin.y));
10073
10241
  const maxY = Math.max(...pins.map((pin) => pin.y));
10074
10242
  if (sidePins.some(
10075
- (pin) => pin.y >= minY - EPS12 && pin.y <= maxY + EPS12 && !connectedPinIds.has(pin.pinId)
10076
- ) || 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) {
10077
10245
  return null;
10078
10246
  }
10079
10247
  const outerPinPosition = Math.max(
10080
10248
  ...pins.map((pin) => pin.x * direction.x + pin.y * direction.y)
10081
10249
  );
10082
10250
  const blockedByText = (this.inputProblem.textBoxes ?? []).some(
10083
- (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
10084
10252
  );
10085
10253
  return blockedByText ? [...connectedTraces] : null;
10086
10254
  }
@@ -10096,7 +10264,7 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
10096
10264
  ...new Set(
10097
10265
  localTraces.flatMap((trace) => trace.tracePath.map((point) => point.x))
10098
10266
  )
10099
- ].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));
10100
10268
  for (const x of railXs) {
10101
10269
  const connectorSource = { x, y: connectorY };
10102
10270
  if (!Object.values(this.traceMap).some(
@@ -10159,8 +10327,8 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
10159
10327
  if (!chip) return null;
10160
10328
  const sides = new Set(
10161
10329
  pins.map((pin) => {
10162
- if (Math.abs(pin.x - chip.bounds.minX) <= EPS12) return "left";
10163
- 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";
10164
10332
  return null;
10165
10333
  })
10166
10334
  );
@@ -10199,16 +10367,16 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
10199
10367
  }
10200
10368
  sharesChipBoundary(bounds) {
10201
10369
  const boundarySearchBounds = {
10202
- minX: bounds.minX - WICK_CLEARANCE - EPS12,
10203
- minY: bounds.minY - WICK_CLEARANCE - EPS12,
10204
- maxX: bounds.maxX + WICK_CLEARANCE + EPS12,
10205
- 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
10206
10374
  };
10207
10375
  const nearbyChips = this.chipObstacleSpatialIndex.getChipsInBounds(boundarySearchBounds);
10208
10376
  for (const chip of nearbyChips) {
10209
10377
  const chipBounds = chip.bounds;
10210
- const adjacentToVerticalSide = Math.abs(bounds.minX - chipBounds.maxX) <= WICK_CLEARANCE + EPS12 || Math.abs(bounds.maxX - chipBounds.minX) <= WICK_CLEARANCE + EPS12;
10211
- 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;
10212
10380
  if (adjacentToVerticalSide && rangesOverlap(
10213
10381
  bounds.minY,
10214
10382
  bounds.maxY,
@@ -10270,7 +10438,7 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
10270
10438
  let nearestDistance = Number.POSITIVE_INFINITY;
10271
10439
  for (const chip of this.chipObstacleSpatialIndex.chips) {
10272
10440
  const bounds = chip.bounds;
10273
- 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) {
10274
10442
  continue;
10275
10443
  }
10276
10444
  for (const [side, distance7] of getSideDistances(point, bounds)) {
@@ -10287,8 +10455,8 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
10287
10455
  let nearestDistanceSq = Number.POSITIVE_INFINITY;
10288
10456
  for (const chip of this.chipObstacleSpatialIndex.chips) {
10289
10457
  const bounds = chip.bounds;
10290
- const dx = point.x < bounds.minX - EPS12 ? bounds.minX - point.x : point.x > bounds.maxX + EPS12 ? point.x - bounds.maxX : 0;
10291
- 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;
10292
10460
  if (dx === 0 && dy === 0) continue;
10293
10461
  const distanceSq = dx ** 2 + dy ** 2;
10294
10462
  if (distanceSq >= nearestDistanceSq) continue;
@@ -10848,11 +11016,11 @@ var getOrientationConstraint = (inputProblem, label) => {
10848
11016
  };
10849
11017
 
10850
11018
  // lib/solvers/TraceAnchoredNetLabelOverlapSolver/geometry.ts
10851
- var EPS13 = 1e-6;
11019
+ var EPS14 = 1e-6;
10852
11020
  var TRACE_BOUNDARY_TOLERANCE2 = 1e-6;
10853
11021
  var getLabelBounds = (label) => getRectBounds(label.center, label.width, label.height);
10854
- 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;
10855
- 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;
10856
11024
  var traceCrossesBoundsInterior2 = (bounds, traces) => {
10857
11025
  for (const trace of traces) {
10858
11026
  const points = trace.tracePath;
@@ -10898,7 +11066,7 @@ var getPointAtTraceDistance = (trace, distance7) => {
10898
11066
  const end = trace.tracePath[i + 1];
10899
11067
  const segmentLength = getManhattanDistance(start, end);
10900
11068
  const nextDistance = pathDistance + segmentLength;
10901
- if (distance7 <= nextDistance + EPS13) {
11069
+ if (distance7 <= nextDistance + EPS14) {
10902
11070
  const offset = Math.max(
10903
11071
  0,
10904
11072
  Math.min(segmentLength, distance7 - pathDistance)
@@ -10937,7 +11105,7 @@ var segmentCrossesBoundsInterior2 = (start, end, bounds) => {
10937
11105
  return false;
10938
11106
  }
10939
11107
  if (isVertical4(start, end)) {
10940
- if (start.x <= interior.minX + EPS13 || start.x >= interior.maxX - EPS13) {
11108
+ if (start.x <= interior.minX + EPS14 || start.x >= interior.maxX - EPS14) {
10941
11109
  return false;
10942
11110
  }
10943
11111
  return rangesOverlap2(
@@ -10948,7 +11116,7 @@ var segmentCrossesBoundsInterior2 = (start, end, bounds) => {
10948
11116
  );
10949
11117
  }
10950
11118
  if (isHorizontal3(start, end)) {
10951
- if (start.y <= interior.minY + EPS13 || start.y >= interior.maxY - EPS13) {
11119
+ if (start.y <= interior.minY + EPS14 || start.y >= interior.maxY - EPS14) {
10952
11120
  return false;
10953
11121
  }
10954
11122
  return rangesOverlap2(
@@ -10962,10 +11130,10 @@ var segmentCrossesBoundsInterior2 = (start, end, bounds) => {
10962
11130
  };
10963
11131
  var isPointOnSegment2 = (point, start, end) => {
10964
11132
  if (isHorizontal3(start, end)) {
10965
- 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;
10966
11134
  }
10967
11135
  if (isVertical4(start, end)) {
10968
- 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;
10969
11137
  }
10970
11138
  return false;
10971
11139
  };
@@ -10973,9 +11141,9 @@ var getSegmentDirection = (start, end) => ({
10973
11141
  x: isVertical4(start, end) ? 0 : Math.sign(end.x - start.x),
10974
11142
  y: isHorizontal3(start, end) ? 0 : Math.sign(end.y - start.y)
10975
11143
  });
10976
- var isHorizontal3 = (start, end) => Math.abs(start.y - end.y) <= EPS13;
10977
- var isVertical4 = (start, end) => Math.abs(start.x - end.x) <= EPS13;
10978
- 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;
10979
11147
  var getUniquePinCount2 = (pinIds) => new Set(pinIds).size;
10980
11148
 
10981
11149
  // lib/solvers/TraceAnchoredNetLabelOverlapSolver/candidates.ts
@@ -11032,7 +11200,7 @@ var getCandidateDistances = (traceLength, vertexDistances) => {
11032
11200
  for (const distance7 of vertexDistances) {
11033
11201
  distances.add(roundDistance(distance7));
11034
11202
  }
11035
- 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);
11036
11204
  };
11037
11205
  var getOrientationsForPoint = (params) => {
11038
11206
  const { inputProblem, label, point, orientationConstraint } = params;
@@ -11121,13 +11289,13 @@ var getOutwardOrientationOptions = (point, chipBounds) => {
11121
11289
  };
11122
11290
  var getOutwardAxisOption = (params) => {
11123
11291
  const { value, min, max, center, positiveOrientation, negativeOrientation } = params;
11124
- if (value > max + EPS13) {
11292
+ if (value > max + EPS14) {
11125
11293
  return {
11126
11294
  orientation: positiveOrientation,
11127
11295
  outwardScore: 1 + value - max
11128
11296
  };
11129
11297
  }
11130
- if (value < min - EPS13) {
11298
+ if (value < min - EPS14) {
11131
11299
  return {
11132
11300
  orientation: negativeOrientation,
11133
11301
  outwardScore: 1 + min - value
@@ -11138,7 +11306,7 @@ var getOutwardAxisOption = (params) => {
11138
11306
  outwardScore: getNormalizedCenterDistance(value, center, max - min)
11139
11307
  };
11140
11308
  };
11141
- 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);
11142
11310
  var ALL_ORIENTATIONS = ["x+", "x-", "y+", "y-"];
11143
11311
  var getFlippedOrientation = (orientation) => {
11144
11312
  switch (orientation) {
@@ -11206,7 +11374,7 @@ var getNetLabelHeight = (inputProblem, label) => {
11206
11374
  )?.netLabelHeight;
11207
11375
  };
11208
11376
  var roundDistance = (distance7) => Number(distance7.toFixed(6));
11209
- 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;
11210
11378
 
11211
11379
  // lib/solvers/TraceAnchoredNetLabelOverlapSolver/visualize.ts
11212
11380
  var CANDIDATE_SELECTED_COLOR4 = "blue";
@@ -15026,15 +15194,15 @@ var pathIntersectsRenderedLabel = (path, label) => {
15026
15194
  };
15027
15195
 
15028
15196
  // lib/solvers/InlineNetLabelSolver/restoreReroutesAroundSupersededLabels.ts
15029
- var EPS14 = 1e-6;
15197
+ var EPS15 = 1e-6;
15030
15198
  var getPathLength5 = (path) => path.slice(1).reduce((length, point, pointIndex) => {
15031
15199
  const previousPoint = path[pointIndex];
15032
15200
  return length + Math.abs(point.x - previousPoint.x) + Math.abs(point.y - previousPoint.y);
15033
15201
  }, 0);
15034
15202
  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
15203
+ (point, index) => Math.abs(point.x - second[index].x) <= EPS15 && Math.abs(point.y - second[index].y) <= EPS15
15036
15204
  );
15037
- 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;
15038
15206
  var getIntersectionKeys = (path, otherPath) => {
15039
15207
  const intersections = /* @__PURE__ */ new Set();
15040
15208
  for (let pathIndex = 0; pathIndex < path.length - 1; pathIndex++) {
@@ -16089,12 +16257,12 @@ var getTraceRecoveryConnectivityMaps = (inputProblem) => {
16089
16257
  };
16090
16258
 
16091
16259
  // lib/solvers/NetLabelToTraceSolver/reduceTraceCrossings.ts
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;
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;
16095
16263
  var compactConsecutivePoints = (path) => path.filter((point, index) => {
16096
16264
  const previousPoint = path[index - 1];
16097
- 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;
16098
16266
  });
16099
16267
  var isValidOrthogonalPath = (path) => {
16100
16268
  if (path.length < 2 || !path.every((point, index) => {
@@ -16132,7 +16300,7 @@ var getEndpointAlignedSegmentCandidates = (tracePath) => {
16132
16300
  }
16133
16301
  const alignedCoordinates = segmentIsVertical ? [previousPoint.x, nextPoint.x] : [previousPoint.y, nextPoint.y];
16134
16302
  for (const alignedCoordinate of alignedCoordinates) {
16135
- if (Math.abs(alignedCoordinate - (segmentIsVertical ? start.x : start.y)) < EPS15) {
16303
+ if (Math.abs(alignedCoordinate - (segmentIsVertical ? start.x : start.y)) < EPS16) {
16136
16304
  continue;
16137
16305
  }
16138
16306
  const candidate = tracePath.map((point) => ({ ...point }));
@@ -16908,10 +17076,14 @@ var SchematicTracePipelineSolver = class extends BaseSolver {
16908
17076
  allLabelPlacements: collisionOutput.netLabelPlacements,
16909
17077
  mergedLabelNetIdMap: labelMergingOutput.mergedLabelNetIdMap,
16910
17078
  paddingBuffer: 0.1,
16911
- operations: ["aligning_same_net_rails"],
17079
+ operations: [
17080
+ "rerouting_generated_net_label_connector_crossings",
17081
+ "aligning_same_net_rails"
17082
+ ],
16912
17083
  eligibleTraceIds: new Set(
16913
17084
  instance.traceCleanupSolver.getOutput().traces.map((trace) => trace.mspPairId)
16914
- )
17085
+ ),
17086
+ netLabelConnectorTraceIds: instance.availableNetOrientationSolver.netLabelConnectorTraceIds
16915
17087
  }
16916
17088
  ];
16917
17089
  }