@tscircuit/schematic-trace-solver 0.0.189 → 0.0.190
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +252 -223
- package/lib/solvers/SameNetJunctionAlignmentSolver/SameNetJunctionAlignmentSolver.ts +4 -9
- package/lib/solvers/SameNetJunctionAlignmentSolver/alignSameNetJunctions.ts +10 -2
- package/lib/solvers/SameNetJunctionAlignmentSolver/collapseSameNetCycles.ts +75 -38
- package/package.json +1 -1
- package/tests/repros/__snapshots__/repro-pmp11282-isolated-dcdc.snap.svg +18 -18
- package/tests/repros/__snapshots__/repro-repeated-power-rail-junctions.snap.svg +255 -0
- package/tests/repros/assets/repro-repeated-power-rail-junctions.input.json +927 -0
- package/tests/repros/repro-repeated-power-rail-junctions.test.ts +22 -0
- package/tests/solvers/SameNetJunctionAlignmentSolver/collapse-same-net-cycles.test.ts +30 -0
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
pointsEqual,
|
|
12
12
|
} from "lib/solvers/TraceCleanupSolver/sameNetRailAlignment/geometry"
|
|
13
13
|
import { simplifyPath } from "lib/solvers/TraceCleanupSolver/simplifyPath"
|
|
14
|
+
import { findPerpendicularPathCrossings } from "lib/solvers/TraceCleanupSolver/sub-solver/findIntersectionsWithObstacles"
|
|
14
15
|
import { getSharedPin } from "./getSharedPin"
|
|
15
16
|
import {
|
|
16
17
|
pathEntersAnyNetLabel,
|
|
@@ -100,6 +101,25 @@ const getPerpendicularPathCrossings = (
|
|
|
100
101
|
return crossings
|
|
101
102
|
}
|
|
102
103
|
|
|
104
|
+
const buildCollapsedSelfCyclePath = (
|
|
105
|
+
path: Point[],
|
|
106
|
+
firstSegmentIndex: number,
|
|
107
|
+
secondSegmentIndex: number,
|
|
108
|
+
) => {
|
|
109
|
+
const intersectionPoint = getSegmentIntersection(
|
|
110
|
+
path[firstSegmentIndex]!,
|
|
111
|
+
path[firstSegmentIndex + 1]!,
|
|
112
|
+
path[secondSegmentIndex]!,
|
|
113
|
+
path[secondSegmentIndex + 1]!,
|
|
114
|
+
)
|
|
115
|
+
if (!intersectionPoint) return path
|
|
116
|
+
return simplifyPath([
|
|
117
|
+
...path.slice(0, firstSegmentIndex + 1),
|
|
118
|
+
intersectionPoint,
|
|
119
|
+
...path.slice(secondSegmentIndex + 1),
|
|
120
|
+
])
|
|
121
|
+
}
|
|
122
|
+
|
|
103
123
|
const buildCollapsedCyclePath = ({
|
|
104
124
|
targetTrace,
|
|
105
125
|
targetPath,
|
|
@@ -209,6 +229,60 @@ const getBestCycleCollapseCandidate = ({
|
|
|
209
229
|
const baselineTargetVisibleLength = getVisibleTraceLength([targetTrace])
|
|
210
230
|
let bestCandidate: CycleCollapseCandidate | null = null
|
|
211
231
|
|
|
232
|
+
const considerTracePath = (tracePath: Point[]) => {
|
|
233
|
+
const candidateTrace = { ...targetTrace, tracePath }
|
|
234
|
+
const candidateTargetVisibleLength = getVisibleTraceLength([candidateTrace])
|
|
235
|
+
if (
|
|
236
|
+
candidateTargetVisibleLength >
|
|
237
|
+
baselineTargetVisibleLength + TRACE_LENGTH_EPSILON
|
|
238
|
+
) {
|
|
239
|
+
return
|
|
240
|
+
}
|
|
241
|
+
const candidateNetLabelPlacements = getNetLabelPlacementsForCycleCollapse({
|
|
242
|
+
targetTrace,
|
|
243
|
+
tracePath,
|
|
244
|
+
netLabelPlacements,
|
|
245
|
+
})
|
|
246
|
+
if (!candidateNetLabelPlacements) return
|
|
247
|
+
|
|
248
|
+
const candidateNetTraces = sameNetTraces.map((trace) => {
|
|
249
|
+
if (trace.mspPairId === targetTrace.mspPairId) return candidateTrace
|
|
250
|
+
return trace
|
|
251
|
+
})
|
|
252
|
+
const netVisibleLength = getVisibleTraceLength(candidateNetTraces)
|
|
253
|
+
if (netVisibleLength >= baselineNetVisibleLength - TRACE_LENGTH_EPSILON) {
|
|
254
|
+
return
|
|
255
|
+
}
|
|
256
|
+
const candidate: CycleCollapseCandidate = {
|
|
257
|
+
tracePath,
|
|
258
|
+
netLabelPlacements: candidateNetLabelPlacements,
|
|
259
|
+
netVisibleLength,
|
|
260
|
+
netVisibleSegmentCount: getVisibleTraceSegmentCount(candidateNetTraces),
|
|
261
|
+
}
|
|
262
|
+
if (candidateIsBetter(candidate, bestCandidate)) {
|
|
263
|
+
bestCandidate = candidate
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
// Comparing a path with itself reports each crossing in both directions.
|
|
268
|
+
const selfCrossings = findPerpendicularPathCrossings(
|
|
269
|
+
targetTrace.tracePath,
|
|
270
|
+
targetTrace.tracePath,
|
|
271
|
+
{ includeTerminalSegments: true },
|
|
272
|
+
).filter(
|
|
273
|
+
({ pathSegmentIndex, otherPathSegmentIndex }) =>
|
|
274
|
+
pathSegmentIndex < otherPathSegmentIndex,
|
|
275
|
+
)
|
|
276
|
+
for (const crossing of selfCrossings) {
|
|
277
|
+
considerTracePath(
|
|
278
|
+
buildCollapsedSelfCyclePath(
|
|
279
|
+
targetTrace.tracePath,
|
|
280
|
+
crossing.pathSegmentIndex,
|
|
281
|
+
crossing.otherPathSegmentIndex,
|
|
282
|
+
),
|
|
283
|
+
)
|
|
284
|
+
}
|
|
285
|
+
|
|
212
286
|
for (const donorTrace of sameNetTraces) {
|
|
213
287
|
if (donorTrace.mspPairId === targetTrace.mspPairId) continue
|
|
214
288
|
const sharedPin = getSharedPin({
|
|
@@ -228,44 +302,7 @@ const getBestCycleCollapseCandidate = ({
|
|
|
228
302
|
donorPath,
|
|
229
303
|
crossing,
|
|
230
304
|
})
|
|
231
|
-
|
|
232
|
-
const candidateTargetVisibleLength = getVisibleTraceLength([
|
|
233
|
-
candidateTrace,
|
|
234
|
-
])
|
|
235
|
-
if (
|
|
236
|
-
candidateTargetVisibleLength >
|
|
237
|
-
baselineTargetVisibleLength + TRACE_LENGTH_EPSILON
|
|
238
|
-
) {
|
|
239
|
-
continue
|
|
240
|
-
}
|
|
241
|
-
const candidateNetLabelPlacements = getNetLabelPlacementsForCycleCollapse(
|
|
242
|
-
{
|
|
243
|
-
targetTrace,
|
|
244
|
-
tracePath,
|
|
245
|
-
netLabelPlacements,
|
|
246
|
-
},
|
|
247
|
-
)
|
|
248
|
-
if (!candidateNetLabelPlacements) continue
|
|
249
|
-
|
|
250
|
-
const candidateNetTraces = sameNetTraces.map((trace) => {
|
|
251
|
-
if (trace.mspPairId === targetTrace.mspPairId) return candidateTrace
|
|
252
|
-
return trace
|
|
253
|
-
})
|
|
254
|
-
const netVisibleLength = getVisibleTraceLength(candidateNetTraces)
|
|
255
|
-
if (netVisibleLength >= baselineNetVisibleLength - TRACE_LENGTH_EPSILON) {
|
|
256
|
-
continue
|
|
257
|
-
}
|
|
258
|
-
const netVisibleSegmentCount =
|
|
259
|
-
getVisibleTraceSegmentCount(candidateNetTraces)
|
|
260
|
-
const candidate = {
|
|
261
|
-
tracePath,
|
|
262
|
-
netLabelPlacements: candidateNetLabelPlacements,
|
|
263
|
-
netVisibleLength,
|
|
264
|
-
netVisibleSegmentCount,
|
|
265
|
-
}
|
|
266
|
-
if (candidateIsBetter(candidate, bestCandidate)) {
|
|
267
|
-
bestCandidate = candidate
|
|
268
|
-
}
|
|
305
|
+
considerTracePath(tracePath)
|
|
269
306
|
}
|
|
270
307
|
}
|
|
271
308
|
|