@tscircuit/schematic-trace-solver 0.0.132 → 0.0.134

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 EPS13 = 1e-9;
328
+ const EPS14 = 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) < -EPS13) return true;
332
+ if ((a.x - rcl.x) * (b.x - rcl.x) < -EPS14) 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) < -EPS13) return true;
335
+ if ((a.y - rcl.y) * (b.y - rcl.y) < -EPS14) return true;
336
336
  }
337
337
  }
338
338
  return false;
339
339
  };
340
- if (Math.abs(p1.x - p2.x) < EPS13 || Math.abs(p1.y - p2.y) < EPS13) {
340
+ if (Math.abs(p1.x - p2.x) < EPS14 || Math.abs(p1.y - p2.y) < EPS14) {
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 };
@@ -1424,8 +1424,8 @@ var SchematicTraceSingleLineSolver2 = class extends BaseSolver {
1424
1424
  if (!collision) {
1425
1425
  const first = path[0];
1426
1426
  const last = path[path.length - 1];
1427
- const EPS13 = 1e-9;
1428
- const samePoint = (p, q) => Math.abs(p.x - q.x) < EPS13 && Math.abs(p.y - q.y) < EPS13;
1427
+ const EPS14 = 1e-9;
1428
+ const samePoint = (p, q) => Math.abs(p.x - q.x) < EPS14 && Math.abs(p.y - q.y) < EPS14;
1429
1429
  if (samePoint(first, { x: PA.x, y: PA.y }) && samePoint(last, { x: PB.x, y: PB.y })) {
1430
1430
  this.solvedTracePath = path;
1431
1431
  this.solved = true;
@@ -1709,13 +1709,13 @@ var applyJogToTerminalSegment = ({
1709
1709
  segmentIndex: si,
1710
1710
  offset,
1711
1711
  JOG_SIZE,
1712
- EPS: EPS13 = 1e-6
1712
+ EPS: EPS14 = 1e-6
1713
1713
  }) => {
1714
1714
  if (si !== 0 && si !== pts.length - 2) return;
1715
1715
  const start = pts[si];
1716
1716
  const end = pts[si + 1];
1717
- const isVertical5 = Math.abs(start.x - end.x) < EPS13;
1718
- const isHorizontal4 = Math.abs(start.y - end.y) < EPS13;
1717
+ const isVertical5 = Math.abs(start.x - end.x) < EPS14;
1718
+ const isHorizontal4 = Math.abs(start.y - end.y) < EPS14;
1719
1719
  if (!isVertical5 && !isHorizontal4) return;
1720
1720
  const segDir = isVertical5 ? end.y > start.y ? 1 : -1 : end.x > start.x ? 1 : -1;
1721
1721
  if (pts.length === 2) {
@@ -2144,7 +2144,7 @@ var TraceOverlapShiftSolver = class extends BaseSolver {
2144
2144
  return islands;
2145
2145
  }
2146
2146
  findNextOverlapIssue() {
2147
- const EPS13 = 2e-3;
2147
+ const EPS14 = 2e-3;
2148
2148
  const netIds = Object.keys(this.traceNetIslands);
2149
2149
  for (let i = 0; i < netIds.length; i++) {
2150
2150
  for (let j = i + 1; j < netIds.length; j++) {
@@ -2171,7 +2171,7 @@ var TraceOverlapShiftSolver = class extends BaseSolver {
2171
2171
  segmentBIndex,
2172
2172
  rangeOverlap
2173
2173
  }) => {
2174
- if (rangeOverlap > EPS13) {
2174
+ if (rangeOverlap > EPS14) {
2175
2175
  const keyA = `${pathAIndex}:${segmentAIndex}`;
2176
2176
  const keyB = `${pathBIndex}:${segmentBIndex}`;
2177
2177
  if (!seenA.has(keyA)) {
@@ -2190,7 +2190,7 @@ var TraceOverlapShiftSolver = class extends BaseSolver {
2190
2190
  }
2191
2191
  return;
2192
2192
  }
2193
- if (rangeOverlap < -EPS13) return;
2193
+ if (rangeOverlap < -EPS14) return;
2194
2194
  const pathA = pathsA[pathAIndex].tracePath;
2195
2195
  const pathB = pathsB[pathBIndex].tracePath;
2196
2196
  const segmentAStart = pathA[segmentAIndex];
@@ -2213,8 +2213,8 @@ var TraceOverlapShiftSolver = class extends BaseSolver {
2213
2213
  for (let sa = 0; sa < ptsA.length - 1; sa++) {
2214
2214
  const a1 = ptsA[sa];
2215
2215
  const a2 = ptsA[sa + 1];
2216
- const aVert = Math.abs(a1.x - a2.x) < EPS13;
2217
- const aHorz = Math.abs(a1.y - a2.y) < EPS13;
2216
+ const aVert = Math.abs(a1.x - a2.x) < EPS14;
2217
+ const aHorz = Math.abs(a1.y - a2.y) < EPS14;
2218
2218
  if (!aVert && !aHorz) continue;
2219
2219
  for (let pb = 0; pb < pathsB.length; pb++) {
2220
2220
  const pathB = pathsB[pb];
@@ -2225,11 +2225,11 @@ var TraceOverlapShiftSolver = class extends BaseSolver {
2225
2225
  for (let sb = 0; sb < ptsB.length - 1; sb++) {
2226
2226
  const b1 = ptsB[sb];
2227
2227
  const b2 = ptsB[sb + 1];
2228
- const bVert = Math.abs(b1.x - b2.x) < EPS13;
2229
- const bHorz = Math.abs(b1.y - b2.y) < EPS13;
2228
+ const bVert = Math.abs(b1.x - b2.x) < EPS14;
2229
+ const bHorz = Math.abs(b1.y - b2.y) < EPS14;
2230
2230
  if (!bVert && !bHorz) continue;
2231
2231
  if (aVert && bVert) {
2232
- if (Math.abs(a1.x - b1.x) < EPS13) {
2232
+ if (Math.abs(a1.x - b1.x) < EPS14) {
2233
2233
  recordCollinearInteraction({
2234
2234
  pathAIndex: pa,
2235
2235
  segmentAIndex: sa,
@@ -2239,7 +2239,7 @@ var TraceOverlapShiftSolver = class extends BaseSolver {
2239
2239
  });
2240
2240
  }
2241
2241
  } else if (aHorz && bHorz) {
2242
- if (Math.abs(a1.y - b1.y) < EPS13) {
2242
+ if (Math.abs(a1.y - b1.y) < EPS14) {
2243
2243
  recordCollinearInteraction({
2244
2244
  pathAIndex: pa,
2245
2245
  segmentAIndex: sa,
@@ -2295,14 +2295,14 @@ var TraceOverlapShiftSolver = class extends BaseSolver {
2295
2295
  return null;
2296
2296
  }
2297
2297
  findNextDiagonalSegment() {
2298
- const EPS13 = 2e-3;
2298
+ const EPS14 = 2e-3;
2299
2299
  for (const mspPairId in this.correctedTraceMap) {
2300
2300
  const tracePath = this.correctedTraceMap[mspPairId].tracePath;
2301
2301
  for (let i = 0; i < tracePath.length - 1; i++) {
2302
2302
  const p1 = tracePath[i];
2303
2303
  const p2 = tracePath[i + 1];
2304
- const isHorizontal4 = Math.abs(p1.y - p2.y) < EPS13;
2305
- const isVertical5 = Math.abs(p1.x - p2.x) < EPS13;
2304
+ const isHorizontal4 = Math.abs(p1.y - p2.y) < EPS14;
2305
+ const isVertical5 = Math.abs(p1.x - p2.x) < EPS14;
2306
2306
  if (!isHorizontal4 && !isVertical5) {
2307
2307
  return { mspPairId, tracePath, i, p1, p2 };
2308
2308
  }
@@ -2316,13 +2316,13 @@ var TraceOverlapShiftSolver = class extends BaseSolver {
2316
2316
  return false;
2317
2317
  }
2318
2318
  const { mspPairId, tracePath, i, p1, p2 } = diagonalInfo;
2319
- const EPS13 = 2e-3;
2319
+ const EPS14 = 2e-3;
2320
2320
  const p0 = i > 0 ? tracePath[i - 1] : null;
2321
2321
  const p3 = i + 2 < tracePath.length ? tracePath[i + 2] : null;
2322
- const prevIsVertical = p0 ? Math.abs(p0.x - p1.x) < EPS13 : false;
2323
- const prevIsHorizontal = p0 ? Math.abs(p0.y - p1.y) < EPS13 : false;
2324
- const nextIsVertical = p3 ? Math.abs(p2.x - p3.x) < EPS13 : false;
2325
- const nextIsHorizontal = p3 ? Math.abs(p2.y - p3.y) < EPS13 : false;
2322
+ const prevIsVertical = p0 ? Math.abs(p0.x - p1.x) < EPS14 : false;
2323
+ const prevIsHorizontal = p0 ? Math.abs(p0.y - p1.y) < EPS14 : false;
2324
+ const nextIsVertical = p3 ? Math.abs(p2.x - p3.x) < EPS14 : false;
2325
+ const nextIsHorizontal = p3 ? Math.abs(p2.y - p3.y) < EPS14 : false;
2326
2326
  const elbow1 = { x: p1.x, y: p2.y };
2327
2327
  const elbow2 = { x: p2.x, y: p1.y };
2328
2328
  let score1 = 0;
@@ -2450,24 +2450,24 @@ var ChipObstacleSpatialIndex = class {
2450
2450
  };
2451
2451
 
2452
2452
  // lib/solvers/NetLabelPlacementSolver/SingleNetLabelPlacementSolver/collisions.ts
2453
- function segmentIntersectsRect2(p1, p2, rect, EPS13 = 1e-9) {
2454
- const isVert = Math.abs(p1.x - p2.x) < EPS13;
2455
- const isHorz = Math.abs(p1.y - p2.y) < EPS13;
2453
+ function segmentIntersectsRect2(p1, p2, rect, EPS14 = 1e-9) {
2454
+ const isVert = Math.abs(p1.x - p2.x) < EPS14;
2455
+ const isHorz = Math.abs(p1.y - p2.y) < EPS14;
2456
2456
  if (!isVert && !isHorz) return false;
2457
2457
  if (isVert) {
2458
2458
  const x = p1.x;
2459
- if (x < rect.minX - EPS13 || x > rect.maxX + EPS13) return false;
2459
+ if (x < rect.minX - EPS14 || x > rect.maxX + EPS14) return false;
2460
2460
  const segMinY = Math.min(p1.y, p2.y);
2461
2461
  const segMaxY = Math.max(p1.y, p2.y);
2462
2462
  const overlap = Math.min(segMaxY, rect.maxY) - Math.max(segMinY, rect.minY);
2463
- return overlap > EPS13;
2463
+ return overlap > EPS14;
2464
2464
  } else {
2465
2465
  const y = p1.y;
2466
- if (y < rect.minY - EPS13 || y > rect.maxY + EPS13) return false;
2466
+ if (y < rect.minY - EPS14 || y > rect.maxY + EPS14) return false;
2467
2467
  const segMinX = Math.min(p1.x, p2.x);
2468
2468
  const segMaxX = Math.max(p1.x, p2.x);
2469
2469
  const overlap = Math.min(segMaxX, rect.maxX) - Math.max(segMinX, rect.minX);
2470
- return overlap > EPS13;
2470
+ return overlap > EPS14;
2471
2471
  }
2472
2472
  }
2473
2473
  function rectIntersectsAnyTrace(bounds, inputTraceMap, hostPathId, hostSegIndex) {
@@ -2864,14 +2864,14 @@ var SingleNetLabelPlacementSolver = class extends BaseSolver {
2864
2864
  };
2865
2865
  let bestCandidate = null;
2866
2866
  let bestScore = -Infinity;
2867
- const EPS13 = 1e-6;
2867
+ const EPS14 = 1e-6;
2868
2868
  for (const curr of tracesToScan) {
2869
2869
  const pts = curr.tracePath.slice();
2870
2870
  for (let si = 0; si < pts.length - 1; si++) {
2871
2871
  const a = pts[si];
2872
2872
  const b = pts[si + 1];
2873
- const isH = Math.abs(a.y - b.y) < EPS13;
2874
- const isV = Math.abs(a.x - b.x) < EPS13;
2873
+ const isH = Math.abs(a.y - b.y) < EPS14;
2874
+ const isV = Math.abs(a.x - b.x) < EPS14;
2875
2875
  if (!isH && !isV) continue;
2876
2876
  const segmentAllowed = isH ? ["y+", "y-"] : ["x+", "x-"];
2877
2877
  const candidateOrients = orientations.filter(
@@ -4619,6 +4619,81 @@ var distance3 = (p1, p2) => {
4619
4619
  return Math.sqrt(Math.pow(p1.x - p2.x, 2) + Math.pow(p1.y - p2.y, 2));
4620
4620
  };
4621
4621
  var manhattanDistance = (p1, p2) => Math.abs(p1.x - p2.x) + Math.abs(p1.y - p2.y);
4622
+ var EPS6 = 1e-9;
4623
+ var between = (value, first, second) => value >= Math.min(first, second) - EPS6 && value <= Math.max(first, second) + EPS6;
4624
+ var getAxisAlignedIntersection = (firstStart, firstEnd, secondStart, secondEnd) => {
4625
+ const firstIsHorizontal = Math.abs(firstStart.y - firstEnd.y) <= EPS6;
4626
+ const firstIsVertical = Math.abs(firstStart.x - firstEnd.x) <= EPS6;
4627
+ const secondIsHorizontal = Math.abs(secondStart.y - secondEnd.y) <= EPS6;
4628
+ const secondIsVertical = Math.abs(secondStart.x - secondEnd.x) <= EPS6;
4629
+ if (firstIsHorizontal && secondIsVertical) {
4630
+ const point = { x: secondStart.x, y: firstStart.y };
4631
+ return between(point.x, firstStart.x, firstEnd.x) && between(point.y, secondStart.y, secondEnd.y) ? point : null;
4632
+ }
4633
+ if (firstIsVertical && secondIsHorizontal) {
4634
+ const point = { x: firstStart.x, y: secondStart.y };
4635
+ return between(point.y, firstStart.y, firstEnd.y) && between(point.x, secondStart.x, secondEnd.x) ? point : null;
4636
+ }
4637
+ if (firstIsHorizontal && secondIsHorizontal && Math.abs(firstStart.y - secondStart.y) <= EPS6) {
4638
+ const overlapMin = Math.max(
4639
+ Math.min(firstStart.x, firstEnd.x),
4640
+ Math.min(secondStart.x, secondEnd.x)
4641
+ );
4642
+ const overlapMax = Math.min(
4643
+ Math.max(firstStart.x, firstEnd.x),
4644
+ Math.max(secondStart.x, secondEnd.x)
4645
+ );
4646
+ if (overlapMin > overlapMax + EPS6) return null;
4647
+ return {
4648
+ x: Math.max(overlapMin, Math.min(firstStart.x, overlapMax)),
4649
+ y: firstStart.y
4650
+ };
4651
+ }
4652
+ if (firstIsVertical && secondIsVertical && Math.abs(firstStart.x - secondStart.x) <= EPS6) {
4653
+ const overlapMin = Math.max(
4654
+ Math.min(firstStart.y, firstEnd.y),
4655
+ Math.min(secondStart.y, secondEnd.y)
4656
+ );
4657
+ const overlapMax = Math.min(
4658
+ Math.max(firstStart.y, firstEnd.y),
4659
+ Math.max(secondStart.y, secondEnd.y)
4660
+ );
4661
+ if (overlapMin > overlapMax + EPS6) return null;
4662
+ return {
4663
+ x: firstStart.x,
4664
+ y: Math.max(overlapMin, Math.min(firstStart.y, overlapMax))
4665
+ };
4666
+ }
4667
+ return null;
4668
+ };
4669
+ var clipPathAtFirstIntersection = (tracePath, existingTraces) => {
4670
+ for (let pathIndex = 0; pathIndex < tracePath.length - 1; pathIndex++) {
4671
+ const pathStart = tracePath[pathIndex];
4672
+ const pathEnd = tracePath[pathIndex + 1];
4673
+ const intersections = existingTraces.flatMap(
4674
+ (trace) => trace.tracePath.slice(0, -1).flatMap((traceStart, traceIndex) => {
4675
+ const intersection2 = getAxisAlignedIntersection(
4676
+ pathStart,
4677
+ pathEnd,
4678
+ traceStart,
4679
+ trace.tracePath[traceIndex + 1]
4680
+ );
4681
+ return intersection2 ? [intersection2] : [];
4682
+ })
4683
+ );
4684
+ intersections.sort(
4685
+ (first, second) => distance3(pathStart, first) - distance3(pathStart, second)
4686
+ );
4687
+ const intersection = intersections[0];
4688
+ if (!intersection) continue;
4689
+ const clippedPath = tracePath.slice(0, pathIndex + 1);
4690
+ if (distance3(clippedPath.at(-1), intersection) > EPS6) {
4691
+ clippedPath.push(intersection);
4692
+ }
4693
+ return clippedPath;
4694
+ }
4695
+ return null;
4696
+ };
4622
4697
  var LongDistancePairSolver = class extends BaseSolver {
4623
4698
  constructor(params) {
4624
4699
  super();
@@ -4733,20 +4808,36 @@ var LongDistancePairSolver = class extends BaseSolver {
4733
4808
  } else if (this.subSolver?.solved) {
4734
4809
  const newTracePath = this.subSolver.solvedTracePath;
4735
4810
  if (newTracePath && this.currentCandidatePair) {
4811
+ const [p1, p2] = this.currentCandidatePair;
4812
+ const globalConnNetId = this.netConnMap.getNetConnectedToId(p1.pinId);
4813
+ const sameNetTraces = this.allSolvedTraces.filter(
4814
+ (trace) => trace.globalConnNetId === globalConnNetId
4815
+ );
4816
+ const inputNetConnection = this.inputProblem.netConnections.find(
4817
+ (connection) => connection.pinIds.length === 3 && connection.pinIds.includes(p1.pinId) && connection.pinIds.includes(p2.pinId)
4818
+ );
4819
+ const sourceChip = this.chipMap[p1.chipId];
4820
+ const targetRailTrace = sameNetTraces.find(
4821
+ (trace) => trace.pinIds.includes(p2.pinId) && trace.pins.every((pin) => pin.chipId === p2.chipId)
4822
+ );
4823
+ const canJoinThreePinNet = inputNetConnection !== void 0 && sourceChip?.pins.length === 2 && targetRailTrace !== void 0;
4824
+ const junctionTracePath = canJoinThreePinNet ? clipPathAtFirstIntersection(newTracePath, sameNetTraces) : null;
4825
+ const acceptedTracePath = junctionTracePath ?? newTracePath;
4826
+ const tracesToCheck = junctionTracePath ? this.allSolvedTraces.filter(
4827
+ (trace) => trace.globalConnNetId !== globalConnNetId
4828
+ ) : this.allSolvedTraces;
4736
4829
  const isTraceClear = !doesTraceOverlapWithExistingTraces(
4737
- newTracePath,
4738
- this.allSolvedTraces
4830
+ acceptedTracePath,
4831
+ tracesToCheck
4739
4832
  );
4740
4833
  if (isTraceClear) {
4741
- const [p1, p2] = this.currentCandidatePair;
4742
- const globalConnNetId = this.netConnMap.getNetConnectedToId(p1.pinId);
4743
4834
  const mspPairId = `${p1.pinId}-${p2.pinId}`;
4744
4835
  const newSolvedTrace = {
4745
4836
  mspPairId,
4746
4837
  dcConnNetId: globalConnNetId,
4747
4838
  globalConnNetId,
4748
4839
  pins: [p1, p2],
4749
- tracePath: newTracePath,
4840
+ tracePath: acceptedTracePath,
4750
4841
  mspConnectionPairIds: [mspPairId],
4751
4842
  pinIds: [p1.pinId, p2.pinId]
4752
4843
  };
@@ -5525,9 +5616,9 @@ var moveRailSegments = (trace, segments, coordinate) => {
5525
5616
  };
5526
5617
 
5527
5618
  // lib/solvers/RailNetLabelCornerPlacementSolver/geometry.ts
5528
- var EPS6 = 1e-6;
5619
+ var EPS7 = 1e-6;
5529
5620
  var isTraceLine = (trace) => getUniquePinCount(trace.pinIds) >= 2;
5530
- var rectsOverlap = (a, b) => Math.min(a.maxX, b.maxX) - Math.max(a.minX, b.minX) > EPS6 && Math.min(a.maxY, b.maxY) - Math.max(a.minY, b.minY) > EPS6;
5621
+ var rectsOverlap = (a, b) => Math.min(a.maxX, b.maxX) - Math.max(a.minX, b.minX) > EPS7 && Math.min(a.maxY, b.maxY) - Math.max(a.minY, b.minY) > EPS7;
5531
5622
  var getTraceCorners = (path) => {
5532
5623
  const corners = [];
5533
5624
  for (let i = 1; i < path.length - 1; i++) {
@@ -5551,11 +5642,11 @@ var getUniquePinCount = (pinIds) => new Set(pinIds).size;
5551
5642
  var isTraceCorner = (a, b, c) => getSegmentOrientation(a, b) !== getSegmentOrientation(b, c);
5552
5643
  var isPointOnSegment = (point, start, end) => {
5553
5644
  if (getSegmentOrientation(start, end) === "horizontal") {
5554
- return Math.abs(point.y - start.y) <= EPS6 && point.x >= Math.min(start.x, end.x) - EPS6 && point.x <= Math.max(start.x, end.x) + EPS6;
5645
+ return Math.abs(point.y - start.y) <= EPS7 && point.x >= Math.min(start.x, end.x) - EPS7 && point.x <= Math.max(start.x, end.x) + EPS7;
5555
5646
  }
5556
- return Math.abs(point.x - start.x) <= EPS6 && point.y >= Math.min(start.y, end.y) - EPS6 && point.y <= Math.max(start.y, end.y) + EPS6;
5647
+ return Math.abs(point.x - start.x) <= EPS7 && point.y >= Math.min(start.y, end.y) - EPS7 && point.y <= Math.max(start.y, end.y) + EPS7;
5557
5648
  };
5558
- var getSegmentOrientation = (a, b) => Math.abs(a.y - b.y) <= EPS6 ? "horizontal" : "vertical";
5649
+ var getSegmentOrientation = (a, b) => Math.abs(a.y - b.y) <= EPS7 ? "horizontal" : "vertical";
5559
5650
 
5560
5651
  // lib/solvers/TraceCleanupSolver/sameNetRailAlignment/preservesLabelAnchors.ts
5561
5652
  var getAnchoredTraceIds = (label, traces) => new Set(
@@ -5571,17 +5662,17 @@ var preservesLabelAnchors = (labels, before, after) => labels.every((label) => {
5571
5662
  });
5572
5663
 
5573
5664
  // lib/solvers/Example28Solver/types.ts
5574
- var EPS7 = 1e-9;
5665
+ var EPS8 = 1e-9;
5575
5666
 
5576
5667
  // lib/solvers/Example28Solver/segmentRunsAlongRectBoundary.ts
5577
5668
  var segmentRunsAlongRectBoundary = (start, end, rect) => {
5578
- const isVertical5 = Math.abs(start.x - end.x) < EPS7;
5579
- const isHorizontal4 = Math.abs(start.y - end.y) < EPS7;
5669
+ const isVertical5 = Math.abs(start.x - end.x) < EPS8;
5670
+ const isHorizontal4 = Math.abs(start.y - end.y) < EPS8;
5580
5671
  if (isVertical5) {
5581
- return Math.abs(start.x - rect.minX) < EPS7 || Math.abs(start.x - rect.maxX) < EPS7;
5672
+ return Math.abs(start.x - rect.minX) < EPS8 || Math.abs(start.x - rect.maxX) < EPS8;
5582
5673
  }
5583
5674
  if (isHorizontal4) {
5584
- return Math.abs(start.y - rect.minY) < EPS7 || Math.abs(start.y - rect.maxY) < EPS7;
5675
+ return Math.abs(start.y - rect.minY) < EPS8 || Math.abs(start.y - rect.maxY) < EPS8;
5585
5676
  }
5586
5677
  return false;
5587
5678
  };
@@ -5596,10 +5687,10 @@ var getPathLength2 = (path) => {
5596
5687
  return length;
5597
5688
  };
5598
5689
  var getDistance2 = (a, b) => Math.abs(a.x - b.x) + Math.abs(a.y - b.y);
5599
- var isAxisAlignedSegment = (start, end) => Math.abs(start.x - end.x) < EPS7 || Math.abs(start.y - end.y) < EPS7;
5600
- var getSegmentOrientation2 = (start, end) => Math.abs(start.y - end.y) < EPS7 ? "horizontal" : "vertical";
5690
+ var isAxisAlignedSegment = (start, end) => Math.abs(start.x - end.x) < EPS8 || Math.abs(start.y - end.y) < EPS8;
5691
+ var getSegmentOrientation2 = (start, end) => Math.abs(start.y - end.y) < EPS8 ? "horizontal" : "vertical";
5601
5692
  var projectPointToSegment = (point, start, end) => {
5602
- if (Math.abs(start.x - end.x) < EPS7) {
5693
+ if (Math.abs(start.x - end.x) < EPS8) {
5603
5694
  return {
5604
5695
  x: start.x,
5605
5696
  y: Math.min(
@@ -5608,7 +5699,7 @@ var projectPointToSegment = (point, start, end) => {
5608
5699
  )
5609
5700
  };
5610
5701
  }
5611
- if (Math.abs(start.y - end.y) < EPS7) {
5702
+ if (Math.abs(start.y - end.y) < EPS8) {
5612
5703
  return {
5613
5704
  x: Math.min(
5614
5705
  Math.max(point.x, Math.min(start.x, end.x)),
@@ -5651,9 +5742,9 @@ var findSegmentContainingPoint = (path, point) => {
5651
5742
  };
5652
5743
  var isPointWithinSegmentPrimaryRange = (point, segment) => {
5653
5744
  if (segment.orientation === "horizontal") {
5654
- return point.x >= Math.min(segment.start.x, segment.end.x) - EPS7 && point.x <= Math.max(segment.start.x, segment.end.x) + EPS7;
5745
+ return point.x >= Math.min(segment.start.x, segment.end.x) - EPS8 && point.x <= Math.max(segment.start.x, segment.end.x) + EPS8;
5655
5746
  }
5656
- return point.y >= Math.min(segment.start.y, segment.end.y) - EPS7 && point.y <= Math.max(segment.start.y, segment.end.y) + EPS7;
5747
+ return point.y >= Math.min(segment.start.y, segment.end.y) - EPS8 && point.y <= Math.max(segment.start.y, segment.end.y) + EPS8;
5657
5748
  };
5658
5749
  var findPreferredReroutedSegment = (path, originalSegmentIndex, originalSegmentCount, orientation, anchorPoint) => {
5659
5750
  const matchingSegments = getSegments(path).filter(
@@ -5681,24 +5772,24 @@ var projectPointToPath = (point, path) => {
5681
5772
  return bestPoint;
5682
5773
  };
5683
5774
  var segmentsIntersect = (a1, a2, b1, b2) => {
5684
- const aVertical = Math.abs(a1.x - a2.x) < EPS7;
5685
- const bVertical = Math.abs(b1.x - b2.x) < EPS7;
5686
- const between = (value, p1, p2) => value >= Math.min(p1, p2) - EPS7 && value <= Math.max(p1, p2) + EPS7;
5775
+ const aVertical = Math.abs(a1.x - a2.x) < EPS8;
5776
+ const bVertical = Math.abs(b1.x - b2.x) < EPS8;
5777
+ const between2 = (value, p1, p2) => value >= Math.min(p1, p2) - EPS8 && value <= Math.max(p1, p2) + EPS8;
5687
5778
  if (aVertical && bVertical) {
5688
- if (Math.abs(a1.x - b1.x) > EPS7) return false;
5779
+ if (Math.abs(a1.x - b1.x) > EPS8) return false;
5689
5780
  const overlap = Math.min(Math.max(a1.y, a2.y), Math.max(b1.y, b2.y)) - Math.max(Math.min(a1.y, a2.y), Math.min(b1.y, b2.y));
5690
- return overlap > EPS7;
5781
+ return overlap > EPS8;
5691
5782
  }
5692
5783
  if (!aVertical && !bVertical) {
5693
- if (Math.abs(a1.y - b1.y) > EPS7) return false;
5784
+ if (Math.abs(a1.y - b1.y) > EPS8) return false;
5694
5785
  const overlap = Math.min(Math.max(a1.x, a2.x), Math.max(b1.x, b2.x)) - Math.max(Math.min(a1.x, a2.x), Math.min(b1.x, b2.x));
5695
- return overlap > EPS7;
5786
+ return overlap > EPS8;
5696
5787
  }
5697
5788
  const verticalA = aVertical ? a1 : b1;
5698
5789
  const verticalB = aVertical ? a2 : b2;
5699
5790
  const horizontalA = aVertical ? b1 : a1;
5700
5791
  const horizontalB = aVertical ? b2 : a2;
5701
- return between(verticalA.x, horizontalA.x, horizontalB.x) && between(horizontalA.y, verticalA.y, verticalB.y);
5792
+ return between2(verticalA.x, horizontalA.x, horizontalB.x) && between2(horizontalA.y, verticalA.y, verticalB.y);
5702
5793
  };
5703
5794
  var countPathIntersections = (pathA, pathB) => {
5704
5795
  let count = 0;
@@ -6068,7 +6159,7 @@ var getTraceObstacles = (allTraces, excludeTraceId) => {
6068
6159
 
6069
6160
  // lib/solvers/TraceCleanupSolver/sub-solver/findIntersectionsWithObstacles.ts
6070
6161
  import { getSegmentIntersection } from "@tscircuit/math-utils/line-intersections";
6071
- var EPS8 = 1e-6;
6162
+ var EPS9 = 1e-6;
6072
6163
  var findIntersectionsWithObstacles = (p1, p2, obstacles) => {
6073
6164
  const intersections = [];
6074
6165
  for (const obstacle of obstacles) {
@@ -6087,17 +6178,17 @@ var findIntersectionsWithObstacles = (p1, p2, obstacles) => {
6087
6178
  }
6088
6179
  return intersections;
6089
6180
  };
6090
- var isSamePoint = (first, second) => Math.abs(first.x - second.x) < EPS8 && Math.abs(first.y - second.y) < EPS8;
6181
+ var isSamePoint = (first, second) => Math.abs(first.x - second.x) < EPS9 && Math.abs(first.y - second.y) < EPS9;
6091
6182
  var findPerpendicularPathCrossings = (path, otherPath) => {
6092
6183
  const crossings = [];
6093
6184
  for (let pathSegmentIndex = 1; pathSegmentIndex < path.length - 2; pathSegmentIndex++) {
6094
6185
  const start = path[pathSegmentIndex];
6095
6186
  const end = path[pathSegmentIndex + 1];
6096
- const isVertical5 = Math.abs(start.x - end.x) < EPS8;
6187
+ const isVertical5 = Math.abs(start.x - end.x) < EPS9;
6097
6188
  for (let otherPathSegmentIndex = 1; otherPathSegmentIndex < otherPath.length - 2; otherPathSegmentIndex++) {
6098
6189
  const otherStart = otherPath[otherPathSegmentIndex];
6099
6190
  const otherEnd = otherPath[otherPathSegmentIndex + 1];
6100
- const otherIsVertical = Math.abs(otherStart.x - otherEnd.x) < EPS8;
6191
+ const otherIsVertical = Math.abs(otherStart.x - otherEnd.x) < EPS9;
6101
6192
  if (isVertical5 === otherIsVertical) continue;
6102
6193
  const intersection = getSegmentIntersection(
6103
6194
  start,
@@ -6117,8 +6208,8 @@ var findPerpendicularPathCrossings = (path, otherPath) => {
6117
6208
  };
6118
6209
 
6119
6210
  // lib/solvers/TraceCleanupSolver/sub-solver/generateLShapeRerouteCandidates.ts
6120
- var EPS9 = 1e-6;
6121
- var isVertical3 = (a, b, eps = EPS9) => Math.abs(a.x - b.x) < eps;
6211
+ var EPS10 = 1e-6;
6212
+ var isVertical3 = (a, b, eps = EPS10) => Math.abs(a.x - b.x) < eps;
6122
6213
  var generateLShapeRerouteCandidates = ({
6123
6214
  lShape,
6124
6215
  rectangle,
@@ -6131,7 +6222,7 @@ var generateLShapeRerouteCandidates = ({
6131
6222
  let c2;
6132
6223
  let i1_padded = interactionPoint1;
6133
6224
  let i2_padded = interactionPoint2;
6134
- if (Math.abs(p2.x - x) < EPS9 && Math.abs(p2.y - (y + height)) < EPS9) {
6225
+ if (Math.abs(p2.x - x) < EPS10 && Math.abs(p2.y - (y + height)) < EPS10) {
6135
6226
  c2 = { x: x + width + padding, y: y - padding };
6136
6227
  if (isVertical3(p1, p2)) {
6137
6228
  i1_padded = { x: interactionPoint1.x, y: interactionPoint1.y - padding };
@@ -6143,7 +6234,7 @@ var generateLShapeRerouteCandidates = ({
6143
6234
  } else {
6144
6235
  i2_padded = { x: interactionPoint2.x + padding, y: interactionPoint2.y };
6145
6236
  }
6146
- } else if (Math.abs(p2.x - (x + width)) < EPS9 && Math.abs(p2.y - (y + height)) < EPS9) {
6237
+ } else if (Math.abs(p2.x - (x + width)) < EPS10 && Math.abs(p2.y - (y + height)) < EPS10) {
6147
6238
  c2 = { x: x - padding, y: y - padding };
6148
6239
  if (isVertical3(p1, p2)) {
6149
6240
  i1_padded = { x: interactionPoint1.x, y: interactionPoint1.y - padding };
@@ -6155,7 +6246,7 @@ var generateLShapeRerouteCandidates = ({
6155
6246
  } else {
6156
6247
  i2_padded = { x: interactionPoint2.x - padding, y: interactionPoint2.y };
6157
6248
  }
6158
- } else if (Math.abs(p2.x - x) < EPS9 && Math.abs(p2.y - y) < EPS9) {
6249
+ } else if (Math.abs(p2.x - x) < EPS10 && Math.abs(p2.y - y) < EPS10) {
6159
6250
  c2 = { x: x + width + padding, y: y + height + padding };
6160
6251
  if (isVertical3(p1, p2)) {
6161
6252
  i1_padded = { x: interactionPoint1.x, y: interactionPoint1.y + padding };
@@ -6167,7 +6258,7 @@ var generateLShapeRerouteCandidates = ({
6167
6258
  } else {
6168
6259
  i2_padded = { x: interactionPoint2.x + padding, y: interactionPoint2.y };
6169
6260
  }
6170
- } else if (Math.abs(p2.x - (x + width)) < EPS9 && Math.abs(p2.y - y) < EPS9) {
6261
+ } else if (Math.abs(p2.x - (x + width)) < EPS10 && Math.abs(p2.y - y) < EPS10) {
6171
6262
  c2 = { x: x - padding, y: y + height + padding };
6172
6263
  if (isVertical3(p1, p2)) {
6173
6264
  i1_padded = { x: interactionPoint1.x, y: interactionPoint1.y + padding };
@@ -6195,7 +6286,7 @@ var generatePerpendicularTraceDetours = ({
6195
6286
  const buildDetours = (path, index) => {
6196
6287
  const start = path[index];
6197
6288
  const end = path[index + 1];
6198
- const movingAxis = Math.abs(start.x - end.x) < EPS9 ? "y" : "x";
6289
+ const movingAxis = Math.abs(start.x - end.x) < EPS10 ? "y" : "x";
6199
6290
  const detourAxis = movingAxis === "x" ? "y" : "x";
6200
6291
  const gate = obstacleStart[movingAxis] + Math.sign(start[movingAxis] - obstacleStart[movingAxis]) * clearance;
6201
6292
  const obstacleRange = [obstacleStart[detourAxis], obstacleEnd[detourAxis]];
@@ -6793,9 +6884,9 @@ var UntangleTraceSubsolver = class extends BaseSolver {
6793
6884
  };
6794
6885
 
6795
6886
  // lib/solvers/TraceCleanupSolver/is4PointRectangle.ts
6796
- var EPS10 = 1e-6;
6797
- var sameX = (a, b) => Math.abs(a.x - b.x) <= EPS10;
6798
- var sameY = (a, b) => Math.abs(a.y - b.y) <= EPS10;
6887
+ var EPS11 = 1e-6;
6888
+ var sameX = (a, b) => Math.abs(a.x - b.x) <= EPS11;
6889
+ var sameY = (a, b) => Math.abs(a.y - b.y) <= EPS11;
6799
6890
  var is4PointRectangle = (path) => {
6800
6891
  if (path.length !== 4) return false;
6801
6892
  const [p0, p1, p2, p3] = path;
@@ -7070,7 +7161,7 @@ var doesPathRunAlongChipBoundary = (path, chipObstacles) => {
7070
7161
  const end = path[i + 1];
7071
7162
  for (const obstacle of chipObstacles) {
7072
7163
  if (!segmentRunsAlongRectBoundary(start, end, obstacle)) continue;
7073
- if (getSegmentOverlapWithRectSpan(start, end, obstacle) > EPS7) {
7164
+ if (getSegmentOverlapWithRectSpan(start, end, obstacle) > EPS8) {
7074
7165
  return true;
7075
7166
  }
7076
7167
  }
@@ -7085,13 +7176,13 @@ var getChipBoundaryOverlap = (path, chipObstacles) => {
7085
7176
  for (const obstacle of chipObstacles) {
7086
7177
  if (!segmentRunsAlongRectBoundary(start, end, obstacle)) continue;
7087
7178
  const overlap = getSegmentOverlapWithRectSpan(start, end, obstacle);
7088
- if (overlap > EPS7) total += overlap;
7179
+ if (overlap > EPS8) total += overlap;
7089
7180
  }
7090
7181
  }
7091
7182
  return total;
7092
7183
  };
7093
7184
  var getSegmentOverlapWithRectSpan = (start, end, rect) => {
7094
- const isVertical5 = Math.abs(start.x - end.x) < EPS7;
7185
+ const isVertical5 = Math.abs(start.x - end.x) < EPS8;
7095
7186
  if (isVertical5) {
7096
7187
  return Math.min(Math.max(start.y, end.y), rect.maxY) - Math.max(Math.min(start.y, end.y), rect.minY);
7097
7188
  }
@@ -7855,16 +7946,16 @@ var createPortOnlyLabelConnectorTrace = ({
7855
7946
  // lib/solvers/AvailableNetOrientationSolver/constants.ts
7856
7947
  var LABEL_SEARCH_STEP = 0.05;
7857
7948
  var WICK_CLEARANCE = 1e-3;
7858
- var EPS11 = 1e-9;
7859
- var TRACE_BOUNDARY_TOLERANCE = WICK_CLEARANCE + EPS11;
7949
+ var EPS12 = 1e-9;
7950
+ var TRACE_BOUNDARY_TOLERANCE = WICK_CLEARANCE + EPS12;
7860
7951
  var CANDIDATE_SELECTED_COLOR2 = "blue";
7861
7952
  var CANDIDATE_REJECTED_COLOR2 = "red";
7862
7953
 
7863
7954
  // lib/solvers/AvailableNetOrientationSolver/geometry.ts
7864
7955
  var isYOrientation = (orientation) => orientation === "y+" || orientation === "y-";
7865
7956
  var isXOrientation = (orientation) => orientation === "x+" || orientation === "x-";
7866
- var rectsOverlap2 = (a, b) => Math.min(a.maxX, b.maxX) - Math.max(a.minX, b.minX) > EPS11 && Math.min(a.maxY, b.maxY) - Math.max(a.minY, b.minY) > EPS11;
7867
- var rangesOverlap = (minA, maxA, minB, maxB) => Math.min(maxA, maxB) - Math.max(minA, minB) > EPS11;
7957
+ 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;
7958
+ var rangesOverlap = (minA, maxA, minB, maxB) => Math.min(maxA, maxB) - Math.max(minA, minB) > EPS12;
7868
7959
  var traceCrossesBoundsInterior = (bounds, traceMap) => {
7869
7960
  for (const trace of Object.values(traceMap)) {
7870
7961
  const points = trace.tracePath;
@@ -7887,7 +7978,7 @@ var segmentCrossesBoundsInterior = (p1, p2, bounds) => {
7887
7978
  return false;
7888
7979
  }
7889
7980
  if (sameX2(p1, p2)) {
7890
- if (p1.x <= interiorBounds.minX + EPS11 || p1.x >= interiorBounds.maxX - EPS11) {
7981
+ if (p1.x <= interiorBounds.minX + EPS12 || p1.x >= interiorBounds.maxX - EPS12) {
7891
7982
  return false;
7892
7983
  }
7893
7984
  return rangesOverlap(
@@ -7898,7 +7989,7 @@ var segmentCrossesBoundsInterior = (p1, p2, bounds) => {
7898
7989
  );
7899
7990
  }
7900
7991
  if (sameY2(p1, p2)) {
7901
- if (p1.y <= interiorBounds.minY + EPS11 || p1.y >= interiorBounds.maxY - EPS11) {
7992
+ if (p1.y <= interiorBounds.minY + EPS12 || p1.y >= interiorBounds.maxY - EPS12) {
7902
7993
  return false;
7903
7994
  }
7904
7995
  return rangesOverlap(
@@ -7954,8 +8045,8 @@ var simplifyOrthogonalPath = (path) => {
7954
8045
  return simplified;
7955
8046
  };
7956
8047
  var pointsEqual2 = (a, b) => sameX2(a, b) && sameY2(a, b);
7957
- var sameX2 = (a, b) => Math.abs(a.x - b.x) <= EPS11;
7958
- var sameY2 = (a, b) => Math.abs(a.y - b.y) <= EPS11;
8048
+ var sameX2 = (a, b) => Math.abs(a.x - b.x) <= EPS12;
8049
+ var sameY2 = (a, b) => Math.abs(a.y - b.y) <= EPS12;
7959
8050
  var getMaxSearchDistance = (inputProblem) => {
7960
8051
  const maxChipWidth = Math.max(
7961
8052
  ...inputProblem.chips.map((chip) => chip.width),
@@ -7964,6 +8055,42 @@ var getMaxSearchDistance = (inputProblem) => {
7964
8055
  return maxChipWidth * 3;
7965
8056
  };
7966
8057
 
8058
+ // lib/solvers/AvailableNetOrientationSolver/orderRoutedLabelsBeforeOverlappingPortLabels.ts
8059
+ var isPortOnlyLabel = (label) => label.mspConnectionPairIds.length === 0;
8060
+ var orderRoutedLabelsBeforeOverlappingPortLabels = ({
8061
+ labelIndices,
8062
+ netLabelPlacements
8063
+ }) => {
8064
+ const orderedLabelIndices = [...labelIndices];
8065
+ for (const routedLabelIndex of labelIndices) {
8066
+ const routedLabel = netLabelPlacements[routedLabelIndex];
8067
+ if (isPortOnlyLabel(routedLabel)) continue;
8068
+ const routedBounds = getRectBounds(
8069
+ routedLabel.center,
8070
+ routedLabel.width,
8071
+ routedLabel.height
8072
+ );
8073
+ const blockingPosition = orderedLabelIndices.findIndex((labelIndex) => {
8074
+ const portOnlyLabel = netLabelPlacements[labelIndex];
8075
+ if (!isPortOnlyLabel(portOnlyLabel)) return false;
8076
+ if (portOnlyLabel.globalConnNetId === routedLabel.globalConnNetId) {
8077
+ return false;
8078
+ }
8079
+ const portOnlyBounds = getRectBounds(
8080
+ portOnlyLabel.center,
8081
+ portOnlyLabel.width,
8082
+ portOnlyLabel.height
8083
+ );
8084
+ return rectsOverlap2(routedBounds, portOnlyBounds);
8085
+ });
8086
+ const routedPosition = orderedLabelIndices.indexOf(routedLabelIndex);
8087
+ if (blockingPosition === -1 || blockingPosition > routedPosition) continue;
8088
+ orderedLabelIndices.splice(routedPosition, 1);
8089
+ orderedLabelIndices.splice(blockingPosition, 0, routedLabelIndex);
8090
+ }
8091
+ return orderedLabelIndices;
8092
+ };
8093
+
7967
8094
  // lib/solvers/AvailableNetOrientationSolver/visualize.ts
7968
8095
  var visualizeAvailableNetOrientationSolver = (params) => {
7969
8096
  const graphics = visualizeInputProblem(params.inputProblem);
@@ -8114,12 +8241,16 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
8114
8241
  }
8115
8242
  }
8116
8243
  this.sortCrowdedTopBankByPin(indices);
8117
- const blockedStandaloneLabelIndex = indices.find((index) => {
8244
+ const orderedIndices = orderRoutedLabelsBeforeOverlappingPortLabels({
8245
+ labelIndices: indices,
8246
+ netLabelPlacements: this.outputNetLabelPlacements
8247
+ });
8248
+ const blockedStandaloneLabelIndex = orderedIndices.find((index) => {
8118
8249
  const label = this.outputNetLabelPlacements[index];
8119
8250
  const orientations = this.getAvailableOrientations(label);
8120
8251
  return this.isPortOnlyLabel(label) && this.isStandaloneSinglePinNetLabel(label) && orientations.length === 1 && isYOrientation(orientations[0]) && this.labelIntersectsDifferentNetTrace(label);
8121
8252
  });
8122
- if (blockedStandaloneLabelIndex === void 0) return indices;
8253
+ if (blockedStandaloneLabelIndex === void 0) return orderedIndices;
8123
8254
  this.blockedStandaloneLabelIndex = blockedStandaloneLabelIndex;
8124
8255
  this.blockedStandaloneLabelTargetAnchorX = null;
8125
8256
  const blockedLabel = this.outputNetLabelPlacements[blockedStandaloneLabelIndex];
@@ -8127,8 +8258,8 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
8127
8258
  const chipSide = this.getChipSideForPoint(blockedLabel.anchorPoint);
8128
8259
  const affectedSlots = [];
8129
8260
  const labelsToOrder = [];
8130
- for (let slot = 0; slot < indices.length; slot++) {
8131
- const index = indices[slot];
8261
+ for (let slot = 0; slot < orderedIndices.length; slot++) {
8262
+ const index = orderedIndices[slot];
8132
8263
  const label = this.outputNetLabelPlacements[index];
8133
8264
  const orientations = this.getAvailableOrientations(label);
8134
8265
  if (this.getChipSideForPoint(label.anchorPoint) === chipSide && orientations.length === 1 && orientations[0] === requiredOrientation) {
@@ -8158,9 +8289,9 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
8158
8289
  ).x;
8159
8290
  }
8160
8291
  for (let i = 0; i < affectedSlots.length; i++) {
8161
- indices[affectedSlots[i]] = labelsToOrder[i];
8292
+ orderedIndices[affectedSlots[i]] = labelsToOrder[i];
8162
8293
  }
8163
- return indices;
8294
+ return orderedIndices;
8164
8295
  }
8165
8296
  sortCrowdedTopBankByPin(indices) {
8166
8297
  const slotsByChip = /* @__PURE__ */ new Map();
@@ -8371,7 +8502,7 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
8371
8502
  index,
8372
8503
  pin: this.pinMap[otherLabel.pinIds[0]]
8373
8504
  })).filter(
8374
- ({ index, pin: otherPin }) => this.crowdedPortOnlyLabelIndices.has(index) && otherPin?.chipId === pin.chipId && otherPin.x > pin.x + EPS11
8505
+ ({ index, pin: otherPin }) => this.crowdedPortOnlyLabelIndices.has(index) && otherPin?.chipId === pin.chipId && otherPin.x > pin.x + EPS12
8375
8506
  ).sort((a, b) => a.pin.x - b.pin.x)[0]?.pin;
8376
8507
  if (orientation === "y-" && nextPinToRight) return null;
8377
8508
  const anchorX = orientation === "y-" ? Math.max(
@@ -8404,7 +8535,7 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
8404
8535
  const centeredAnchorY = hasUpFacingStack ? (lowestUpFacingLabelY + highestUpFacingLabelY) / 2 : stackedAnchorY;
8405
8536
  const anchorYs = orientation === "y-" ? [centeredAnchorY, stackedAnchorY] : [stackedAnchorY];
8406
8537
  for (const anchorY of anchorYs) {
8407
- if (anchorY - label.anchorPoint.y > this.maxSearchDistance + EPS11) {
8538
+ if (anchorY - label.anchorPoint.y > this.maxSearchDistance + EPS12) {
8408
8539
  continue;
8409
8540
  }
8410
8541
  const candidate = this.createCandidate(
@@ -8433,11 +8564,11 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
8433
8564
  if (trace.globalConnNetId !== label.globalConnNetId) return false;
8434
8565
  const path = trace.tracePath;
8435
8566
  return path.some((point, pointIndex) => {
8436
- if (Math.abs(point.x - label.anchorPoint.x) > EPS11 || Math.abs(point.y - label.anchorPoint.y) > EPS11) {
8567
+ if (Math.abs(point.x - label.anchorPoint.x) > EPS12 || Math.abs(point.y - label.anchorPoint.y) > EPS12) {
8437
8568
  return false;
8438
8569
  }
8439
8570
  return [path[pointIndex - 1], path[pointIndex + 1]].some(
8440
- (neighbor) => neighbor && Math.abs(neighbor.x - point.x) <= EPS11 && (neighbor.y - point.y) * direction.y > EPS11
8571
+ (neighbor) => neighbor && Math.abs(neighbor.x - point.x) <= EPS12 && (neighbor.y - point.y) * direction.y > EPS12
8441
8572
  );
8442
8573
  });
8443
8574
  });
@@ -8527,7 +8658,7 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
8527
8658
  orientation
8528
8659
  );
8529
8660
  if (outwardDirection.x === 0 && outwardDirection.y === 0) continue;
8530
- for (let distance5 = LABEL_SEARCH_STEP; distance5 <= this.maxSearchDistance + EPS11; distance5 += LABEL_SEARCH_STEP) {
8661
+ for (let distance5 = LABEL_SEARCH_STEP; distance5 <= this.maxSearchDistance + EPS12; distance5 += LABEL_SEARCH_STEP) {
8531
8662
  const anchorPoint = {
8532
8663
  x: connectorSource.x + outwardDirection.x * distance5,
8533
8664
  y: connectorSource.y + outwardDirection.y * distance5
@@ -8582,7 +8713,7 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
8582
8713
  );
8583
8714
  const maxSearchDistance = this.getSearchDistanceLimit(label, orientation);
8584
8715
  const maxOutwardDistance = outwardDirection.x === 0 && outwardDirection.y === 0 ? 0 : this.maxSearchDistance;
8585
- for (let outwardDistance = 0; outwardDistance <= maxOutwardDistance + EPS11; outwardDistance += LABEL_SEARCH_STEP) {
8716
+ for (let outwardDistance = 0; outwardDistance <= maxOutwardDistance + EPS12; outwardDistance += LABEL_SEARCH_STEP) {
8586
8717
  const baseAnchor = {
8587
8718
  x: initialBaseAnchor.x + outwardDirection.x * outwardDistance,
8588
8719
  y: initialBaseAnchor.y + outwardDirection.y * outwardDistance
@@ -8656,7 +8787,7 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
8656
8787
  phase = "shift",
8657
8788
  stopOnTraceCollision = true
8658
8789
  } = params;
8659
- for (let distance5 = LABEL_SEARCH_STEP; distance5 <= maxSearchDistance + EPS11; distance5 += LABEL_SEARCH_STEP) {
8790
+ for (let distance5 = LABEL_SEARCH_STEP; distance5 <= maxSearchDistance + EPS12; distance5 += LABEL_SEARCH_STEP) {
8660
8791
  const anchorPoint = {
8661
8792
  x: baseAnchor.x + direction.x * distance5,
8662
8793
  y: baseAnchor.y + direction.y * distance5
@@ -8962,9 +9093,9 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
8962
9093
  const { anchorPoint, orientation } = candidate;
8963
9094
  const chipBounds = chip.bounds;
8964
9095
  if (isYOrientation(orientation)) {
8965
- return anchorPoint.x < chipBounds.minX - EPS11 || anchorPoint.x > chipBounds.maxX + EPS11;
9096
+ return anchorPoint.x < chipBounds.minX - EPS12 || anchorPoint.x > chipBounds.maxX + EPS12;
8966
9097
  }
8967
- return anchorPoint.y < chipBounds.minY - EPS11 || anchorPoint.y > chipBounds.maxY + EPS11;
9098
+ return anchorPoint.y < chipBounds.minY - EPS12 || anchorPoint.y > chipBounds.maxY + EPS12;
8968
9099
  });
8969
9100
  }
8970
9101
  getBoundsStatus(candidateBoundsCheck) {
@@ -9065,8 +9196,8 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
9065
9196
  if (!chip) return null;
9066
9197
  const sides = new Set(
9067
9198
  pins.map((pin) => {
9068
- if (Math.abs(pin.x - chip.bounds.minX) <= EPS11) return "left";
9069
- if (Math.abs(pin.x - chip.bounds.maxX) <= EPS11) return "right";
9199
+ if (Math.abs(pin.x - chip.bounds.minX) <= EPS12) return "left";
9200
+ if (Math.abs(pin.x - chip.bounds.maxX) <= EPS12) return "right";
9070
9201
  return null;
9071
9202
  })
9072
9203
  );
@@ -9099,8 +9230,8 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
9099
9230
  sharesChipBoundary(bounds) {
9100
9231
  for (const chip of this.chipObstacleSpatialIndex.chips) {
9101
9232
  const chipBounds = chip.bounds;
9102
- const adjacentToVerticalSide = Math.abs(bounds.minX - chipBounds.maxX) <= WICK_CLEARANCE + EPS11 || Math.abs(bounds.maxX - chipBounds.minX) <= WICK_CLEARANCE + EPS11;
9103
- const adjacentToHorizontalSide = Math.abs(bounds.minY - chipBounds.maxY) <= WICK_CLEARANCE + EPS11 || Math.abs(bounds.maxY - chipBounds.minY) <= WICK_CLEARANCE + EPS11;
9233
+ const adjacentToVerticalSide = Math.abs(bounds.minX - chipBounds.maxX) <= WICK_CLEARANCE + EPS12 || Math.abs(bounds.maxX - chipBounds.minX) <= WICK_CLEARANCE + EPS12;
9234
+ const adjacentToHorizontalSide = Math.abs(bounds.minY - chipBounds.maxY) <= WICK_CLEARANCE + EPS12 || Math.abs(bounds.maxY - chipBounds.minY) <= WICK_CLEARANCE + EPS12;
9104
9235
  if (adjacentToVerticalSide && rangesOverlap(
9105
9236
  bounds.minY,
9106
9237
  bounds.maxY,
@@ -9162,7 +9293,7 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
9162
9293
  let nearestDistance = Number.POSITIVE_INFINITY;
9163
9294
  for (const chip of this.chipObstacleSpatialIndex.chips) {
9164
9295
  const bounds = chip.bounds;
9165
- if (point.x < bounds.minX - EPS11 || point.x > bounds.maxX + EPS11 || point.y < bounds.minY - EPS11 || point.y > bounds.maxY + EPS11) {
9296
+ if (point.x < bounds.minX - EPS12 || point.x > bounds.maxX + EPS12 || point.y < bounds.minY - EPS12 || point.y > bounds.maxY + EPS12) {
9166
9297
  continue;
9167
9298
  }
9168
9299
  for (const [side, distance5] of getSideDistances(point, bounds)) {
@@ -9179,8 +9310,8 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
9179
9310
  let nearestDistanceSq = Number.POSITIVE_INFINITY;
9180
9311
  for (const chip of this.chipObstacleSpatialIndex.chips) {
9181
9312
  const bounds = chip.bounds;
9182
- const dx = point.x < bounds.minX - EPS11 ? bounds.minX - point.x : point.x > bounds.maxX + EPS11 ? point.x - bounds.maxX : 0;
9183
- const dy = point.y < bounds.minY - EPS11 ? bounds.minY - point.y : point.y > bounds.maxY + EPS11 ? point.y - bounds.maxY : 0;
9313
+ const dx = point.x < bounds.minX - EPS12 ? bounds.minX - point.x : point.x > bounds.maxX + EPS12 ? point.x - bounds.maxX : 0;
9314
+ const dy = point.y < bounds.minY - EPS12 ? bounds.minY - point.y : point.y > bounds.maxY + EPS12 ? point.y - bounds.maxY : 0;
9184
9315
  if (dx === 0 && dy === 0) continue;
9185
9316
  const distanceSq = dx ** 2 + dy ** 2;
9186
9317
  if (distanceSq >= nearestDistanceSq) continue;
@@ -9496,7 +9627,7 @@ var RailNetLabelCornerPlacementSolver = class extends BaseSolver {
9496
9627
  for (const anchorPoint of getTraceCorners(path)) {
9497
9628
  const cornerIndex = path.indexOf(anchorPoint);
9498
9629
  const anchorAlignedToPin = pins.some(
9499
- (pin) => Math.abs(pin.x - anchorPoint.x) <= EPS6
9630
+ (pin) => Math.abs(pin.x - anchorPoint.x) <= EPS7
9500
9631
  );
9501
9632
  const pinAligned = anchorAlignedToPin || allowRailAlignedFallback && this.isPinAlignedCorner(path, cornerIndex);
9502
9633
  if (!pinAligned) continue;
@@ -9536,12 +9667,12 @@ var RailNetLabelCornerPlacementSolver = class extends BaseSolver {
9536
9667
  return traceCrossesBoundsInterior(bounds, otherNetTraceMap);
9537
9668
  }
9538
9669
  pointsEqual(a, b) {
9539
- return Math.abs(a.x - b.x) <= EPS6 && Math.abs(a.y - b.y) <= EPS6;
9670
+ return Math.abs(a.x - b.x) <= EPS7 && Math.abs(a.y - b.y) <= EPS7;
9540
9671
  }
9541
9672
  getVerticalSegmentPointIndices(path, cornerIndex) {
9542
9673
  const corner = path[cornerIndex];
9543
- const previousIsVertical = Math.abs(path[cornerIndex - 1].x - corner.x) <= EPS6;
9544
- const nextIsVertical = Math.abs(path[cornerIndex + 1].x - corner.x) <= EPS6;
9674
+ const previousIsVertical = Math.abs(path[cornerIndex - 1].x - corner.x) <= EPS7;
9675
+ const nextIsVertical = Math.abs(path[cornerIndex + 1].x - corner.x) <= EPS7;
9545
9676
  if (previousIsVertical === nextIsVertical) return null;
9546
9677
  const indices = previousIsVertical ? [cornerIndex - 1, cornerIndex] : [cornerIndex, cornerIndex + 1];
9547
9678
  return indices;
@@ -9591,7 +9722,7 @@ var RailNetLabelCornerPlacementSolver = class extends BaseSolver {
9591
9722
  const end = otherTrace.tracePath[i + 1];
9592
9723
  if (!segmentCrossesBoundsInterior(start, end, labelBounds)) continue;
9593
9724
  const halfLabelWidth = label.width / 2;
9594
- if (Math.abs(start.x - end.x) <= EPS6) {
9725
+ if (Math.abs(start.x - end.x) <= EPS7) {
9595
9726
  shiftedCoordinates.add(
9596
9727
  start.x - halfLabelWidth - LABEL_TRACE_CLEARANCE3
9597
9728
  );
@@ -9609,7 +9740,7 @@ var RailNetLabelCornerPlacementSolver = class extends BaseSolver {
9609
9740
  }
9610
9741
  }
9611
9742
  return [...shiftedCoordinates].flatMap((x) => {
9612
- if (Math.abs(x - corner.x) <= EPS6) return [];
9743
+ if (Math.abs(x - corner.x) <= EPS7) return [];
9613
9744
  const reroutedTracePath = simplifyPath(
9614
9745
  path.map(
9615
9746
  (point, pointIndex) => verticalPointIndices.includes(pointIndex) ? { ...point, x } : point
@@ -9740,11 +9871,11 @@ var getOrientationConstraint = (inputProblem, label) => {
9740
9871
  };
9741
9872
 
9742
9873
  // lib/solvers/TraceAnchoredNetLabelOverlapSolver/geometry.ts
9743
- var EPS12 = 1e-6;
9874
+ var EPS13 = 1e-6;
9744
9875
  var TRACE_BOUNDARY_TOLERANCE2 = 1e-6;
9745
9876
  var getLabelBounds = (label) => getRectBounds(label.center, label.width, label.height);
9746
- var rectsOverlap3 = (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;
9747
- var rectsTouchOrOverlap = (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;
9877
+ 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;
9878
+ 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;
9748
9879
  var traceCrossesBoundsInterior2 = (bounds, traces) => {
9749
9880
  for (const trace of traces) {
9750
9881
  const points = trace.tracePath;
@@ -9790,7 +9921,7 @@ var getPointAtTraceDistance = (trace, distance5) => {
9790
9921
  const end = trace.tracePath[i + 1];
9791
9922
  const segmentLength = getManhattanDistance(start, end);
9792
9923
  const nextDistance = pathDistance + segmentLength;
9793
- if (distance5 <= nextDistance + EPS12) {
9924
+ if (distance5 <= nextDistance + EPS13) {
9794
9925
  const offset = Math.max(
9795
9926
  0,
9796
9927
  Math.min(segmentLength, distance5 - pathDistance)
@@ -9829,7 +9960,7 @@ var segmentCrossesBoundsInterior2 = (start, end, bounds) => {
9829
9960
  return false;
9830
9961
  }
9831
9962
  if (isVertical4(start, end)) {
9832
- if (start.x <= interior.minX + EPS12 || start.x >= interior.maxX - EPS12) {
9963
+ if (start.x <= interior.minX + EPS13 || start.x >= interior.maxX - EPS13) {
9833
9964
  return false;
9834
9965
  }
9835
9966
  return rangesOverlap2(
@@ -9840,7 +9971,7 @@ var segmentCrossesBoundsInterior2 = (start, end, bounds) => {
9840
9971
  );
9841
9972
  }
9842
9973
  if (isHorizontal3(start, end)) {
9843
- if (start.y <= interior.minY + EPS12 || start.y >= interior.maxY - EPS12) {
9974
+ if (start.y <= interior.minY + EPS13 || start.y >= interior.maxY - EPS13) {
9844
9975
  return false;
9845
9976
  }
9846
9977
  return rangesOverlap2(
@@ -9854,10 +9985,10 @@ var segmentCrossesBoundsInterior2 = (start, end, bounds) => {
9854
9985
  };
9855
9986
  var isPointOnSegment2 = (point, start, end) => {
9856
9987
  if (isHorizontal3(start, end)) {
9857
- return Math.abs(point.y - start.y) <= EPS12 && point.x >= Math.min(start.x, end.x) - EPS12 && point.x <= Math.max(start.x, end.x) + EPS12;
9988
+ 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;
9858
9989
  }
9859
9990
  if (isVertical4(start, end)) {
9860
- return Math.abs(point.x - start.x) <= EPS12 && point.y >= Math.min(start.y, end.y) - EPS12 && point.y <= Math.max(start.y, end.y) + EPS12;
9991
+ 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;
9861
9992
  }
9862
9993
  return false;
9863
9994
  };
@@ -9865,9 +9996,9 @@ var getSegmentDirection = (start, end) => ({
9865
9996
  x: isVertical4(start, end) ? 0 : Math.sign(end.x - start.x),
9866
9997
  y: isHorizontal3(start, end) ? 0 : Math.sign(end.y - start.y)
9867
9998
  });
9868
- var isHorizontal3 = (start, end) => Math.abs(start.y - end.y) <= EPS12;
9869
- var isVertical4 = (start, end) => Math.abs(start.x - end.x) <= EPS12;
9870
- var rangesOverlap2 = (minA, maxA, minB, maxB) => Math.min(maxA, maxB) - Math.max(minA, minB) > EPS12;
9999
+ var isHorizontal3 = (start, end) => Math.abs(start.y - end.y) <= EPS13;
10000
+ var isVertical4 = (start, end) => Math.abs(start.x - end.x) <= EPS13;
10001
+ var rangesOverlap2 = (minA, maxA, minB, maxB) => Math.min(maxA, maxB) - Math.max(minA, minB) > EPS13;
9871
10002
  var getUniquePinCount2 = (pinIds) => new Set(pinIds).size;
9872
10003
 
9873
10004
  // lib/solvers/TraceAnchoredNetLabelOverlapSolver/candidates.ts
@@ -9924,7 +10055,7 @@ var getCandidateDistances = (traceLength, vertexDistances) => {
9924
10055
  for (const distance5 of vertexDistances) {
9925
10056
  distances.add(roundDistance(distance5));
9926
10057
  }
9927
- return [...distances].filter((distance5) => distance5 >= -EPS12 && distance5 <= traceLength + EPS12).sort((a, b) => a - b);
10058
+ return [...distances].filter((distance5) => distance5 >= -EPS13 && distance5 <= traceLength + EPS13).sort((a, b) => a - b);
9928
10059
  };
9929
10060
  var getOrientationsForPoint = (params) => {
9930
10061
  const { inputProblem, label, point, orientationConstraint } = params;
@@ -10013,13 +10144,13 @@ var getOutwardOrientationOptions = (point, chipBounds) => {
10013
10144
  };
10014
10145
  var getOutwardAxisOption = (params) => {
10015
10146
  const { value, min, max, center, positiveOrientation, negativeOrientation } = params;
10016
- if (value > max + EPS12) {
10147
+ if (value > max + EPS13) {
10017
10148
  return {
10018
10149
  orientation: positiveOrientation,
10019
10150
  outwardScore: 1 + value - max
10020
10151
  };
10021
10152
  }
10022
- if (value < min - EPS12) {
10153
+ if (value < min - EPS13) {
10023
10154
  return {
10024
10155
  orientation: negativeOrientation,
10025
10156
  outwardScore: 1 + min - value
@@ -10030,7 +10161,7 @@ var getOutwardAxisOption = (params) => {
10030
10161
  outwardScore: getNormalizedCenterDistance(value, center, max - min)
10031
10162
  };
10032
10163
  };
10033
- var getNormalizedCenterDistance = (value, center, span) => Math.abs(value - center) / Math.max(EPS12, span / 2);
10164
+ var getNormalizedCenterDistance = (value, center, span) => Math.abs(value - center) / Math.max(EPS13, span / 2);
10034
10165
  var ALL_ORIENTATIONS = ["x+", "x-", "y+", "y-"];
10035
10166
  var getFlippedOrientation = (orientation) => {
10036
10167
  switch (orientation) {
@@ -10103,7 +10234,7 @@ var getNetLabelHeight = (inputProblem, label) => {
10103
10234
  )?.netLabelHeight;
10104
10235
  };
10105
10236
  var roundDistance = (distance5) => Number(distance5.toFixed(6));
10106
- var isSamePlacement = (label, point, orientation) => Math.abs(point.x - label.anchorPoint.x) <= EPS12 && Math.abs(point.y - label.anchorPoint.y) <= EPS12 && orientation === label.orientation;
10237
+ var isSamePlacement = (label, point, orientation) => Math.abs(point.x - label.anchorPoint.x) <= EPS13 && Math.abs(point.y - label.anchorPoint.y) <= EPS13 && orientation === label.orientation;
10107
10238
 
10108
10239
  // lib/solvers/TraceAnchoredNetLabelOverlapSolver/visualize.ts
10109
10240
  var CANDIDATE_SELECTED_COLOR4 = "blue";