@tscircuit/core 0.0.2118 → 0.0.2119

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +394 -341
  2. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -93724,6 +93724,265 @@ var balanceZShapes = ({
93724
93724
  tracePath: finalSimplifiedPath
93725
93725
  };
93726
93726
  };
93727
+ var LABEL_SEARCH_STEP = 0.05;
93728
+ var MAX_RECORDED_CANDIDATES = 2e3;
93729
+ var WICK_CLEARANCE = 1e-3;
93730
+ var EPS8 = 1e-9;
93731
+ var TRACE_BOUNDARY_TOLERANCE = WICK_CLEARANCE + EPS8;
93732
+ var CANDIDATE_SELECTED_COLOR = "blue";
93733
+ var CANDIDATE_REJECTED_COLOR = "red";
93734
+ var isYOrientation = (orientation2) => orientation2 === "y+" || orientation2 === "y-";
93735
+ var isXOrientation = (orientation2) => orientation2 === "x+" || orientation2 === "x-";
93736
+ var rectsOverlap = (a2, b2) => Math.min(a2.maxX, b2.maxX) - Math.max(a2.minX, b2.minX) > EPS8 && Math.min(a2.maxY, b2.maxY) - Math.max(a2.minY, b2.minY) > EPS8;
93737
+ var rangesOverlap = (minA, maxA, minB, maxB) => Math.min(maxA, maxB) - Math.max(minA, minB) > EPS8;
93738
+ var traceCrossesBoundsInterior = (bounds, traceMap) => {
93739
+ for (const trace of Object.values(traceMap)) {
93740
+ const points = trace.tracePath;
93741
+ for (let i2 = 0; i2 < points.length - 1; i2++) {
93742
+ if (segmentCrossesBoundsInterior(points[i2], points[i2 + 1], bounds)) {
93743
+ return true;
93744
+ }
93745
+ }
93746
+ }
93747
+ return false;
93748
+ };
93749
+ var segmentCrossesBoundsInterior = (p1, p2, bounds) => {
93750
+ const interiorBounds = {
93751
+ minX: bounds.minX + TRACE_BOUNDARY_TOLERANCE,
93752
+ minY: bounds.minY + TRACE_BOUNDARY_TOLERANCE,
93753
+ maxX: bounds.maxX - TRACE_BOUNDARY_TOLERANCE,
93754
+ maxY: bounds.maxY - TRACE_BOUNDARY_TOLERANCE
93755
+ };
93756
+ if (interiorBounds.minX >= interiorBounds.maxX || interiorBounds.minY >= interiorBounds.maxY) {
93757
+ return false;
93758
+ }
93759
+ if (sameX(p1, p2)) {
93760
+ if (p1.x <= interiorBounds.minX + EPS8 || p1.x >= interiorBounds.maxX - EPS8) {
93761
+ return false;
93762
+ }
93763
+ return rangesOverlap(
93764
+ Math.min(p1.y, p2.y),
93765
+ Math.max(p1.y, p2.y),
93766
+ interiorBounds.minY,
93767
+ interiorBounds.maxY
93768
+ );
93769
+ }
93770
+ if (sameY(p1, p2)) {
93771
+ if (p1.y <= interiorBounds.minY + EPS8 || p1.y >= interiorBounds.maxY - EPS8) {
93772
+ return false;
93773
+ }
93774
+ return rangesOverlap(
93775
+ Math.min(p1.x, p2.x),
93776
+ Math.max(p1.x, p2.x),
93777
+ interiorBounds.minX,
93778
+ interiorBounds.maxX
93779
+ );
93780
+ }
93781
+ return false;
93782
+ };
93783
+ var tracePathCrossesAnyBounds = (tracePath, bounds) => {
93784
+ for (let i2 = 0; i2 < tracePath.length - 1; i2++) {
93785
+ if (segmentCrossesBoundsInterior(tracePath[i2], tracePath[i2 + 1], bounds)) {
93786
+ return true;
93787
+ }
93788
+ }
93789
+ return false;
93790
+ };
93791
+ var tracePathIntersectsBounds = (tracePath, bounds) => {
93792
+ for (let i2 = 0; i2 < tracePath.length - 1; i2++) {
93793
+ if (segmentIntersectsRect2(tracePath[i2], tracePath[i2 + 1], bounds)) {
93794
+ return true;
93795
+ }
93796
+ }
93797
+ return false;
93798
+ };
93799
+ var getSideDistances = (point6, bounds) => [
93800
+ ["left", Math.abs(point6.x - bounds.minX)],
93801
+ ["right", Math.abs(point6.x - bounds.maxX)],
93802
+ ["bottom", Math.abs(point6.y - bounds.minY)],
93803
+ ["top", Math.abs(point6.y - bounds.maxY)]
93804
+ ];
93805
+ var getConnectorTracePath = (source, target, orientation2) => simplifyOrthogonalPath(
93806
+ isYOrientation(orientation2) ? [source, { x: target.x, y: source.y }, target] : [source, { x: source.x, y: target.y }, target]
93807
+ );
93808
+ var simplifyOrthogonalPath = (path) => {
93809
+ const deduped = path.filter(
93810
+ (point6, index2) => index2 === 0 || !pointsEqual3(point6, path[index2 - 1])
93811
+ );
93812
+ if (deduped.length < 3) return deduped;
93813
+ const simplified = [deduped[0]];
93814
+ for (let i2 = 1; i2 < deduped.length - 1; i2++) {
93815
+ const prev = simplified[simplified.length - 1];
93816
+ const point6 = deduped[i2];
93817
+ const next = deduped[i2 + 1];
93818
+ if (sameX(prev, point6) && sameX(point6, next) || sameY(prev, point6) && sameY(point6, next)) {
93819
+ continue;
93820
+ }
93821
+ simplified.push(point6);
93822
+ }
93823
+ simplified.push(deduped[deduped.length - 1]);
93824
+ return simplified;
93825
+ };
93826
+ var pointsEqual3 = (a2, b2) => sameX(a2, b2) && sameY(a2, b2);
93827
+ var sameX = (a2, b2) => Math.abs(a2.x - b2.x) <= EPS8;
93828
+ var sameY = (a2, b2) => Math.abs(a2.y - b2.y) <= EPS8;
93829
+ var getMaxSearchDistance = (inputProblem) => {
93830
+ const maxChipWidth = Math.max(
93831
+ ...inputProblem.chips.map((chip) => chip.width),
93832
+ 1
93833
+ );
93834
+ return maxChipWidth * 3;
93835
+ };
93836
+ var EPS9 = 1e-6;
93837
+ var isTraceLine = (trace) => getUniquePinCount(trace.pinIds) >= 2;
93838
+ var rectsOverlap2 = (a2, b2) => Math.min(a2.maxX, b2.maxX) - Math.max(a2.minX, b2.minX) > EPS9 && Math.min(a2.maxY, b2.maxY) - Math.max(a2.minY, b2.minY) > EPS9;
93839
+ var getTraceCorners = (path) => {
93840
+ const corners = [];
93841
+ for (let i2 = 1; i2 < path.length - 1; i2++) {
93842
+ const previousPoint = path[i2 - 1];
93843
+ const cornerPoint = path[i2];
93844
+ const nextPoint = path[i2 + 1];
93845
+ if (isTraceCorner(previousPoint, cornerPoint, nextPoint)) {
93846
+ corners.push(cornerPoint);
93847
+ }
93848
+ }
93849
+ return corners;
93850
+ };
93851
+ var tracePathContainsPoint = (path, point6) => {
93852
+ for (let i2 = 0; i2 < path.length - 1; i2++) {
93853
+ if (isPointOnSegment(point6, path[i2], path[i2 + 1])) return true;
93854
+ }
93855
+ return false;
93856
+ };
93857
+ var getDistance2 = (a2, b2) => Math.abs(a2.x - b2.x) + Math.abs(a2.y - b2.y);
93858
+ var getUniquePinCount = (pinIds) => new Set(pinIds).size;
93859
+ var isTraceCorner = (a2, b2, c2) => getSegmentOrientation(a2, b2) !== getSegmentOrientation(b2, c2);
93860
+ var isPointOnSegment = (point6, start, end) => {
93861
+ if (getSegmentOrientation(start, end) === "horizontal") {
93862
+ return Math.abs(point6.y - start.y) <= EPS9 && point6.x >= Math.min(start.x, end.x) - EPS9 && point6.x <= Math.max(start.x, end.x) + EPS9;
93863
+ }
93864
+ return Math.abs(point6.x - start.x) <= EPS9 && point6.y >= Math.min(start.y, end.y) - EPS9 && point6.y <= Math.max(start.y, end.y) + EPS9;
93865
+ };
93866
+ var getSegmentOrientation = (a2, b2) => Math.abs(a2.y - b2.y) <= EPS9 ? "horizontal" : "vertical";
93867
+ var getGroundNetIds = (inputProblem, netConnMap) => {
93868
+ const groundNetIds = /* @__PURE__ */ new Set();
93869
+ for (const connection of inputProblem.netConnections) {
93870
+ if (!connection.isGround) continue;
93871
+ const netId = netConnMap.getNetConnectedToId(connection.netId);
93872
+ if (netId) groundNetIds.add(netId);
93873
+ }
93874
+ return groundNetIds;
93875
+ };
93876
+ var placeGroundRailLabelsAtOuterEnd = ({
93877
+ inputProblem,
93878
+ traces,
93879
+ netLabelPlacements
93880
+ }) => {
93881
+ const { netConnMap } = getConnectivityMapsFromInputProblem(inputProblem);
93882
+ const groundNetIds = getGroundNetIds(inputProblem, netConnMap);
93883
+ if (groundNetIds.size === 0) return netLabelPlacements;
93884
+ const chipMap = new Map(inputProblem.chips.map((chip) => [chip.chipId, chip]));
93885
+ const traceMap = Object.fromEntries(
93886
+ traces.map((trace) => [trace.mspPairId, trace])
93887
+ );
93888
+ const obstacles = getObstacleRects(inputProblem);
93889
+ const output = [...netLabelPlacements];
93890
+ for (const rail of traces) {
93891
+ if (!groundNetIds.has(rail.globalConnNetId)) continue;
93892
+ const [a2, b2] = rail.pins;
93893
+ if (a2.chipId === b2.chipId || !nearlyEqual(a2.y, b2.y) || ![a2, b2].every(
93894
+ (pin) => pin._facingDirection === "y-" && chipMap.get(pin.chipId)?.pins.length === 2
93895
+ ))
93896
+ continue;
93897
+ const path = simplifyPath(rail.tracePath);
93898
+ if (path.length !== 4 || !isVertical2(path[0], path[1]) || !isHorizontal22(path[1], path[2]) || !isVertical2(path[2], path[3]) || path[1].y >= a2.y)
93899
+ continue;
93900
+ for (const feed of traces) {
93901
+ if (feed.globalConnNetId !== rail.globalConnNetId) continue;
93902
+ const shared = feed.pins.find((pin) => rail.pinIds.includes(pin.pinId));
93903
+ const icPin = feed.pins.find(
93904
+ (pin) => !rail.pinIds.includes(pin.pinId) && (chipMap.get(pin.chipId)?.pins.length ?? 0) > 2
93905
+ );
93906
+ if (!shared || !icPin || !nearlyEqual(icPin.y, path[1].y)) continue;
93907
+ const outer = shared.pinId === a2.pinId ? b2 : a2;
93908
+ if (Math.abs(outer.x - icPin.x) <= Math.abs(shared.x - icPin.x)) continue;
93909
+ const anchorPoint = { x: outer.x, y: path[1].y };
93910
+ if (!tracePathContainsPoint(rail.tracePath, anchorPoint)) continue;
93911
+ for (let index2 = 0; index2 < output.length; index2++) {
93912
+ const label = output[index2];
93913
+ if (label.globalConnNetId !== rail.globalConnNetId || label.orientation !== "y-" || !label.mspConnectionPairIds.some(
93914
+ (id) => id === feed.mspPairId || id === rail.mspPairId
93915
+ ) || !tracePathContainsPoint(feed.tracePath, label.anchorPoint) && !tracePathContainsPoint(rail.tracePath, label.anchorPoint))
93916
+ continue;
93917
+ const center = getCenterFromAnchor(
93918
+ anchorPoint,
93919
+ label.orientation,
93920
+ label.width,
93921
+ label.height
93922
+ );
93923
+ const bounds = getRectBounds(center, label.width, label.height);
93924
+ if (obstacles.some((obstacle) => rectsOverlap2(bounds, obstacle)) || traceCrossesBoundsInterior(bounds, traceMap) || output.some(
93925
+ (other, otherIndex) => otherIndex !== index2 && rectsOverlap2(
93926
+ bounds,
93927
+ getRectBounds(other.center, other.width, other.height)
93928
+ )
93929
+ ))
93930
+ continue;
93931
+ output[index2] = {
93932
+ ...label,
93933
+ anchorPoint,
93934
+ center,
93935
+ mspConnectionPairIds: [rail.mspPairId],
93936
+ pinIds: [...rail.pinIds]
93937
+ };
93938
+ }
93939
+ }
93940
+ }
93941
+ for (let index2 = 0; index2 < output.length; index2++) {
93942
+ const label = output[index2];
93943
+ if (label.orientation !== "y-" || !groundNetIds.has(label.globalConnNetId))
93944
+ continue;
93945
+ const hasSharedRail = inputProblem.netConnections.some(
93946
+ (candidate) => candidate.pinIds.length > 2 && netConnMap.getNetConnectedToId(candidate.netId) === label.globalConnNetId
93947
+ );
93948
+ if (!hasSharedRail) continue;
93949
+ const columnSegments = traces.filter((trace) => trace.globalConnNetId === label.globalConnNetId).flatMap(
93950
+ (trace) => trace.tracePath.slice(1).flatMap((end, pointIndex) => {
93951
+ const start = trace.tracePath[pointIndex];
93952
+ return nearlyEqual(start.x, label.anchorPoint.x) && nearlyEqual(end.x, label.anchorPoint.x) ? [
93953
+ {
93954
+ minY: Math.min(start.y, end.y),
93955
+ maxY: Math.max(start.y, end.y)
93956
+ }
93957
+ ] : [];
93958
+ })
93959
+ ).sort((a2, b2) => b2.maxY - a2.maxY);
93960
+ let lowestY = label.anchorPoint.y;
93961
+ for (const segment2 of columnSegments) {
93962
+ if (segment2.maxY + RAIL_ALIGNMENT_EPSILON >= lowestY && segment2.minY < lowestY) {
93963
+ lowestY = segment2.minY;
93964
+ }
93965
+ }
93966
+ if (nearlyEqual(lowestY, label.anchorPoint.y)) continue;
93967
+ const anchorPoint = { x: label.anchorPoint.x, y: lowestY };
93968
+ const center = getCenterFromAnchor(
93969
+ anchorPoint,
93970
+ label.orientation,
93971
+ label.width,
93972
+ label.height
93973
+ );
93974
+ const bounds = getRectBounds(center, label.width, label.height);
93975
+ if (obstacles.some((obstacle) => rectsOverlap2(bounds, obstacle)) || traceCrossesBoundsInterior(bounds, traceMap) || output.some(
93976
+ (other, otherIndex) => otherIndex !== index2 && rectsOverlap2(
93977
+ bounds,
93978
+ getRectBounds(other.center, other.width, other.height)
93979
+ )
93980
+ ))
93981
+ continue;
93982
+ output[index2] = { ...label, anchorPoint, center };
93983
+ }
93984
+ return output;
93985
+ };
93727
93986
  var getAlongBounds = (orientation2, minAlong, maxAlong) => orientation2 === "vertical" ? { minX: 0, maxX: 0, minY: minAlong, maxY: maxAlong } : { minX: minAlong, maxX: maxAlong, minY: 0, maxY: 0 };
93728
93987
  var hasPositiveAlongOverlap = (orientation2, first, second) => {
93729
93988
  const overlap = boundsIntersection(first, second);
@@ -93768,37 +94027,6 @@ var getRailAlignmentFallbackCoordinates = ({
93768
94027
  }
93769
94028
  return getDistinctCoordinates(coordinates);
93770
94029
  };
93771
- var EPS8 = 1e-6;
93772
- var isTraceLine = (trace) => getUniquePinCount(trace.pinIds) >= 2;
93773
- var rectsOverlap = (a2, b2) => Math.min(a2.maxX, b2.maxX) - Math.max(a2.minX, b2.minX) > EPS8 && Math.min(a2.maxY, b2.maxY) - Math.max(a2.minY, b2.minY) > EPS8;
93774
- var getTraceCorners = (path) => {
93775
- const corners = [];
93776
- for (let i2 = 1; i2 < path.length - 1; i2++) {
93777
- const previousPoint = path[i2 - 1];
93778
- const cornerPoint = path[i2];
93779
- const nextPoint = path[i2 + 1];
93780
- if (isTraceCorner(previousPoint, cornerPoint, nextPoint)) {
93781
- corners.push(cornerPoint);
93782
- }
93783
- }
93784
- return corners;
93785
- };
93786
- var tracePathContainsPoint = (path, point6) => {
93787
- for (let i2 = 0; i2 < path.length - 1; i2++) {
93788
- if (isPointOnSegment(point6, path[i2], path[i2 + 1])) return true;
93789
- }
93790
- return false;
93791
- };
93792
- var getDistance2 = (a2, b2) => Math.abs(a2.x - b2.x) + Math.abs(a2.y - b2.y);
93793
- var getUniquePinCount = (pinIds) => new Set(pinIds).size;
93794
- var isTraceCorner = (a2, b2, c2) => getSegmentOrientation(a2, b2) !== getSegmentOrientation(b2, c2);
93795
- var isPointOnSegment = (point6, start, end) => {
93796
- if (getSegmentOrientation(start, end) === "horizontal") {
93797
- return Math.abs(point6.y - start.y) <= EPS8 && point6.x >= Math.min(start.x, end.x) - EPS8 && point6.x <= Math.max(start.x, end.x) + EPS8;
93798
- }
93799
- return Math.abs(point6.x - start.x) <= EPS8 && point6.y >= Math.min(start.y, end.y) - EPS8 && point6.y <= Math.max(start.y, end.y) + EPS8;
93800
- };
93801
- var getSegmentOrientation = (a2, b2) => Math.abs(a2.y - b2.y) <= EPS8 ? "horizontal" : "vertical";
93802
94030
  var hasLabelOnAdjacentInteriorLeg = (segment2, trace, anchorPoint) => {
93803
94031
  const pathsFromRailEnds = [
93804
94032
  trace.tracePath.slice(0, segment2.segmentIndex + 1).reverse(),
@@ -93937,15 +94165,15 @@ var preservesLabelAnchors = (labels, before, after) => labels.every((label) => {
93937
94165
  const anchoredAfter = getAnchoredTraceIds(label, after);
93938
94166
  return [...anchoredBefore].every((traceId) => anchoredAfter.has(traceId));
93939
94167
  });
93940
- var EPS9 = 1e-9;
94168
+ var EPS10 = 1e-9;
93941
94169
  var segmentRunsAlongRectBoundary = (start, end, rect) => {
93942
- const isVertical6 = Math.abs(start.x - end.x) < EPS9;
93943
- const isHorizontal5 = Math.abs(start.y - end.y) < EPS9;
94170
+ const isVertical6 = Math.abs(start.x - end.x) < EPS10;
94171
+ const isHorizontal5 = Math.abs(start.y - end.y) < EPS10;
93944
94172
  if (isVertical6) {
93945
- return Math.abs(start.x - rect.minX) < EPS9 || Math.abs(start.x - rect.maxX) < EPS9;
94173
+ return Math.abs(start.x - rect.minX) < EPS10 || Math.abs(start.x - rect.maxX) < EPS10;
93946
94174
  }
93947
94175
  if (isHorizontal5) {
93948
- return Math.abs(start.y - rect.minY) < EPS9 || Math.abs(start.y - rect.maxY) < EPS9;
94176
+ return Math.abs(start.y - rect.minY) < EPS10 || Math.abs(start.y - rect.maxY) < EPS10;
93949
94177
  }
93950
94178
  return false;
93951
94179
  };
@@ -93958,10 +94186,10 @@ var getPathLength4 = (path) => {
93958
94186
  return length8;
93959
94187
  };
93960
94188
  var getDistance22 = (a2, b2) => Math.abs(a2.x - b2.x) + Math.abs(a2.y - b2.y);
93961
- var isAxisAlignedSegment = (start, end) => Math.abs(start.x - end.x) < EPS9 || Math.abs(start.y - end.y) < EPS9;
93962
- var getSegmentOrientation2 = (start, end) => Math.abs(start.y - end.y) < EPS9 ? "horizontal" : "vertical";
94189
+ var isAxisAlignedSegment = (start, end) => Math.abs(start.x - end.x) < EPS10 || Math.abs(start.y - end.y) < EPS10;
94190
+ var getSegmentOrientation2 = (start, end) => Math.abs(start.y - end.y) < EPS10 ? "horizontal" : "vertical";
93963
94191
  var projectPointToSegment = (point6, start, end) => {
93964
- if (Math.abs(start.x - end.x) < EPS9) {
94192
+ if (Math.abs(start.x - end.x) < EPS10) {
93965
94193
  return {
93966
94194
  x: start.x,
93967
94195
  y: Math.min(
@@ -93970,7 +94198,7 @@ var projectPointToSegment = (point6, start, end) => {
93970
94198
  )
93971
94199
  };
93972
94200
  }
93973
- if (Math.abs(start.y - end.y) < EPS9) {
94201
+ if (Math.abs(start.y - end.y) < EPS10) {
93974
94202
  return {
93975
94203
  x: Math.min(
93976
94204
  Math.max(point6.x, Math.min(start.x, end.x)),
@@ -94013,9 +94241,9 @@ var findSegmentContainingPoint = (path, point6) => {
94013
94241
  };
94014
94242
  var isPointWithinSegmentPrimaryRange = (point6, segment2) => {
94015
94243
  if (segment2.orientation === "horizontal") {
94016
- return point6.x >= Math.min(segment2.start.x, segment2.end.x) - EPS9 && point6.x <= Math.max(segment2.start.x, segment2.end.x) + EPS9;
94244
+ return point6.x >= Math.min(segment2.start.x, segment2.end.x) - EPS10 && point6.x <= Math.max(segment2.start.x, segment2.end.x) + EPS10;
94017
94245
  }
94018
- return point6.y >= Math.min(segment2.start.y, segment2.end.y) - EPS9 && point6.y <= Math.max(segment2.start.y, segment2.end.y) + EPS9;
94246
+ return point6.y >= Math.min(segment2.start.y, segment2.end.y) - EPS10 && point6.y <= Math.max(segment2.start.y, segment2.end.y) + EPS10;
94019
94247
  };
94020
94248
  var findPreferredReroutedSegment = (path, originalSegmentIndex, originalSegmentCount, orientation2, anchorPoint) => {
94021
94249
  const matchingSegments = getSegments3(path).filter(
@@ -94043,18 +94271,18 @@ var projectPointToPath = (point6, path) => {
94043
94271
  return bestPoint;
94044
94272
  };
94045
94273
  var segmentsIntersect2 = (a1, a2, b1, b2) => {
94046
- const aVertical = Math.abs(a1.x - a2.x) < EPS9;
94047
- const bVertical = Math.abs(b1.x - b2.x) < EPS9;
94048
- const between2 = (value, p1, p2) => value >= Math.min(p1, p2) - EPS9 && value <= Math.max(p1, p2) + EPS9;
94274
+ const aVertical = Math.abs(a1.x - a2.x) < EPS10;
94275
+ const bVertical = Math.abs(b1.x - b2.x) < EPS10;
94276
+ const between2 = (value, p1, p2) => value >= Math.min(p1, p2) - EPS10 && value <= Math.max(p1, p2) + EPS10;
94049
94277
  if (aVertical && bVertical) {
94050
- if (Math.abs(a1.x - b1.x) > EPS9) return false;
94278
+ if (Math.abs(a1.x - b1.x) > EPS10) return false;
94051
94279
  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));
94052
- return overlap > EPS9;
94280
+ return overlap > EPS10;
94053
94281
  }
94054
94282
  if (!aVertical && !bVertical) {
94055
- if (Math.abs(a1.y - b1.y) > EPS9) return false;
94283
+ if (Math.abs(a1.y - b1.y) > EPS10) return false;
94056
94284
  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));
94057
- return overlap > EPS9;
94285
+ return overlap > EPS10;
94058
94286
  }
94059
94287
  const verticalA = aVertical ? a1 : b1;
94060
94288
  const verticalB = aVertical ? a2 : b2;
@@ -94125,6 +94353,7 @@ var tracePathChanged = (original, candidate) => original.tracePath.length !== ca
94125
94353
  (point6, index2) => !pointsEqual22(point6, original.tracePath[index2])
94126
94354
  );
94127
94355
  var evaluateRailGroup = ({
94356
+ inputProblem,
94128
94357
  group,
94129
94358
  traces,
94130
94359
  netLabelPlacements,
@@ -94147,6 +94376,11 @@ var evaluateRailGroup = ({
94147
94376
  const otherNetTraces = traces.filter(
94148
94377
  (trace) => trace.globalConnNetId !== group[0].globalConnNetId
94149
94378
  );
94379
+ const { netConnMap } = getConnectivityMapsFromInputProblem(inputProblem);
94380
+ const groundNetIds = getGroundNetIds(inputProblem, netConnMap);
94381
+ const groundLabelIndices = netLabelPlacements.flatMap(
94382
+ (label, index2) => label.globalConnNetId === group[0].globalConnNetId && groundNetIds.has(label.globalConnNetId) ? [index2] : []
94383
+ );
94150
94384
  const immutableSameNetTraces = traces.filter(
94151
94385
  (trace) => trace.globalConnNetId === group[0].globalConnNetId && !eligibleTraceIds.has(trace.mspPairId)
94152
94386
  );
@@ -94166,11 +94400,24 @@ var evaluateRailGroup = ({
94166
94400
  const allCandidateTraces = traces.map(
94167
94401
  (trace) => candidateMap.get(trace.mspPairId) ?? trace
94168
94402
  );
94403
+ const placedGroundLabels = groundLabelIndices.length ? placeGroundRailLabelsAtOuterEnd({
94404
+ inputProblem,
94405
+ traces: allCandidateTraces,
94406
+ netLabelPlacements
94407
+ }) : netLabelPlacements;
94408
+ const groundLabelBounds = groundLabelIndices.map((index2) => {
94409
+ const label = placedGroundLabels[index2];
94410
+ return getRectBounds(label.center, label.width, label.height);
94411
+ });
94169
94412
  const candidatesAreClear = candidateTraces.every(
94170
94413
  (candidate2) => !isPathCollidingWithObstacles(candidate2.tracePath, obstacles) && detectTraceLabelOverlap({
94171
94414
  traces: [candidate2],
94172
94415
  netLabels: netLabelPlacements
94173
- }).length === 0 && !doesPathOverlapTraceStrokes(candidate2.tracePath, otherNetTraces) && !doesPathCoincideWithTraces(
94416
+ }).length === 0 && // Ground labels may move to the new rail end later in the pipeline.
94417
+ // Reject alignment if even that placement leaves a symbol crossed.
94418
+ !groundLabelBounds.some(
94419
+ (bounds) => tracePathCrossesAnyBounds(candidate2.tracePath, bounds)
94420
+ ) && !doesPathOverlapTraceStrokes(candidate2.tracePath, otherNetTraces) && !doesPathCoincideWithTraces(
94174
94421
  candidate2.tracePath,
94175
94422
  immutableSameNetTraces.filter(
94176
94423
  (trace) => trace.mspPairId !== candidate2.mspPairId
@@ -94439,6 +94686,7 @@ var alignSameNetRails = ({
94439
94686
  let applied = null;
94440
94687
  for (const group of groups) {
94441
94688
  applied = evaluateRailGroup({
94689
+ inputProblem,
94442
94690
  group,
94443
94691
  traces: outputTraces,
94444
94692
  netLabelPlacements,
@@ -94493,7 +94741,7 @@ var getTraceObstacles = (allTraces, excludeTraceId) => {
94493
94741
  }
94494
94742
  return obstacles;
94495
94743
  };
94496
- var EPS10 = 1e-6;
94744
+ var EPS11 = 1e-6;
94497
94745
  var findIntersectionsWithObstacles = (p1, p2, obstacles) => {
94498
94746
  const intersections2 = [];
94499
94747
  for (const obstacle of obstacles) {
@@ -94512,7 +94760,7 @@ var findIntersectionsWithObstacles = (p1, p2, obstacles) => {
94512
94760
  }
94513
94761
  return intersections2;
94514
94762
  };
94515
- var isSamePoint = (first, second) => Math.abs(first.x - second.x) < EPS10 && Math.abs(first.y - second.y) < EPS10;
94763
+ var isSamePoint = (first, second) => Math.abs(first.x - second.x) < EPS11 && Math.abs(first.y - second.y) < EPS11;
94516
94764
  var findPerpendicularPathCrossings = (path, otherPath, options = {}) => {
94517
94765
  const crossings = [];
94518
94766
  const firstPathSegmentIndex = options.includeTerminalSegments ? 0 : 1;
@@ -94522,11 +94770,11 @@ var findPerpendicularPathCrossings = (path, otherPath, options = {}) => {
94522
94770
  for (let pathSegmentIndex = firstPathSegmentIndex; pathSegmentIndex < lastPathSegmentIndex; pathSegmentIndex++) {
94523
94771
  const start = path[pathSegmentIndex];
94524
94772
  const end = path[pathSegmentIndex + 1];
94525
- const isVertical6 = Math.abs(start.x - end.x) < EPS10;
94773
+ const isVertical6 = Math.abs(start.x - end.x) < EPS11;
94526
94774
  for (let otherPathSegmentIndex = firstOtherPathSegmentIndex; otherPathSegmentIndex < lastOtherPathSegmentIndex; otherPathSegmentIndex++) {
94527
94775
  const otherStart = otherPath[otherPathSegmentIndex];
94528
94776
  const otherEnd = otherPath[otherPathSegmentIndex + 1];
94529
- const otherIsVertical = Math.abs(otherStart.x - otherEnd.x) < EPS10;
94777
+ const otherIsVertical = Math.abs(otherStart.x - otherEnd.x) < EPS11;
94530
94778
  if (isVertical6 === otherIsVertical) continue;
94531
94779
  const intersection2 = getSegmentIntersection(
94532
94780
  start,
@@ -94544,8 +94792,8 @@ var findPerpendicularPathCrossings = (path, otherPath, options = {}) => {
94544
94792
  }
94545
94793
  return crossings;
94546
94794
  };
94547
- var EPS11 = 1e-6;
94548
- var isVertical3 = (a2, b2, eps = EPS11) => Math.abs(a2.x - b2.x) < eps;
94795
+ var EPS12 = 1e-6;
94796
+ var isVertical3 = (a2, b2, eps = EPS12) => Math.abs(a2.x - b2.x) < eps;
94549
94797
  var generateLShapeRerouteCandidates = ({
94550
94798
  lShape,
94551
94799
  rectangle,
@@ -94558,7 +94806,7 @@ var generateLShapeRerouteCandidates = ({
94558
94806
  let c2;
94559
94807
  let i1_padded = interactionPoint1;
94560
94808
  let i2_padded = interactionPoint2;
94561
- if (Math.abs(p2.x - x2) < EPS11 && Math.abs(p2.y - (y2 + height)) < EPS11) {
94809
+ if (Math.abs(p2.x - x2) < EPS12 && Math.abs(p2.y - (y2 + height)) < EPS12) {
94562
94810
  c2 = { x: x2 + width + padding, y: y2 - padding };
94563
94811
  if (isVertical3(p1, p2)) {
94564
94812
  i1_padded = { x: interactionPoint1.x, y: interactionPoint1.y - padding };
@@ -94570,7 +94818,7 @@ var generateLShapeRerouteCandidates = ({
94570
94818
  } else {
94571
94819
  i2_padded = { x: interactionPoint2.x + padding, y: interactionPoint2.y };
94572
94820
  }
94573
- } else if (Math.abs(p2.x - (x2 + width)) < EPS11 && Math.abs(p2.y - (y2 + height)) < EPS11) {
94821
+ } else if (Math.abs(p2.x - (x2 + width)) < EPS12 && Math.abs(p2.y - (y2 + height)) < EPS12) {
94574
94822
  c2 = { x: x2 - padding, y: y2 - padding };
94575
94823
  if (isVertical3(p1, p2)) {
94576
94824
  i1_padded = { x: interactionPoint1.x, y: interactionPoint1.y - padding };
@@ -94582,7 +94830,7 @@ var generateLShapeRerouteCandidates = ({
94582
94830
  } else {
94583
94831
  i2_padded = { x: interactionPoint2.x - padding, y: interactionPoint2.y };
94584
94832
  }
94585
- } else if (Math.abs(p2.x - x2) < EPS11 && Math.abs(p2.y - y2) < EPS11) {
94833
+ } else if (Math.abs(p2.x - x2) < EPS12 && Math.abs(p2.y - y2) < EPS12) {
94586
94834
  c2 = { x: x2 + width + padding, y: y2 + height + padding };
94587
94835
  if (isVertical3(p1, p2)) {
94588
94836
  i1_padded = { x: interactionPoint1.x, y: interactionPoint1.y + padding };
@@ -94594,7 +94842,7 @@ var generateLShapeRerouteCandidates = ({
94594
94842
  } else {
94595
94843
  i2_padded = { x: interactionPoint2.x + padding, y: interactionPoint2.y };
94596
94844
  }
94597
- } else if (Math.abs(p2.x - (x2 + width)) < EPS11 && Math.abs(p2.y - y2) < EPS11) {
94845
+ } else if (Math.abs(p2.x - (x2 + width)) < EPS12 && Math.abs(p2.y - y2) < EPS12) {
94598
94846
  c2 = { x: x2 - padding, y: y2 + height + padding };
94599
94847
  if (isVertical3(p1, p2)) {
94600
94848
  i1_padded = { x: interactionPoint1.x, y: interactionPoint1.y + padding };
@@ -94668,7 +94916,7 @@ var generatePerpendicularTraceDetours = ({
94668
94916
  const buildDetours = (path, index2) => {
94669
94917
  const start = path[index2];
94670
94918
  const end = path[index2 + 1];
94671
- const movingAxis = Math.abs(start.x - end.x) < EPS11 ? "y" : "x";
94919
+ const movingAxis = Math.abs(start.x - end.x) < EPS12 ? "y" : "x";
94672
94920
  const detourAxis = movingAxis === "x" ? "y" : "x";
94673
94921
  const bounds = obstacleBounds ?? {
94674
94922
  minX: Math.min(obstacleStart.x, obstacleEnd.x),
@@ -95274,14 +95522,14 @@ var UntangleTraceSubsolver = class extends BaseSolver10 {
95274
95522
  }
95275
95523
  }
95276
95524
  };
95277
- var EPS12 = 1e-6;
95278
- var sameX = (a2, b2) => Math.abs(a2.x - b2.x) <= EPS12;
95279
- var sameY = (a2, b2) => Math.abs(a2.y - b2.y) <= EPS12;
95525
+ var EPS13 = 1e-6;
95526
+ var sameX2 = (a2, b2) => Math.abs(a2.x - b2.x) <= EPS13;
95527
+ var sameY2 = (a2, b2) => Math.abs(a2.y - b2.y) <= EPS13;
95280
95528
  var is4PointRectangle = (path) => {
95281
95529
  if (path.length !== 4) return false;
95282
95530
  const [p0, p1, p2, p3] = path;
95283
- const isHVHC = sameY(p0, p1) && sameX(p1, p2) && sameY(p2, p3) && sameX(p0, p3);
95284
- const isVHVC = sameX(p0, p1) && sameY(p1, p2) && sameX(p2, p3) && sameY(p0, p3);
95531
+ const isHVHC = sameY2(p0, p1) && sameX2(p1, p2) && sameY2(p2, p3) && sameX2(p0, p3);
95532
+ const isVHVC = sameX2(p0, p1) && sameY2(p1, p2) && sameX2(p2, p3) && sameY2(p0, p3);
95285
95533
  return isHVHC || isVHVC;
95286
95534
  };
95287
95535
  var getInteriorShortcutPaths = (path) => {
@@ -95312,7 +95560,7 @@ var getInteriorShortcutPaths = (path) => {
95312
95560
  }
95313
95561
  return candidates;
95314
95562
  };
95315
- var EPS13 = 1e-6;
95563
+ var EPS14 = 1e-6;
95316
95564
  var getConnectorObstacleBounds = (connector, segmentIndex, labels) => {
95317
95565
  const start = connector.tracePath[segmentIndex];
95318
95566
  const end = connector.tracePath[segmentIndex + 1];
@@ -95409,7 +95657,7 @@ var rerouteGeneratedNetLabelConnectorCrossings = ({
95409
95657
  path
95410
95658
  }))
95411
95659
  ).filter(
95412
- (candidate) => getPathLength4(candidate.path) <= getPathLength4(trace.tracePath) + EPS13 && countTurns(candidate.path) <= countTurns(trace.tracePath) + 2 && !isPathCollidingWithObstacles(
95660
+ (candidate) => getPathLength4(candidate.path) <= getPathLength4(trace.tracePath) + EPS14 && countTurns(candidate.path) <= countTurns(trace.tracePath) + 2 && !isPathCollidingWithObstacles(
95413
95661
  candidate.path,
95414
95662
  componentAndTextObstacles
95415
95663
  ) && !hasCollisionsWithLabels(candidate.path, foreignLabelBounds) && !isPathColliding(candidate.path, foreignTraces, trace.mspPairId).isColliding && !doesPathCoincideWithTraces(candidate.path, foreignTraces)
@@ -95420,7 +95668,7 @@ var rerouteGeneratedNetLabelConnectorCrossings = ({
95420
95668
  });
95421
95669
  candidates.sort((first, second) => {
95422
95670
  const lengthDifference = getPathLength4(first.path) - getPathLength4(second.path);
95423
- return Math.abs(lengthDifference) > EPS13 ? lengthDifference : countTurns(first.path) - countTurns(second.path);
95671
+ return Math.abs(lengthDifference) > EPS14 ? lengthDifference : countTurns(first.path) - countTurns(second.path);
95424
95672
  });
95425
95673
  const bestCandidate = candidates[0];
95426
95674
  if (!bestCandidate) break;
@@ -95788,7 +96036,7 @@ var doesPathRunAlongChipBoundary = (path, chipObstacles) => {
95788
96036
  const end = path[i2 + 1];
95789
96037
  for (const obstacle of chipObstacles) {
95790
96038
  if (!segmentRunsAlongRectBoundary(start, end, obstacle)) continue;
95791
- if (getSegmentOverlapWithRectSpan(start, end, obstacle) > EPS9) {
96039
+ if (getSegmentOverlapWithRectSpan(start, end, obstacle) > EPS10) {
95792
96040
  return true;
95793
96041
  }
95794
96042
  }
@@ -95803,13 +96051,13 @@ var getChipBoundaryOverlap = (path, chipObstacles) => {
95803
96051
  for (const obstacle of chipObstacles) {
95804
96052
  if (!segmentRunsAlongRectBoundary(start, end, obstacle)) continue;
95805
96053
  const overlap = getSegmentOverlapWithRectSpan(start, end, obstacle);
95806
- if (overlap > EPS9) total += overlap;
96054
+ if (overlap > EPS10) total += overlap;
95807
96055
  }
95808
96056
  }
95809
96057
  return total;
95810
96058
  };
95811
96059
  var getSegmentOverlapWithRectSpan = (start, end, rect) => {
95812
- const isVertical6 = Math.abs(start.x - end.x) < EPS9;
96060
+ const isVertical6 = Math.abs(start.x - end.x) < EPS10;
95813
96061
  if (isVertical6) {
95814
96062
  return Math.min(Math.max(start.y, end.y), rect.maxY) - Math.max(Math.min(start.y, end.y), rect.minY);
95815
96063
  }
@@ -96255,8 +96503,8 @@ var scoreSolutionTracePath = (params) => {
96255
96503
  }
96256
96504
  return { chipEdgeRuns, traceCrossings };
96257
96505
  };
96258
- var CANDIDATE_SELECTED_COLOR = "blue";
96259
- var CANDIDATE_REJECTED_COLOR = "red";
96506
+ var CANDIDATE_SELECTED_COLOR2 = "blue";
96507
+ var CANDIDATE_REJECTED_COLOR2 = "red";
96260
96508
  var visualizeExample28Solver = (state) => {
96261
96509
  const graphics = visualizeInputProblem(state.inputProblem);
96262
96510
  drawTraces(graphics, state);
@@ -96302,7 +96550,7 @@ label intersections: ${candidate.score.labelIntersections}
96302
96550
  trace intersections: ${candidate.score.traceIntersections}` : "";
96303
96551
  graphics.lines.push({
96304
96552
  points: candidate.path,
96305
- strokeColor: candidate.selected ? CANDIDATE_SELECTED_COLOR : CANDIDATE_REJECTED_COLOR,
96553
+ strokeColor: candidate.selected ? CANDIDATE_SELECTED_COLOR2 : CANDIDATE_REJECTED_COLOR2,
96306
96554
  strokeDash: candidate.selected ? void 0 : "4 2",
96307
96555
  label: `${candidate.selected ? "selected" : candidate.status} reroute${scoreLabel}`
96308
96556
  });
@@ -96316,7 +96564,7 @@ var drawCurrentOverlap = (graphics, state) => {
96316
96564
  width: label.width,
96317
96565
  height: label.height,
96318
96566
  fill: "rgba(255, 0, 0, 0.2)",
96319
- strokeColor: CANDIDATE_REJECTED_COLOR,
96567
+ strokeColor: CANDIDATE_REJECTED_COLOR2,
96320
96568
  label: `overlap target
96321
96569
  ${label.netId ?? label.globalConnNetId}`
96322
96570
  });
@@ -96559,107 +96807,6 @@ var createPortOnlyLabelConnectorTrace = ({
96559
96807
  pinIds: label.pinIds
96560
96808
  };
96561
96809
  };
96562
- var LABEL_SEARCH_STEP = 0.05;
96563
- var MAX_RECORDED_CANDIDATES = 2e3;
96564
- var WICK_CLEARANCE = 1e-3;
96565
- var EPS14 = 1e-9;
96566
- var TRACE_BOUNDARY_TOLERANCE = WICK_CLEARANCE + EPS14;
96567
- var CANDIDATE_SELECTED_COLOR2 = "blue";
96568
- var CANDIDATE_REJECTED_COLOR2 = "red";
96569
- var isYOrientation = (orientation2) => orientation2 === "y+" || orientation2 === "y-";
96570
- var isXOrientation = (orientation2) => orientation2 === "x+" || orientation2 === "x-";
96571
- var rectsOverlap2 = (a2, b2) => Math.min(a2.maxX, b2.maxX) - Math.max(a2.minX, b2.minX) > EPS14 && Math.min(a2.maxY, b2.maxY) - Math.max(a2.minY, b2.minY) > EPS14;
96572
- var rangesOverlap = (minA, maxA, minB, maxB) => Math.min(maxA, maxB) - Math.max(minA, minB) > EPS14;
96573
- var traceCrossesBoundsInterior = (bounds, traceMap) => {
96574
- for (const trace of Object.values(traceMap)) {
96575
- const points = trace.tracePath;
96576
- for (let i2 = 0; i2 < points.length - 1; i2++) {
96577
- if (segmentCrossesBoundsInterior(points[i2], points[i2 + 1], bounds)) {
96578
- return true;
96579
- }
96580
- }
96581
- }
96582
- return false;
96583
- };
96584
- var segmentCrossesBoundsInterior = (p1, p2, bounds) => {
96585
- const interiorBounds = {
96586
- minX: bounds.minX + TRACE_BOUNDARY_TOLERANCE,
96587
- minY: bounds.minY + TRACE_BOUNDARY_TOLERANCE,
96588
- maxX: bounds.maxX - TRACE_BOUNDARY_TOLERANCE,
96589
- maxY: bounds.maxY - TRACE_BOUNDARY_TOLERANCE
96590
- };
96591
- if (interiorBounds.minX >= interiorBounds.maxX || interiorBounds.minY >= interiorBounds.maxY) {
96592
- return false;
96593
- }
96594
- if (sameX2(p1, p2)) {
96595
- if (p1.x <= interiorBounds.minX + EPS14 || p1.x >= interiorBounds.maxX - EPS14) {
96596
- return false;
96597
- }
96598
- return rangesOverlap(
96599
- Math.min(p1.y, p2.y),
96600
- Math.max(p1.y, p2.y),
96601
- interiorBounds.minY,
96602
- interiorBounds.maxY
96603
- );
96604
- }
96605
- if (sameY2(p1, p2)) {
96606
- if (p1.y <= interiorBounds.minY + EPS14 || p1.y >= interiorBounds.maxY - EPS14) {
96607
- return false;
96608
- }
96609
- return rangesOverlap(
96610
- Math.min(p1.x, p2.x),
96611
- Math.max(p1.x, p2.x),
96612
- interiorBounds.minX,
96613
- interiorBounds.maxX
96614
- );
96615
- }
96616
- return false;
96617
- };
96618
- var tracePathIntersectsBounds = (tracePath, bounds) => {
96619
- for (let i2 = 0; i2 < tracePath.length - 1; i2++) {
96620
- if (segmentIntersectsRect2(tracePath[i2], tracePath[i2 + 1], bounds)) {
96621
- return true;
96622
- }
96623
- }
96624
- return false;
96625
- };
96626
- var getSideDistances = (point6, bounds) => [
96627
- ["left", Math.abs(point6.x - bounds.minX)],
96628
- ["right", Math.abs(point6.x - bounds.maxX)],
96629
- ["bottom", Math.abs(point6.y - bounds.minY)],
96630
- ["top", Math.abs(point6.y - bounds.maxY)]
96631
- ];
96632
- var getConnectorTracePath = (source, target, orientation2) => simplifyOrthogonalPath(
96633
- isYOrientation(orientation2) ? [source, { x: target.x, y: source.y }, target] : [source, { x: source.x, y: target.y }, target]
96634
- );
96635
- var simplifyOrthogonalPath = (path) => {
96636
- const deduped = path.filter(
96637
- (point6, index2) => index2 === 0 || !pointsEqual3(point6, path[index2 - 1])
96638
- );
96639
- if (deduped.length < 3) return deduped;
96640
- const simplified = [deduped[0]];
96641
- for (let i2 = 1; i2 < deduped.length - 1; i2++) {
96642
- const prev = simplified[simplified.length - 1];
96643
- const point6 = deduped[i2];
96644
- const next = deduped[i2 + 1];
96645
- if (sameX2(prev, point6) && sameX2(point6, next) || sameY2(prev, point6) && sameY2(point6, next)) {
96646
- continue;
96647
- }
96648
- simplified.push(point6);
96649
- }
96650
- simplified.push(deduped[deduped.length - 1]);
96651
- return simplified;
96652
- };
96653
- var pointsEqual3 = (a2, b2) => sameX2(a2, b2) && sameY2(a2, b2);
96654
- var sameX2 = (a2, b2) => Math.abs(a2.x - b2.x) <= EPS14;
96655
- var sameY2 = (a2, b2) => Math.abs(a2.y - b2.y) <= EPS14;
96656
- var getMaxSearchDistance = (inputProblem) => {
96657
- const maxChipWidth = Math.max(
96658
- ...inputProblem.chips.map((chip) => chip.width),
96659
- 1
96660
- );
96661
- return maxChipWidth * 3;
96662
- };
96663
96810
  var isPortOnlyLabel = (label) => label.mspConnectionPairIds.length === 0;
96664
96811
  var orderRoutedLabelsBeforeOverlappingPortLabels = ({
96665
96812
  labelIndices,
@@ -96685,7 +96832,7 @@ var orderRoutedLabelsBeforeOverlappingPortLabels = ({
96685
96832
  portOnlyLabel.width,
96686
96833
  portOnlyLabel.height
96687
96834
  );
96688
- return rectsOverlap2(routedBounds, portOnlyBounds);
96835
+ return rectsOverlap(routedBounds, portOnlyBounds);
96689
96836
  });
96690
96837
  const routedPosition = orderedLabelIndices.indexOf(routedLabelIndex);
96691
96838
  if (blockingPosition === -1 || blockingPosition > routedPosition) continue;
@@ -96738,7 +96885,7 @@ var drawCurrentLabel = (graphics, currentLabel, solved) => {
96738
96885
  width: currentLabel.width,
96739
96886
  height: currentLabel.height,
96740
96887
  fill: "rgba(255, 0, 0, 0.2)",
96741
- strokeColor: CANDIDATE_REJECTED_COLOR2,
96888
+ strokeColor: CANDIDATE_REJECTED_COLOR,
96742
96889
  label: `available orientation target
96743
96890
  ${currentLabel.netId ?? currentLabel.globalConnNetId}`
96744
96891
  });
@@ -96746,7 +96893,7 @@ ${currentLabel.netId ?? currentLabel.globalConnNetId}`
96746
96893
  var drawCurrentCandidates2 = (graphics, candidates, solved) => {
96747
96894
  if (solved) return;
96748
96895
  for (const candidate of candidates) {
96749
- const color3 = candidate.selected ? CANDIDATE_SELECTED_COLOR2 : CANDIDATE_REJECTED_COLOR2;
96896
+ const color3 = candidate.selected ? CANDIDATE_SELECTED_COLOR : CANDIDATE_REJECTED_COLOR;
96750
96897
  const distanceLabel = candidate.distance === void 0 ? "" : `
96751
96898
  distance: ${candidate.distance.toFixed(3)}`;
96752
96899
  const outwardDistanceLabel = candidate.outwardDistance === void 0 || candidate.outwardDistance === 0 ? "" : `
@@ -96804,7 +96951,7 @@ var AvailableNetOrientationObstacleIndex = class {
96804
96951
  }
96805
96952
  getTraceSegmentsInBounds(bounds) {
96806
96953
  if (!this.traceSegmentIndex) return [];
96807
- const searchBounds = getPaddedBounds(bounds, EPS14);
96954
+ const searchBounds = getPaddedBounds(bounds, EPS8);
96808
96955
  return this.traceSegmentIndex.search(
96809
96956
  searchBounds.minX,
96810
96957
  searchBounds.minY,
@@ -96817,7 +96964,7 @@ var AvailableNetOrientationObstacleIndex = class {
96817
96964
  for (let pointIndex = 0; pointIndex < tracePath.length - 1; pointIndex++) {
96818
96965
  const segmentBounds = getPaddedBounds(
96819
96966
  getSegmentBounds(tracePath[pointIndex], tracePath[pointIndex + 1]),
96820
- EPS14
96967
+ EPS8
96821
96968
  );
96822
96969
  for (const labelIndex of this.getLabelIndicesInBounds(segmentBounds)) {
96823
96970
  labelIndices.add(labelIndex);
@@ -96830,7 +96977,7 @@ var AvailableNetOrientationObstacleIndex = class {
96830
96977
  const start = tracePath[pointIndex];
96831
96978
  const end = tracePath[pointIndex + 1];
96832
96979
  const nearbyChips = this.chipObstacleSpatialIndex.getChipsInBounds(
96833
- getPaddedBounds(getSegmentBounds(start, end), EPS14)
96980
+ getPaddedBounds(getSegmentBounds(start, end), EPS8)
96834
96981
  );
96835
96982
  for (const chip of nearbyChips) {
96836
96983
  if (segmentCrossesBoundsInterior(start, end, chip.bounds)) return true;
@@ -97088,7 +97235,7 @@ var AvailableNetOrientationSolver = class extends BaseSolver10 {
97088
97235
  if (otherIndex === labelIndex) return false;
97089
97236
  if (otherLabel.globalConnNetId === label.globalConnNetId) return false;
97090
97237
  const otherBounds = this.getHorizontalConstraintMismatchBounds(otherLabel);
97091
- return otherBounds ? rectsOverlap2(bounds2, otherBounds) : false;
97238
+ return otherBounds ? rectsOverlap(bounds2, otherBounds) : false;
97092
97239
  });
97093
97240
  if (overlapsHorizontalConstraintMismatch) return true;
97094
97241
  }
@@ -97097,7 +97244,7 @@ var AvailableNetOrientationSolver = class extends BaseSolver10 {
97097
97244
  return this.outputNetLabelPlacements.some((otherLabel, otherIndex) => {
97098
97245
  if (otherIndex === labelIndex) return false;
97099
97246
  if (otherLabel.globalConnNetId === label.globalConnNetId) return false;
97100
- return rectsOverlap2(
97247
+ return rectsOverlap(
97101
97248
  bounds,
97102
97249
  getRectBounds(otherLabel.center, otherLabel.width, otherLabel.height)
97103
97250
  );
@@ -97134,7 +97281,7 @@ var AvailableNetOrientationSolver = class extends BaseSolver10 {
97134
97281
  const bounds = getRectBounds(label.center, label.width, label.height);
97135
97282
  return labelIndices.slice(position + 1).some((otherIndex) => {
97136
97283
  const other = this.outputNetLabelPlacements[otherIndex];
97137
- return rectsOverlap2(
97284
+ return rectsOverlap(
97138
97285
  bounds,
97139
97286
  getRectBounds(other.center, other.width, other.height)
97140
97287
  );
@@ -97285,7 +97432,7 @@ var AvailableNetOrientationSolver = class extends BaseSolver10 {
97285
97432
  labelIndex,
97286
97433
  orientations
97287
97434
  );
97288
- const rotatedCandidateNeedsLateralBranch = rotatedCandidate !== null && Math.abs(rotatedCandidate.anchorPoint.x - label.anchorPoint.x) > EPS14;
97435
+ const rotatedCandidateNeedsLateralBranch = rotatedCandidate !== null && Math.abs(rotatedCandidate.anchorPoint.x - label.anchorPoint.x) > EPS8;
97289
97436
  if (isDownwardGroundRail && rotatedCandidateNeedsLateralBranch) {
97290
97437
  const downwardRailCandidate = this.findValidCandidateInShiftColumn({
97291
97438
  label,
@@ -97344,7 +97491,7 @@ var AvailableNetOrientationSolver = class extends BaseSolver10 {
97344
97491
  index: index2,
97345
97492
  pin: this.pinMap[otherLabel.pinIds[0]]
97346
97493
  })).filter(
97347
- ({ index: index2, pin: otherPin }) => this.crowdedPortOnlyLabelIndices.has(index2) && otherPin?.chipId === pin.chipId && otherPin.x > pin.x + EPS14
97494
+ ({ index: index2, pin: otherPin }) => this.crowdedPortOnlyLabelIndices.has(index2) && otherPin?.chipId === pin.chipId && otherPin.x > pin.x + EPS8
97348
97495
  ).sort((a2, b2) => a2.pin.x - b2.pin.x)[0]?.pin;
97349
97496
  if (orientation2 === "y-" && nextPinToRight) return null;
97350
97497
  const anchorX = orientation2 === "y-" ? Math.max(
@@ -97377,7 +97524,7 @@ var AvailableNetOrientationSolver = class extends BaseSolver10 {
97377
97524
  const centeredAnchorY = hasUpFacingStack ? (lowestUpFacingLabelY + highestUpFacingLabelY) / 2 : stackedAnchorY;
97378
97525
  const anchorYs = orientation2 === "y-" ? [centeredAnchorY, stackedAnchorY] : [stackedAnchorY];
97379
97526
  for (const anchorY of anchorYs) {
97380
- if (anchorY - label.anchorPoint.y > this.maxSearchDistance + EPS14) {
97527
+ if (anchorY - label.anchorPoint.y > this.maxSearchDistance + EPS8) {
97381
97528
  continue;
97382
97529
  }
97383
97530
  const candidate = this.createCandidate(
@@ -97406,11 +97553,11 @@ var AvailableNetOrientationSolver = class extends BaseSolver10 {
97406
97553
  if (trace.globalConnNetId !== label.globalConnNetId) return false;
97407
97554
  const path = trace.tracePath;
97408
97555
  return path.some((point6, pointIndex) => {
97409
- if (Math.abs(point6.x - label.anchorPoint.x) > EPS14 || Math.abs(point6.y - label.anchorPoint.y) > EPS14) {
97556
+ if (Math.abs(point6.x - label.anchorPoint.x) > EPS8 || Math.abs(point6.y - label.anchorPoint.y) > EPS8) {
97410
97557
  return false;
97411
97558
  }
97412
97559
  return [path[pointIndex - 1], path[pointIndex + 1]].some(
97413
- (neighbor) => neighbor && Math.abs(neighbor.x - point6.x) <= EPS14 && (neighbor.y - point6.y) * direction.y > EPS14
97560
+ (neighbor) => neighbor && Math.abs(neighbor.x - point6.x) <= EPS8 && (neighbor.y - point6.y) * direction.y > EPS8
97414
97561
  );
97415
97562
  });
97416
97563
  });
@@ -97500,7 +97647,7 @@ var AvailableNetOrientationSolver = class extends BaseSolver10 {
97500
97647
  orientation2
97501
97648
  );
97502
97649
  if (outwardDirection2.x === 0 && outwardDirection2.y === 0) continue;
97503
- for (let distance33 = LABEL_SEARCH_STEP; distance33 <= this.maxSearchDistance + EPS14; distance33 += LABEL_SEARCH_STEP) {
97650
+ for (let distance33 = LABEL_SEARCH_STEP; distance33 <= this.maxSearchDistance + EPS8; distance33 += LABEL_SEARCH_STEP) {
97504
97651
  const anchorPoint = {
97505
97652
  x: connectorSource.x + outwardDirection2.x * distance33,
97506
97653
  y: connectorSource.y + outwardDirection2.y * distance33
@@ -97578,7 +97725,7 @@ var AvailableNetOrientationSolver = class extends BaseSolver10 {
97578
97725
  const furthestRowPoints = points.filter(
97579
97726
  (point6) => Math.abs(
97580
97727
  point6.x * direction.x + point6.y * direction.y - furthestAlong
97581
- ) <= EPS14
97728
+ ) <= EPS8
97582
97729
  );
97583
97730
  const directHostPinIds = new Set(
97584
97731
  [...directHostTraceIds].flatMap(
@@ -97599,7 +97746,7 @@ var AvailableNetOrientationSolver = class extends BaseSolver10 {
97599
97746
  preferNearestBendOnOutwardRow: adjacentTraces.some(
97600
97747
  (trace) => furthestRowPoints.some(
97601
97748
  (point6) => trace.tracePath.some(
97602
- (tracePoint) => Math.abs(tracePoint.x - point6.x) <= EPS14 && Math.abs(tracePoint.y - point6.y) <= EPS14
97749
+ (tracePoint) => Math.abs(tracePoint.x - point6.x) <= EPS8 && Math.abs(tracePoint.y - point6.y) <= EPS8
97603
97750
  )
97604
97751
  )
97605
97752
  )
@@ -97611,7 +97758,7 @@ var AvailableNetOrientationSolver = class extends BaseSolver10 {
97611
97758
  for (let i2 = 0; i2 < otherTrace.tracePath.length - 1; i2++) {
97612
97759
  const start = otherTrace.tracePath[i2];
97613
97760
  const end = otherTrace.tracePath[i2 + 1];
97614
- if (Math.abs(start.x - end.x) <= EPS14 && Math.abs(start.y - end.y) > EPS14) {
97761
+ if (Math.abs(start.x - end.x) <= EPS8 && Math.abs(start.y - end.y) > EPS8) {
97615
97762
  verticalRailXs.add(start.x);
97616
97763
  }
97617
97764
  }
@@ -97619,7 +97766,7 @@ var AvailableNetOrientationSolver = class extends BaseSolver10 {
97619
97766
  for (let i2 = 0; i2 < trace.tracePath.length - 1; i2++) {
97620
97767
  const start = trace.tracePath[i2];
97621
97768
  const end = trace.tracePath[i2 + 1];
97622
- if (Math.abs(start.x - end.x) <= EPS14 && Math.abs(start.y - end.y) > EPS14 && [...verticalRailXs].some((x2) => Math.abs(x2 - start.x) <= EPS14)) {
97769
+ if (Math.abs(start.x - end.x) <= EPS8 && Math.abs(start.y - end.y) > EPS8 && [...verticalRailXs].some((x2) => Math.abs(x2 - start.x) <= EPS8)) {
97623
97770
  return true;
97624
97771
  }
97625
97772
  }
@@ -97638,7 +97785,7 @@ var AvailableNetOrientationSolver = class extends BaseSolver10 {
97638
97785
  );
97639
97786
  const maxSearchDistance = this.getSearchDistanceLimit(label, orientation2);
97640
97787
  const maxOutwardDistance = outwardDirection2.x === 0 && outwardDirection2.y === 0 ? 0 : this.maxSearchDistance;
97641
- for (let outwardDistance = 0; outwardDistance <= maxOutwardDistance + EPS14; outwardDistance += LABEL_SEARCH_STEP) {
97788
+ for (let outwardDistance = 0; outwardDistance <= maxOutwardDistance + EPS8; outwardDistance += LABEL_SEARCH_STEP) {
97642
97789
  const baseAnchor = {
97643
97790
  x: initialBaseAnchor.x + outwardDirection2.x * outwardDistance,
97644
97791
  y: initialBaseAnchor.y + outwardDirection2.y * outwardDistance
@@ -97714,7 +97861,7 @@ var AvailableNetOrientationSolver = class extends BaseSolver10 {
97714
97861
  connectorSource,
97715
97862
  startDistance = LABEL_SEARCH_STEP
97716
97863
  } = params;
97717
- for (let distance33 = startDistance; distance33 <= maxSearchDistance + EPS14; distance33 += LABEL_SEARCH_STEP) {
97864
+ for (let distance33 = startDistance; distance33 <= maxSearchDistance + EPS8; distance33 += LABEL_SEARCH_STEP) {
97718
97865
  const anchorPoint = {
97719
97866
  x: baseAnchor.x + direction.x * distance33,
97720
97867
  y: baseAnchor.y + direction.y * distance33
@@ -97828,14 +97975,14 @@ var AvailableNetOrientationSolver = class extends BaseSolver10 {
97828
97975
  for (let pointIndex = 0; pointIndex < hostTrace.tracePath.length - 1; pointIndex++) {
97829
97976
  const start = hostTrace.tracePath[pointIndex];
97830
97977
  const end = hostTrace.tracePath[pointIndex + 1];
97831
- const segmentIsPerpendicularToLabel = isYOrientation(orientation2) ? Math.abs(start.y - end.y) <= EPS14 : Math.abs(start.x - end.x) <= EPS14;
97978
+ const segmentIsPerpendicularToLabel = isYOrientation(orientation2) ? Math.abs(start.y - end.y) <= EPS8 : Math.abs(start.x - end.x) <= EPS8;
97832
97979
  if (!segmentIsPerpendicularToLabel) continue;
97833
97980
  const source = isYOrientation(orientation2) ? { x: targetAnchor.x, y: start.y } : { x: start.x, y: targetAnchor.y };
97834
97981
  if (!tracePathContainsPoint([start, end], label.anchorPoint) || !tracePathContainsPoint([start, end], source)) {
97835
97982
  continue;
97836
97983
  }
97837
97984
  const targetDistanceAlongOrientation = (targetAnchor.x - source.x) * orientationDirection.x + (targetAnchor.y - source.y) * orientationDirection.y;
97838
- if (targetDistanceAlongOrientation >= -EPS14) {
97985
+ if (targetDistanceAlongOrientation >= -EPS8) {
97839
97986
  projectedSources.push(source);
97840
97987
  }
97841
97988
  }
@@ -98094,9 +98241,9 @@ var AvailableNetOrientationSolver = class extends BaseSolver10 {
98094
98241
  const { anchorPoint, orientation: orientation2 } = candidate;
98095
98242
  const chipBounds = chip.bounds;
98096
98243
  if (isYOrientation(orientation2)) {
98097
- return anchorPoint.x < chipBounds.minX - EPS14 || anchorPoint.x > chipBounds.maxX + EPS14;
98244
+ return anchorPoint.x < chipBounds.minX - EPS8 || anchorPoint.x > chipBounds.maxX + EPS8;
98098
98245
  }
98099
- return anchorPoint.y < chipBounds.minY - EPS14 || anchorPoint.y > chipBounds.maxY + EPS14;
98246
+ return anchorPoint.y < chipBounds.minY - EPS8 || anchorPoint.y > chipBounds.maxY + EPS8;
98100
98247
  });
98101
98248
  }
98102
98249
  staysOutsideConnectedPinRow(params) {
@@ -98104,9 +98251,9 @@ var AvailableNetOrientationSolver = class extends BaseSolver10 {
98104
98251
  const pin = this.pinMap[label.pinIds[0]];
98105
98252
  if (!pin || !isYOrientation(candidate.orientation)) return false;
98106
98253
  if (candidate.anchorPoint.x < pin.x) {
98107
- return bounds.maxX <= pin.x + CONNECTED_PIN_ROW_OVERLAP_TOLERANCE + EPS14;
98254
+ return bounds.maxX <= pin.x + CONNECTED_PIN_ROW_OVERLAP_TOLERANCE + EPS8;
98108
98255
  }
98109
- return bounds.minX >= pin.x - CONNECTED_PIN_ROW_OVERLAP_TOLERANCE - EPS14;
98256
+ return bounds.minX >= pin.x - CONNECTED_PIN_ROW_OVERLAP_TOLERANCE - EPS8;
98110
98257
  }
98111
98258
  getBoundsStatus(candidateBoundsCheck) {
98112
98259
  const { bounds, labelIndex, label, ignoreChipCollisions } = candidateBoundsCheck;
@@ -98187,14 +98334,14 @@ var AvailableNetOrientationSolver = class extends BaseSolver10 {
98187
98334
  candidate.width,
98188
98335
  candidate.height
98189
98336
  );
98190
- if (labelBounds.minY < chip.bounds.minY - EPS14 || labelBounds.maxY > chip.bounds.maxY + EPS14) {
98337
+ if (labelBounds.minY < chip.bounds.minY - EPS8 || labelBounds.maxY > chip.bounds.maxY + EPS8) {
98191
98338
  return false;
98192
98339
  }
98193
- if (candidate.anchorPoint.x >= chip.bounds.minX - EPS14 && candidate.anchorPoint.x <= chip.bounds.maxX + EPS14) {
98340
+ if (candidate.anchorPoint.x >= chip.bounds.minX - EPS8 && candidate.anchorPoint.x <= chip.bounds.maxX + EPS8) {
98194
98341
  return false;
98195
98342
  }
98196
98343
  return chip.pins.every(
98197
- (pin) => label.pinIds.includes(pin.pinId) || pin.y <= labelBounds.minY + EPS14 || pin.y >= labelBounds.maxY - EPS14
98344
+ (pin) => label.pinIds.includes(pin.pinId) || pin.y <= labelBounds.minY + EPS8 || pin.y >= labelBounds.maxY - EPS8
98198
98345
  );
98199
98346
  }
98200
98347
  getTextBlockedMultiPinRailTraces(label, orientation2) {
@@ -98221,20 +98368,20 @@ var AvailableNetOrientationSolver = class extends BaseSolver10 {
98221
98368
  const pins = [...connectedPinIds].map((pinId) => this.pinMap[pinId]);
98222
98369
  const direction = dir(orientation2);
98223
98370
  const pinX = pins[0].x;
98224
- if (pins.some((pin) => Math.abs(pin.x - pinX) > EPS14)) return null;
98225
- const sidePins = this.inputProblem.chips.find((chip) => chip.chipId === componentId).pins.filter((pin) => Math.abs(pin.x - pinX) <= EPS14);
98371
+ if (pins.some((pin) => Math.abs(pin.x - pinX) > EPS8)) return null;
98372
+ const sidePins = this.inputProblem.chips.find((chip) => chip.chipId === componentId).pins.filter((pin) => Math.abs(pin.x - pinX) <= EPS8);
98226
98373
  const minY = Math.min(...pins.map((pin) => pin.y));
98227
98374
  const maxY = Math.max(...pins.map((pin) => pin.y));
98228
98375
  if (sidePins.some(
98229
- (pin) => pin.y >= minY - EPS14 && pin.y <= maxY + EPS14 && !connectedPinIds.has(pin.pinId)
98230
- ) || orientation2 === "y-" && minY > Math.min(...sidePins.map((pin) => pin.y)) + EPS14 || orientation2 === "y+" && maxY < Math.max(...sidePins.map((pin) => pin.y)) - EPS14) {
98376
+ (pin) => pin.y >= minY - EPS8 && pin.y <= maxY + EPS8 && !connectedPinIds.has(pin.pinId)
98377
+ ) || orientation2 === "y-" && minY > Math.min(...sidePins.map((pin) => pin.y)) + EPS8 || orientation2 === "y+" && maxY < Math.max(...sidePins.map((pin) => pin.y)) - EPS8) {
98231
98378
  return null;
98232
98379
  }
98233
98380
  const outerPinPosition = Math.max(
98234
98381
  ...pins.map((pin) => pin.x * direction.x + pin.y * direction.y)
98235
98382
  );
98236
98383
  const blockedByText = (this.inputProblem.textBoxes ?? []).some(
98237
- (textBox) => textBox.chipId === componentId && textBox.center.x * direction.x + textBox.center.y * direction.y > outerPinPosition + EPS14
98384
+ (textBox) => textBox.chipId === componentId && textBox.center.x * direction.x + textBox.center.y * direction.y > outerPinPosition + EPS8
98238
98385
  );
98239
98386
  return blockedByText ? [...connectedTraces] : null;
98240
98387
  }
@@ -98250,7 +98397,7 @@ var AvailableNetOrientationSolver = class extends BaseSolver10 {
98250
98397
  ...new Set(
98251
98398
  localTraces.flatMap((trace) => trace.tracePath.map((point6) => point6.x))
98252
98399
  )
98253
- ].filter((x2) => Math.abs(x2 - pinX) > EPS14).sort((a2, b2) => Math.abs(a2 - pinX) - Math.abs(b2 - pinX));
98400
+ ].filter((x2) => Math.abs(x2 - pinX) > EPS8).sort((a2, b2) => Math.abs(a2 - pinX) - Math.abs(b2 - pinX));
98254
98401
  for (const x2 of railXs) {
98255
98402
  const connectorSource = { x: x2, y: connectorY };
98256
98403
  if (!Object.values(this.traceMap).some(
@@ -98313,8 +98460,8 @@ var AvailableNetOrientationSolver = class extends BaseSolver10 {
98313
98460
  if (!chip) return null;
98314
98461
  const sides = new Set(
98315
98462
  pins.map((pin) => {
98316
- if (Math.abs(pin.x - chip.bounds.minX) <= EPS14) return "left";
98317
- if (Math.abs(pin.x - chip.bounds.maxX) <= EPS14) return "right";
98463
+ if (Math.abs(pin.x - chip.bounds.minX) <= EPS8) return "left";
98464
+ if (Math.abs(pin.x - chip.bounds.maxX) <= EPS8) return "right";
98318
98465
  return null;
98319
98466
  })
98320
98467
  );
@@ -98351,7 +98498,7 @@ var AvailableNetOrientationSolver = class extends BaseSolver10 {
98351
98498
  return null;
98352
98499
  }
98353
98500
  const renderedWidth = this.getNetConnectionForLabel(label)?.netLabelHeight;
98354
- if (renderedWidth === void 0 || renderedWidth <= label.width + label.height + EPS14) {
98501
+ if (renderedWidth === void 0 || renderedWidth <= label.width + label.height + EPS8) {
98355
98502
  return null;
98356
98503
  }
98357
98504
  const placementBaseCenter = getCenterFromAnchor(
@@ -98420,22 +98567,22 @@ var AvailableNetOrientationSolver = class extends BaseSolver10 {
98420
98567
  otherBounds.minX -= LABEL_SEARCH_STEP;
98421
98568
  otherBounds.maxX += LABEL_SEARCH_STEP;
98422
98569
  }
98423
- if (rectsOverlap2(bounds, otherBounds)) return true;
98570
+ if (rectsOverlap(bounds, otherBounds)) return true;
98424
98571
  }
98425
98572
  return false;
98426
98573
  }
98427
98574
  sharesChipBoundary(bounds) {
98428
98575
  const boundarySearchBounds = {
98429
- minX: bounds.minX - WICK_CLEARANCE - EPS14,
98430
- minY: bounds.minY - WICK_CLEARANCE - EPS14,
98431
- maxX: bounds.maxX + WICK_CLEARANCE + EPS14,
98432
- maxY: bounds.maxY + WICK_CLEARANCE + EPS14
98576
+ minX: bounds.minX - WICK_CLEARANCE - EPS8,
98577
+ minY: bounds.minY - WICK_CLEARANCE - EPS8,
98578
+ maxX: bounds.maxX + WICK_CLEARANCE + EPS8,
98579
+ maxY: bounds.maxY + WICK_CLEARANCE + EPS8
98433
98580
  };
98434
98581
  const nearbyChips = this.chipObstacleSpatialIndex.getChipsInBounds(boundarySearchBounds);
98435
98582
  for (const chip of nearbyChips) {
98436
98583
  const chipBounds = chip.bounds;
98437
- const adjacentToVerticalSide = Math.abs(bounds.minX - chipBounds.maxX) <= WICK_CLEARANCE + EPS14 || Math.abs(bounds.maxX - chipBounds.minX) <= WICK_CLEARANCE + EPS14;
98438
- const adjacentToHorizontalSide = Math.abs(bounds.minY - chipBounds.maxY) <= WICK_CLEARANCE + EPS14 || Math.abs(bounds.maxY - chipBounds.minY) <= WICK_CLEARANCE + EPS14;
98584
+ const adjacentToVerticalSide = Math.abs(bounds.minX - chipBounds.maxX) <= WICK_CLEARANCE + EPS8 || Math.abs(bounds.maxX - chipBounds.minX) <= WICK_CLEARANCE + EPS8;
98585
+ const adjacentToHorizontalSide = Math.abs(bounds.minY - chipBounds.maxY) <= WICK_CLEARANCE + EPS8 || Math.abs(bounds.maxY - chipBounds.minY) <= WICK_CLEARANCE + EPS8;
98439
98586
  if (adjacentToVerticalSide && rangesOverlap(
98440
98587
  bounds.minY,
98441
98588
  bounds.maxY,
@@ -98497,7 +98644,7 @@ var AvailableNetOrientationSolver = class extends BaseSolver10 {
98497
98644
  let nearestDistance = Number.POSITIVE_INFINITY;
98498
98645
  for (const chip of this.chipObstacleSpatialIndex.chips) {
98499
98646
  const bounds = chip.bounds;
98500
- if (point6.x < bounds.minX - EPS14 || point6.x > bounds.maxX + EPS14 || point6.y < bounds.minY - EPS14 || point6.y > bounds.maxY + EPS14) {
98647
+ if (point6.x < bounds.minX - EPS8 || point6.x > bounds.maxX + EPS8 || point6.y < bounds.minY - EPS8 || point6.y > bounds.maxY + EPS8) {
98501
98648
  continue;
98502
98649
  }
98503
98650
  for (const [side, distance33] of getSideDistances(point6, bounds)) {
@@ -98514,8 +98661,8 @@ var AvailableNetOrientationSolver = class extends BaseSolver10 {
98514
98661
  let nearestDistanceSq = Number.POSITIVE_INFINITY;
98515
98662
  for (const chip of this.chipObstacleSpatialIndex.chips) {
98516
98663
  const bounds = chip.bounds;
98517
- const dx2 = point6.x < bounds.minX - EPS14 ? bounds.minX - point6.x : point6.x > bounds.maxX + EPS14 ? point6.x - bounds.maxX : 0;
98518
- const dy2 = point6.y < bounds.minY - EPS14 ? bounds.minY - point6.y : point6.y > bounds.maxY + EPS14 ? point6.y - bounds.maxY : 0;
98664
+ const dx2 = point6.x < bounds.minX - EPS8 ? bounds.minX - point6.x : point6.x > bounds.maxX + EPS8 ? point6.x - bounds.maxX : 0;
98665
+ const dy2 = point6.y < bounds.minY - EPS8 ? bounds.minY - point6.y : point6.y > bounds.maxY + EPS8 ? point6.y - bounds.maxY : 0;
98519
98666
  if (dx2 === 0 && dy2 === 0) continue;
98520
98667
  const distanceSq = dx2 ** 2 + dy2 ** 2;
98521
98668
  if (distanceSq >= nearestDistanceSq) continue;
@@ -98667,7 +98814,7 @@ var getRemovableRailLabelConnectors = ({
98667
98814
  const endpoints = [connector.tracePath[0], connector.tracePath.at(-1)];
98668
98815
  if (!endpoints[0] || !endpoints[1]) continue;
98669
98816
  const labelEnd = endpoints.findIndex(
98670
- (point6) => getDistance2(point6, label.anchorPoint) <= EPS8
98817
+ (point6) => getDistance2(point6, label.anchorPoint) <= EPS9
98671
98818
  );
98672
98819
  if (labelEnd === -1) continue;
98673
98820
  const source = endpoints[1 - labelEnd];
@@ -98714,11 +98861,11 @@ var getStraightPortConnectorCandidate = ({
98714
98861
  continue;
98715
98862
  const path = simplifyPath(connector.tracePath);
98716
98863
  if (path.length < 4) continue;
98717
- if (getDistance2(path.at(-1), pin) <= EPS8) path.reverse();
98718
- if (getDistance2(path[0], pin) > EPS8 || getDistance2(path.at(-1), label.anchorPoint) > EPS8 || Math.abs(path[1].y - pin.y) > EPS8)
98864
+ if (getDistance2(path.at(-1), pin) <= EPS9) path.reverse();
98865
+ if (getDistance2(path[0], pin) > EPS9 || getDistance2(path.at(-1), label.anchorPoint) > EPS9 || Math.abs(path[1].y - pin.y) > EPS9)
98719
98866
  continue;
98720
98867
  const anchorPoint = { x: label.anchorPoint.x, y: pin.y };
98721
- if ((anchorPoint.x - pin.x) * (path[1].x - pin.x) <= EPS8) continue;
98868
+ if ((anchorPoint.x - pin.x) * (path[1].x - pin.x) <= EPS9) continue;
98722
98869
  const reroutedTracePath = [path[0], anchorPoint];
98723
98870
  const protectedPoints = [
98724
98871
  ...getSameNetJunctions(connector, traces),
@@ -98756,13 +98903,13 @@ var getSimplifiedRailConnectorCandidates = (params) => {
98756
98903
  if (countTurns(path) < 2) continue;
98757
98904
  for (const source of getTraceCorners(simplifyPath(rail.tracePath))) {
98758
98905
  const anchor = label.anchorPoint;
98759
- if ((anchor.y - source.y) * direction < -EPS8) continue;
98906
+ if ((anchor.y - source.y) * direction < -EPS9) continue;
98760
98907
  const reroutedTracePath = simplifyPath([
98761
98908
  source,
98762
98909
  { x: anchor.x, y: source.y },
98763
98910
  anchor
98764
98911
  ]);
98765
- if (countTurns(reroutedTracePath) >= countTurns(path) || getPathLength4(reroutedTracePath) > getPathLength4(path) + EPS8)
98912
+ if (countTurns(reroutedTracePath) >= countTurns(path) || getPathLength4(reroutedTracePath) > getPathLength4(path) + EPS9)
98766
98913
  continue;
98767
98914
  if (traces.some(
98768
98915
  (other) => other.globalConnNetId !== connector.globalConnNetId && countPathIntersections(reroutedTracePath, other.tracePath) > countPathIntersections(path, other.tracePath)
@@ -98996,13 +99143,13 @@ var RailNetLabelCornerPlacementSolver = class extends BaseSolver10 {
98996
99143
  }
98997
99144
  intersectsAnyChip(bounds) {
98998
99145
  return this.inputProblem.chips.some(
98999
- (chip) => rectsOverlap(bounds, getRectBounds(chip.center, chip.width, chip.height))
99146
+ (chip) => rectsOverlap2(bounds, getRectBounds(chip.center, chip.width, chip.height))
99000
99147
  );
99001
99148
  }
99002
99149
  intersectsAnyOtherNetLabel(bounds, labelIndex) {
99003
99150
  return this.outputNetLabelPlacements.some((label, index2) => {
99004
99151
  if (index2 === labelIndex) return false;
99005
- return rectsOverlap(
99152
+ return rectsOverlap2(
99006
99153
  bounds,
99007
99154
  getRectBounds(label.center, label.width, label.height)
99008
99155
  );
@@ -99023,7 +99170,7 @@ var RailNetLabelCornerPlacementSolver = class extends BaseSolver10 {
99023
99170
  for (const anchorPoint of getTraceCorners(path)) {
99024
99171
  const cornerIndex = path.indexOf(anchorPoint);
99025
99172
  const anchorAlignedToPin = pins.some(
99026
- (pin) => Math.abs(pin.x - anchorPoint.x) <= EPS8
99173
+ (pin) => Math.abs(pin.x - anchorPoint.x) <= EPS9
99027
99174
  );
99028
99175
  const pinAligned = anchorAlignedToPin || allowRailAlignedFallback && this.isPinAlignedCorner(path, cornerIndex);
99029
99176
  if (!pinAligned) continue;
@@ -99116,7 +99263,7 @@ var RailNetLabelCornerPlacementSolver = class extends BaseSolver10 {
99116
99263
  return [];
99117
99264
  }
99118
99265
  const pins = this.inputProblem.chips.flatMap((chip) => chip.pins).filter((pin) => label.pinIds.includes(pin.pinId));
99119
- if (pins.length !== 2 || pins[0]._facingDirection !== pins[1]._facingDirection || pins[0]._facingDirection !== "x+" && pins[0]._facingDirection !== "x-" || Math.abs(pins[0].y - pins[1].y) > EPS8) {
99266
+ if (pins.length !== 2 || pins[0]._facingDirection !== pins[1]._facingDirection || pins[0]._facingDirection !== "x+" && pins[0]._facingDirection !== "x-" || Math.abs(pins[0].y - pins[1].y) > EPS9) {
99120
99267
  return [];
99121
99268
  }
99122
99269
  const configuredOrientations = this.inputProblem.availableNetLabelOrientations[label.netId];
@@ -99141,7 +99288,7 @@ var RailNetLabelCornerPlacementSolver = class extends BaseSolver10 {
99141
99288
  getMaxSearchDistance(this.inputProblem),
99142
99289
  label.height * 2
99143
99290
  );
99144
- for (let distance33 = WICK_CLEARANCE + LABEL_SEARCH_STEP; distance33 <= maxSearchDistance + EPS8; distance33 += LABEL_SEARCH_STEP) {
99291
+ for (let distance33 = WICK_CLEARANCE + LABEL_SEARCH_STEP; distance33 <= maxSearchDistance + EPS9; distance33 += LABEL_SEARCH_STEP) {
99145
99292
  const anchorPoint = {
99146
99293
  x: sourcePoint.x,
99147
99294
  y: sourcePoint.y + direction * distance33
@@ -99193,12 +99340,12 @@ var RailNetLabelCornerPlacementSolver = class extends BaseSolver10 {
99193
99340
  return traceCrossesBoundsInterior(bounds, this.traceMap);
99194
99341
  }
99195
99342
  pointsEqual(a2, b2) {
99196
- return Math.abs(a2.x - b2.x) <= EPS8 && Math.abs(a2.y - b2.y) <= EPS8;
99343
+ return Math.abs(a2.x - b2.x) <= EPS9 && Math.abs(a2.y - b2.y) <= EPS9;
99197
99344
  }
99198
99345
  getVerticalSegmentPointIndices(path, cornerIndex) {
99199
99346
  const corner = path[cornerIndex];
99200
- const previousIsVertical = Math.abs(path[cornerIndex - 1].x - corner.x) <= EPS8;
99201
- const nextIsVertical = Math.abs(path[cornerIndex + 1].x - corner.x) <= EPS8;
99347
+ const previousIsVertical = Math.abs(path[cornerIndex - 1].x - corner.x) <= EPS9;
99348
+ const nextIsVertical = Math.abs(path[cornerIndex + 1].x - corner.x) <= EPS9;
99202
99349
  if (previousIsVertical === nextIsVertical) return null;
99203
99350
  const indices = previousIsVertical ? [cornerIndex - 1, cornerIndex] : [cornerIndex, cornerIndex + 1];
99204
99351
  return indices;
@@ -99235,7 +99382,7 @@ var RailNetLabelCornerPlacementSolver = class extends BaseSolver10 {
99235
99382
  label.height
99236
99383
  );
99237
99384
  const labelBounds = getRectBounds(center, label.width, label.height);
99238
- const collidingChipBounds = this.inputProblem.chips.map((chip) => getRectBounds(chip.center, chip.width, chip.height)).filter((chipBounds) => rectsOverlap(labelBounds, chipBounds));
99385
+ const collidingChipBounds = this.inputProblem.chips.map((chip) => getRectBounds(chip.center, chip.width, chip.height)).filter((chipBounds) => rectsOverlap2(labelBounds, chipBounds));
99239
99386
  const shiftedCoordinates = /* @__PURE__ */ new Set();
99240
99387
  for (const chipBounds of collidingChipBounds) {
99241
99388
  shiftedCoordinates.add(chipBounds.minX - label.width / 2);
@@ -99248,7 +99395,7 @@ var RailNetLabelCornerPlacementSolver = class extends BaseSolver10 {
99248
99395
  const end = otherTrace.tracePath[i2 + 1];
99249
99396
  if (!segmentCrossesBoundsInterior(start, end, labelBounds)) continue;
99250
99397
  const halfLabelWidth = label.width / 2;
99251
- if (Math.abs(start.x - end.x) <= EPS8) {
99398
+ if (Math.abs(start.x - end.x) <= EPS9) {
99252
99399
  shiftedCoordinates.add(
99253
99400
  start.x - halfLabelWidth - LABEL_TRACE_CLEARANCE3
99254
99401
  );
@@ -99266,7 +99413,7 @@ var RailNetLabelCornerPlacementSolver = class extends BaseSolver10 {
99266
99413
  }
99267
99414
  }
99268
99415
  return [...shiftedCoordinates].flatMap((x2) => {
99269
- if (Math.abs(x2 - corner.x) <= EPS8) return [];
99416
+ if (Math.abs(x2 - corner.x) <= EPS9) return [];
99270
99417
  const reroutedTracePath = simplifyPath(
99271
99418
  path.map(
99272
99419
  (point6, pointIndex) => verticalPointIndices.includes(pointIndex) ? { ...point6, x: x2 } : point6
@@ -102705,7 +102852,7 @@ var candidateIsClear = ({
102705
102852
  }
102706
102853
  }
102707
102854
  for (const obstacle of obstacles) {
102708
- if (rectsOverlap(candidateBounds, obstacle) && !rectsOverlap(originalBounds, obstacle)) {
102855
+ if (rectsOverlap2(candidateBounds, obstacle) && !rectsOverlap2(originalBounds, obstacle)) {
102709
102856
  return false;
102710
102857
  }
102711
102858
  }
@@ -102723,7 +102870,7 @@ var candidateIsClear = ({
102723
102870
  candidateOther.width,
102724
102871
  candidateOther.height
102725
102872
  );
102726
- if (rectsOverlap(candidateBounds, candidateOtherBounds) && !rectsOverlap(originalBounds, originalOtherBounds)) {
102873
+ if (rectsOverlap2(candidateBounds, candidateOtherBounds) && !rectsOverlap2(originalBounds, originalOtherBounds)) {
102727
102874
  return false;
102728
102875
  }
102729
102876
  }
@@ -103036,100 +103183,6 @@ var alignSameNetJunctions = ({
103036
103183
  collapsedCycleCount: cycleCollapse.collapsedCycleCount
103037
103184
  };
103038
103185
  };
103039
- var placeGroundRailLabelsAtOuterEnd = ({
103040
- inputProblem,
103041
- traces,
103042
- netLabelPlacements
103043
- }) => {
103044
- const { netConnMap } = getConnectivityMapsFromInputProblem(inputProblem);
103045
- const groundNetId = netConnMap.getNetConnectedToId("GND");
103046
- if (!groundNetId) return netLabelPlacements;
103047
- const chipMap = new Map(inputProblem.chips.map((chip) => [chip.chipId, chip]));
103048
- const traceMap = Object.fromEntries(
103049
- traces.map((trace) => [trace.mspPairId, trace])
103050
- );
103051
- const obstacles = getObstacleRects(inputProblem);
103052
- const output = [...netLabelPlacements];
103053
- for (const rail of traces) {
103054
- if (rail.globalConnNetId !== groundNetId) continue;
103055
- const [a2, b2] = rail.pins;
103056
- if (a2.chipId === b2.chipId || !nearlyEqual(a2.y, b2.y) || ![a2, b2].every(
103057
- (pin) => pin._facingDirection === "y-" && chipMap.get(pin.chipId)?.pins.length === 2
103058
- ))
103059
- continue;
103060
- const path = simplifyPath(rail.tracePath);
103061
- if (path.length !== 4 || !isVertical2(path[0], path[1]) || !isHorizontal22(path[1], path[2]) || !isVertical2(path[2], path[3]) || path[1].y >= a2.y)
103062
- continue;
103063
- for (const feed of traces) {
103064
- if (feed.globalConnNetId !== groundNetId) continue;
103065
- const shared = feed.pins.find((pin) => rail.pinIds.includes(pin.pinId));
103066
- const icPin = feed.pins.find(
103067
- (pin) => !rail.pinIds.includes(pin.pinId) && (chipMap.get(pin.chipId)?.pins.length ?? 0) > 2
103068
- );
103069
- if (!shared || !icPin || !nearlyEqual(icPin.y, path[1].y)) continue;
103070
- const outer = shared.pinId === a2.pinId ? b2 : a2;
103071
- if (Math.abs(outer.x - icPin.x) <= Math.abs(shared.x - icPin.x)) continue;
103072
- const anchorPoint = { x: outer.x, y: path[1].y };
103073
- if (!tracePathContainsPoint(rail.tracePath, anchorPoint)) continue;
103074
- for (let index2 = 0; index2 < output.length; index2++) {
103075
- const label = output[index2];
103076
- if (label.globalConnNetId !== groundNetId || label.orientation !== "y-" || !label.mspConnectionPairIds.some(
103077
- (id) => id === feed.mspPairId || id === rail.mspPairId
103078
- ) || !tracePathContainsPoint(feed.tracePath, label.anchorPoint) && !tracePathContainsPoint(rail.tracePath, label.anchorPoint))
103079
- continue;
103080
- const center = getCenterFromAnchor(
103081
- anchorPoint,
103082
- label.orientation,
103083
- label.width,
103084
- label.height
103085
- );
103086
- const bounds = getRectBounds(center, label.width, label.height);
103087
- if (obstacles.some((obstacle) => rectsOverlap(bounds, obstacle)) || traceCrossesBoundsInterior(bounds, traceMap) || output.some(
103088
- (other, otherIndex) => otherIndex !== index2 && rectsOverlap(
103089
- bounds,
103090
- getRectBounds(other.center, other.width, other.height)
103091
- )
103092
- ))
103093
- continue;
103094
- output[index2] = {
103095
- ...label,
103096
- anchorPoint,
103097
- center,
103098
- mspConnectionPairIds: [rail.mspPairId],
103099
- pinIds: [...rail.pinIds]
103100
- };
103101
- }
103102
- }
103103
- }
103104
- for (let index2 = 0; index2 < output.length; index2++) {
103105
- const label = output[index2];
103106
- if (label.orientation !== "y-") continue;
103107
- const connection = inputProblem.netConnections.find(
103108
- (candidate) => candidate.isGround && candidate.netId === label.netId && candidate.pinIds.length > 2
103109
- );
103110
- if (!connection) continue;
103111
- const anchorPoint = traces.filter((trace) => trace.globalConnNetId === label.globalConnNetId).flatMap((trace) => trace.tracePath).filter(
103112
- (point6) => nearlyEqual(point6.x, label.anchorPoint.x) && point6.y < label.anchorPoint.y
103113
- ).sort((a2, b2) => a2.y - b2.y)[0];
103114
- if (!anchorPoint) continue;
103115
- const center = getCenterFromAnchor(
103116
- anchorPoint,
103117
- label.orientation,
103118
- label.width,
103119
- label.height
103120
- );
103121
- const bounds = getRectBounds(center, label.width, label.height);
103122
- if (obstacles.some((obstacle) => rectsOverlap(bounds, obstacle)) || traceCrossesBoundsInterior(bounds, traceMap) || output.some(
103123
- (other, otherIndex) => otherIndex !== index2 && rectsOverlap(
103124
- bounds,
103125
- getRectBounds(other.center, other.width, other.height)
103126
- )
103127
- ))
103128
- continue;
103129
- output[index2] = { ...label, anchorPoint, center };
103130
- }
103131
- return output;
103132
- };
103133
103186
  var MAX_LOCAL_RAIL_SHIFT = 0.5;
103134
103187
  var MIN_ESCAPE_LENGTH = 1;
103135
103188
  var shortenSameSideRailToLabelAnchor = ({
@@ -118287,7 +118340,7 @@ function Group_getRoutingPhasePlans(group) {
118287
118340
  var package_default = {
118288
118341
  name: "@tscircuit/core",
118289
118342
  type: "module",
118290
- version: "0.0.2117",
118343
+ version: "0.0.2118",
118291
118344
  types: "dist/index.d.ts",
118292
118345
  main: "dist/index.js",
118293
118346
  module: "dist/index.js",
@@ -118348,7 +118401,7 @@ var package_default = {
118348
118401
  "@tscircuit/ngspice-spice-engine": "^0.0.20",
118349
118402
  "@tscircuit/props": "^0.0.697",
118350
118403
  "@tscircuit/schematic-match-adapt": "^0.0.18",
118351
- "@tscircuit/schematic-trace-solver": "https://jscdn.tscircuit.com/@tscircuit/schematic-trace-solver/0.0.229.tgz",
118404
+ "@tscircuit/schematic-trace-solver": "https://jscdn.tscircuit.com/@tscircuit/schematic-trace-solver/0.0.230.tgz",
118352
118405
  "@tscircuit/solver-utils": "^0.0.16",
118353
118406
  "@tscircuit/soup-util": "^0.0.41",
118354
118407
  "@tscircuit/via-stitch-solver": "github:tscircuit/via-stitch-solver#64f2ac7781b795bdc0d74ba411988e60767fa653",