@tscircuit/schematic-trace-solver 0.0.154 → 0.0.156
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.d.ts +3 -1
- package/dist/index.js +331 -114
- package/lib/solvers/AvailableNetOrientationSolver/AvailableNetOrientationSolver.ts +60 -16
- package/lib/solvers/SchematicTraceLinesSolver/SchematicTraceLinesSolver.ts +38 -0
- package/lib/solvers/SchematicTraceLinesSolver/SchematicTraceSingleLineSolver2/SchematicTraceSingleLineSolver2.ts +19 -11
- package/lib/solvers/TraceCleanupSolver/alignSameNetRails.ts +17 -0
- package/lib/solvers/TraceCleanupSolver/sameNetRailAlignment/evaluateRailGroup.ts +32 -4
- package/lib/solvers/TraceCleanupSolver/sameNetRailAlignment/getComponentSideRailSegments.ts +28 -5
- package/lib/solvers/TraceCleanupSolver/sameNetRailAlignment/getFixedLabelCoordinate.ts +114 -0
- package/lib/solvers/TraceCleanupSolver/sameNetRailAlignment/getRailGroups.ts +98 -32
- package/lib/solvers/TraceCleanupSolver/sameNetRailAlignment/moveRailSegments.ts +2 -0
- package/package.json +1 -1
- package/site/bug-reports/bug-report-20260825T045913Z.page.tsx +4 -0
- package/tests/bug-reports/bug-report-20260707T134549Z/__snapshots__/bug-report-20260707T134549Z.snap.svg +2 -2
- package/tests/bug-reports/bug-report-20260730T061837Z/__snapshots__/bug-report-20260730T061837Z.snap.svg +2 -2
- package/tests/bug-reports/bug-report-20260825T045913Z/__snapshots__/bug-report-20260825T045913Z.snap.svg +271 -0
- package/tests/bug-reports/bug-report-20260825T045913Z/bug-report-20260825T045913Z.json +874 -0
- package/tests/bug-reports/bug-report-20260825T045913Z/bug-report-20260825T045913Z.test.ts +23 -0
- package/tests/bug-reports/bug-report-20260825T103621Z/__snapshots__/bug-report-20260825T103621Z.snap.svg +2 -2
- package/tests/examples/__snapshots__/example51.snap.svg +2 -2
- package/tests/repros/__snapshots__/repro-ti-power-output-section.snap.svg +45 -45
package/dist/index.js
CHANGED
|
@@ -1255,6 +1255,7 @@ var SchematicTraceSingleLineSolver2 = class extends BaseSolver {
|
|
|
1255
1255
|
endpointTextObstacles;
|
|
1256
1256
|
aabb;
|
|
1257
1257
|
baseElbow;
|
|
1258
|
+
preferExteriorDetours;
|
|
1258
1259
|
solvedTracePath = null;
|
|
1259
1260
|
queue = [];
|
|
1260
1261
|
visited = /* @__PURE__ */ new Set();
|
|
@@ -1264,6 +1265,7 @@ var SchematicTraceSingleLineSolver2 = class extends BaseSolver {
|
|
|
1264
1265
|
this.connectionPair = params.connectionPair;
|
|
1265
1266
|
this.inputProblem = params.inputProblem;
|
|
1266
1267
|
this.chipMap = params.chipMap;
|
|
1268
|
+
this.preferExteriorDetours = params.preferExteriorDetours ?? true;
|
|
1267
1269
|
for (const pin of this.pins) {
|
|
1268
1270
|
if (!pin._facingDirection) {
|
|
1269
1271
|
const chip = this.chipMap[pin.chipId];
|
|
@@ -1316,7 +1318,8 @@ var SchematicTraceSingleLineSolver2 = class extends BaseSolver {
|
|
|
1316
1318
|
chipMap: this.chipMap,
|
|
1317
1319
|
pins: this.pins,
|
|
1318
1320
|
connectionPair: this.connectionPair,
|
|
1319
|
-
inputProblem: this.inputProblem
|
|
1321
|
+
inputProblem: this.inputProblem,
|
|
1322
|
+
preferExteriorDetours: this.preferExteriorDetours
|
|
1320
1323
|
};
|
|
1321
1324
|
}
|
|
1322
1325
|
getTextBoxPaddingForConnectionPair() {
|
|
@@ -1481,7 +1484,6 @@ var SchematicTraceSingleLineSolver2 = class extends BaseSolver {
|
|
|
1481
1484
|
const isEndpointChipObstacle = rect.kind === "chip" && this.pins.some((pin) => pin.chipId === rect.chipId);
|
|
1482
1485
|
const canGenerateEndpointDetour = path.length === 3 || path.length === 4 && this.connectionPair !== void 0 && !isEndpointChipObstacle;
|
|
1483
1486
|
if (canGenerateEndpointDetour && (isFirstSegment || isLastSegment)) {
|
|
1484
|
-
const compareDetours = path.length === 4 ? (a2, b2) => this.getPinBandPenalty(a2) - this.getPinBandPenalty(b2) || this.pathLength(a2) - this.pathLength(b2) : (a2, b2) => this.pathLength(a2) - this.pathLength(b2) || this.getPinBandPenalty(a2) - this.getPinBandPenalty(b2);
|
|
1485
1487
|
const detours = generateEndpointCollisionDetours({
|
|
1486
1488
|
path,
|
|
1487
1489
|
collidingSegmentIndex: segIndex,
|
|
@@ -1491,7 +1493,12 @@ var SchematicTraceSingleLineSolver2 = class extends BaseSolver {
|
|
|
1491
1493
|
if (this.visited.has(key)) return false;
|
|
1492
1494
|
this.visited.add(key);
|
|
1493
1495
|
return true;
|
|
1494
|
-
}).sort(
|
|
1496
|
+
}).sort((a2, b2) => {
|
|
1497
|
+
if (path.length === 4 && this.preferExteriorDetours) {
|
|
1498
|
+
return this.getPinBandPenalty(a2) - this.getPinBandPenalty(b2) || this.pathLength(a2) - this.pathLength(b2);
|
|
1499
|
+
}
|
|
1500
|
+
return this.pathLength(a2) - this.pathLength(b2) || this.getPinBandPenalty(a2) - this.getPinBandPenalty(b2);
|
|
1501
|
+
});
|
|
1495
1502
|
for (const detour of detours) {
|
|
1496
1503
|
const nextCollisionRects = new Set(collisionRects);
|
|
1497
1504
|
nextCollisionRects.add(rect);
|
|
@@ -1644,6 +1651,24 @@ var SchematicTraceSingleLineSolver2 = class extends BaseSolver {
|
|
|
1644
1651
|
import { getBounds } from "graphics-debug";
|
|
1645
1652
|
|
|
1646
1653
|
// lib/solvers/SchematicTraceLinesSolver/SchematicTraceLinesSolver.ts
|
|
1654
|
+
var shouldPreferExteriorDetours = ({
|
|
1655
|
+
connectionPair,
|
|
1656
|
+
allConnectionPairs,
|
|
1657
|
+
inputProblem
|
|
1658
|
+
}) => {
|
|
1659
|
+
const [firstPin, secondPin] = connectionPair.pins;
|
|
1660
|
+
const belongsToNetConnection = inputProblem.netConnections.some(
|
|
1661
|
+
(netConnection) => netConnection.pinIds.includes(firstPin.pinId) && netConnection.pinIds.includes(secondPin.pinId)
|
|
1662
|
+
);
|
|
1663
|
+
if (belongsToNetConnection) return true;
|
|
1664
|
+
return allConnectionPairs.some((otherPair) => {
|
|
1665
|
+
if (otherPair === connectionPair) return false;
|
|
1666
|
+
const [otherFirstPin, otherSecondPin] = otherPair.pins;
|
|
1667
|
+
const sameOrder = firstPin.chipId === otherFirstPin.chipId && secondPin.chipId === otherSecondPin.chipId;
|
|
1668
|
+
if (sameOrder) return true;
|
|
1669
|
+
return firstPin.chipId === otherSecondPin.chipId && secondPin.chipId === otherFirstPin.chipId;
|
|
1670
|
+
});
|
|
1671
|
+
};
|
|
1647
1672
|
var SchematicTraceLinesSolver = class extends BaseSolver {
|
|
1648
1673
|
inputProblem;
|
|
1649
1674
|
mspConnectionPairs;
|
|
@@ -1711,7 +1736,12 @@ var SchematicTraceLinesSolver = class extends BaseSolver {
|
|
|
1711
1736
|
inputProblem: this.inputProblem,
|
|
1712
1737
|
pins,
|
|
1713
1738
|
connectionPair,
|
|
1714
|
-
chipMap: this.chipMap
|
|
1739
|
+
chipMap: this.chipMap,
|
|
1740
|
+
preferExteriorDetours: shouldPreferExteriorDetours({
|
|
1741
|
+
connectionPair,
|
|
1742
|
+
allConnectionPairs: this.mspConnectionPairs,
|
|
1743
|
+
inputProblem: this.inputProblem
|
|
1744
|
+
})
|
|
1715
1745
|
});
|
|
1716
1746
|
}
|
|
1717
1747
|
visualize() {
|
|
@@ -5690,22 +5720,8 @@ var getRailAlignmentFallbackCoordinates = ({
|
|
|
5690
5720
|
return getDistinctCoordinates(coordinates);
|
|
5691
5721
|
};
|
|
5692
5722
|
|
|
5693
|
-
// lib/solvers/TraceCleanupSolver/sameNetRailAlignment/
|
|
5694
|
-
|
|
5695
|
-
const pointsToMove = /* @__PURE__ */ new Set();
|
|
5696
|
-
for (const segment of segments) {
|
|
5697
|
-
pointsToMove.add(segment.segmentIndex);
|
|
5698
|
-
pointsToMove.add(segment.segmentIndex + 1);
|
|
5699
|
-
}
|
|
5700
|
-
const orientation = segments[0].orientation;
|
|
5701
|
-
const tracePath = simplifyPath(
|
|
5702
|
-
trace.tracePath.map((point, index) => {
|
|
5703
|
-
if (!pointsToMove.has(index)) return point;
|
|
5704
|
-
return orientation === "vertical" ? { ...point, x: coordinate } : { ...point, y: coordinate };
|
|
5705
|
-
})
|
|
5706
|
-
);
|
|
5707
|
-
return { ...trace, tracePath };
|
|
5708
|
-
};
|
|
5723
|
+
// lib/solvers/TraceCleanupSolver/sameNetRailAlignment/getFixedLabelCoordinate.ts
|
|
5724
|
+
import { distance as distance4 } from "@tscircuit/math-utils";
|
|
5709
5725
|
|
|
5710
5726
|
// lib/solvers/RailNetLabelCornerPlacementSolver/geometry.ts
|
|
5711
5727
|
var EPS7 = 1e-6;
|
|
@@ -5740,6 +5756,95 @@ var isPointOnSegment = (point, start, end) => {
|
|
|
5740
5756
|
};
|
|
5741
5757
|
var getSegmentOrientation = (a, b) => Math.abs(a.y - b.y) <= EPS7 ? "horizontal" : "vertical";
|
|
5742
5758
|
|
|
5759
|
+
// lib/solvers/TraceCleanupSolver/sameNetRailAlignment/getFixedLabelCoordinate.ts
|
|
5760
|
+
var getTransitivelyConnectedTraceIds = (group, traces) => {
|
|
5761
|
+
const groupNetId = group[0].globalConnNetId;
|
|
5762
|
+
const sameNetTraces = traces.filter(
|
|
5763
|
+
(trace) => trace.globalConnNetId === groupNetId
|
|
5764
|
+
);
|
|
5765
|
+
const connectedTraceIds = new Set(group.map((segment) => segment.traceId));
|
|
5766
|
+
const connectedPinIds = new Set(
|
|
5767
|
+
sameNetTraces.filter((trace) => connectedTraceIds.has(trace.mspPairId)).flatMap((trace) => trace.pinIds)
|
|
5768
|
+
);
|
|
5769
|
+
for (let changed = true; changed; ) {
|
|
5770
|
+
changed = false;
|
|
5771
|
+
for (const trace of sameNetTraces) {
|
|
5772
|
+
if (connectedTraceIds.has(trace.mspPairId)) continue;
|
|
5773
|
+
if (!trace.pinIds.some((pinId) => connectedPinIds.has(pinId))) continue;
|
|
5774
|
+
connectedTraceIds.add(trace.mspPairId);
|
|
5775
|
+
for (const pinId of trace.pinIds) connectedPinIds.add(pinId);
|
|
5776
|
+
changed = true;
|
|
5777
|
+
}
|
|
5778
|
+
}
|
|
5779
|
+
return connectedTraceIds;
|
|
5780
|
+
};
|
|
5781
|
+
var getLabelsLinkedToRailGroup = (group, netLabelPlacements, traces) => {
|
|
5782
|
+
const traceIds = getTransitivelyConnectedTraceIds(group, traces);
|
|
5783
|
+
return netLabelPlacements.filter(
|
|
5784
|
+
(label) => label.mspConnectionPairIds.some((traceId) => traceIds.has(traceId))
|
|
5785
|
+
);
|
|
5786
|
+
};
|
|
5787
|
+
var getFixedLabelCoordinate = (group, netLabelPlacements, traces) => {
|
|
5788
|
+
const traceMap = new Map(traces.map((trace) => [trace.mspPairId, trace]));
|
|
5789
|
+
const groupTraceIds = new Set(group.map((segment) => segment.traceId));
|
|
5790
|
+
const groupHasOnlySingleRailTraces = [...groupTraceIds].every(
|
|
5791
|
+
(traceId) => traceMap.get(traceId)?.tracePath.length === 4
|
|
5792
|
+
);
|
|
5793
|
+
if (!groupHasOnlySingleRailTraces) return null;
|
|
5794
|
+
const orientation = group[0].orientation;
|
|
5795
|
+
const linkedLabels = getLabelsLinkedToRailGroup(
|
|
5796
|
+
group,
|
|
5797
|
+
netLabelPlacements,
|
|
5798
|
+
traces
|
|
5799
|
+
);
|
|
5800
|
+
const anchoringLabels = linkedLabels.filter(
|
|
5801
|
+
(label) => label.orientation === group[0].componentFacingDirection && label.mspConnectionPairIds.some((traceId) => {
|
|
5802
|
+
const trace = traceMap.get(traceId);
|
|
5803
|
+
return trace && tracePathContainsPoint(trace.tracePath, label.anchorPoint);
|
|
5804
|
+
})
|
|
5805
|
+
);
|
|
5806
|
+
const coordinates = getDistinctCoordinates(
|
|
5807
|
+
anchoringLabels.map(
|
|
5808
|
+
(label) => orientation === "vertical" ? label.anchorPoint.x : label.anchorPoint.y
|
|
5809
|
+
)
|
|
5810
|
+
);
|
|
5811
|
+
if (coordinates.length !== 1) return null;
|
|
5812
|
+
const labelCoordinate = coordinates[0];
|
|
5813
|
+
const coordinate = group.find(
|
|
5814
|
+
(segment) => Math.abs(segment.coordinate - labelCoordinate) <= RAIL_ALIGNMENT_EPSILON
|
|
5815
|
+
)?.coordinate ?? labelCoordinate;
|
|
5816
|
+
const labelIsAnchoredToRoutedBackbone = anchoringLabels.some(
|
|
5817
|
+
(label) => label.mspConnectionPairIds.some(
|
|
5818
|
+
(traceId) => (traceMap.get(traceId)?.tracePath.length ?? 0) > 4
|
|
5819
|
+
)
|
|
5820
|
+
);
|
|
5821
|
+
if (labelIsAnchoredToRoutedBackbone) return coordinate;
|
|
5822
|
+
const coordinateIsLocalToEveryTrace = group.every((segment) => {
|
|
5823
|
+
const trace = traceMap.get(segment.traceId);
|
|
5824
|
+
if (!trace) return false;
|
|
5825
|
+
return Math.abs(segment.coordinate - coordinate) <= distance4(trace.pins[0], trace.pins[1]) + RAIL_ALIGNMENT_EPSILON;
|
|
5826
|
+
});
|
|
5827
|
+
return coordinateIsLocalToEveryTrace ? coordinate : null;
|
|
5828
|
+
};
|
|
5829
|
+
|
|
5830
|
+
// lib/solvers/TraceCleanupSolver/sameNetRailAlignment/moveRailSegments.ts
|
|
5831
|
+
var moveRailSegments = (trace, segments, coordinate) => {
|
|
5832
|
+
const pointsToMove = /* @__PURE__ */ new Set();
|
|
5833
|
+
for (const segment of segments) {
|
|
5834
|
+
if (nearlyEqual(segment.coordinate, coordinate)) continue;
|
|
5835
|
+
pointsToMove.add(segment.segmentIndex);
|
|
5836
|
+
pointsToMove.add(segment.segmentIndex + 1);
|
|
5837
|
+
}
|
|
5838
|
+
const orientation = segments[0].orientation;
|
|
5839
|
+
const tracePath = simplifyPath(
|
|
5840
|
+
trace.tracePath.map((point, index) => {
|
|
5841
|
+
if (!pointsToMove.has(index)) return point;
|
|
5842
|
+
return orientation === "vertical" ? { ...point, x: coordinate } : { ...point, y: coordinate };
|
|
5843
|
+
})
|
|
5844
|
+
);
|
|
5845
|
+
return { ...trace, tracePath };
|
|
5846
|
+
};
|
|
5847
|
+
|
|
5743
5848
|
// lib/solvers/TraceCleanupSolver/sameNetRailAlignment/preservesLabelAnchors.ts
|
|
5744
5849
|
var getAnchoredTraceIds = (label, traces) => new Set(
|
|
5745
5850
|
traces.filter(
|
|
@@ -5855,10 +5960,10 @@ var projectPointToPath = (point, path) => {
|
|
|
5855
5960
|
let bestDistance = Number.POSITIVE_INFINITY;
|
|
5856
5961
|
for (let i = 0; i < path.length - 1; i++) {
|
|
5857
5962
|
const projectedPoint = projectPointToSegment(point, path[i], path[i + 1]);
|
|
5858
|
-
const
|
|
5859
|
-
if (
|
|
5963
|
+
const distance7 = getDistance2(point, projectedPoint);
|
|
5964
|
+
if (distance7 < bestDistance) {
|
|
5860
5965
|
bestPoint = projectedPoint;
|
|
5861
|
-
bestDistance =
|
|
5966
|
+
bestDistance = distance7;
|
|
5862
5967
|
}
|
|
5863
5968
|
}
|
|
5864
5969
|
return bestPoint;
|
|
@@ -5964,13 +6069,18 @@ var evaluateRailGroup = ({
|
|
|
5964
6069
|
const originalCoordinates = getDistinctCoordinates(
|
|
5965
6070
|
group.map((segment) => segment.coordinate)
|
|
5966
6071
|
);
|
|
6072
|
+
const fixedLabelCoordinate = getFixedLabelCoordinate(
|
|
6073
|
+
group,
|
|
6074
|
+
netLabelPlacements,
|
|
6075
|
+
traces
|
|
6076
|
+
);
|
|
5967
6077
|
const otherNetTraces = traces.filter(
|
|
5968
6078
|
(trace) => trace.globalConnNetId !== group[0].globalConnNetId
|
|
5969
6079
|
);
|
|
5970
6080
|
const immutableSameNetTraces = traces.filter(
|
|
5971
6081
|
(trace) => trace.globalConnNetId === group[0].globalConnNetId && !eligibleTraceIds.has(trace.mspPairId)
|
|
5972
6082
|
);
|
|
5973
|
-
const evaluateCoordinates = (coordinates) => {
|
|
6083
|
+
const evaluateCoordinates = (coordinates, options) => {
|
|
5974
6084
|
let best = null;
|
|
5975
6085
|
for (const coordinate of coordinates) {
|
|
5976
6086
|
const candidateMap = /* @__PURE__ */ new Map();
|
|
@@ -6006,7 +6116,9 @@ var evaluateRailGroup = ({
|
|
|
6006
6116
|
allCandidateTraces
|
|
6007
6117
|
);
|
|
6008
6118
|
if (metrics.otherNetCrossings > baseline.otherNetCrossings) continue;
|
|
6009
|
-
if (!isReadabilityImprovement(metrics, baseline))
|
|
6119
|
+
if (options?.coordinateIsFixedByLabel ? metrics.turnCount > baseline.turnCount : !isReadabilityImprovement(metrics, baseline)) {
|
|
6120
|
+
continue;
|
|
6121
|
+
}
|
|
6010
6122
|
const score = {
|
|
6011
6123
|
...metrics,
|
|
6012
6124
|
displacement: group.reduce(
|
|
@@ -6022,13 +6134,21 @@ var evaluateRailGroup = ({
|
|
|
6022
6134
|
return tracePathChanged(original, candidate2);
|
|
6023
6135
|
}).map((trace) => trace.mspPairId);
|
|
6024
6136
|
if (changedTraceIds.length === 0) continue;
|
|
6025
|
-
const candidate = {
|
|
6137
|
+
const candidate = {
|
|
6138
|
+
traces: allCandidateTraces,
|
|
6139
|
+
changedTraceIds,
|
|
6140
|
+
score
|
|
6141
|
+
};
|
|
6026
6142
|
if (!best || scoreIsBetter(candidate.score, best.score)) best = candidate;
|
|
6027
6143
|
}
|
|
6028
6144
|
return best;
|
|
6029
6145
|
};
|
|
6030
|
-
const originalCandidate = evaluateCoordinates(
|
|
6146
|
+
const originalCandidate = evaluateCoordinates(
|
|
6147
|
+
fixedLabelCoordinate === null ? originalCoordinates : [fixedLabelCoordinate],
|
|
6148
|
+
{ coordinateIsFixedByLabel: fixedLabelCoordinate !== null }
|
|
6149
|
+
);
|
|
6031
6150
|
if (originalCandidate) return originalCandidate;
|
|
6151
|
+
if (fixedLabelCoordinate !== null) return null;
|
|
6032
6152
|
return evaluateCoordinates(
|
|
6033
6153
|
getRailAlignmentFallbackCoordinates({
|
|
6034
6154
|
group,
|
|
@@ -6039,6 +6159,7 @@ var evaluateRailGroup = ({
|
|
|
6039
6159
|
};
|
|
6040
6160
|
|
|
6041
6161
|
// lib/solvers/TraceCleanupSolver/sameNetRailAlignment/getComponentSideRailSegments.ts
|
|
6162
|
+
import { distance as distance5 } from "@tscircuit/math-utils";
|
|
6042
6163
|
var getMovableRailSegments = (trace) => {
|
|
6043
6164
|
const segments = [];
|
|
6044
6165
|
const path = trace.tracePath;
|
|
@@ -6083,8 +6204,9 @@ var railIsOutsideComponent = (segment, chip, facingDirection) => {
|
|
|
6083
6204
|
return segment.orientation === "horizontal" && segment.coordinate <= minY + RAIL_ALIGNMENT_EPSILON;
|
|
6084
6205
|
}
|
|
6085
6206
|
};
|
|
6086
|
-
var getComponentSideRailSegments = (trace, chipMap) => {
|
|
6207
|
+
var getComponentSideRailSegments = (trace, chipMap, options) => {
|
|
6087
6208
|
const segments = [];
|
|
6209
|
+
const isLocalConnection = distance5(trace.pins[0], trace.pins[1]) <= (options?.maxMspPairDistance ?? DEFAULT_MAX_MSP_PAIR_DISTANCE);
|
|
6088
6210
|
for (const segment of getMovableRailSegments(trace)) {
|
|
6089
6211
|
const associations = trace.pins.flatMap((pin, pinIndex) => {
|
|
6090
6212
|
const chip = chipMap.get(pin.chipId);
|
|
@@ -6102,9 +6224,18 @@ var getComponentSideRailSegments = (trace, chipMap) => {
|
|
|
6102
6224
|
];
|
|
6103
6225
|
});
|
|
6104
6226
|
associations.sort((a, b) => a.distanceFromEndpoint - b.distanceFromEndpoint);
|
|
6105
|
-
const
|
|
6106
|
-
|
|
6107
|
-
|
|
6227
|
+
const minimumDistance = associations[0]?.distanceFromEndpoint;
|
|
6228
|
+
const nearestAssociationKeys = /* @__PURE__ */ new Set();
|
|
6229
|
+
for (const association of associations) {
|
|
6230
|
+
if (nearestAssociationKeys.size > 0 && (!options?.includeTiedEndpointAssociations || !isLocalConnection)) {
|
|
6231
|
+
break;
|
|
6232
|
+
}
|
|
6233
|
+
if (association.distanceFromEndpoint !== minimumDistance) continue;
|
|
6234
|
+
const associationKey = `${association.componentId}:${association.componentFacingDirection}`;
|
|
6235
|
+
if (nearestAssociationKeys.has(associationKey)) continue;
|
|
6236
|
+
nearestAssociationKeys.add(associationKey);
|
|
6237
|
+
segments.push({ ...segment, ...association });
|
|
6238
|
+
}
|
|
6108
6239
|
}
|
|
6109
6240
|
return segments;
|
|
6110
6241
|
};
|
|
@@ -6135,41 +6266,90 @@ var tracesSharePin = (a, b, traceMap) => {
|
|
|
6135
6266
|
return traceMap.get(b.traceId).pins.some((pin) => aPinIds.has(pin.pinId));
|
|
6136
6267
|
};
|
|
6137
6268
|
var canJoinRailGroup = (start, current, candidate, traceMap, obstacles) => candidate.globalConnNetId === start.globalConnNetId && candidate.orientation === start.orientation && candidate.componentId === start.componentId && candidate.componentFacingDirection === start.componentFacingDirection && (rangesTouchOrOverlap(current, candidate) || tracesSharePin(current, candidate, traceMap)) && corridorIsClear(current, candidate, obstacles);
|
|
6138
|
-
var getRailGroups = (traces, eligibleTraceIds, inputProblem, obstacles) => {
|
|
6269
|
+
var getRailGroups = (traces, eligibleTraceIds, inputProblem, obstacles, netLabelPlacements) => {
|
|
6139
6270
|
const chipMap = new Map(inputProblem.chips.map((chip) => [chip.chipId, chip]));
|
|
6140
|
-
const segments = traces.filter((trace) => eligibleTraceIds.has(trace.mspPairId)).flatMap((trace) => getComponentSideRailSegments(trace, chipMap));
|
|
6141
6271
|
const traceMap = new Map(traces.map((trace) => [trace.mspPairId, trace]));
|
|
6142
|
-
const
|
|
6143
|
-
|
|
6144
|
-
|
|
6145
|
-
|
|
6146
|
-
const
|
|
6147
|
-
const
|
|
6148
|
-
|
|
6149
|
-
|
|
6150
|
-
|
|
6151
|
-
const
|
|
6152
|
-
group
|
|
6153
|
-
|
|
6154
|
-
|
|
6155
|
-
const
|
|
6156
|
-
|
|
6157
|
-
|
|
6272
|
+
const eligibleTraces = traces.filter(
|
|
6273
|
+
(trace) => eligibleTraceIds.has(trace.mspPairId)
|
|
6274
|
+
);
|
|
6275
|
+
const collectConnectedGroups = (segments) => {
|
|
6276
|
+
const visited = /* @__PURE__ */ new Set();
|
|
6277
|
+
const connectedGroups = [];
|
|
6278
|
+
for (let startIndex = 0; startIndex < segments.length; startIndex++) {
|
|
6279
|
+
if (visited.has(startIndex)) continue;
|
|
6280
|
+
const start = segments[startIndex];
|
|
6281
|
+
const queue = [startIndex];
|
|
6282
|
+
const group = [];
|
|
6283
|
+
visited.add(startIndex);
|
|
6284
|
+
for (let queueIndex = 0; queueIndex < queue.length; queueIndex++) {
|
|
6285
|
+
const current = segments[queue[queueIndex]];
|
|
6286
|
+
group.push(current);
|
|
6287
|
+
for (let candidateIndex = 0; candidateIndex < segments.length; candidateIndex++) {
|
|
6288
|
+
if (visited.has(candidateIndex)) continue;
|
|
6289
|
+
const candidate = segments[candidateIndex];
|
|
6290
|
+
if (!canJoinRailGroup(start, current, candidate, traceMap, obstacles)) {
|
|
6291
|
+
continue;
|
|
6292
|
+
}
|
|
6293
|
+
visited.add(candidateIndex);
|
|
6294
|
+
queue.push(candidateIndex);
|
|
6158
6295
|
}
|
|
6159
|
-
visited.add(candidateIndex);
|
|
6160
|
-
queue.push(candidateIndex);
|
|
6161
6296
|
}
|
|
6297
|
+
connectedGroups.push(group);
|
|
6162
6298
|
}
|
|
6299
|
+
return connectedGroups;
|
|
6300
|
+
};
|
|
6301
|
+
const groupKey = (group) => [
|
|
6302
|
+
group[0].componentId,
|
|
6303
|
+
group[0].componentFacingDirection,
|
|
6304
|
+
group[0].orientation,
|
|
6305
|
+
...group.map((segment) => `${segment.traceId}:${segment.segmentIndex}`).sort()
|
|
6306
|
+
].join("|");
|
|
6307
|
+
const selectedGroups = [];
|
|
6308
|
+
const selectedGroupKeys = /* @__PURE__ */ new Set();
|
|
6309
|
+
const addEligibleGroup = (group, options) => {
|
|
6163
6310
|
const traceCount = new Set(group.map((segment) => segment.traceId)).size;
|
|
6311
|
+
if (traceCount < 2) return;
|
|
6312
|
+
const fixedLabelCoordinate = getFixedLabelCoordinate(
|
|
6313
|
+
group,
|
|
6314
|
+
netLabelPlacements,
|
|
6315
|
+
traces
|
|
6316
|
+
);
|
|
6317
|
+
if (options?.requireFixedLabel && fixedLabelCoordinate === null) return;
|
|
6164
6318
|
const hasDifferentCoordinates = group.some(
|
|
6165
6319
|
(segment) => !nearlyEqual(segment.coordinate, group[0].coordinate)
|
|
6166
6320
|
);
|
|
6167
|
-
|
|
6321
|
+
const hasDifferentFixedLabelCoordinate = fixedLabelCoordinate !== null && !nearlyEqual(fixedLabelCoordinate, group[0].coordinate);
|
|
6322
|
+
if (!hasDifferentCoordinates && !hasDifferentFixedLabelCoordinate) return;
|
|
6323
|
+
const key = groupKey(group);
|
|
6324
|
+
if (selectedGroupKeys.has(key)) return;
|
|
6325
|
+
selectedGroupKeys.add(key);
|
|
6326
|
+
selectedGroups.push(group);
|
|
6327
|
+
};
|
|
6328
|
+
const primarySegments = eligibleTraces.flatMap(
|
|
6329
|
+
(trace) => getComponentSideRailSegments(trace, chipMap)
|
|
6330
|
+
);
|
|
6331
|
+
for (const group of collectConnectedGroups(primarySegments)) {
|
|
6332
|
+
addEligibleGroup(group);
|
|
6333
|
+
}
|
|
6334
|
+
const tiedEndpointSegments = eligibleTraces.flatMap(
|
|
6335
|
+
(trace) => getComponentSideRailSegments(trace, chipMap, {
|
|
6336
|
+
includeTiedEndpointAssociations: true,
|
|
6337
|
+
maxMspPairDistance: inputProblem.maxMspPairDistance
|
|
6338
|
+
})
|
|
6339
|
+
);
|
|
6340
|
+
for (const group of collectConnectedGroups(tiedEndpointSegments)) {
|
|
6341
|
+
addEligibleGroup(group, { requireFixedLabel: true });
|
|
6168
6342
|
}
|
|
6169
|
-
return
|
|
6343
|
+
return selectedGroups;
|
|
6170
6344
|
};
|
|
6171
6345
|
|
|
6172
6346
|
// lib/solvers/TraceCleanupSolver/alignSameNetRails.ts
|
|
6347
|
+
var getTraceStateKey = (traces) => JSON.stringify(
|
|
6348
|
+
traces.map((trace) => ({
|
|
6349
|
+
mspPairId: trace.mspPairId,
|
|
6350
|
+
tracePath: trace.tracePath
|
|
6351
|
+
}))
|
|
6352
|
+
);
|
|
6173
6353
|
var alignSameNetRails = ({
|
|
6174
6354
|
inputProblem,
|
|
6175
6355
|
traces,
|
|
@@ -6177,6 +6357,7 @@ var alignSameNetRails = ({
|
|
|
6177
6357
|
eligibleTraceIds
|
|
6178
6358
|
}) => {
|
|
6179
6359
|
let outputTraces = [...traces];
|
|
6360
|
+
const seenTraceStates = /* @__PURE__ */ new Set([getTraceStateKey(outputTraces)]);
|
|
6180
6361
|
const obstacles = getObstacleRects(inputProblem);
|
|
6181
6362
|
const alignedTraceIds = /* @__PURE__ */ new Set();
|
|
6182
6363
|
let alignedRailGroupCount = 0;
|
|
@@ -6189,7 +6370,8 @@ var alignSameNetRails = ({
|
|
|
6189
6370
|
outputTraces,
|
|
6190
6371
|
eligibleTraceIds,
|
|
6191
6372
|
inputProblem,
|
|
6192
|
-
obstacles
|
|
6373
|
+
obstacles,
|
|
6374
|
+
netLabelPlacements
|
|
6193
6375
|
);
|
|
6194
6376
|
let applied = null;
|
|
6195
6377
|
for (const group of groups) {
|
|
@@ -6203,9 +6385,13 @@ var alignSameNetRails = ({
|
|
|
6203
6385
|
if (applied) break;
|
|
6204
6386
|
}
|
|
6205
6387
|
if (!applied) break;
|
|
6388
|
+
const candidateStateKey = getTraceStateKey(applied.traces);
|
|
6389
|
+
const repeatsSeenState = seenTraceStates.has(candidateStateKey);
|
|
6390
|
+
if (!repeatsSeenState) seenTraceStates.add(candidateStateKey);
|
|
6206
6391
|
outputTraces = applied.traces;
|
|
6207
6392
|
alignedRailGroupCount++;
|
|
6208
6393
|
for (const traceId of applied.changedTraceIds) alignedTraceIds.add(traceId);
|
|
6394
|
+
if (repeatsSeenState) break;
|
|
6209
6395
|
}
|
|
6210
6396
|
return {
|
|
6211
6397
|
traces: outputTraces,
|
|
@@ -7801,11 +7987,11 @@ var getLabelHugDistance = (tracePath, obstacleLabel) => {
|
|
|
7801
7987
|
obstacleLabel.width,
|
|
7802
7988
|
obstacleLabel.height
|
|
7803
7989
|
);
|
|
7804
|
-
let
|
|
7990
|
+
let distance7 = 0;
|
|
7805
7991
|
for (const point of tracePath) {
|
|
7806
|
-
|
|
7992
|
+
distance7 += getPointDistanceFromRect(point, bounds);
|
|
7807
7993
|
}
|
|
7808
|
-
return
|
|
7994
|
+
return distance7;
|
|
7809
7995
|
};
|
|
7810
7996
|
var getPointDistanceFromRect = (point, rect) => {
|
|
7811
7997
|
const dx = Math.max(rect.minX - point.x, 0, point.x - rect.maxX);
|
|
@@ -8082,16 +8268,16 @@ var Example28Solver = class extends BaseSolver {
|
|
|
8082
8268
|
const outward = dir(label.orientation);
|
|
8083
8269
|
if (outward.x === 0 && outward.y === 0) return null;
|
|
8084
8270
|
for (let step = 1; step <= LABEL_MAX_OUTWARD_STEPS; step++) {
|
|
8085
|
-
const
|
|
8271
|
+
const distance7 = step * LABEL_OUTWARD_STEP;
|
|
8086
8272
|
const candidate = {
|
|
8087
8273
|
...label,
|
|
8088
8274
|
anchorPoint: {
|
|
8089
|
-
x: label.anchorPoint.x + outward.x *
|
|
8090
|
-
y: label.anchorPoint.y + outward.y *
|
|
8275
|
+
x: label.anchorPoint.x + outward.x * distance7,
|
|
8276
|
+
y: label.anchorPoint.y + outward.y * distance7
|
|
8091
8277
|
},
|
|
8092
8278
|
center: {
|
|
8093
|
-
x: label.center.x + outward.x *
|
|
8094
|
-
y: label.center.y + outward.y *
|
|
8279
|
+
x: label.center.x + outward.x * distance7,
|
|
8280
|
+
y: label.center.y + outward.y * distance7
|
|
8095
8281
|
}
|
|
8096
8282
|
};
|
|
8097
8283
|
const candidateWithClearance = {
|
|
@@ -8960,10 +9146,8 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
|
|
|
8960
9146
|
}
|
|
8961
9147
|
findValidTraceAnchorCandidate(label, orientation, labelIndex) {
|
|
8962
9148
|
const direction = dir(orientation);
|
|
8963
|
-
const
|
|
8964
|
-
|
|
8965
|
-
orientation
|
|
8966
|
-
).sort((a, b) => {
|
|
9149
|
+
const { points } = this.getTraceAnchorCandidates(label, orientation);
|
|
9150
|
+
const candidatePoints = points.sort((a, b) => {
|
|
8967
9151
|
const aAlongDirection = a.x * direction.x + a.y * direction.y;
|
|
8968
9152
|
const bAlongDirection = b.x * direction.x + b.y * direction.y;
|
|
8969
9153
|
return bAlongDirection - aAlongDirection;
|
|
@@ -8986,19 +9170,19 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
|
|
|
8986
9170
|
}
|
|
8987
9171
|
findValidOutwardTraceAnchorCandidate(label, orientation, labelIndex) {
|
|
8988
9172
|
const direction = dir(orientation);
|
|
8989
|
-
const
|
|
8990
|
-
|
|
8991
|
-
|
|
8992
|
-
).sort((a, b) => {
|
|
9173
|
+
const preservedColumnAnchor = this.getSearchStartAnchor(label, orientation);
|
|
9174
|
+
const { points, preferNearestBendOnOutwardRow } = this.getTraceAnchorCandidates(label, orientation);
|
|
9175
|
+
const candidatePoints = points.sort((a, b) => {
|
|
8993
9176
|
const aAlongDirection = a.x * direction.x + a.y * direction.y;
|
|
8994
9177
|
const bAlongDirection = b.x * direction.x + b.y * direction.y;
|
|
8995
|
-
|
|
9178
|
+
if (!preferNearestBendOnOutwardRow) {
|
|
9179
|
+
return bAlongDirection - aAlongDirection;
|
|
9180
|
+
}
|
|
9181
|
+
const aPerpendicularDistance = isYOrientation(orientation) ? Math.abs(a.x - preservedColumnAnchor.x) : Math.abs(a.y - preservedColumnAnchor.y);
|
|
9182
|
+
const bPerpendicularDistance = isYOrientation(orientation) ? Math.abs(b.x - preservedColumnAnchor.x) : Math.abs(b.y - preservedColumnAnchor.y);
|
|
9183
|
+
return bAlongDirection - aAlongDirection || aPerpendicularDistance - bPerpendicularDistance;
|
|
8996
9184
|
});
|
|
8997
9185
|
for (const connectorSource of candidatePoints) {
|
|
8998
|
-
const preservedColumnAnchor = this.getSearchStartAnchor(
|
|
8999
|
-
label,
|
|
9000
|
-
orientation
|
|
9001
|
-
);
|
|
9002
9186
|
const preservedColumnCandidate = this.createCandidate(
|
|
9003
9187
|
label,
|
|
9004
9188
|
{
|
|
@@ -9024,10 +9208,10 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
|
|
|
9024
9208
|
orientation
|
|
9025
9209
|
);
|
|
9026
9210
|
if (outwardDirection.x === 0 && outwardDirection.y === 0) continue;
|
|
9027
|
-
for (let
|
|
9211
|
+
for (let distance7 = LABEL_SEARCH_STEP; distance7 <= this.maxSearchDistance + EPS12; distance7 += LABEL_SEARCH_STEP) {
|
|
9028
9212
|
const anchorPoint = {
|
|
9029
|
-
x: connectorSource.x + outwardDirection.x *
|
|
9030
|
-
y: connectorSource.y + outwardDirection.y *
|
|
9213
|
+
x: connectorSource.x + outwardDirection.x * distance7,
|
|
9214
|
+
y: connectorSource.y + outwardDirection.y * distance7
|
|
9031
9215
|
};
|
|
9032
9216
|
const candidate = this.createCandidate(
|
|
9033
9217
|
label,
|
|
@@ -9040,7 +9224,7 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
|
|
|
9040
9224
|
label,
|
|
9041
9225
|
labelIndex,
|
|
9042
9226
|
"outward-trace-anchor",
|
|
9043
|
-
|
|
9227
|
+
distance7
|
|
9044
9228
|
);
|
|
9045
9229
|
this.recordCandidateResult(result);
|
|
9046
9230
|
if (result.status === "valid") {
|
|
@@ -9051,10 +9235,11 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
|
|
|
9051
9235
|
}
|
|
9052
9236
|
return null;
|
|
9053
9237
|
}
|
|
9054
|
-
|
|
9238
|
+
getTraceAnchorCandidates(label, orientation) {
|
|
9055
9239
|
const seen = /* @__PURE__ */ new Set();
|
|
9056
9240
|
const points = [];
|
|
9057
|
-
const
|
|
9241
|
+
const directHostTraceIds = new Set(label.mspConnectionPairIds ?? []);
|
|
9242
|
+
const connectedTraceIds = new Set(directHostTraceIds);
|
|
9058
9243
|
if (isYOrientation(orientation)) {
|
|
9059
9244
|
const connectedPinIds = /* @__PURE__ */ new Set();
|
|
9060
9245
|
for (const traceId of connectedTraceIds) {
|
|
@@ -9094,7 +9279,39 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
|
|
|
9094
9279
|
points.push(point);
|
|
9095
9280
|
}
|
|
9096
9281
|
}
|
|
9097
|
-
|
|
9282
|
+
const direction = dir(orientation);
|
|
9283
|
+
const furthestAlong = Math.max(
|
|
9284
|
+
...points.map((point) => point.x * direction.x + point.y * direction.y)
|
|
9285
|
+
);
|
|
9286
|
+
const furthestRowPoints = points.filter(
|
|
9287
|
+
(point) => Math.abs(
|
|
9288
|
+
point.x * direction.x + point.y * direction.y - furthestAlong
|
|
9289
|
+
) <= EPS12
|
|
9290
|
+
);
|
|
9291
|
+
const directHostPinIds = new Set(
|
|
9292
|
+
[...directHostTraceIds].flatMap(
|
|
9293
|
+
(traceId) => this.traceMap[traceId]?.pinIds ?? []
|
|
9294
|
+
)
|
|
9295
|
+
);
|
|
9296
|
+
const adjacentTraces = [...connectedTraceIds].flatMap((traceId) => {
|
|
9297
|
+
if (directHostTraceIds.has(traceId)) return [];
|
|
9298
|
+
const trace = this.traceMap[traceId];
|
|
9299
|
+
if (!trace?.pinIds.some((pinId) => directHostPinIds.has(pinId))) return [];
|
|
9300
|
+
return [trace];
|
|
9301
|
+
});
|
|
9302
|
+
return {
|
|
9303
|
+
points,
|
|
9304
|
+
// Prefer the nearest bend when the outward row is on a trace directly
|
|
9305
|
+
// adjacent to the label's host. Deeper transitive chains keep their
|
|
9306
|
+
// stable trace ordering.
|
|
9307
|
+
preferNearestBendOnOutwardRow: adjacentTraces.some(
|
|
9308
|
+
(trace) => furthestRowPoints.some(
|
|
9309
|
+
(point) => trace.tracePath.some(
|
|
9310
|
+
(tracePoint) => Math.abs(tracePoint.x - point.x) <= EPS12 && Math.abs(tracePoint.y - point.y) <= EPS12
|
|
9311
|
+
)
|
|
9312
|
+
)
|
|
9313
|
+
)
|
|
9314
|
+
};
|
|
9098
9315
|
}
|
|
9099
9316
|
sharesVerticalRailWithAny(trace, otherTraces) {
|
|
9100
9317
|
const verticalRailXs = /* @__PURE__ */ new Set();
|
|
@@ -9203,10 +9420,10 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
|
|
|
9203
9420
|
phase = "shift",
|
|
9204
9421
|
stopOnTraceCollision = true
|
|
9205
9422
|
} = params;
|
|
9206
|
-
for (let
|
|
9423
|
+
for (let distance7 = LABEL_SEARCH_STEP; distance7 <= maxSearchDistance + EPS12; distance7 += LABEL_SEARCH_STEP) {
|
|
9207
9424
|
const anchorPoint = {
|
|
9208
|
-
x: baseAnchor.x + direction.x *
|
|
9209
|
-
y: baseAnchor.y + direction.y *
|
|
9425
|
+
x: baseAnchor.x + direction.x * distance7,
|
|
9426
|
+
y: baseAnchor.y + direction.y * distance7
|
|
9210
9427
|
};
|
|
9211
9428
|
const candidate = this.createCandidate(label, anchorPoint, orientation);
|
|
9212
9429
|
const result = this.evaluateCandidate(
|
|
@@ -9214,7 +9431,7 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
|
|
|
9214
9431
|
label,
|
|
9215
9432
|
labelIndex,
|
|
9216
9433
|
phase,
|
|
9217
|
-
|
|
9434
|
+
distance7,
|
|
9218
9435
|
outwardDistance
|
|
9219
9436
|
);
|
|
9220
9437
|
this.recordCandidateResult(result);
|
|
@@ -9226,11 +9443,11 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
|
|
|
9226
9443
|
}
|
|
9227
9444
|
return null;
|
|
9228
9445
|
}
|
|
9229
|
-
evaluateCandidate(candidate, label, labelIndex, phase,
|
|
9446
|
+
evaluateCandidate(candidate, label, labelIndex, phase, distance7, outwardDistance) {
|
|
9230
9447
|
return {
|
|
9231
9448
|
...candidate,
|
|
9232
9449
|
phase,
|
|
9233
|
-
distance:
|
|
9450
|
+
distance: distance7,
|
|
9234
9451
|
outwardDistance,
|
|
9235
9452
|
selected: false,
|
|
9236
9453
|
status: this.getCandidateStatus({
|
|
@@ -9736,10 +9953,10 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
|
|
|
9736
9953
|
if (point.x < bounds.minX - EPS12 || point.x > bounds.maxX + EPS12 || point.y < bounds.minY - EPS12 || point.y > bounds.maxY + EPS12) {
|
|
9737
9954
|
continue;
|
|
9738
9955
|
}
|
|
9739
|
-
for (const [side,
|
|
9740
|
-
if (
|
|
9956
|
+
for (const [side, distance7] of getSideDistances(point, bounds)) {
|
|
9957
|
+
if (distance7 < nearestDistance) {
|
|
9741
9958
|
nearestSide = side;
|
|
9742
|
-
nearestDistance =
|
|
9959
|
+
nearestDistance = distance7;
|
|
9743
9960
|
}
|
|
9744
9961
|
}
|
|
9745
9962
|
}
|
|
@@ -9768,10 +9985,10 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
|
|
|
9768
9985
|
let nearestSide = null;
|
|
9769
9986
|
let nearestDistance = Number.POSITIVE_INFINITY;
|
|
9770
9987
|
for (const chip of this.chipObstacleSpatialIndex.chips) {
|
|
9771
|
-
for (const [side,
|
|
9772
|
-
if (
|
|
9988
|
+
for (const [side, distance7] of getSideDistances(point, chip.bounds)) {
|
|
9989
|
+
if (distance7 < nearestDistance) {
|
|
9773
9990
|
nearestSide = side;
|
|
9774
|
-
nearestDistance =
|
|
9991
|
+
nearestDistance = distance7;
|
|
9775
9992
|
}
|
|
9776
9993
|
}
|
|
9777
9994
|
}
|
|
@@ -10354,17 +10571,17 @@ var getTraceLength = (trace) => {
|
|
|
10354
10571
|
}
|
|
10355
10572
|
return length;
|
|
10356
10573
|
};
|
|
10357
|
-
var getPointAtTraceDistance = (trace,
|
|
10574
|
+
var getPointAtTraceDistance = (trace, distance7) => {
|
|
10358
10575
|
let pathDistance = 0;
|
|
10359
10576
|
for (let i = 0; i < trace.tracePath.length - 1; i++) {
|
|
10360
10577
|
const start = trace.tracePath[i];
|
|
10361
10578
|
const end = trace.tracePath[i + 1];
|
|
10362
10579
|
const segmentLength = getManhattanDistance(start, end);
|
|
10363
10580
|
const nextDistance = pathDistance + segmentLength;
|
|
10364
|
-
if (
|
|
10581
|
+
if (distance7 <= nextDistance + EPS13) {
|
|
10365
10582
|
const offset = Math.max(
|
|
10366
10583
|
0,
|
|
10367
|
-
Math.min(segmentLength,
|
|
10584
|
+
Math.min(segmentLength, distance7 - pathDistance)
|
|
10368
10585
|
);
|
|
10369
10586
|
const direction = getSegmentDirection(start, end);
|
|
10370
10587
|
return {
|
|
@@ -10489,13 +10706,13 @@ var getCandidateDistances = (traceLength, vertexDistances) => {
|
|
|
10489
10706
|
const distances = /* @__PURE__ */ new Set();
|
|
10490
10707
|
const maxSteps = Math.ceil(traceLength / CANDIDATE_STEP);
|
|
10491
10708
|
for (let i = 0; i <= maxSteps; i++) {
|
|
10492
|
-
const
|
|
10493
|
-
distances.add(roundDistance(
|
|
10709
|
+
const distance7 = Math.min(traceLength, i * CANDIDATE_STEP);
|
|
10710
|
+
distances.add(roundDistance(distance7));
|
|
10494
10711
|
}
|
|
10495
|
-
for (const
|
|
10496
|
-
distances.add(roundDistance(
|
|
10712
|
+
for (const distance7 of vertexDistances) {
|
|
10713
|
+
distances.add(roundDistance(distance7));
|
|
10497
10714
|
}
|
|
10498
|
-
return [...distances].filter((
|
|
10715
|
+
return [...distances].filter((distance7) => distance7 >= -EPS13 && distance7 <= traceLength + EPS13).sort((a, b) => a - b);
|
|
10499
10716
|
};
|
|
10500
10717
|
var getOrientationsForPoint = (params) => {
|
|
10501
10718
|
const { inputProblem, label, point, orientationConstraint } = params;
|
|
@@ -10668,7 +10885,7 @@ var getNetLabelHeight = (inputProblem, label) => {
|
|
|
10668
10885
|
(nc) => nc.pinIds.some((pid) => label.pinIds.includes(pid))
|
|
10669
10886
|
)?.netLabelHeight;
|
|
10670
10887
|
};
|
|
10671
|
-
var roundDistance = (
|
|
10888
|
+
var roundDistance = (distance7) => Number(distance7.toFixed(6));
|
|
10672
10889
|
var isSamePlacement = (label, point, orientation) => Math.abs(point.x - label.anchorPoint.x) <= EPS13 && Math.abs(point.y - label.anchorPoint.y) <= EPS13 && orientation === label.orientation;
|
|
10673
10890
|
|
|
10674
10891
|
// lib/solvers/TraceAnchoredNetLabelOverlapSolver/visualize.ts
|
|
@@ -11649,7 +11866,7 @@ ${c.status}`
|
|
|
11649
11866
|
};
|
|
11650
11867
|
|
|
11651
11868
|
// lib/solvers/UnroutedTraceRecoverySolver/UnroutedTraceRecoverySolver.ts
|
|
11652
|
-
import { distance as
|
|
11869
|
+
import { distance as distance6, doSegmentsIntersect as doSegmentsIntersect3 } from "@tscircuit/math-utils";
|
|
11653
11870
|
var ROUTE_CLEARANCE = 0.2;
|
|
11654
11871
|
var COORDINATE_TOLERANCE = 1e-9;
|
|
11655
11872
|
var GROUND_NET_ID = "GND";
|
|
@@ -11811,7 +12028,7 @@ var getJunctionCandidates = ({
|
|
|
11811
12028
|
facingDirection: pin._facingDirection
|
|
11812
12029
|
});
|
|
11813
12030
|
for (const junctionPoint of junctionPoints) {
|
|
11814
|
-
if (
|
|
12031
|
+
if (distance6(pin, junctionPoint) > maxConnectionDistance) {
|
|
11815
12032
|
continue;
|
|
11816
12033
|
}
|
|
11817
12034
|
candidates.push(
|
|
@@ -12027,7 +12244,7 @@ var UnroutedTraceRecoverySolver = class extends BaseSolver {
|
|
|
12027
12244
|
if (connectionPair.globalConnNetId === this.groundGlobalConnNetId) {
|
|
12028
12245
|
return;
|
|
12029
12246
|
}
|
|
12030
|
-
if (
|
|
12247
|
+
if (distance6(connectionPair.pins[0], connectionPair.pins[1]) > this.maxConnectionDistance) {
|
|
12031
12248
|
return;
|
|
12032
12249
|
}
|
|
12033
12250
|
const obstacles = getObstacleRects(this.inputProblem);
|
|
@@ -13010,17 +13227,17 @@ var getRequiredOutwardDistance = (label, inlineBounds) => {
|
|
|
13010
13227
|
const targetMinY = Math.max(...nearby.map((bounds) => bounds.maxY));
|
|
13011
13228
|
return Math.max(0, targetMinY - labelBounds.minY + LABEL_CLEARANCE2);
|
|
13012
13229
|
};
|
|
13013
|
-
var moveLabel = (label, orientation,
|
|
13230
|
+
var moveLabel = (label, orientation, distance7) => {
|
|
13014
13231
|
const direction = dir(orientation);
|
|
13015
13232
|
return {
|
|
13016
13233
|
...label,
|
|
13017
13234
|
anchorPoint: {
|
|
13018
|
-
x: label.anchorPoint.x + direction.x *
|
|
13019
|
-
y: label.anchorPoint.y + direction.y *
|
|
13235
|
+
x: label.anchorPoint.x + direction.x * distance7,
|
|
13236
|
+
y: label.anchorPoint.y + direction.y * distance7
|
|
13020
13237
|
},
|
|
13021
13238
|
center: {
|
|
13022
|
-
x: label.center.x + direction.x *
|
|
13023
|
-
y: label.center.y + direction.y *
|
|
13239
|
+
x: label.center.x + direction.x * distance7,
|
|
13240
|
+
y: label.center.y + direction.y * distance7
|
|
13024
13241
|
}
|
|
13025
13242
|
};
|
|
13026
13243
|
};
|
|
@@ -13145,15 +13362,15 @@ var pushAnchoredNetLabelsAwayFromInlineLabels = ({
|
|
|
13145
13362
|
const movedLabelIndices = /* @__PURE__ */ new Set();
|
|
13146
13363
|
for (let triggerIndex = 0; triggerIndex < outputLabels.length; triggerIndex++) {
|
|
13147
13364
|
const trigger = outputLabels[triggerIndex];
|
|
13148
|
-
const
|
|
13149
|
-
if (
|
|
13365
|
+
const distance7 = getRequiredOutwardDistance(trigger, inlineBounds);
|
|
13366
|
+
if (distance7 <= POINT_EPSILON || distance7 > MAX_OUTWARD_DISTANCE) continue;
|
|
13150
13367
|
const { group, ownerChipIds } = getContiguousLabelGroup({
|
|
13151
13368
|
triggerIndex,
|
|
13152
13369
|
labels: outputLabels,
|
|
13153
13370
|
chipIdByPinId
|
|
13154
13371
|
});
|
|
13155
13372
|
const distances = new Map(
|
|
13156
|
-
[...group].map((labelIndex) => [labelIndex,
|
|
13373
|
+
[...group].map((labelIndex) => [labelIndex, distance7])
|
|
13157
13374
|
);
|
|
13158
13375
|
let failed = false;
|
|
13159
13376
|
for (let iteration = 0; iteration < outputLabels.length; iteration++) {
|