@tscircuit/schematic-trace-solver 0.0.153 → 0.0.155
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 +1 -1
- package/dist/index.js +354 -118
- package/lib/solvers/AvailableNetOrientationSolver/AvailableNetOrientationSolver.ts +60 -16
- package/lib/solvers/SameNetJunctionAlignmentSolver/alignSameNetJunctions.ts +81 -8
- 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-20260825T103621Z.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-20260825T103621Z/__snapshots__/bug-report-20260825T103621Z.snap.svg +452 -0
- package/tests/bug-reports/bug-report-20260825T103621Z/bug-report-20260825T103621Z.json +1696 -0
- package/tests/bug-reports/bug-report-20260825T103621Z/bug-report-20260825T103621Z.test.ts +12 -0
- package/tests/examples/__snapshots__/example51.snap.svg +2 -2
- package/tests/repros/__snapshots__/repro-pga300-c6-trace-alignment.snap.svg +88 -0
- package/tests/repros/__snapshots__/repro-ti-power-output-section.snap.svg +45 -45
- package/tests/repros/assets/repro-pga300-c6-trace-alignment.input.json +97 -0
- package/tests/repros/repro-pga300-c6-trace-alignment.test.ts +36 -0
package/dist/index.js
CHANGED
|
@@ -5690,22 +5690,8 @@ var getRailAlignmentFallbackCoordinates = ({
|
|
|
5690
5690
|
return getDistinctCoordinates(coordinates);
|
|
5691
5691
|
};
|
|
5692
5692
|
|
|
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
|
-
};
|
|
5693
|
+
// lib/solvers/TraceCleanupSolver/sameNetRailAlignment/getFixedLabelCoordinate.ts
|
|
5694
|
+
import { distance as distance4 } from "@tscircuit/math-utils";
|
|
5709
5695
|
|
|
5710
5696
|
// lib/solvers/RailNetLabelCornerPlacementSolver/geometry.ts
|
|
5711
5697
|
var EPS7 = 1e-6;
|
|
@@ -5740,6 +5726,95 @@ var isPointOnSegment = (point, start, end) => {
|
|
|
5740
5726
|
};
|
|
5741
5727
|
var getSegmentOrientation = (a, b) => Math.abs(a.y - b.y) <= EPS7 ? "horizontal" : "vertical";
|
|
5742
5728
|
|
|
5729
|
+
// lib/solvers/TraceCleanupSolver/sameNetRailAlignment/getFixedLabelCoordinate.ts
|
|
5730
|
+
var getTransitivelyConnectedTraceIds = (group, traces) => {
|
|
5731
|
+
const groupNetId = group[0].globalConnNetId;
|
|
5732
|
+
const sameNetTraces = traces.filter(
|
|
5733
|
+
(trace) => trace.globalConnNetId === groupNetId
|
|
5734
|
+
);
|
|
5735
|
+
const connectedTraceIds = new Set(group.map((segment) => segment.traceId));
|
|
5736
|
+
const connectedPinIds = new Set(
|
|
5737
|
+
sameNetTraces.filter((trace) => connectedTraceIds.has(trace.mspPairId)).flatMap((trace) => trace.pinIds)
|
|
5738
|
+
);
|
|
5739
|
+
for (let changed = true; changed; ) {
|
|
5740
|
+
changed = false;
|
|
5741
|
+
for (const trace of sameNetTraces) {
|
|
5742
|
+
if (connectedTraceIds.has(trace.mspPairId)) continue;
|
|
5743
|
+
if (!trace.pinIds.some((pinId) => connectedPinIds.has(pinId))) continue;
|
|
5744
|
+
connectedTraceIds.add(trace.mspPairId);
|
|
5745
|
+
for (const pinId of trace.pinIds) connectedPinIds.add(pinId);
|
|
5746
|
+
changed = true;
|
|
5747
|
+
}
|
|
5748
|
+
}
|
|
5749
|
+
return connectedTraceIds;
|
|
5750
|
+
};
|
|
5751
|
+
var getLabelsLinkedToRailGroup = (group, netLabelPlacements, traces) => {
|
|
5752
|
+
const traceIds = getTransitivelyConnectedTraceIds(group, traces);
|
|
5753
|
+
return netLabelPlacements.filter(
|
|
5754
|
+
(label) => label.mspConnectionPairIds.some((traceId) => traceIds.has(traceId))
|
|
5755
|
+
);
|
|
5756
|
+
};
|
|
5757
|
+
var getFixedLabelCoordinate = (group, netLabelPlacements, traces) => {
|
|
5758
|
+
const traceMap = new Map(traces.map((trace) => [trace.mspPairId, trace]));
|
|
5759
|
+
const groupTraceIds = new Set(group.map((segment) => segment.traceId));
|
|
5760
|
+
const groupHasOnlySingleRailTraces = [...groupTraceIds].every(
|
|
5761
|
+
(traceId) => traceMap.get(traceId)?.tracePath.length === 4
|
|
5762
|
+
);
|
|
5763
|
+
if (!groupHasOnlySingleRailTraces) return null;
|
|
5764
|
+
const orientation = group[0].orientation;
|
|
5765
|
+
const linkedLabels = getLabelsLinkedToRailGroup(
|
|
5766
|
+
group,
|
|
5767
|
+
netLabelPlacements,
|
|
5768
|
+
traces
|
|
5769
|
+
);
|
|
5770
|
+
const anchoringLabels = linkedLabels.filter(
|
|
5771
|
+
(label) => label.orientation === group[0].componentFacingDirection && label.mspConnectionPairIds.some((traceId) => {
|
|
5772
|
+
const trace = traceMap.get(traceId);
|
|
5773
|
+
return trace && tracePathContainsPoint(trace.tracePath, label.anchorPoint);
|
|
5774
|
+
})
|
|
5775
|
+
);
|
|
5776
|
+
const coordinates = getDistinctCoordinates(
|
|
5777
|
+
anchoringLabels.map(
|
|
5778
|
+
(label) => orientation === "vertical" ? label.anchorPoint.x : label.anchorPoint.y
|
|
5779
|
+
)
|
|
5780
|
+
);
|
|
5781
|
+
if (coordinates.length !== 1) return null;
|
|
5782
|
+
const labelCoordinate = coordinates[0];
|
|
5783
|
+
const coordinate = group.find(
|
|
5784
|
+
(segment) => Math.abs(segment.coordinate - labelCoordinate) <= RAIL_ALIGNMENT_EPSILON
|
|
5785
|
+
)?.coordinate ?? labelCoordinate;
|
|
5786
|
+
const labelIsAnchoredToRoutedBackbone = anchoringLabels.some(
|
|
5787
|
+
(label) => label.mspConnectionPairIds.some(
|
|
5788
|
+
(traceId) => (traceMap.get(traceId)?.tracePath.length ?? 0) > 4
|
|
5789
|
+
)
|
|
5790
|
+
);
|
|
5791
|
+
if (labelIsAnchoredToRoutedBackbone) return coordinate;
|
|
5792
|
+
const coordinateIsLocalToEveryTrace = group.every((segment) => {
|
|
5793
|
+
const trace = traceMap.get(segment.traceId);
|
|
5794
|
+
if (!trace) return false;
|
|
5795
|
+
return Math.abs(segment.coordinate - coordinate) <= distance4(trace.pins[0], trace.pins[1]) + RAIL_ALIGNMENT_EPSILON;
|
|
5796
|
+
});
|
|
5797
|
+
return coordinateIsLocalToEveryTrace ? coordinate : null;
|
|
5798
|
+
};
|
|
5799
|
+
|
|
5800
|
+
// lib/solvers/TraceCleanupSolver/sameNetRailAlignment/moveRailSegments.ts
|
|
5801
|
+
var moveRailSegments = (trace, segments, coordinate) => {
|
|
5802
|
+
const pointsToMove = /* @__PURE__ */ new Set();
|
|
5803
|
+
for (const segment of segments) {
|
|
5804
|
+
if (nearlyEqual(segment.coordinate, coordinate)) continue;
|
|
5805
|
+
pointsToMove.add(segment.segmentIndex);
|
|
5806
|
+
pointsToMove.add(segment.segmentIndex + 1);
|
|
5807
|
+
}
|
|
5808
|
+
const orientation = segments[0].orientation;
|
|
5809
|
+
const tracePath = simplifyPath(
|
|
5810
|
+
trace.tracePath.map((point, index) => {
|
|
5811
|
+
if (!pointsToMove.has(index)) return point;
|
|
5812
|
+
return orientation === "vertical" ? { ...point, x: coordinate } : { ...point, y: coordinate };
|
|
5813
|
+
})
|
|
5814
|
+
);
|
|
5815
|
+
return { ...trace, tracePath };
|
|
5816
|
+
};
|
|
5817
|
+
|
|
5743
5818
|
// lib/solvers/TraceCleanupSolver/sameNetRailAlignment/preservesLabelAnchors.ts
|
|
5744
5819
|
var getAnchoredTraceIds = (label, traces) => new Set(
|
|
5745
5820
|
traces.filter(
|
|
@@ -5855,10 +5930,10 @@ var projectPointToPath = (point, path) => {
|
|
|
5855
5930
|
let bestDistance = Number.POSITIVE_INFINITY;
|
|
5856
5931
|
for (let i = 0; i < path.length - 1; i++) {
|
|
5857
5932
|
const projectedPoint = projectPointToSegment(point, path[i], path[i + 1]);
|
|
5858
|
-
const
|
|
5859
|
-
if (
|
|
5933
|
+
const distance7 = getDistance2(point, projectedPoint);
|
|
5934
|
+
if (distance7 < bestDistance) {
|
|
5860
5935
|
bestPoint = projectedPoint;
|
|
5861
|
-
bestDistance =
|
|
5936
|
+
bestDistance = distance7;
|
|
5862
5937
|
}
|
|
5863
5938
|
}
|
|
5864
5939
|
return bestPoint;
|
|
@@ -5964,13 +6039,18 @@ var evaluateRailGroup = ({
|
|
|
5964
6039
|
const originalCoordinates = getDistinctCoordinates(
|
|
5965
6040
|
group.map((segment) => segment.coordinate)
|
|
5966
6041
|
);
|
|
6042
|
+
const fixedLabelCoordinate = getFixedLabelCoordinate(
|
|
6043
|
+
group,
|
|
6044
|
+
netLabelPlacements,
|
|
6045
|
+
traces
|
|
6046
|
+
);
|
|
5967
6047
|
const otherNetTraces = traces.filter(
|
|
5968
6048
|
(trace) => trace.globalConnNetId !== group[0].globalConnNetId
|
|
5969
6049
|
);
|
|
5970
6050
|
const immutableSameNetTraces = traces.filter(
|
|
5971
6051
|
(trace) => trace.globalConnNetId === group[0].globalConnNetId && !eligibleTraceIds.has(trace.mspPairId)
|
|
5972
6052
|
);
|
|
5973
|
-
const evaluateCoordinates = (coordinates) => {
|
|
6053
|
+
const evaluateCoordinates = (coordinates, options) => {
|
|
5974
6054
|
let best = null;
|
|
5975
6055
|
for (const coordinate of coordinates) {
|
|
5976
6056
|
const candidateMap = /* @__PURE__ */ new Map();
|
|
@@ -6006,7 +6086,9 @@ var evaluateRailGroup = ({
|
|
|
6006
6086
|
allCandidateTraces
|
|
6007
6087
|
);
|
|
6008
6088
|
if (metrics.otherNetCrossings > baseline.otherNetCrossings) continue;
|
|
6009
|
-
if (!isReadabilityImprovement(metrics, baseline))
|
|
6089
|
+
if (options?.coordinateIsFixedByLabel ? metrics.turnCount > baseline.turnCount : !isReadabilityImprovement(metrics, baseline)) {
|
|
6090
|
+
continue;
|
|
6091
|
+
}
|
|
6010
6092
|
const score = {
|
|
6011
6093
|
...metrics,
|
|
6012
6094
|
displacement: group.reduce(
|
|
@@ -6022,13 +6104,21 @@ var evaluateRailGroup = ({
|
|
|
6022
6104
|
return tracePathChanged(original, candidate2);
|
|
6023
6105
|
}).map((trace) => trace.mspPairId);
|
|
6024
6106
|
if (changedTraceIds.length === 0) continue;
|
|
6025
|
-
const candidate = {
|
|
6107
|
+
const candidate = {
|
|
6108
|
+
traces: allCandidateTraces,
|
|
6109
|
+
changedTraceIds,
|
|
6110
|
+
score
|
|
6111
|
+
};
|
|
6026
6112
|
if (!best || scoreIsBetter(candidate.score, best.score)) best = candidate;
|
|
6027
6113
|
}
|
|
6028
6114
|
return best;
|
|
6029
6115
|
};
|
|
6030
|
-
const originalCandidate = evaluateCoordinates(
|
|
6116
|
+
const originalCandidate = evaluateCoordinates(
|
|
6117
|
+
fixedLabelCoordinate === null ? originalCoordinates : [fixedLabelCoordinate],
|
|
6118
|
+
{ coordinateIsFixedByLabel: fixedLabelCoordinate !== null }
|
|
6119
|
+
);
|
|
6031
6120
|
if (originalCandidate) return originalCandidate;
|
|
6121
|
+
if (fixedLabelCoordinate !== null) return null;
|
|
6032
6122
|
return evaluateCoordinates(
|
|
6033
6123
|
getRailAlignmentFallbackCoordinates({
|
|
6034
6124
|
group,
|
|
@@ -6039,6 +6129,7 @@ var evaluateRailGroup = ({
|
|
|
6039
6129
|
};
|
|
6040
6130
|
|
|
6041
6131
|
// lib/solvers/TraceCleanupSolver/sameNetRailAlignment/getComponentSideRailSegments.ts
|
|
6132
|
+
import { distance as distance5 } from "@tscircuit/math-utils";
|
|
6042
6133
|
var getMovableRailSegments = (trace) => {
|
|
6043
6134
|
const segments = [];
|
|
6044
6135
|
const path = trace.tracePath;
|
|
@@ -6083,8 +6174,9 @@ var railIsOutsideComponent = (segment, chip, facingDirection) => {
|
|
|
6083
6174
|
return segment.orientation === "horizontal" && segment.coordinate <= minY + RAIL_ALIGNMENT_EPSILON;
|
|
6084
6175
|
}
|
|
6085
6176
|
};
|
|
6086
|
-
var getComponentSideRailSegments = (trace, chipMap) => {
|
|
6177
|
+
var getComponentSideRailSegments = (trace, chipMap, options) => {
|
|
6087
6178
|
const segments = [];
|
|
6179
|
+
const isLocalConnection = distance5(trace.pins[0], trace.pins[1]) <= (options?.maxMspPairDistance ?? DEFAULT_MAX_MSP_PAIR_DISTANCE);
|
|
6088
6180
|
for (const segment of getMovableRailSegments(trace)) {
|
|
6089
6181
|
const associations = trace.pins.flatMap((pin, pinIndex) => {
|
|
6090
6182
|
const chip = chipMap.get(pin.chipId);
|
|
@@ -6102,9 +6194,18 @@ var getComponentSideRailSegments = (trace, chipMap) => {
|
|
|
6102
6194
|
];
|
|
6103
6195
|
});
|
|
6104
6196
|
associations.sort((a, b) => a.distanceFromEndpoint - b.distanceFromEndpoint);
|
|
6105
|
-
const
|
|
6106
|
-
|
|
6107
|
-
|
|
6197
|
+
const minimumDistance = associations[0]?.distanceFromEndpoint;
|
|
6198
|
+
const nearestAssociationKeys = /* @__PURE__ */ new Set();
|
|
6199
|
+
for (const association of associations) {
|
|
6200
|
+
if (nearestAssociationKeys.size > 0 && (!options?.includeTiedEndpointAssociations || !isLocalConnection)) {
|
|
6201
|
+
break;
|
|
6202
|
+
}
|
|
6203
|
+
if (association.distanceFromEndpoint !== minimumDistance) continue;
|
|
6204
|
+
const associationKey = `${association.componentId}:${association.componentFacingDirection}`;
|
|
6205
|
+
if (nearestAssociationKeys.has(associationKey)) continue;
|
|
6206
|
+
nearestAssociationKeys.add(associationKey);
|
|
6207
|
+
segments.push({ ...segment, ...association });
|
|
6208
|
+
}
|
|
6108
6209
|
}
|
|
6109
6210
|
return segments;
|
|
6110
6211
|
};
|
|
@@ -6135,41 +6236,90 @@ var tracesSharePin = (a, b, traceMap) => {
|
|
|
6135
6236
|
return traceMap.get(b.traceId).pins.some((pin) => aPinIds.has(pin.pinId));
|
|
6136
6237
|
};
|
|
6137
6238
|
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) => {
|
|
6239
|
+
var getRailGroups = (traces, eligibleTraceIds, inputProblem, obstacles, netLabelPlacements) => {
|
|
6139
6240
|
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
6241
|
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
|
-
|
|
6242
|
+
const eligibleTraces = traces.filter(
|
|
6243
|
+
(trace) => eligibleTraceIds.has(trace.mspPairId)
|
|
6244
|
+
);
|
|
6245
|
+
const collectConnectedGroups = (segments) => {
|
|
6246
|
+
const visited = /* @__PURE__ */ new Set();
|
|
6247
|
+
const connectedGroups = [];
|
|
6248
|
+
for (let startIndex = 0; startIndex < segments.length; startIndex++) {
|
|
6249
|
+
if (visited.has(startIndex)) continue;
|
|
6250
|
+
const start = segments[startIndex];
|
|
6251
|
+
const queue = [startIndex];
|
|
6252
|
+
const group = [];
|
|
6253
|
+
visited.add(startIndex);
|
|
6254
|
+
for (let queueIndex = 0; queueIndex < queue.length; queueIndex++) {
|
|
6255
|
+
const current = segments[queue[queueIndex]];
|
|
6256
|
+
group.push(current);
|
|
6257
|
+
for (let candidateIndex = 0; candidateIndex < segments.length; candidateIndex++) {
|
|
6258
|
+
if (visited.has(candidateIndex)) continue;
|
|
6259
|
+
const candidate = segments[candidateIndex];
|
|
6260
|
+
if (!canJoinRailGroup(start, current, candidate, traceMap, obstacles)) {
|
|
6261
|
+
continue;
|
|
6262
|
+
}
|
|
6263
|
+
visited.add(candidateIndex);
|
|
6264
|
+
queue.push(candidateIndex);
|
|
6158
6265
|
}
|
|
6159
|
-
visited.add(candidateIndex);
|
|
6160
|
-
queue.push(candidateIndex);
|
|
6161
6266
|
}
|
|
6267
|
+
connectedGroups.push(group);
|
|
6162
6268
|
}
|
|
6269
|
+
return connectedGroups;
|
|
6270
|
+
};
|
|
6271
|
+
const groupKey = (group) => [
|
|
6272
|
+
group[0].componentId,
|
|
6273
|
+
group[0].componentFacingDirection,
|
|
6274
|
+
group[0].orientation,
|
|
6275
|
+
...group.map((segment) => `${segment.traceId}:${segment.segmentIndex}`).sort()
|
|
6276
|
+
].join("|");
|
|
6277
|
+
const selectedGroups = [];
|
|
6278
|
+
const selectedGroupKeys = /* @__PURE__ */ new Set();
|
|
6279
|
+
const addEligibleGroup = (group, options) => {
|
|
6163
6280
|
const traceCount = new Set(group.map((segment) => segment.traceId)).size;
|
|
6281
|
+
if (traceCount < 2) return;
|
|
6282
|
+
const fixedLabelCoordinate = getFixedLabelCoordinate(
|
|
6283
|
+
group,
|
|
6284
|
+
netLabelPlacements,
|
|
6285
|
+
traces
|
|
6286
|
+
);
|
|
6287
|
+
if (options?.requireFixedLabel && fixedLabelCoordinate === null) return;
|
|
6164
6288
|
const hasDifferentCoordinates = group.some(
|
|
6165
6289
|
(segment) => !nearlyEqual(segment.coordinate, group[0].coordinate)
|
|
6166
6290
|
);
|
|
6167
|
-
|
|
6291
|
+
const hasDifferentFixedLabelCoordinate = fixedLabelCoordinate !== null && !nearlyEqual(fixedLabelCoordinate, group[0].coordinate);
|
|
6292
|
+
if (!hasDifferentCoordinates && !hasDifferentFixedLabelCoordinate) return;
|
|
6293
|
+
const key = groupKey(group);
|
|
6294
|
+
if (selectedGroupKeys.has(key)) return;
|
|
6295
|
+
selectedGroupKeys.add(key);
|
|
6296
|
+
selectedGroups.push(group);
|
|
6297
|
+
};
|
|
6298
|
+
const primarySegments = eligibleTraces.flatMap(
|
|
6299
|
+
(trace) => getComponentSideRailSegments(trace, chipMap)
|
|
6300
|
+
);
|
|
6301
|
+
for (const group of collectConnectedGroups(primarySegments)) {
|
|
6302
|
+
addEligibleGroup(group);
|
|
6303
|
+
}
|
|
6304
|
+
const tiedEndpointSegments = eligibleTraces.flatMap(
|
|
6305
|
+
(trace) => getComponentSideRailSegments(trace, chipMap, {
|
|
6306
|
+
includeTiedEndpointAssociations: true,
|
|
6307
|
+
maxMspPairDistance: inputProblem.maxMspPairDistance
|
|
6308
|
+
})
|
|
6309
|
+
);
|
|
6310
|
+
for (const group of collectConnectedGroups(tiedEndpointSegments)) {
|
|
6311
|
+
addEligibleGroup(group, { requireFixedLabel: true });
|
|
6168
6312
|
}
|
|
6169
|
-
return
|
|
6313
|
+
return selectedGroups;
|
|
6170
6314
|
};
|
|
6171
6315
|
|
|
6172
6316
|
// lib/solvers/TraceCleanupSolver/alignSameNetRails.ts
|
|
6317
|
+
var getTraceStateKey = (traces) => JSON.stringify(
|
|
6318
|
+
traces.map((trace) => ({
|
|
6319
|
+
mspPairId: trace.mspPairId,
|
|
6320
|
+
tracePath: trace.tracePath
|
|
6321
|
+
}))
|
|
6322
|
+
);
|
|
6173
6323
|
var alignSameNetRails = ({
|
|
6174
6324
|
inputProblem,
|
|
6175
6325
|
traces,
|
|
@@ -6177,6 +6327,7 @@ var alignSameNetRails = ({
|
|
|
6177
6327
|
eligibleTraceIds
|
|
6178
6328
|
}) => {
|
|
6179
6329
|
let outputTraces = [...traces];
|
|
6330
|
+
const seenTraceStates = /* @__PURE__ */ new Set([getTraceStateKey(outputTraces)]);
|
|
6180
6331
|
const obstacles = getObstacleRects(inputProblem);
|
|
6181
6332
|
const alignedTraceIds = /* @__PURE__ */ new Set();
|
|
6182
6333
|
let alignedRailGroupCount = 0;
|
|
@@ -6189,7 +6340,8 @@ var alignSameNetRails = ({
|
|
|
6189
6340
|
outputTraces,
|
|
6190
6341
|
eligibleTraceIds,
|
|
6191
6342
|
inputProblem,
|
|
6192
|
-
obstacles
|
|
6343
|
+
obstacles,
|
|
6344
|
+
netLabelPlacements
|
|
6193
6345
|
);
|
|
6194
6346
|
let applied = null;
|
|
6195
6347
|
for (const group of groups) {
|
|
@@ -6203,9 +6355,13 @@ var alignSameNetRails = ({
|
|
|
6203
6355
|
if (applied) break;
|
|
6204
6356
|
}
|
|
6205
6357
|
if (!applied) break;
|
|
6358
|
+
const candidateStateKey = getTraceStateKey(applied.traces);
|
|
6359
|
+
const repeatsSeenState = seenTraceStates.has(candidateStateKey);
|
|
6360
|
+
if (!repeatsSeenState) seenTraceStates.add(candidateStateKey);
|
|
6206
6361
|
outputTraces = applied.traces;
|
|
6207
6362
|
alignedRailGroupCount++;
|
|
6208
6363
|
for (const traceId of applied.changedTraceIds) alignedTraceIds.add(traceId);
|
|
6364
|
+
if (repeatsSeenState) break;
|
|
6209
6365
|
}
|
|
6210
6366
|
return {
|
|
6211
6367
|
traces: outputTraces,
|
|
@@ -7801,11 +7957,11 @@ var getLabelHugDistance = (tracePath, obstacleLabel) => {
|
|
|
7801
7957
|
obstacleLabel.width,
|
|
7802
7958
|
obstacleLabel.height
|
|
7803
7959
|
);
|
|
7804
|
-
let
|
|
7960
|
+
let distance7 = 0;
|
|
7805
7961
|
for (const point of tracePath) {
|
|
7806
|
-
|
|
7962
|
+
distance7 += getPointDistanceFromRect(point, bounds);
|
|
7807
7963
|
}
|
|
7808
|
-
return
|
|
7964
|
+
return distance7;
|
|
7809
7965
|
};
|
|
7810
7966
|
var getPointDistanceFromRect = (point, rect) => {
|
|
7811
7967
|
const dx = Math.max(rect.minX - point.x, 0, point.x - rect.maxX);
|
|
@@ -8082,16 +8238,16 @@ var Example28Solver = class extends BaseSolver {
|
|
|
8082
8238
|
const outward = dir(label.orientation);
|
|
8083
8239
|
if (outward.x === 0 && outward.y === 0) return null;
|
|
8084
8240
|
for (let step = 1; step <= LABEL_MAX_OUTWARD_STEPS; step++) {
|
|
8085
|
-
const
|
|
8241
|
+
const distance7 = step * LABEL_OUTWARD_STEP;
|
|
8086
8242
|
const candidate = {
|
|
8087
8243
|
...label,
|
|
8088
8244
|
anchorPoint: {
|
|
8089
|
-
x: label.anchorPoint.x + outward.x *
|
|
8090
|
-
y: label.anchorPoint.y + outward.y *
|
|
8245
|
+
x: label.anchorPoint.x + outward.x * distance7,
|
|
8246
|
+
y: label.anchorPoint.y + outward.y * distance7
|
|
8091
8247
|
},
|
|
8092
8248
|
center: {
|
|
8093
|
-
x: label.center.x + outward.x *
|
|
8094
|
-
y: label.center.y + outward.y *
|
|
8249
|
+
x: label.center.x + outward.x * distance7,
|
|
8250
|
+
y: label.center.y + outward.y * distance7
|
|
8095
8251
|
}
|
|
8096
8252
|
};
|
|
8097
8253
|
const candidateWithClearance = {
|
|
@@ -8960,10 +9116,8 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
|
|
|
8960
9116
|
}
|
|
8961
9117
|
findValidTraceAnchorCandidate(label, orientation, labelIndex) {
|
|
8962
9118
|
const direction = dir(orientation);
|
|
8963
|
-
const
|
|
8964
|
-
|
|
8965
|
-
orientation
|
|
8966
|
-
).sort((a, b) => {
|
|
9119
|
+
const { points } = this.getTraceAnchorCandidates(label, orientation);
|
|
9120
|
+
const candidatePoints = points.sort((a, b) => {
|
|
8967
9121
|
const aAlongDirection = a.x * direction.x + a.y * direction.y;
|
|
8968
9122
|
const bAlongDirection = b.x * direction.x + b.y * direction.y;
|
|
8969
9123
|
return bAlongDirection - aAlongDirection;
|
|
@@ -8986,19 +9140,19 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
|
|
|
8986
9140
|
}
|
|
8987
9141
|
findValidOutwardTraceAnchorCandidate(label, orientation, labelIndex) {
|
|
8988
9142
|
const direction = dir(orientation);
|
|
8989
|
-
const
|
|
8990
|
-
|
|
8991
|
-
|
|
8992
|
-
).sort((a, b) => {
|
|
9143
|
+
const preservedColumnAnchor = this.getSearchStartAnchor(label, orientation);
|
|
9144
|
+
const { points, preferNearestBendOnOutwardRow } = this.getTraceAnchorCandidates(label, orientation);
|
|
9145
|
+
const candidatePoints = points.sort((a, b) => {
|
|
8993
9146
|
const aAlongDirection = a.x * direction.x + a.y * direction.y;
|
|
8994
9147
|
const bAlongDirection = b.x * direction.x + b.y * direction.y;
|
|
8995
|
-
|
|
9148
|
+
if (!preferNearestBendOnOutwardRow) {
|
|
9149
|
+
return bAlongDirection - aAlongDirection;
|
|
9150
|
+
}
|
|
9151
|
+
const aPerpendicularDistance = isYOrientation(orientation) ? Math.abs(a.x - preservedColumnAnchor.x) : Math.abs(a.y - preservedColumnAnchor.y);
|
|
9152
|
+
const bPerpendicularDistance = isYOrientation(orientation) ? Math.abs(b.x - preservedColumnAnchor.x) : Math.abs(b.y - preservedColumnAnchor.y);
|
|
9153
|
+
return bAlongDirection - aAlongDirection || aPerpendicularDistance - bPerpendicularDistance;
|
|
8996
9154
|
});
|
|
8997
9155
|
for (const connectorSource of candidatePoints) {
|
|
8998
|
-
const preservedColumnAnchor = this.getSearchStartAnchor(
|
|
8999
|
-
label,
|
|
9000
|
-
orientation
|
|
9001
|
-
);
|
|
9002
9156
|
const preservedColumnCandidate = this.createCandidate(
|
|
9003
9157
|
label,
|
|
9004
9158
|
{
|
|
@@ -9024,10 +9178,10 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
|
|
|
9024
9178
|
orientation
|
|
9025
9179
|
);
|
|
9026
9180
|
if (outwardDirection.x === 0 && outwardDirection.y === 0) continue;
|
|
9027
|
-
for (let
|
|
9181
|
+
for (let distance7 = LABEL_SEARCH_STEP; distance7 <= this.maxSearchDistance + EPS12; distance7 += LABEL_SEARCH_STEP) {
|
|
9028
9182
|
const anchorPoint = {
|
|
9029
|
-
x: connectorSource.x + outwardDirection.x *
|
|
9030
|
-
y: connectorSource.y + outwardDirection.y *
|
|
9183
|
+
x: connectorSource.x + outwardDirection.x * distance7,
|
|
9184
|
+
y: connectorSource.y + outwardDirection.y * distance7
|
|
9031
9185
|
};
|
|
9032
9186
|
const candidate = this.createCandidate(
|
|
9033
9187
|
label,
|
|
@@ -9040,7 +9194,7 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
|
|
|
9040
9194
|
label,
|
|
9041
9195
|
labelIndex,
|
|
9042
9196
|
"outward-trace-anchor",
|
|
9043
|
-
|
|
9197
|
+
distance7
|
|
9044
9198
|
);
|
|
9045
9199
|
this.recordCandidateResult(result);
|
|
9046
9200
|
if (result.status === "valid") {
|
|
@@ -9051,10 +9205,11 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
|
|
|
9051
9205
|
}
|
|
9052
9206
|
return null;
|
|
9053
9207
|
}
|
|
9054
|
-
|
|
9208
|
+
getTraceAnchorCandidates(label, orientation) {
|
|
9055
9209
|
const seen = /* @__PURE__ */ new Set();
|
|
9056
9210
|
const points = [];
|
|
9057
|
-
const
|
|
9211
|
+
const directHostTraceIds = new Set(label.mspConnectionPairIds ?? []);
|
|
9212
|
+
const connectedTraceIds = new Set(directHostTraceIds);
|
|
9058
9213
|
if (isYOrientation(orientation)) {
|
|
9059
9214
|
const connectedPinIds = /* @__PURE__ */ new Set();
|
|
9060
9215
|
for (const traceId of connectedTraceIds) {
|
|
@@ -9094,7 +9249,39 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
|
|
|
9094
9249
|
points.push(point);
|
|
9095
9250
|
}
|
|
9096
9251
|
}
|
|
9097
|
-
|
|
9252
|
+
const direction = dir(orientation);
|
|
9253
|
+
const furthestAlong = Math.max(
|
|
9254
|
+
...points.map((point) => point.x * direction.x + point.y * direction.y)
|
|
9255
|
+
);
|
|
9256
|
+
const furthestRowPoints = points.filter(
|
|
9257
|
+
(point) => Math.abs(
|
|
9258
|
+
point.x * direction.x + point.y * direction.y - furthestAlong
|
|
9259
|
+
) <= EPS12
|
|
9260
|
+
);
|
|
9261
|
+
const directHostPinIds = new Set(
|
|
9262
|
+
[...directHostTraceIds].flatMap(
|
|
9263
|
+
(traceId) => this.traceMap[traceId]?.pinIds ?? []
|
|
9264
|
+
)
|
|
9265
|
+
);
|
|
9266
|
+
const adjacentTraces = [...connectedTraceIds].flatMap((traceId) => {
|
|
9267
|
+
if (directHostTraceIds.has(traceId)) return [];
|
|
9268
|
+
const trace = this.traceMap[traceId];
|
|
9269
|
+
if (!trace?.pinIds.some((pinId) => directHostPinIds.has(pinId))) return [];
|
|
9270
|
+
return [trace];
|
|
9271
|
+
});
|
|
9272
|
+
return {
|
|
9273
|
+
points,
|
|
9274
|
+
// Prefer the nearest bend when the outward row is on a trace directly
|
|
9275
|
+
// adjacent to the label's host. Deeper transitive chains keep their
|
|
9276
|
+
// stable trace ordering.
|
|
9277
|
+
preferNearestBendOnOutwardRow: adjacentTraces.some(
|
|
9278
|
+
(trace) => furthestRowPoints.some(
|
|
9279
|
+
(point) => trace.tracePath.some(
|
|
9280
|
+
(tracePoint) => Math.abs(tracePoint.x - point.x) <= EPS12 && Math.abs(tracePoint.y - point.y) <= EPS12
|
|
9281
|
+
)
|
|
9282
|
+
)
|
|
9283
|
+
)
|
|
9284
|
+
};
|
|
9098
9285
|
}
|
|
9099
9286
|
sharesVerticalRailWithAny(trace, otherTraces) {
|
|
9100
9287
|
const verticalRailXs = /* @__PURE__ */ new Set();
|
|
@@ -9203,10 +9390,10 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
|
|
|
9203
9390
|
phase = "shift",
|
|
9204
9391
|
stopOnTraceCollision = true
|
|
9205
9392
|
} = params;
|
|
9206
|
-
for (let
|
|
9393
|
+
for (let distance7 = LABEL_SEARCH_STEP; distance7 <= maxSearchDistance + EPS12; distance7 += LABEL_SEARCH_STEP) {
|
|
9207
9394
|
const anchorPoint = {
|
|
9208
|
-
x: baseAnchor.x + direction.x *
|
|
9209
|
-
y: baseAnchor.y + direction.y *
|
|
9395
|
+
x: baseAnchor.x + direction.x * distance7,
|
|
9396
|
+
y: baseAnchor.y + direction.y * distance7
|
|
9210
9397
|
};
|
|
9211
9398
|
const candidate = this.createCandidate(label, anchorPoint, orientation);
|
|
9212
9399
|
const result = this.evaluateCandidate(
|
|
@@ -9214,7 +9401,7 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
|
|
|
9214
9401
|
label,
|
|
9215
9402
|
labelIndex,
|
|
9216
9403
|
phase,
|
|
9217
|
-
|
|
9404
|
+
distance7,
|
|
9218
9405
|
outwardDistance
|
|
9219
9406
|
);
|
|
9220
9407
|
this.recordCandidateResult(result);
|
|
@@ -9226,11 +9413,11 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
|
|
|
9226
9413
|
}
|
|
9227
9414
|
return null;
|
|
9228
9415
|
}
|
|
9229
|
-
evaluateCandidate(candidate, label, labelIndex, phase,
|
|
9416
|
+
evaluateCandidate(candidate, label, labelIndex, phase, distance7, outwardDistance) {
|
|
9230
9417
|
return {
|
|
9231
9418
|
...candidate,
|
|
9232
9419
|
phase,
|
|
9233
|
-
distance:
|
|
9420
|
+
distance: distance7,
|
|
9234
9421
|
outwardDistance,
|
|
9235
9422
|
selected: false,
|
|
9236
9423
|
status: this.getCandidateStatus({
|
|
@@ -9736,10 +9923,10 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
|
|
|
9736
9923
|
if (point.x < bounds.minX - EPS12 || point.x > bounds.maxX + EPS12 || point.y < bounds.minY - EPS12 || point.y > bounds.maxY + EPS12) {
|
|
9737
9924
|
continue;
|
|
9738
9925
|
}
|
|
9739
|
-
for (const [side,
|
|
9740
|
-
if (
|
|
9926
|
+
for (const [side, distance7] of getSideDistances(point, bounds)) {
|
|
9927
|
+
if (distance7 < nearestDistance) {
|
|
9741
9928
|
nearestSide = side;
|
|
9742
|
-
nearestDistance =
|
|
9929
|
+
nearestDistance = distance7;
|
|
9743
9930
|
}
|
|
9744
9931
|
}
|
|
9745
9932
|
}
|
|
@@ -9768,10 +9955,10 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
|
|
|
9768
9955
|
let nearestSide = null;
|
|
9769
9956
|
let nearestDistance = Number.POSITIVE_INFINITY;
|
|
9770
9957
|
for (const chip of this.chipObstacleSpatialIndex.chips) {
|
|
9771
|
-
for (const [side,
|
|
9772
|
-
if (
|
|
9958
|
+
for (const [side, distance7] of getSideDistances(point, chip.bounds)) {
|
|
9959
|
+
if (distance7 < nearestDistance) {
|
|
9773
9960
|
nearestSide = side;
|
|
9774
|
-
nearestDistance =
|
|
9961
|
+
nearestDistance = distance7;
|
|
9775
9962
|
}
|
|
9776
9963
|
}
|
|
9777
9964
|
}
|
|
@@ -10354,17 +10541,17 @@ var getTraceLength = (trace) => {
|
|
|
10354
10541
|
}
|
|
10355
10542
|
return length;
|
|
10356
10543
|
};
|
|
10357
|
-
var getPointAtTraceDistance = (trace,
|
|
10544
|
+
var getPointAtTraceDistance = (trace, distance7) => {
|
|
10358
10545
|
let pathDistance = 0;
|
|
10359
10546
|
for (let i = 0; i < trace.tracePath.length - 1; i++) {
|
|
10360
10547
|
const start = trace.tracePath[i];
|
|
10361
10548
|
const end = trace.tracePath[i + 1];
|
|
10362
10549
|
const segmentLength = getManhattanDistance(start, end);
|
|
10363
10550
|
const nextDistance = pathDistance + segmentLength;
|
|
10364
|
-
if (
|
|
10551
|
+
if (distance7 <= nextDistance + EPS13) {
|
|
10365
10552
|
const offset = Math.max(
|
|
10366
10553
|
0,
|
|
10367
|
-
Math.min(segmentLength,
|
|
10554
|
+
Math.min(segmentLength, distance7 - pathDistance)
|
|
10368
10555
|
);
|
|
10369
10556
|
const direction = getSegmentDirection(start, end);
|
|
10370
10557
|
return {
|
|
@@ -10489,13 +10676,13 @@ var getCandidateDistances = (traceLength, vertexDistances) => {
|
|
|
10489
10676
|
const distances = /* @__PURE__ */ new Set();
|
|
10490
10677
|
const maxSteps = Math.ceil(traceLength / CANDIDATE_STEP);
|
|
10491
10678
|
for (let i = 0; i <= maxSteps; i++) {
|
|
10492
|
-
const
|
|
10493
|
-
distances.add(roundDistance(
|
|
10679
|
+
const distance7 = Math.min(traceLength, i * CANDIDATE_STEP);
|
|
10680
|
+
distances.add(roundDistance(distance7));
|
|
10494
10681
|
}
|
|
10495
|
-
for (const
|
|
10496
|
-
distances.add(roundDistance(
|
|
10682
|
+
for (const distance7 of vertexDistances) {
|
|
10683
|
+
distances.add(roundDistance(distance7));
|
|
10497
10684
|
}
|
|
10498
|
-
return [...distances].filter((
|
|
10685
|
+
return [...distances].filter((distance7) => distance7 >= -EPS13 && distance7 <= traceLength + EPS13).sort((a, b) => a - b);
|
|
10499
10686
|
};
|
|
10500
10687
|
var getOrientationsForPoint = (params) => {
|
|
10501
10688
|
const { inputProblem, label, point, orientationConstraint } = params;
|
|
@@ -10668,7 +10855,7 @@ var getNetLabelHeight = (inputProblem, label) => {
|
|
|
10668
10855
|
(nc) => nc.pinIds.some((pid) => label.pinIds.includes(pid))
|
|
10669
10856
|
)?.netLabelHeight;
|
|
10670
10857
|
};
|
|
10671
|
-
var roundDistance = (
|
|
10858
|
+
var roundDistance = (distance7) => Number(distance7.toFixed(6));
|
|
10672
10859
|
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
10860
|
|
|
10674
10861
|
// lib/solvers/TraceAnchoredNetLabelOverlapSolver/visualize.ts
|
|
@@ -11649,7 +11836,7 @@ ${c.status}`
|
|
|
11649
11836
|
};
|
|
11650
11837
|
|
|
11651
11838
|
// lib/solvers/UnroutedTraceRecoverySolver/UnroutedTraceRecoverySolver.ts
|
|
11652
|
-
import { distance as
|
|
11839
|
+
import { distance as distance6, doSegmentsIntersect as doSegmentsIntersect3 } from "@tscircuit/math-utils";
|
|
11653
11840
|
var ROUTE_CLEARANCE = 0.2;
|
|
11654
11841
|
var COORDINATE_TOLERANCE = 1e-9;
|
|
11655
11842
|
var GROUND_NET_ID = "GND";
|
|
@@ -11811,7 +11998,7 @@ var getJunctionCandidates = ({
|
|
|
11811
11998
|
facingDirection: pin._facingDirection
|
|
11812
11999
|
});
|
|
11813
12000
|
for (const junctionPoint of junctionPoints) {
|
|
11814
|
-
if (
|
|
12001
|
+
if (distance6(pin, junctionPoint) > maxConnectionDistance) {
|
|
11815
12002
|
continue;
|
|
11816
12003
|
}
|
|
11817
12004
|
candidates.push(
|
|
@@ -12027,7 +12214,7 @@ var UnroutedTraceRecoverySolver = class extends BaseSolver {
|
|
|
12027
12214
|
if (connectionPair.globalConnNetId === this.groundGlobalConnNetId) {
|
|
12028
12215
|
return;
|
|
12029
12216
|
}
|
|
12030
|
-
if (
|
|
12217
|
+
if (distance6(connectionPair.pins[0], connectionPair.pins[1]) > this.maxConnectionDistance) {
|
|
12031
12218
|
return;
|
|
12032
12219
|
}
|
|
12033
12220
|
const obstacles = getObstacleRects(this.inputProblem);
|
|
@@ -12139,6 +12326,7 @@ var pathEntersAnyNetLabel = ({
|
|
|
12139
12326
|
// lib/solvers/SameNetJunctionAlignmentSolver/alignSameNetJunctions.ts
|
|
12140
12327
|
var MAX_ALIGNED_LOAD_PIN_OFFSET = 0.2;
|
|
12141
12328
|
var MAX_SAME_NET_LABEL_BOUNDARY_RAIL_OFFSET = 0.2;
|
|
12329
|
+
var MAX_SHARED_PIN_RAIL_OFFSET = 0.05;
|
|
12142
12330
|
var getSharedPin = ({
|
|
12143
12331
|
donorTrace,
|
|
12144
12332
|
branchTrace
|
|
@@ -12178,6 +12366,28 @@ var railIsOnFacingSide = ({
|
|
|
12178
12366
|
if (pin._facingDirection === "y+") return railY > pin.y;
|
|
12179
12367
|
return false;
|
|
12180
12368
|
};
|
|
12369
|
+
var railIsOnSharedPinFacingSide = ({
|
|
12370
|
+
railY,
|
|
12371
|
+
pin
|
|
12372
|
+
}) => {
|
|
12373
|
+
if (pin._facingDirection === "y+") return railY > pin.y;
|
|
12374
|
+
if (pin._facingDirection === "y-") return railY < pin.y;
|
|
12375
|
+
return false;
|
|
12376
|
+
};
|
|
12377
|
+
var getHorizontalPinApproachPoint = ({
|
|
12378
|
+
branchTrace,
|
|
12379
|
+
sharedPin,
|
|
12380
|
+
otherPin
|
|
12381
|
+
}) => {
|
|
12382
|
+
if (otherPin._facingDirection !== "x-" && otherPin._facingDirection !== "x+") {
|
|
12383
|
+
return null;
|
|
12384
|
+
}
|
|
12385
|
+
const sharedToOtherPath = branchTrace.pins[0].pinId === sharedPin.pinId ? branchTrace.tracePath : [...branchTrace.tracePath].reverse();
|
|
12386
|
+
const approachPoint = sharedToOtherPath.at(-2);
|
|
12387
|
+
if (!approachPoint || !nearlyEqual(approachPoint.y, otherPin.y)) return null;
|
|
12388
|
+
const approachesFromFacingSide = otherPin._facingDirection === "x-" ? approachPoint.x < otherPin.x : approachPoint.x > otherPin.x;
|
|
12389
|
+
return approachesFromFacingSide ? approachPoint : null;
|
|
12390
|
+
};
|
|
12181
12391
|
var getAttachedLabelIndexes = (trace, netLabelPlacements) => netLabelPlacements.flatMap((label, index) => {
|
|
12182
12392
|
const labelOwnsTrace = label.mspConnectionPairIds.includes(trace.mspPairId) || label.mspConnectionPairIds.length === 0 && label.globalConnNetId === trace.globalConnNetId;
|
|
12183
12393
|
return labelOwnsTrace && tracePathContainsPoint(trace.tracePath, label.anchorPoint) ? [index] : [];
|
|
@@ -12226,19 +12436,45 @@ var getAlignedBranchPath = ({
|
|
|
12226
12436
|
if (branchRail && nearlyEqual(branchRail.start.y, donorRail.start.y)) {
|
|
12227
12437
|
return null;
|
|
12228
12438
|
}
|
|
12229
|
-
|
|
12439
|
+
const railFacesOtherPin = railIsOnFacingSide({
|
|
12440
|
+
railY: donorRail.start.y,
|
|
12441
|
+
pin: otherPin
|
|
12442
|
+
});
|
|
12443
|
+
const railFacesSharedPin = railIsOnSharedPinFacingSide({
|
|
12444
|
+
railY: donorRail.start.y,
|
|
12445
|
+
pin: sharedPin
|
|
12446
|
+
}) && Math.abs(donorRail.start.y - sharedPin.y) <= MAX_SHARED_PIN_RAIL_OFFSET;
|
|
12447
|
+
if (!railFacesOtherPin && !railFacesSharedPin) {
|
|
12230
12448
|
return null;
|
|
12231
12449
|
}
|
|
12232
12450
|
const junction = getJunctionPoint({ segment: donorRail, sharedPin });
|
|
12233
12451
|
const extendsDonorRail = donorOtherPin.x < junction.x && otherPin.x > junction.x || donorOtherPin.x > junction.x && otherPin.x < junction.x;
|
|
12234
12452
|
if (!extendsDonorRail) return null;
|
|
12235
|
-
|
|
12236
|
-
|
|
12237
|
-
|
|
12238
|
-
|
|
12239
|
-
|
|
12240
|
-
|
|
12241
|
-
|
|
12453
|
+
let sharedToOther;
|
|
12454
|
+
if (!railFacesOtherPin && railFacesSharedPin) {
|
|
12455
|
+
const approachPoint = getHorizontalPinApproachPoint({
|
|
12456
|
+
branchTrace,
|
|
12457
|
+
sharedPin,
|
|
12458
|
+
otherPin
|
|
12459
|
+
});
|
|
12460
|
+
if (!approachPoint) return null;
|
|
12461
|
+
sharedToOther = simplifyPath([
|
|
12462
|
+
{ x: sharedPin.x, y: sharedPin.y },
|
|
12463
|
+
{ x: junction.x, y: sharedPin.y },
|
|
12464
|
+
{ x: junction.x, y: junction.y },
|
|
12465
|
+
{ x: approachPoint.x, y: junction.y },
|
|
12466
|
+
{ x: approachPoint.x, y: otherPin.y },
|
|
12467
|
+
{ x: otherPin.x, y: otherPin.y }
|
|
12468
|
+
]);
|
|
12469
|
+
} else {
|
|
12470
|
+
sharedToOther = simplifyPath([
|
|
12471
|
+
{ x: sharedPin.x, y: sharedPin.y },
|
|
12472
|
+
{ x: junction.x, y: sharedPin.y },
|
|
12473
|
+
{ x: junction.x, y: junction.y },
|
|
12474
|
+
{ x: otherPin.x, y: junction.y },
|
|
12475
|
+
{ x: otherPin.x, y: otherPin.y }
|
|
12476
|
+
]);
|
|
12477
|
+
}
|
|
12242
12478
|
if (branchTrace.pins[0].pinId === sharedPin.pinId) return sharedToOther;
|
|
12243
12479
|
return [...sharedToOther].reverse();
|
|
12244
12480
|
};
|
|
@@ -12961,17 +13197,17 @@ var getRequiredOutwardDistance = (label, inlineBounds) => {
|
|
|
12961
13197
|
const targetMinY = Math.max(...nearby.map((bounds) => bounds.maxY));
|
|
12962
13198
|
return Math.max(0, targetMinY - labelBounds.minY + LABEL_CLEARANCE2);
|
|
12963
13199
|
};
|
|
12964
|
-
var moveLabel = (label, orientation,
|
|
13200
|
+
var moveLabel = (label, orientation, distance7) => {
|
|
12965
13201
|
const direction = dir(orientation);
|
|
12966
13202
|
return {
|
|
12967
13203
|
...label,
|
|
12968
13204
|
anchorPoint: {
|
|
12969
|
-
x: label.anchorPoint.x + direction.x *
|
|
12970
|
-
y: label.anchorPoint.y + direction.y *
|
|
13205
|
+
x: label.anchorPoint.x + direction.x * distance7,
|
|
13206
|
+
y: label.anchorPoint.y + direction.y * distance7
|
|
12971
13207
|
},
|
|
12972
13208
|
center: {
|
|
12973
|
-
x: label.center.x + direction.x *
|
|
12974
|
-
y: label.center.y + direction.y *
|
|
13209
|
+
x: label.center.x + direction.x * distance7,
|
|
13210
|
+
y: label.center.y + direction.y * distance7
|
|
12975
13211
|
}
|
|
12976
13212
|
};
|
|
12977
13213
|
};
|
|
@@ -13096,15 +13332,15 @@ var pushAnchoredNetLabelsAwayFromInlineLabels = ({
|
|
|
13096
13332
|
const movedLabelIndices = /* @__PURE__ */ new Set();
|
|
13097
13333
|
for (let triggerIndex = 0; triggerIndex < outputLabels.length; triggerIndex++) {
|
|
13098
13334
|
const trigger = outputLabels[triggerIndex];
|
|
13099
|
-
const
|
|
13100
|
-
if (
|
|
13335
|
+
const distance7 = getRequiredOutwardDistance(trigger, inlineBounds);
|
|
13336
|
+
if (distance7 <= POINT_EPSILON || distance7 > MAX_OUTWARD_DISTANCE) continue;
|
|
13101
13337
|
const { group, ownerChipIds } = getContiguousLabelGroup({
|
|
13102
13338
|
triggerIndex,
|
|
13103
13339
|
labels: outputLabels,
|
|
13104
13340
|
chipIdByPinId
|
|
13105
13341
|
});
|
|
13106
13342
|
const distances = new Map(
|
|
13107
|
-
[...group].map((labelIndex) => [labelIndex,
|
|
13343
|
+
[...group].map((labelIndex) => [labelIndex, distance7])
|
|
13108
13344
|
);
|
|
13109
13345
|
let failed = false;
|
|
13110
13346
|
for (let iteration = 0; iteration < outputLabels.length; iteration++) {
|