@tscircuit/schematic-trace-solver 0.0.93 → 0.0.94
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js
CHANGED
|
@@ -5653,6 +5653,30 @@ var getSegmentOverlapWithRectSpan = (start, end, rect) => {
|
|
|
5653
5653
|
|
|
5654
5654
|
// lib/solvers/Example28Solver/reroute.ts
|
|
5655
5655
|
var LABEL_CLEARANCE = 0.1;
|
|
5656
|
+
var MAX_CORRIDOR_SHIFTS = 16;
|
|
5657
|
+
var corridorHasOtherNetTrace = ({
|
|
5658
|
+
x,
|
|
5659
|
+
lowY,
|
|
5660
|
+
highY,
|
|
5661
|
+
outputTraces,
|
|
5662
|
+
netId
|
|
5663
|
+
}) => {
|
|
5664
|
+
for (const other of outputTraces) {
|
|
5665
|
+
if (other.globalConnNetId === netId) continue;
|
|
5666
|
+
const path = other.tracePath;
|
|
5667
|
+
for (let i = 0; i + 1 < path.length; i++) {
|
|
5668
|
+
const start = path[i];
|
|
5669
|
+
const end = path[i + 1];
|
|
5670
|
+
if (Math.abs(start.x - end.x) >= 1e-9) continue;
|
|
5671
|
+
if (Math.abs(start.x - x) >= LABEL_CLEARANCE / 2) continue;
|
|
5672
|
+
const segLowY = Math.min(start.y, end.y);
|
|
5673
|
+
const segHighY = Math.max(start.y, end.y);
|
|
5674
|
+
if (Math.min(highY, segHighY) - Math.max(lowY, segLowY) > 1e-6)
|
|
5675
|
+
return true;
|
|
5676
|
+
}
|
|
5677
|
+
}
|
|
5678
|
+
return false;
|
|
5679
|
+
};
|
|
5656
5680
|
var findBestReroutePath = ({
|
|
5657
5681
|
trace,
|
|
5658
5682
|
obstacleLabel,
|
|
@@ -5691,8 +5715,11 @@ var generateRerouteCandidateResults = ({
|
|
|
5691
5715
|
const seen = /* @__PURE__ */ new Set();
|
|
5692
5716
|
const candidateResults = [];
|
|
5693
5717
|
const horizontalSegmentPushCandidate = generateHorizontalSegmentPushCandidate(
|
|
5694
|
-
|
|
5695
|
-
|
|
5718
|
+
{
|
|
5719
|
+
trace,
|
|
5720
|
+
label,
|
|
5721
|
+
outputTraces
|
|
5722
|
+
}
|
|
5696
5723
|
);
|
|
5697
5724
|
if (horizontalSegmentPushCandidate) {
|
|
5698
5725
|
candidateResults.push(
|
|
@@ -5886,7 +5913,11 @@ var selectBestReroutePath = ({
|
|
|
5886
5913
|
}
|
|
5887
5914
|
return bestPath;
|
|
5888
5915
|
};
|
|
5889
|
-
var generateHorizontalSegmentPushCandidate = (
|
|
5916
|
+
var generateHorizontalSegmentPushCandidate = ({
|
|
5917
|
+
trace,
|
|
5918
|
+
label,
|
|
5919
|
+
outputTraces
|
|
5920
|
+
}) => {
|
|
5890
5921
|
const labelDirection = dir(label.orientation);
|
|
5891
5922
|
if (labelDirection.x === 0) return null;
|
|
5892
5923
|
const path = trace.tracePath;
|
|
@@ -5911,6 +5942,20 @@ var generateHorizontalSegmentPushCandidate = (trace, label) => {
|
|
|
5911
5942
|
if (labelDirection.x > 0) {
|
|
5912
5943
|
segmentPushX = bounds.maxX + LABEL_CLEARANCE;
|
|
5913
5944
|
}
|
|
5945
|
+
const corridorStep = labelDirection.x > 0 ? LABEL_CLEARANCE : -LABEL_CLEARANCE;
|
|
5946
|
+
const verticalLowY = Math.min(verticalStart.y, verticalEnd.y);
|
|
5947
|
+
const verticalHighY = Math.max(verticalStart.y, verticalEnd.y);
|
|
5948
|
+
for (let shift = 0; shift < MAX_CORRIDOR_SHIFTS; shift++) {
|
|
5949
|
+
const occupied = corridorHasOtherNetTrace({
|
|
5950
|
+
x: segmentPushX,
|
|
5951
|
+
lowY: verticalLowY,
|
|
5952
|
+
highY: verticalHighY,
|
|
5953
|
+
outputTraces,
|
|
5954
|
+
netId: trace.globalConnNetId
|
|
5955
|
+
});
|
|
5956
|
+
if (!occupied) break;
|
|
5957
|
+
segmentPushX += corridorStep;
|
|
5958
|
+
}
|
|
5914
5959
|
const segmentPushStartY = getClearedHorizontalY({
|
|
5915
5960
|
start: previousAnchor,
|
|
5916
5961
|
end: { x: segmentPushX, y: verticalStart.y },
|
|
@@ -8,13 +8,13 @@ import { detectTraceLabelOverlap } from "lib/solvers/TraceLabelOverlapAvoidanceS
|
|
|
8
8
|
import { generateRerouteCandidates } from "lib/solvers/TraceLabelOverlapAvoidanceSolver/rerouteCollidingTrace"
|
|
9
9
|
import type { InputProblem } from "lib/types/InputProblem"
|
|
10
10
|
import { dir } from "lib/utils/dir"
|
|
11
|
+
import { getChipBoundaryOverlap } from "./doesPathRunAlongChipBoundary"
|
|
11
12
|
import {
|
|
12
13
|
countPathIntersections,
|
|
13
14
|
getPathKey,
|
|
14
15
|
getPathLength,
|
|
15
16
|
isPathCollidingWithChipInterior,
|
|
16
17
|
} from "./geometry"
|
|
17
|
-
import { getChipBoundaryOverlap } from "./doesPathRunAlongChipBoundary"
|
|
18
18
|
import type {
|
|
19
19
|
ChipObstacle,
|
|
20
20
|
RerouteCandidateResult,
|
|
@@ -22,6 +22,43 @@ import type {
|
|
|
22
22
|
} from "./types"
|
|
23
23
|
|
|
24
24
|
const LABEL_CLEARANCE = 0.1
|
|
25
|
+
// How many LABEL_CLEARANCE-wide corridors to try before giving up on finding a
|
|
26
|
+
// free one for a pushed segment.
|
|
27
|
+
const MAX_CORRIDOR_SHIFTS = 16
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Whether a vertical trace segment of a different net already runs along the
|
|
31
|
+
* corridor at `x`, overlapping the [lowY, highY] span (within a corridor width).
|
|
32
|
+
*/
|
|
33
|
+
const corridorHasOtherNetTrace = ({
|
|
34
|
+
x,
|
|
35
|
+
lowY,
|
|
36
|
+
highY,
|
|
37
|
+
outputTraces,
|
|
38
|
+
netId,
|
|
39
|
+
}: {
|
|
40
|
+
x: number
|
|
41
|
+
lowY: number
|
|
42
|
+
highY: number
|
|
43
|
+
outputTraces: SolvedTracePath[]
|
|
44
|
+
netId: string
|
|
45
|
+
}): boolean => {
|
|
46
|
+
for (const other of outputTraces) {
|
|
47
|
+
if (other.globalConnNetId === netId) continue
|
|
48
|
+
const path = other.tracePath
|
|
49
|
+
for (let i = 0; i + 1 < path.length; i++) {
|
|
50
|
+
const start = path[i]!
|
|
51
|
+
const end = path[i + 1]!
|
|
52
|
+
if (Math.abs(start.x - end.x) >= 1e-9) continue
|
|
53
|
+
if (Math.abs(start.x - x) >= LABEL_CLEARANCE / 2) continue
|
|
54
|
+
const segLowY = Math.min(start.y, end.y)
|
|
55
|
+
const segHighY = Math.max(start.y, end.y)
|
|
56
|
+
if (Math.min(highY, segHighY) - Math.max(lowY, segLowY) > 1e-6)
|
|
57
|
+
return true
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return false
|
|
61
|
+
}
|
|
25
62
|
|
|
26
63
|
export const findBestReroutePath = ({
|
|
27
64
|
trace,
|
|
@@ -78,8 +115,11 @@ export const generateRerouteCandidateResults = ({
|
|
|
78
115
|
const seen = new Set<string>()
|
|
79
116
|
const candidateResults: RerouteCandidateResult[] = []
|
|
80
117
|
const horizontalSegmentPushCandidate = generateHorizontalSegmentPushCandidate(
|
|
81
|
-
|
|
82
|
-
|
|
118
|
+
{
|
|
119
|
+
trace,
|
|
120
|
+
label,
|
|
121
|
+
outputTraces,
|
|
122
|
+
},
|
|
83
123
|
)
|
|
84
124
|
|
|
85
125
|
if (horizontalSegmentPushCandidate) {
|
|
@@ -328,10 +368,15 @@ const selectBestReroutePath = ({
|
|
|
328
368
|
return bestPath
|
|
329
369
|
}
|
|
330
370
|
|
|
331
|
-
const generateHorizontalSegmentPushCandidate = (
|
|
332
|
-
trace
|
|
333
|
-
label
|
|
334
|
-
|
|
371
|
+
const generateHorizontalSegmentPushCandidate = ({
|
|
372
|
+
trace,
|
|
373
|
+
label,
|
|
374
|
+
outputTraces,
|
|
375
|
+
}: {
|
|
376
|
+
trace: SolvedTracePath
|
|
377
|
+
label: NetLabelPlacement
|
|
378
|
+
outputTraces: SolvedTracePath[]
|
|
379
|
+
}): Point[] | null => {
|
|
335
380
|
const labelDirection = dir(label.orientation)
|
|
336
381
|
if (labelDirection.x === 0) return null
|
|
337
382
|
|
|
@@ -367,6 +412,25 @@ const generateHorizontalSegmentPushCandidate = (
|
|
|
367
412
|
if (labelDirection.x > 0) {
|
|
368
413
|
segmentPushX = bounds.maxX + LABEL_CLEARANCE
|
|
369
414
|
}
|
|
415
|
+
|
|
416
|
+
// Two traces escaping the same label block would otherwise be pushed to the
|
|
417
|
+
// identical corridor and stack on one line. Slide the corridor further out
|
|
418
|
+
// until it no longer coincides with a different-net trace already routed
|
|
419
|
+
// there, giving each escaping trace its own parallel corridor.
|
|
420
|
+
const corridorStep = labelDirection.x > 0 ? LABEL_CLEARANCE : -LABEL_CLEARANCE
|
|
421
|
+
const verticalLowY = Math.min(verticalStart.y, verticalEnd.y)
|
|
422
|
+
const verticalHighY = Math.max(verticalStart.y, verticalEnd.y)
|
|
423
|
+
for (let shift = 0; shift < MAX_CORRIDOR_SHIFTS; shift++) {
|
|
424
|
+
const occupied = corridorHasOtherNetTrace({
|
|
425
|
+
x: segmentPushX,
|
|
426
|
+
lowY: verticalLowY,
|
|
427
|
+
highY: verticalHighY,
|
|
428
|
+
outputTraces,
|
|
429
|
+
netId: trace.globalConnNetId,
|
|
430
|
+
})
|
|
431
|
+
if (!occupied) break
|
|
432
|
+
segmentPushX += corridorStep
|
|
433
|
+
}
|
|
370
434
|
const segmentPushStartY = getClearedHorizontalY({
|
|
371
435
|
start: previousAnchor,
|
|
372
436
|
end: { x: segmentPushX, y: verticalStart.y },
|