@tscircuit/schematic-trace-solver 0.0.49 → 0.0.51
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 +133 -1
- package/dist/index.js +1084 -41
- package/lib/solvers/AvailableNetOrientationSolver/AvailableNetOrientationSolver.ts +682 -0
- package/lib/solvers/AvailableNetOrientationSolver/constants.ts +6 -0
- package/lib/solvers/AvailableNetOrientationSolver/geometry.ts +192 -0
- package/lib/solvers/AvailableNetOrientationSolver/traces.ts +43 -0
- package/lib/solvers/AvailableNetOrientationSolver/types.ts +44 -0
- package/lib/solvers/AvailableNetOrientationSolver/visualize.ts +123 -0
- package/lib/solvers/SchematicTracePipelineSolver/SchematicTracePipelineSolver.ts +30 -0
- package/lib/solvers/VccNetLabelCornerPlacementSolver/VccNetLabelCornerPlacementSolver.ts +268 -0
- package/lib/solvers/VccNetLabelCornerPlacementSolver/geometry.ts +59 -0
- package/lib/solvers/VccNetLabelCornerPlacementSolver/types.ts +37 -0
- package/lib/solvers/VccNetLabelCornerPlacementSolver/visualize.ts +114 -0
- package/package.json +1 -1
- package/tests/assets/example22.json +1 -1
- package/tests/examples/__snapshots__/example12.snap.svg +33 -30
- package/tests/examples/__snapshots__/example13.snap.svg +10 -4
- package/tests/examples/__snapshots__/example14.snap.svg +72 -66
- package/tests/examples/__snapshots__/example16.snap.svg +33 -27
- package/tests/examples/__snapshots__/example20.snap.svg +29 -23
- package/tests/examples/__snapshots__/example21.snap.svg +77 -65
- package/tests/examples/__snapshots__/example22.snap.svg +31 -25
- package/tests/examples/__snapshots__/example31.snap.svg +12 -12
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
import type { Point } from "@tscircuit/math-utils"
|
|
2
|
+
import type { SolvedTracePath } from "lib/solvers/SchematicTraceLinesSolver/SchematicTraceLinesSolver"
|
|
3
|
+
import type { InputProblem } from "lib/types/InputProblem"
|
|
4
|
+
import type { FacingDirection } from "lib/utils/dir"
|
|
5
|
+
import { EPS, TRACE_BOUNDARY_TOLERANCE } from "./constants"
|
|
6
|
+
import type { Bounds, ChipSide } from "./types"
|
|
7
|
+
|
|
8
|
+
export const isYOrientation = (
|
|
9
|
+
orientation: FacingDirection,
|
|
10
|
+
): orientation is "y+" | "y-" => orientation === "y+" || orientation === "y-"
|
|
11
|
+
|
|
12
|
+
export const isXOrientation = (
|
|
13
|
+
orientation: FacingDirection,
|
|
14
|
+
): orientation is "x+" | "x-" => orientation === "x+" || orientation === "x-"
|
|
15
|
+
|
|
16
|
+
export const rectsOverlap = (a: Bounds, b: Bounds) =>
|
|
17
|
+
Math.min(a.maxX, b.maxX) - Math.max(a.minX, b.minX) > EPS &&
|
|
18
|
+
Math.min(a.maxY, b.maxY) - Math.max(a.minY, b.minY) > EPS
|
|
19
|
+
|
|
20
|
+
export const rangesOverlap = (
|
|
21
|
+
minA: number,
|
|
22
|
+
maxA: number,
|
|
23
|
+
minB: number,
|
|
24
|
+
maxB: number,
|
|
25
|
+
) => Math.min(maxA, maxB) - Math.max(minA, minB) > EPS
|
|
26
|
+
|
|
27
|
+
export const traceCrossesBoundsInterior = (
|
|
28
|
+
bounds: Bounds,
|
|
29
|
+
traceMap: Record<string, SolvedTracePath>,
|
|
30
|
+
) => {
|
|
31
|
+
for (const trace of Object.values(traceMap)) {
|
|
32
|
+
const points = trace.tracePath
|
|
33
|
+
for (let i = 0; i < points.length - 1; i++) {
|
|
34
|
+
if (segmentCrossesBoundsInterior(points[i]!, points[i + 1]!, bounds)) {
|
|
35
|
+
return true
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return false
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const segmentCrossesBoundsInterior = (p1: Point, p2: Point, bounds: Bounds) => {
|
|
44
|
+
const interiorBounds = {
|
|
45
|
+
minX: bounds.minX + TRACE_BOUNDARY_TOLERANCE,
|
|
46
|
+
minY: bounds.minY + TRACE_BOUNDARY_TOLERANCE,
|
|
47
|
+
maxX: bounds.maxX - TRACE_BOUNDARY_TOLERANCE,
|
|
48
|
+
maxY: bounds.maxY - TRACE_BOUNDARY_TOLERANCE,
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if (
|
|
52
|
+
interiorBounds.minX >= interiorBounds.maxX ||
|
|
53
|
+
interiorBounds.minY >= interiorBounds.maxY
|
|
54
|
+
) {
|
|
55
|
+
return false
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (sameX(p1, p2)) {
|
|
59
|
+
if (
|
|
60
|
+
p1.x <= interiorBounds.minX + EPS ||
|
|
61
|
+
p1.x >= interiorBounds.maxX - EPS
|
|
62
|
+
) {
|
|
63
|
+
return false
|
|
64
|
+
}
|
|
65
|
+
return rangesOverlap(
|
|
66
|
+
Math.min(p1.y, p2.y),
|
|
67
|
+
Math.max(p1.y, p2.y),
|
|
68
|
+
interiorBounds.minY,
|
|
69
|
+
interiorBounds.maxY,
|
|
70
|
+
)
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
if (sameY(p1, p2)) {
|
|
74
|
+
if (
|
|
75
|
+
p1.y <= interiorBounds.minY + EPS ||
|
|
76
|
+
p1.y >= interiorBounds.maxY - EPS
|
|
77
|
+
) {
|
|
78
|
+
return false
|
|
79
|
+
}
|
|
80
|
+
return rangesOverlap(
|
|
81
|
+
Math.min(p1.x, p2.x),
|
|
82
|
+
Math.max(p1.x, p2.x),
|
|
83
|
+
interiorBounds.minX,
|
|
84
|
+
interiorBounds.maxX,
|
|
85
|
+
)
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return false
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export const tracePathCrossesAnyTrace = (
|
|
92
|
+
tracePath: Point[],
|
|
93
|
+
traceMap: Record<string, SolvedTracePath>,
|
|
94
|
+
) => {
|
|
95
|
+
for (const trace of Object.values(traceMap)) {
|
|
96
|
+
const points = trace.tracePath
|
|
97
|
+
for (let i = 0; i < tracePath.length - 1; i++) {
|
|
98
|
+
for (let j = 0; j < points.length - 1; j++) {
|
|
99
|
+
if (
|
|
100
|
+
segmentsStrictlyCross(
|
|
101
|
+
tracePath[i]!,
|
|
102
|
+
tracePath[i + 1]!,
|
|
103
|
+
points[j]!,
|
|
104
|
+
points[j + 1]!,
|
|
105
|
+
)
|
|
106
|
+
) {
|
|
107
|
+
return true
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
return false
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
const segmentsStrictlyCross = (a1: Point, a2: Point, b1: Point, b2: Point) => {
|
|
117
|
+
if (sameX(a1, a2) && sameY(b1, b2)) {
|
|
118
|
+
return (
|
|
119
|
+
a1.x > Math.min(b1.x, b2.x) + EPS &&
|
|
120
|
+
a1.x < Math.max(b1.x, b2.x) - EPS &&
|
|
121
|
+
b1.y > Math.min(a1.y, a2.y) + EPS &&
|
|
122
|
+
b1.y < Math.max(a1.y, a2.y) - EPS
|
|
123
|
+
)
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
if (sameY(a1, a2) && sameX(b1, b2)) {
|
|
127
|
+
return (
|
|
128
|
+
b1.x > Math.min(a1.x, a2.x) + EPS &&
|
|
129
|
+
b1.x < Math.max(a1.x, a2.x) - EPS &&
|
|
130
|
+
a1.y > Math.min(b1.y, b2.y) + EPS &&
|
|
131
|
+
a1.y < Math.max(b1.y, b2.y) - EPS
|
|
132
|
+
)
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
return false
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
export const getSideDistances = (point: Point, bounds: Bounds) =>
|
|
139
|
+
[
|
|
140
|
+
["left", Math.abs(point.x - bounds.minX)] as const,
|
|
141
|
+
["right", Math.abs(point.x - bounds.maxX)] as const,
|
|
142
|
+
["bottom", Math.abs(point.y - bounds.minY)] as const,
|
|
143
|
+
["top", Math.abs(point.y - bounds.maxY)] as const,
|
|
144
|
+
] satisfies Array<readonly [ChipSide, number]>
|
|
145
|
+
|
|
146
|
+
export const getConnectorTracePath = (
|
|
147
|
+
source: Point,
|
|
148
|
+
target: Point,
|
|
149
|
+
orientation: FacingDirection,
|
|
150
|
+
) =>
|
|
151
|
+
simplifyOrthogonalPath(
|
|
152
|
+
isYOrientation(orientation)
|
|
153
|
+
? [source, { x: target.x, y: source.y }, target]
|
|
154
|
+
: [source, { x: source.x, y: target.y }, target],
|
|
155
|
+
)
|
|
156
|
+
|
|
157
|
+
const simplifyOrthogonalPath = (path: Point[]) => {
|
|
158
|
+
const deduped = path.filter(
|
|
159
|
+
(point, index) => index === 0 || !pointsEqual(point, path[index - 1]!),
|
|
160
|
+
)
|
|
161
|
+
if (deduped.length < 3) return deduped
|
|
162
|
+
|
|
163
|
+
const simplified: Point[] = [deduped[0]!]
|
|
164
|
+
for (let i = 1; i < deduped.length - 1; i++) {
|
|
165
|
+
const prev = simplified[simplified.length - 1]!
|
|
166
|
+
const point = deduped[i]!
|
|
167
|
+
const next = deduped[i + 1]!
|
|
168
|
+
if (
|
|
169
|
+
(sameX(prev, point) && sameX(point, next)) ||
|
|
170
|
+
(sameY(prev, point) && sameY(point, next))
|
|
171
|
+
) {
|
|
172
|
+
continue
|
|
173
|
+
}
|
|
174
|
+
simplified.push(point)
|
|
175
|
+
}
|
|
176
|
+
simplified.push(deduped[deduped.length - 1]!)
|
|
177
|
+
return simplified
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
const pointsEqual = (a: Point, b: Point) => sameX(a, b) && sameY(a, b)
|
|
181
|
+
|
|
182
|
+
const sameX = (a: Point, b: Point) => Math.abs(a.x - b.x) <= EPS
|
|
183
|
+
|
|
184
|
+
const sameY = (a: Point, b: Point) => Math.abs(a.y - b.y) <= EPS
|
|
185
|
+
|
|
186
|
+
export const getMaxSearchDistance = (inputProblem: InputProblem) => {
|
|
187
|
+
const maxChipWidth = Math.max(
|
|
188
|
+
...inputProblem.chips.map((chip) => chip.width),
|
|
189
|
+
1,
|
|
190
|
+
)
|
|
191
|
+
return maxChipWidth * 3
|
|
192
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { NetLabelPlacement } from "lib/solvers/NetLabelPlacementSolver/NetLabelPlacementSolver"
|
|
2
|
+
import type { SolvedTracePath } from "lib/solvers/SchematicTraceLinesSolver/SchematicTraceLinesSolver"
|
|
3
|
+
import type { InputPin, InputProblem } from "lib/types/InputProblem"
|
|
4
|
+
import type { CandidateLabel } from "./types"
|
|
5
|
+
|
|
6
|
+
export const getPinMap = (inputProblem: InputProblem) => {
|
|
7
|
+
const pinMap: Record<string, InputPin & { chipId: string }> = {}
|
|
8
|
+
for (const chip of inputProblem.chips) {
|
|
9
|
+
for (const pin of chip.pins) {
|
|
10
|
+
pinMap[pin.pinId] = { ...pin, chipId: chip.chipId }
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
return pinMap
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export const getTracePins = (
|
|
17
|
+
label: NetLabelPlacement,
|
|
18
|
+
pinMap: Record<string, InputPin & { chipId: string }>,
|
|
19
|
+
): SolvedTracePath["pins"] => {
|
|
20
|
+
const pins = label.pinIds.flatMap((pinId) => {
|
|
21
|
+
const pin = pinMap[pinId]
|
|
22
|
+
return pin ? [pin] : []
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
if (pins.length >= 2) return [pins[0]!, pins[1]!]
|
|
26
|
+
if (pins.length === 1) return [pins[0]!, pins[0]!]
|
|
27
|
+
|
|
28
|
+
const syntheticPin = {
|
|
29
|
+
pinId: `${label.globalConnNetId}-netlabel-anchor`,
|
|
30
|
+
x: label.anchorPoint.x,
|
|
31
|
+
y: label.anchorPoint.y,
|
|
32
|
+
chipId: "available-net-orientation",
|
|
33
|
+
}
|
|
34
|
+
return [syntheticPin, syntheticPin]
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export const toNetLabelPlacementPatch = (candidate: CandidateLabel) => ({
|
|
38
|
+
orientation: candidate.orientation,
|
|
39
|
+
anchorPoint: candidate.anchorPoint,
|
|
40
|
+
center: candidate.center,
|
|
41
|
+
width: candidate.width,
|
|
42
|
+
height: candidate.height,
|
|
43
|
+
})
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { Point } from "@tscircuit/math-utils"
|
|
2
|
+
import type { NetLabelPlacement } from "lib/solvers/NetLabelPlacementSolver/NetLabelPlacementSolver"
|
|
3
|
+
import type { SolvedTracePath } from "lib/solvers/SchematicTraceLinesSolver/SchematicTraceLinesSolver"
|
|
4
|
+
import type { InputProblem } from "lib/types/InputProblem"
|
|
5
|
+
import type { FacingDirection } from "lib/utils/dir"
|
|
6
|
+
|
|
7
|
+
export interface AvailableNetOrientationSolverParams {
|
|
8
|
+
inputProblem: InputProblem
|
|
9
|
+
traces: SolvedTracePath[]
|
|
10
|
+
netLabelPlacements: NetLabelPlacement[]
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export type Bounds = {
|
|
14
|
+
minX: number
|
|
15
|
+
minY: number
|
|
16
|
+
maxX: number
|
|
17
|
+
maxY: number
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export type ChipSide = "left" | "right" | "top" | "bottom"
|
|
21
|
+
|
|
22
|
+
export type CandidateLabel = {
|
|
23
|
+
orientation: FacingDirection
|
|
24
|
+
anchorPoint: Point
|
|
25
|
+
center: Point
|
|
26
|
+
width: number
|
|
27
|
+
height: number
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export type CandidateStatus =
|
|
31
|
+
| "valid"
|
|
32
|
+
| "chip-collision"
|
|
33
|
+
| "trace-collision"
|
|
34
|
+
| "netlabel-collision"
|
|
35
|
+
|
|
36
|
+
export type CandidatePhase = "rotate" | "shift"
|
|
37
|
+
|
|
38
|
+
export type EvaluatedCandidate = CandidateLabel & {
|
|
39
|
+
status: CandidateStatus
|
|
40
|
+
selected: boolean
|
|
41
|
+
phase: CandidatePhase
|
|
42
|
+
distance?: number
|
|
43
|
+
outwardDistance?: number
|
|
44
|
+
}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import type { GraphicsObject } from "graphics-debug"
|
|
2
|
+
import type { NetLabelPlacement } from "lib/solvers/NetLabelPlacementSolver/NetLabelPlacementSolver"
|
|
3
|
+
import type { SolvedTracePath } from "lib/solvers/SchematicTraceLinesSolver/SchematicTraceLinesSolver"
|
|
4
|
+
import { visualizeInputProblem } from "lib/solvers/SchematicTracePipelineSolver/visualizeInputProblem"
|
|
5
|
+
import type { InputProblem } from "lib/types/InputProblem"
|
|
6
|
+
import { getColorFromString } from "lib/utils/getColorFromString"
|
|
7
|
+
import { CANDIDATE_REJECTED_COLOR, CANDIDATE_SELECTED_COLOR } from "./constants"
|
|
8
|
+
import type { EvaluatedCandidate } from "./types"
|
|
9
|
+
|
|
10
|
+
export const visualizeAvailableNetOrientationSolver = (params: {
|
|
11
|
+
inputProblem: InputProblem
|
|
12
|
+
traces: SolvedTracePath[]
|
|
13
|
+
outputNetLabelPlacements: NetLabelPlacement[]
|
|
14
|
+
currentLabel: NetLabelPlacement | null
|
|
15
|
+
currentCandidateResults: EvaluatedCandidate[]
|
|
16
|
+
solved: boolean
|
|
17
|
+
}): GraphicsObject => {
|
|
18
|
+
const graphics = visualizeInputProblem(params.inputProblem)
|
|
19
|
+
ensureGraphicsArrays(graphics)
|
|
20
|
+
|
|
21
|
+
drawTraces(graphics, params.traces)
|
|
22
|
+
drawNetLabels(graphics, params.outputNetLabelPlacements)
|
|
23
|
+
drawCurrentLabel(graphics, params.currentLabel, params.solved)
|
|
24
|
+
drawCurrentCandidates(graphics, params.currentCandidateResults, params.solved)
|
|
25
|
+
|
|
26
|
+
return graphics
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const drawTraces = (graphics: GraphicsObject, traces: SolvedTracePath[]) => {
|
|
30
|
+
for (const trace of traces) {
|
|
31
|
+
graphics.lines!.push({
|
|
32
|
+
points: trace.tracePath,
|
|
33
|
+
strokeColor: "purple",
|
|
34
|
+
} as any)
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const drawNetLabels = (
|
|
39
|
+
graphics: GraphicsObject,
|
|
40
|
+
labels: NetLabelPlacement[],
|
|
41
|
+
) => {
|
|
42
|
+
for (const label of labels) {
|
|
43
|
+
graphics.rects!.push({
|
|
44
|
+
center: label.center,
|
|
45
|
+
width: label.width,
|
|
46
|
+
height: label.height,
|
|
47
|
+
fill: getColorFromString(label.globalConnNetId, 0.35),
|
|
48
|
+
strokeColor: getColorFromString(label.globalConnNetId, 0.9),
|
|
49
|
+
label: `netId: ${label.netId}\nglobalConnNetId: ${label.globalConnNetId}`,
|
|
50
|
+
} as any)
|
|
51
|
+
graphics.points!.push({
|
|
52
|
+
x: label.anchorPoint.x,
|
|
53
|
+
y: label.anchorPoint.y,
|
|
54
|
+
color: getColorFromString(label.globalConnNetId, 0.9),
|
|
55
|
+
label: `anchorPoint\norientation: ${label.orientation}`,
|
|
56
|
+
} as any)
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const drawCurrentLabel = (
|
|
61
|
+
graphics: GraphicsObject,
|
|
62
|
+
currentLabel: NetLabelPlacement | null,
|
|
63
|
+
solved: boolean,
|
|
64
|
+
) => {
|
|
65
|
+
if (!currentLabel || solved) return
|
|
66
|
+
|
|
67
|
+
graphics.rects!.push({
|
|
68
|
+
center: currentLabel.center,
|
|
69
|
+
width: currentLabel.width,
|
|
70
|
+
height: currentLabel.height,
|
|
71
|
+
fill: "rgba(255, 0, 0, 0.2)",
|
|
72
|
+
strokeColor: CANDIDATE_REJECTED_COLOR,
|
|
73
|
+
label: `available orientation target\n${currentLabel.netId ?? currentLabel.globalConnNetId}`,
|
|
74
|
+
} as any)
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const drawCurrentCandidates = (
|
|
78
|
+
graphics: GraphicsObject,
|
|
79
|
+
candidates: EvaluatedCandidate[],
|
|
80
|
+
solved: boolean,
|
|
81
|
+
) => {
|
|
82
|
+
if (solved) return
|
|
83
|
+
|
|
84
|
+
for (const candidate of candidates) {
|
|
85
|
+
const color = candidate.selected
|
|
86
|
+
? CANDIDATE_SELECTED_COLOR
|
|
87
|
+
: CANDIDATE_REJECTED_COLOR
|
|
88
|
+
const distanceLabel =
|
|
89
|
+
candidate.distance === undefined
|
|
90
|
+
? ""
|
|
91
|
+
: `\ndistance: ${candidate.distance.toFixed(3)}`
|
|
92
|
+
const outwardDistanceLabel =
|
|
93
|
+
candidate.outwardDistance === undefined || candidate.outwardDistance === 0
|
|
94
|
+
? ""
|
|
95
|
+
: `\noutward distance: ${candidate.outwardDistance.toFixed(3)}`
|
|
96
|
+
|
|
97
|
+
graphics.rects!.push({
|
|
98
|
+
center: candidate.center,
|
|
99
|
+
width: candidate.width,
|
|
100
|
+
height: candidate.height,
|
|
101
|
+
fill: candidate.selected
|
|
102
|
+
? "rgba(0, 0, 255, 0.2)"
|
|
103
|
+
: "rgba(255, 0, 0, 0.15)",
|
|
104
|
+
strokeColor: color,
|
|
105
|
+
strokeDash: candidate.selected ? undefined : "4 2",
|
|
106
|
+
label: `${candidate.selected ? "selected" : candidate.status} available orientation\nphase: ${candidate.phase}\norientation: ${candidate.orientation}${distanceLabel}${outwardDistanceLabel}`,
|
|
107
|
+
} as any)
|
|
108
|
+
graphics.points!.push({
|
|
109
|
+
x: candidate.anchorPoint.x,
|
|
110
|
+
y: candidate.anchorPoint.y,
|
|
111
|
+
color,
|
|
112
|
+
label: `candidate anchor\n${candidate.phase}\n${candidate.orientation}`,
|
|
113
|
+
} as any)
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
const ensureGraphicsArrays = (graphics: GraphicsObject) => {
|
|
118
|
+
if (!graphics.lines) graphics.lines = []
|
|
119
|
+
if (!graphics.points) graphics.points = []
|
|
120
|
+
if (!graphics.rects) graphics.rects = []
|
|
121
|
+
if (!graphics.circles) graphics.circles = []
|
|
122
|
+
if (!graphics.texts) graphics.texts = []
|
|
123
|
+
}
|
|
@@ -21,6 +21,8 @@ import { LongDistancePairSolver } from "../LongDistancePairSolver/LongDistancePa
|
|
|
21
21
|
import { MergedNetLabelObstacleSolver } from "../TraceLabelOverlapAvoidanceSolver/sub-solvers/LabelMergingSolver/LabelMergingSolver"
|
|
22
22
|
import { TraceCleanupSolver } from "../TraceCleanupSolver/TraceCleanupSolver"
|
|
23
23
|
import { Example28Solver } from "../Example28Solver/Example28Solver"
|
|
24
|
+
import { AvailableNetOrientationSolver } from "../AvailableNetOrientationSolver/AvailableNetOrientationSolver"
|
|
25
|
+
import { VccNetLabelCornerPlacementSolver } from "../VccNetLabelCornerPlacementSolver/VccNetLabelCornerPlacementSolver"
|
|
24
26
|
|
|
25
27
|
type PipelineStep<T extends new (...args: any[]) => BaseSolver> = {
|
|
26
28
|
solverName: string
|
|
@@ -71,6 +73,8 @@ export class SchematicTracePipelineSolver extends BaseSolver {
|
|
|
71
73
|
traceLabelOverlapAvoidanceSolver?: TraceLabelOverlapAvoidanceSolver
|
|
72
74
|
traceCleanupSolver?: TraceCleanupSolver
|
|
73
75
|
example28Solver?: Example28Solver
|
|
76
|
+
availableNetOrientationSolver?: AvailableNetOrientationSolver
|
|
77
|
+
vccNetLabelCornerPlacementSolver?: VccNetLabelCornerPlacementSolver
|
|
74
78
|
|
|
75
79
|
startTimeOfPhase: Record<string, number>
|
|
76
80
|
endTimeOfPhase: Record<string, number>
|
|
@@ -240,6 +244,32 @@ export class SchematicTracePipelineSolver extends BaseSolver {
|
|
|
240
244
|
},
|
|
241
245
|
]
|
|
242
246
|
}),
|
|
247
|
+
definePipelineStep(
|
|
248
|
+
"availableNetOrientationSolver",
|
|
249
|
+
AvailableNetOrientationSolver,
|
|
250
|
+
(instance) => [
|
|
251
|
+
{
|
|
252
|
+
inputProblem: instance.inputProblem,
|
|
253
|
+
traces: instance.example28Solver!.outputTraces,
|
|
254
|
+
netLabelPlacements:
|
|
255
|
+
instance.example28Solver!.outputNetLabelPlacements,
|
|
256
|
+
},
|
|
257
|
+
],
|
|
258
|
+
),
|
|
259
|
+
definePipelineStep(
|
|
260
|
+
"vccNetLabelCornerPlacementSolver",
|
|
261
|
+
VccNetLabelCornerPlacementSolver,
|
|
262
|
+
(instance) => {
|
|
263
|
+
return [
|
|
264
|
+
{
|
|
265
|
+
inputProblem: instance.inputProblem,
|
|
266
|
+
traces: instance.availableNetOrientationSolver!.traces,
|
|
267
|
+
netLabelPlacements:
|
|
268
|
+
instance.availableNetOrientationSolver!.outputNetLabelPlacements,
|
|
269
|
+
},
|
|
270
|
+
]
|
|
271
|
+
},
|
|
272
|
+
),
|
|
243
273
|
]
|
|
244
274
|
|
|
245
275
|
constructor(inputProblem: InputProblem) {
|