@tscircuit/schematic-trace-solver 0.0.35 → 0.0.36
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 -0
- package/dist/index.js +37 -11
- package/lib/solvers/NetLabelPlacementSolver/NetLabelPlacementSolver.ts +13 -0
- package/lib/solvers/NetLabelPlacementSolver/SingleNetLabelPlacementSolver/SingleNetLabelPlacementSolver.ts +11 -1
- package/lib/solvers/NetLabelPlacementSolver/SingleNetLabelPlacementSolver/geometry.ts +13 -3
- package/lib/solvers/NetLabelPlacementSolver/SingleNetLabelPlacementSolver/solvePortOnlyPin.ts +10 -2
- package/lib/types/InputProblem.ts +1 -0
- package/package.json +1 -1
- package/tests/examples/__snapshots__/example20.snap.svg +235 -0
- package/tests/examples/example20.test.tsx +190 -0
package/dist/index.d.ts
CHANGED
|
@@ -79,6 +79,7 @@ interface InputDirectConnection {
|
|
|
79
79
|
interface InputNetConnection {
|
|
80
80
|
netId: string;
|
|
81
81
|
pinIds: Array<PinId>;
|
|
82
|
+
netLabelWidth?: number;
|
|
82
83
|
}
|
|
83
84
|
interface InputProblem {
|
|
84
85
|
chips: Array<InputChip>;
|
|
@@ -279,6 +280,7 @@ declare class SingleNetLabelPlacementSolver extends BaseSolver {
|
|
|
279
280
|
overlappingSameNetTraceGroup: OverlappingSameNetTraceGroup;
|
|
280
281
|
availableOrientations: Array<FacingDirection>;
|
|
281
282
|
chipObstacleSpatialIndex: ChipObstacleSpatialIndex;
|
|
283
|
+
netLabelWidth?: number;
|
|
282
284
|
netLabelPlacement: NetLabelPlacement | null;
|
|
283
285
|
testedCandidates: Array<{
|
|
284
286
|
center: {
|
|
@@ -306,6 +308,7 @@ declare class SingleNetLabelPlacementSolver extends BaseSolver {
|
|
|
306
308
|
inputTraceMap: Record<MspConnectionPairId, SolvedTracePath>;
|
|
307
309
|
overlappingSameNetTraceGroup: OverlappingSameNetTraceGroup;
|
|
308
310
|
availableOrientations: FacingDirection[];
|
|
311
|
+
netLabelWidth?: number;
|
|
309
312
|
});
|
|
310
313
|
getConstructorParams(): ConstructorParameters<typeof SingleNetLabelPlacementSolver>[0];
|
|
311
314
|
_step(): void;
|
package/dist/index.js
CHANGED
|
@@ -1371,15 +1371,18 @@ var ChipObstacleSpatialIndex = class {
|
|
|
1371
1371
|
// lib/solvers/NetLabelPlacementSolver/SingleNetLabelPlacementSolver/geometry.ts
|
|
1372
1372
|
var NET_LABEL_HORIZONTAL_WIDTH = 0.45;
|
|
1373
1373
|
var NET_LABEL_HORIZONTAL_HEIGHT = 0.2;
|
|
1374
|
-
function getDimsForOrientation(
|
|
1374
|
+
function getDimsForOrientation(params) {
|
|
1375
|
+
const { orientation, netLabelWidth } = params;
|
|
1376
|
+
const horizWidth = typeof netLabelWidth === "number" ? netLabelWidth : NET_LABEL_HORIZONTAL_WIDTH;
|
|
1375
1377
|
if (orientation === "y+" || orientation === "y-") {
|
|
1376
1378
|
return {
|
|
1379
|
+
// Rotated, so width/height swap
|
|
1377
1380
|
width: NET_LABEL_HORIZONTAL_HEIGHT,
|
|
1378
|
-
height:
|
|
1381
|
+
height: horizWidth
|
|
1379
1382
|
};
|
|
1380
1383
|
}
|
|
1381
1384
|
return {
|
|
1382
|
-
width:
|
|
1385
|
+
width: horizWidth,
|
|
1383
1386
|
height: NET_LABEL_HORIZONTAL_HEIGHT
|
|
1384
1387
|
};
|
|
1385
1388
|
}
|
|
@@ -1508,7 +1511,8 @@ function solveNetLabelPlacementForPortOnlyPin(params) {
|
|
|
1508
1511
|
inputTraceMap,
|
|
1509
1512
|
chipObstacleSpatialIndex,
|
|
1510
1513
|
overlappingSameNetTraceGroup,
|
|
1511
|
-
availableOrientations
|
|
1514
|
+
availableOrientations,
|
|
1515
|
+
netLabelWidth
|
|
1512
1516
|
} = params;
|
|
1513
1517
|
const pinId = overlappingSameNetTraceGroup.portOnlyPinId;
|
|
1514
1518
|
if (!pinId) {
|
|
@@ -1540,7 +1544,10 @@ function solveNetLabelPlacementForPortOnlyPin(params) {
|
|
|
1540
1544
|
const outwardOf = (o) => o === "x+" ? { x: 1, y: 0 } : o === "x-" ? { x: -1, y: 0 } : o === "y+" ? { x: 0, y: 1 } : { x: 0, y: -1 };
|
|
1541
1545
|
const testedCandidates = [];
|
|
1542
1546
|
for (const orientation of orientations) {
|
|
1543
|
-
const { width: width2, height: height2 } = getDimsForOrientation(
|
|
1547
|
+
const { width: width2, height: height2 } = getDimsForOrientation({
|
|
1548
|
+
orientation,
|
|
1549
|
+
netLabelWidth
|
|
1550
|
+
});
|
|
1544
1551
|
const baseCenter2 = getCenterFromAnchor(anchor, orientation, width2, height2);
|
|
1545
1552
|
const outward2 = outwardOf(orientation);
|
|
1546
1553
|
const offset2 = 1e-3;
|
|
@@ -1607,7 +1614,10 @@ function solveNetLabelPlacementForPortOnlyPin(params) {
|
|
|
1607
1614
|
return { placement, testedCandidates };
|
|
1608
1615
|
}
|
|
1609
1616
|
const fallbackOrientation = pinFacingDirection;
|
|
1610
|
-
const { width, height } = getDimsForOrientation(
|
|
1617
|
+
const { width, height } = getDimsForOrientation({
|
|
1618
|
+
orientation: fallbackOrientation,
|
|
1619
|
+
netLabelWidth
|
|
1620
|
+
});
|
|
1611
1621
|
const baseCenter = getCenterFromAnchor(
|
|
1612
1622
|
anchor,
|
|
1613
1623
|
fallbackOrientation,
|
|
@@ -1699,6 +1709,8 @@ var SingleNetLabelPlacementSolver = class extends BaseSolver {
|
|
|
1699
1709
|
overlappingSameNetTraceGroup;
|
|
1700
1710
|
availableOrientations;
|
|
1701
1711
|
chipObstacleSpatialIndex;
|
|
1712
|
+
// Optional override for the width of the net label (per netId)
|
|
1713
|
+
netLabelWidth;
|
|
1702
1714
|
netLabelPlacement = null;
|
|
1703
1715
|
testedCandidates = [];
|
|
1704
1716
|
constructor(params) {
|
|
@@ -1707,6 +1719,7 @@ var SingleNetLabelPlacementSolver = class extends BaseSolver {
|
|
|
1707
1719
|
this.inputTraceMap = params.inputTraceMap;
|
|
1708
1720
|
this.overlappingSameNetTraceGroup = params.overlappingSameNetTraceGroup;
|
|
1709
1721
|
this.availableOrientations = params.availableOrientations;
|
|
1722
|
+
this.netLabelWidth = params.netLabelWidth;
|
|
1710
1723
|
this.chipObstacleSpatialIndex = params.inputProblem._chipObstacleSpatialIndex ?? new ChipObstacleSpatialIndex(params.inputProblem.chips);
|
|
1711
1724
|
}
|
|
1712
1725
|
getConstructorParams() {
|
|
@@ -1714,7 +1727,8 @@ var SingleNetLabelPlacementSolver = class extends BaseSolver {
|
|
|
1714
1727
|
inputProblem: this.inputProblem,
|
|
1715
1728
|
inputTraceMap: this.inputTraceMap,
|
|
1716
1729
|
overlappingSameNetTraceGroup: this.overlappingSameNetTraceGroup,
|
|
1717
|
-
availableOrientations: this.availableOrientations
|
|
1730
|
+
availableOrientations: this.availableOrientations,
|
|
1731
|
+
netLabelWidth: this.netLabelWidth
|
|
1718
1732
|
};
|
|
1719
1733
|
}
|
|
1720
1734
|
_step() {
|
|
@@ -1728,7 +1742,8 @@ var SingleNetLabelPlacementSolver = class extends BaseSolver {
|
|
|
1728
1742
|
inputTraceMap: this.inputTraceMap,
|
|
1729
1743
|
chipObstacleSpatialIndex: this.chipObstacleSpatialIndex,
|
|
1730
1744
|
overlappingSameNetTraceGroup: this.overlappingSameNetTraceGroup,
|
|
1731
|
-
availableOrientations: this.availableOrientations
|
|
1745
|
+
availableOrientations: this.availableOrientations,
|
|
1746
|
+
netLabelWidth: this.netLabelWidth
|
|
1732
1747
|
});
|
|
1733
1748
|
this.testedCandidates.push(...res.testedCandidates);
|
|
1734
1749
|
if (res.placement) {
|
|
@@ -1796,7 +1811,10 @@ var SingleNetLabelPlacementSolver = class extends BaseSolver {
|
|
|
1796
1811
|
const anchors = anchorsForSegment(a, b);
|
|
1797
1812
|
for (const anchor of anchors) {
|
|
1798
1813
|
for (const orientation of candidateOrients) {
|
|
1799
|
-
const { width, height } = getDimsForOrientation(
|
|
1814
|
+
const { width, height } = getDimsForOrientation({
|
|
1815
|
+
orientation,
|
|
1816
|
+
netLabelWidth: this.netLabelWidth
|
|
1817
|
+
});
|
|
1800
1818
|
const center = getCenterFromAnchor(
|
|
1801
1819
|
anchor,
|
|
1802
1820
|
orientation,
|
|
@@ -2075,11 +2093,15 @@ var NetLabelPlacementSolver = class extends BaseSolver {
|
|
|
2075
2093
|
const isAlreadyFull = currOrients.length === 4 && fullOrients.every((o) => currOrients.includes(o));
|
|
2076
2094
|
if (!this.triedAnyOrientationFallbackForCurrentGroup && !isAlreadyFull && this.currentGroup) {
|
|
2077
2095
|
this.triedAnyOrientationFallbackForCurrentGroup = true;
|
|
2096
|
+
const netLabelWidth2 = this.currentGroup.netId ? this.inputProblem.netConnections.find(
|
|
2097
|
+
(nc) => nc.netId === this.currentGroup.netId
|
|
2098
|
+
)?.netLabelWidth : void 0;
|
|
2078
2099
|
this.activeSubSolver = new SingleNetLabelPlacementSolver({
|
|
2079
2100
|
inputProblem: this.inputProblem,
|
|
2080
2101
|
inputTraceMap: this.inputTraceMap,
|
|
2081
2102
|
overlappingSameNetTraceGroup: this.currentGroup,
|
|
2082
|
-
availableOrientations: fullOrients
|
|
2103
|
+
availableOrientations: fullOrients,
|
|
2104
|
+
netLabelWidth: netLabelWidth2
|
|
2083
2105
|
});
|
|
2084
2106
|
return;
|
|
2085
2107
|
}
|
|
@@ -2099,11 +2121,15 @@ var NetLabelPlacementSolver = class extends BaseSolver {
|
|
|
2099
2121
|
const netId = nextOverlappingSameNetTraceGroup.netId ?? nextOverlappingSameNetTraceGroup.globalConnNetId;
|
|
2100
2122
|
this.currentGroup = nextOverlappingSameNetTraceGroup;
|
|
2101
2123
|
this.triedAnyOrientationFallbackForCurrentGroup = false;
|
|
2124
|
+
const netLabelWidth = this.currentGroup.netId ? this.inputProblem.netConnections.find(
|
|
2125
|
+
(nc) => nc.netId === this.currentGroup.netId
|
|
2126
|
+
)?.netLabelWidth : void 0;
|
|
2102
2127
|
this.activeSubSolver = new SingleNetLabelPlacementSolver({
|
|
2103
2128
|
inputProblem: this.inputProblem,
|
|
2104
2129
|
inputTraceMap: this.inputTraceMap,
|
|
2105
2130
|
overlappingSameNetTraceGroup: nextOverlappingSameNetTraceGroup,
|
|
2106
|
-
availableOrientations: this.inputProblem.availableNetLabelOrientations[netId] ?? ["x+", "x-", "y+", "y-"]
|
|
2131
|
+
availableOrientations: this.inputProblem.availableNetLabelOrientations[netId] ?? ["x+", "x-", "y+", "y-"],
|
|
2132
|
+
netLabelWidth
|
|
2107
2133
|
});
|
|
2108
2134
|
}
|
|
2109
2135
|
visualize() {
|
|
@@ -273,11 +273,17 @@ export class NetLabelPlacementSolver extends BaseSolver {
|
|
|
273
273
|
this.currentGroup
|
|
274
274
|
) {
|
|
275
275
|
this.triedAnyOrientationFallbackForCurrentGroup = true
|
|
276
|
+
const netLabelWidth = this.currentGroup.netId
|
|
277
|
+
? this.inputProblem.netConnections.find(
|
|
278
|
+
(nc) => nc.netId === this.currentGroup!.netId,
|
|
279
|
+
)?.netLabelWidth
|
|
280
|
+
: undefined
|
|
276
281
|
this.activeSubSolver = new SingleNetLabelPlacementSolver({
|
|
277
282
|
inputProblem: this.inputProblem,
|
|
278
283
|
inputTraceMap: this.inputTraceMap,
|
|
279
284
|
overlappingSameNetTraceGroup: this.currentGroup,
|
|
280
285
|
availableOrientations: fullOrients,
|
|
286
|
+
netLabelWidth,
|
|
281
287
|
})
|
|
282
288
|
return
|
|
283
289
|
}
|
|
@@ -307,6 +313,12 @@ export class NetLabelPlacementSolver extends BaseSolver {
|
|
|
307
313
|
this.currentGroup = nextOverlappingSameNetTraceGroup
|
|
308
314
|
this.triedAnyOrientationFallbackForCurrentGroup = false
|
|
309
315
|
|
|
316
|
+
const netLabelWidth = this.currentGroup.netId
|
|
317
|
+
? this.inputProblem.netConnections.find(
|
|
318
|
+
(nc) => nc.netId === this.currentGroup!.netId,
|
|
319
|
+
)?.netLabelWidth
|
|
320
|
+
: undefined
|
|
321
|
+
|
|
310
322
|
this.activeSubSolver = new SingleNetLabelPlacementSolver({
|
|
311
323
|
inputProblem: this.inputProblem,
|
|
312
324
|
inputTraceMap: this.inputTraceMap,
|
|
@@ -314,6 +326,7 @@ export class NetLabelPlacementSolver extends BaseSolver {
|
|
|
314
326
|
availableOrientations: this.inputProblem.availableNetLabelOrientations[
|
|
315
327
|
netId
|
|
316
328
|
] ?? ["x+", "x-", "y+", "y-"],
|
|
329
|
+
netLabelWidth,
|
|
317
330
|
})
|
|
318
331
|
}
|
|
319
332
|
|
|
@@ -58,6 +58,9 @@ export class SingleNetLabelPlacementSolver extends BaseSolver {
|
|
|
58
58
|
|
|
59
59
|
chipObstacleSpatialIndex: ChipObstacleSpatialIndex
|
|
60
60
|
|
|
61
|
+
// Optional override for the width of the net label (per netId)
|
|
62
|
+
netLabelWidth?: number
|
|
63
|
+
|
|
61
64
|
netLabelPlacement: NetLabelPlacement | null = null
|
|
62
65
|
testedCandidates: Array<{
|
|
63
66
|
center: { x: number; y: number }
|
|
@@ -75,12 +78,14 @@ export class SingleNetLabelPlacementSolver extends BaseSolver {
|
|
|
75
78
|
inputTraceMap: Record<MspConnectionPairId, SolvedTracePath>
|
|
76
79
|
overlappingSameNetTraceGroup: OverlappingSameNetTraceGroup
|
|
77
80
|
availableOrientations: FacingDirection[]
|
|
81
|
+
netLabelWidth?: number
|
|
78
82
|
}) {
|
|
79
83
|
super()
|
|
80
84
|
this.inputProblem = params.inputProblem
|
|
81
85
|
this.inputTraceMap = params.inputTraceMap
|
|
82
86
|
this.overlappingSameNetTraceGroup = params.overlappingSameNetTraceGroup
|
|
83
87
|
this.availableOrientations = params.availableOrientations
|
|
88
|
+
this.netLabelWidth = params.netLabelWidth
|
|
84
89
|
|
|
85
90
|
this.chipObstacleSpatialIndex =
|
|
86
91
|
params.inputProblem._chipObstacleSpatialIndex ??
|
|
@@ -95,6 +100,7 @@ export class SingleNetLabelPlacementSolver extends BaseSolver {
|
|
|
95
100
|
inputTraceMap: this.inputTraceMap,
|
|
96
101
|
overlappingSameNetTraceGroup: this.overlappingSameNetTraceGroup,
|
|
97
102
|
availableOrientations: this.availableOrientations,
|
|
103
|
+
netLabelWidth: this.netLabelWidth,
|
|
98
104
|
}
|
|
99
105
|
}
|
|
100
106
|
|
|
@@ -112,6 +118,7 @@ export class SingleNetLabelPlacementSolver extends BaseSolver {
|
|
|
112
118
|
chipObstacleSpatialIndex: this.chipObstacleSpatialIndex,
|
|
113
119
|
overlappingSameNetTraceGroup: this.overlappingSameNetTraceGroup,
|
|
114
120
|
availableOrientations: this.availableOrientations,
|
|
121
|
+
netLabelWidth: this.netLabelWidth,
|
|
115
122
|
})
|
|
116
123
|
this.testedCandidates.push(...res.testedCandidates)
|
|
117
124
|
if (res.placement) {
|
|
@@ -220,7 +227,10 @@ export class SingleNetLabelPlacementSolver extends BaseSolver {
|
|
|
220
227
|
const anchors = anchorsForSegment(a, b)
|
|
221
228
|
for (const anchor of anchors) {
|
|
222
229
|
for (const orientation of candidateOrients) {
|
|
223
|
-
const { width, height } = getDimsForOrientation(
|
|
230
|
+
const { width, height } = getDimsForOrientation({
|
|
231
|
+
orientation,
|
|
232
|
+
netLabelWidth: this.netLabelWidth,
|
|
233
|
+
})
|
|
224
234
|
const center = getCenterFromAnchor(
|
|
225
235
|
anchor,
|
|
226
236
|
orientation,
|
|
@@ -3,15 +3,25 @@ import type { FacingDirection } from "lib/utils/dir"
|
|
|
3
3
|
export const NET_LABEL_HORIZONTAL_WIDTH = 0.45
|
|
4
4
|
export const NET_LABEL_HORIZONTAL_HEIGHT = 0.2
|
|
5
5
|
|
|
6
|
-
export function getDimsForOrientation(
|
|
6
|
+
export function getDimsForOrientation(params: {
|
|
7
|
+
orientation: FacingDirection
|
|
8
|
+
netLabelWidth?: number
|
|
9
|
+
}) {
|
|
10
|
+
const { orientation, netLabelWidth } = params
|
|
11
|
+
const horizWidth =
|
|
12
|
+
typeof netLabelWidth === "number"
|
|
13
|
+
? netLabelWidth
|
|
14
|
+
: NET_LABEL_HORIZONTAL_WIDTH
|
|
15
|
+
|
|
7
16
|
if (orientation === "y+" || orientation === "y-") {
|
|
8
17
|
return {
|
|
18
|
+
// Rotated, so width/height swap
|
|
9
19
|
width: NET_LABEL_HORIZONTAL_HEIGHT,
|
|
10
|
-
height:
|
|
20
|
+
height: horizWidth,
|
|
11
21
|
}
|
|
12
22
|
}
|
|
13
23
|
return {
|
|
14
|
-
width:
|
|
24
|
+
width: horizWidth,
|
|
15
25
|
height: NET_LABEL_HORIZONTAL_HEIGHT,
|
|
16
26
|
}
|
|
17
27
|
}
|
package/lib/solvers/NetLabelPlacementSolver/SingleNetLabelPlacementSolver/solvePortOnlyPin.ts
CHANGED
|
@@ -21,6 +21,7 @@ export function solveNetLabelPlacementForPortOnlyPin(params: {
|
|
|
21
21
|
chipObstacleSpatialIndex: ChipObstacleSpatialIndex
|
|
22
22
|
overlappingSameNetTraceGroup: OverlappingSameNetTraceGroup
|
|
23
23
|
availableOrientations: FacingDirection[]
|
|
24
|
+
netLabelWidth?: number
|
|
24
25
|
}): {
|
|
25
26
|
placement: NetLabelPlacement | null
|
|
26
27
|
testedCandidates: Array<{
|
|
@@ -41,6 +42,7 @@ export function solveNetLabelPlacementForPortOnlyPin(params: {
|
|
|
41
42
|
chipObstacleSpatialIndex,
|
|
42
43
|
overlappingSameNetTraceGroup,
|
|
43
44
|
availableOrientations,
|
|
45
|
+
netLabelWidth,
|
|
44
46
|
} = params
|
|
45
47
|
|
|
46
48
|
const pinId = overlappingSameNetTraceGroup.portOnlyPinId
|
|
@@ -98,7 +100,10 @@ export function solveNetLabelPlacementForPortOnlyPin(params: {
|
|
|
98
100
|
}> = []
|
|
99
101
|
|
|
100
102
|
for (const orientation of orientations) {
|
|
101
|
-
const { width, height } = getDimsForOrientation(
|
|
103
|
+
const { width, height } = getDimsForOrientation({
|
|
104
|
+
orientation,
|
|
105
|
+
netLabelWidth,
|
|
106
|
+
})
|
|
102
107
|
// Place label fully outside the chip: shift center slightly outward
|
|
103
108
|
const baseCenter = getCenterFromAnchor(anchor, orientation, width, height)
|
|
104
109
|
const outward = outwardOf(orientation)
|
|
@@ -176,7 +181,10 @@ export function solveNetLabelPlacementForPortOnlyPin(params: {
|
|
|
176
181
|
|
|
177
182
|
// If no valid placements found, return placement using pin's facing direction
|
|
178
183
|
const fallbackOrientation = pinFacingDirection
|
|
179
|
-
const { width, height } = getDimsForOrientation(
|
|
184
|
+
const { width, height } = getDimsForOrientation({
|
|
185
|
+
orientation: fallbackOrientation,
|
|
186
|
+
netLabelWidth,
|
|
187
|
+
})
|
|
180
188
|
const baseCenter = getCenterFromAnchor(
|
|
181
189
|
anchor,
|
|
182
190
|
fallbackOrientation,
|
package/package.json
CHANGED
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
<svg width="640" height="640" viewBox="0 0 640 640" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<rect width="100%" height="100%" fill="white" />
|
|
3
|
+
<g>
|
|
4
|
+
<circle data-type="point" data-label="U3.8
|
|
5
|
+
x-" data-x="-1.4" data-y="0.42500000000000004" cx="220.08485425212754" cy="293.25559941049465" r="3" fill="hsl(88, 100%, 50%, 0.8)" />
|
|
6
|
+
</g>
|
|
7
|
+
<g>
|
|
8
|
+
<circle data-type="point" data-label="U3.4
|
|
9
|
+
x-" data-x="-1.4" data-y="-0.42500000000000004" cx="220.08485425212754" cy="363.20249325997025" r="3" fill="hsl(84, 100%, 50%, 0.8)" />
|
|
10
|
+
</g>
|
|
11
|
+
<g>
|
|
12
|
+
<circle data-type="point" data-label="U3.1
|
|
13
|
+
x+" data-x="1.4" data-y="0.5" cx="450.49815163863525" cy="287.08381465907036" r="3" fill="hsl(81, 100%, 50%, 0.8)" />
|
|
14
|
+
</g>
|
|
15
|
+
<g>
|
|
16
|
+
<circle data-type="point" data-label="U3.6
|
|
17
|
+
x+" data-x="1.4" data-y="0.30000000000000004" cx="450.49815163863525" cy="303.5419073295352" r="3" fill="hsl(86, 100%, 50%, 0.8)" />
|
|
18
|
+
</g>
|
|
19
|
+
<g>
|
|
20
|
+
<circle data-type="point" data-label="U3.5
|
|
21
|
+
x+" data-x="1.4" data-y="0.10000000000000009" cx="450.49815163863525" cy="320" r="3" fill="hsl(85, 100%, 50%, 0.8)" />
|
|
22
|
+
</g>
|
|
23
|
+
<g>
|
|
24
|
+
<circle data-type="point" data-label="U3.2
|
|
25
|
+
x+" data-x="1.4" data-y="-0.09999999999999998" cx="450.49815163863525" cy="336.45809267046485" r="3" fill="hsl(82, 100%, 50%, 0.8)" />
|
|
26
|
+
</g>
|
|
27
|
+
<g>
|
|
28
|
+
<circle data-type="point" data-label="U3.3
|
|
29
|
+
x+" data-x="1.4" data-y="-0.3" cx="450.49815163863525" cy="352.9161853409297" r="3" fill="hsl(83, 100%, 50%, 0.8)" />
|
|
30
|
+
</g>
|
|
31
|
+
<g>
|
|
32
|
+
<circle data-type="point" data-label="U3.7
|
|
33
|
+
x+" data-x="1.4" data-y="-0.5" cx="450.49815163863525" cy="369.37427801139455" r="3" fill="hsl(87, 100%, 50%, 0.8)" />
|
|
34
|
+
</g>
|
|
35
|
+
<g>
|
|
36
|
+
<circle data-type="point" data-label="C20.1
|
|
37
|
+
y+" data-x="-2.3148566499999994" data-y="0.5512093000000002" cx="144.8008766226725" cy="282.86977763412216" r="3" fill="hsl(140, 100%, 50%, 0.8)" />
|
|
38
|
+
</g>
|
|
39
|
+
<g>
|
|
40
|
+
<circle data-type="point" data-label="C20.2
|
|
41
|
+
y-" data-x="-2.31430995" data-y="-0.5512093000000002" cx="144.84586481898717" cy="373.58831503634275" r="3" fill="hsl(141, 100%, 50%, 0.8)" />
|
|
42
|
+
</g>
|
|
43
|
+
<g>
|
|
44
|
+
<circle data-type="point" data-label="R11.1
|
|
45
|
+
y+" data-x="1.7580660749999977" data-y="2.3025814000000002" cx="479.96357486113317" cy="138.7485560227891" r="3" fill="hsl(125, 100%, 50%, 0.8)" />
|
|
46
|
+
</g>
|
|
47
|
+
<g>
|
|
48
|
+
<circle data-type="point" data-label="R11.2
|
|
49
|
+
y-" data-x="1.757519574999999" data-y="1.2" cx="479.91860312291124" cy="229.4804903124434" r="3" fill="hsl(126, 100%, 50%, 0.8)" />
|
|
50
|
+
</g>
|
|
51
|
+
<g>
|
|
52
|
+
<circle data-type="point" data-label="R12.1
|
|
53
|
+
y-" data-x="-1.7580660749999977" data-y="-3.3025814000000002" cx="190.61943102962965" cy="600" r="3" fill="hsl(6, 100%, 50%, 0.8)" />
|
|
54
|
+
</g>
|
|
55
|
+
<g>
|
|
56
|
+
<circle data-type="point" data-label="R12.2
|
|
57
|
+
y+" data-x="-1.757519574999999" data-y="-2.2" cx="190.66440276785158" cy="509.2680657103457" r="3" fill="hsl(7, 100%, 50%, 0.8)" />
|
|
58
|
+
</g>
|
|
59
|
+
<g>
|
|
60
|
+
<circle data-type="point" data-label="R13.1
|
|
61
|
+
y-" data-x="1.7580660749999977" data-y="-3.3025814000000002" cx="479.96357486113317" cy="600" r="3" fill="hsl(247, 100%, 50%, 0.8)" />
|
|
62
|
+
</g>
|
|
63
|
+
<g>
|
|
64
|
+
<circle data-type="point" data-label="R13.2
|
|
65
|
+
y+" data-x="1.757519574999999" data-y="-2.2" cx="479.91860312291124" cy="509.2680657103457" r="3" fill="hsl(248, 100%, 50%, 0.8)" />
|
|
66
|
+
</g>
|
|
67
|
+
<g>
|
|
68
|
+
<circle data-type="point" data-label="" data-x="-1.8574283249999997" data-y="0.7512093000000004" cx="182.44286543740003" cy="266.4116849636573" r="3" fill="hsl(40, 100%, 50%, 0.9)" />
|
|
69
|
+
</g>
|
|
70
|
+
<g>
|
|
71
|
+
<circle data-type="point" data-label="" data-x="1.5790330374999988" data-y="2.5025814000000004" cx="465.23086324988424" cy="122.29046335232425" r="3" fill="hsl(40, 100%, 50%, 0.9)" />
|
|
72
|
+
</g>
|
|
73
|
+
<g>
|
|
74
|
+
<circle data-type="point" data-label="" data-x="-2.31430995" data-y="-0.7512093000000004" cx="144.84586481898717" cy="390.0464077068076" r="3" fill="hsl(40, 100%, 50%, 0.9)" />
|
|
75
|
+
</g>
|
|
76
|
+
<g>
|
|
77
|
+
<circle data-type="point" data-label="" data-x="1.757519574999999" data-y="0.85" cx="479.91860312291124" cy="258.2821524857569" r="3" fill="hsl(40, 100%, 50%, 0.9)" />
|
|
78
|
+
</g>
|
|
79
|
+
<g>
|
|
80
|
+
<circle data-type="point" data-label="" data-x="1.757519574999999" data-y="-2" cx="479.91860312291124" cy="492.80997303988084" r="3" fill="hsl(40, 100%, 50%, 0.9)" />
|
|
81
|
+
</g>
|
|
82
|
+
<g>
|
|
83
|
+
<polyline data-points="-2.3148566499999994,0.5512093000000002 -1.4,0.42500000000000004" data-type="line" data-label="" points="144.8008766226725,282.86977763412216 220.08485425212754,293.25559941049465" fill="none" stroke="hsl(256, 100%, 50%, 0.8)" stroke-width="1" />
|
|
84
|
+
</g>
|
|
85
|
+
<g>
|
|
86
|
+
<polyline data-points="-2.31430995,-0.5512093000000002 -1.4,-0.42500000000000004" data-type="line" data-label="" points="144.84586481898717,373.58831503634275 220.08485425212754,363.20249325997025" fill="none" stroke="hsl(256, 100%, 50%, 0.8)" stroke-width="1" />
|
|
87
|
+
</g>
|
|
88
|
+
<g>
|
|
89
|
+
<polyline data-points="1.757519574999999,1.2 1.4,0.5" data-type="line" data-label="" points="479.91860312291124,229.4804903124434 450.49815163863525,287.08381465907036" fill="none" stroke="hsl(144, 100%, 50%, 0.8)" stroke-width="1" />
|
|
90
|
+
</g>
|
|
91
|
+
<g>
|
|
92
|
+
<polyline data-points="1.757519574999999,-2.2 -1.757519574999999,-2.2" data-type="line" data-label="" points="479.91860312291124,509.2680657103457 190.66440276785158,509.2680657103457" fill="none" stroke="hsl(144, 100%, 50%, 0.8)" stroke-width="1" />
|
|
93
|
+
</g>
|
|
94
|
+
<g>
|
|
95
|
+
<polyline data-points="-1.4,0.42500000000000004 1.4,-0.3" data-type="line" data-label="" points="220.08485425212754,293.25559941049465 450.49815163863525,352.9161853409297" fill="none" stroke="hsl(73, 100%, 50%, 0.8)" stroke-width="1" stroke-dasharray="4 2" />
|
|
96
|
+
</g>
|
|
97
|
+
<g>
|
|
98
|
+
<polyline data-points="-1.4,0.42500000000000004 1.4,-0.5" data-type="line" data-label="" points="220.08485425212754,293.25559941049465 450.49815163863525,369.37427801139455" fill="none" stroke="hsl(73, 100%, 50%, 0.8)" stroke-width="1" stroke-dasharray="4 2" />
|
|
99
|
+
</g>
|
|
100
|
+
<g>
|
|
101
|
+
<polyline data-points="-1.4,0.42500000000000004 -2.3148566499999994,0.5512093000000002" data-type="line" data-label="" points="220.08485425212754,293.25559941049465 144.8008766226725,282.86977763412216" fill="none" stroke="hsl(73, 100%, 50%, 0.8)" stroke-width="1" stroke-dasharray="4 2" />
|
|
102
|
+
</g>
|
|
103
|
+
<g>
|
|
104
|
+
<polyline data-points="-1.4,0.42500000000000004 1.7580660749999977,2.3025814000000002" data-type="line" data-label="" points="220.08485425212754,293.25559941049465 479.96357486113317,138.7485560227891" fill="none" stroke="hsl(73, 100%, 50%, 0.8)" stroke-width="1" stroke-dasharray="4 2" />
|
|
105
|
+
</g>
|
|
106
|
+
<g>
|
|
107
|
+
<polyline data-points="1.4,-0.3 1.4,-0.5" data-type="line" data-label="" points="450.49815163863525,352.9161853409297 450.49815163863525,369.37427801139455" fill="none" stroke="hsl(73, 100%, 50%, 0.8)" stroke-width="1" stroke-dasharray="4 2" />
|
|
108
|
+
</g>
|
|
109
|
+
<g>
|
|
110
|
+
<polyline data-points="1.4,-0.3 -2.3148566499999994,0.5512093000000002" data-type="line" data-label="" points="450.49815163863525,352.9161853409297 144.8008766226725,282.86977763412216" fill="none" stroke="hsl(73, 100%, 50%, 0.8)" stroke-width="1" stroke-dasharray="4 2" />
|
|
111
|
+
</g>
|
|
112
|
+
<g>
|
|
113
|
+
<polyline data-points="1.4,-0.3 1.7580660749999977,2.3025814000000002" data-type="line" data-label="" points="450.49815163863525,352.9161853409297 479.96357486113317,138.7485560227891" fill="none" stroke="hsl(73, 100%, 50%, 0.8)" stroke-width="1" stroke-dasharray="4 2" />
|
|
114
|
+
</g>
|
|
115
|
+
<g>
|
|
116
|
+
<polyline data-points="1.4,-0.5 -2.3148566499999994,0.5512093000000002" data-type="line" data-label="" points="450.49815163863525,369.37427801139455 144.8008766226725,282.86977763412216" fill="none" stroke="hsl(73, 100%, 50%, 0.8)" stroke-width="1" stroke-dasharray="4 2" />
|
|
117
|
+
</g>
|
|
118
|
+
<g>
|
|
119
|
+
<polyline data-points="1.4,-0.5 1.7580660749999977,2.3025814000000002" data-type="line" data-label="" points="450.49815163863525,369.37427801139455 479.96357486113317,138.7485560227891" fill="none" stroke="hsl(73, 100%, 50%, 0.8)" stroke-width="1" stroke-dasharray="4 2" />
|
|
120
|
+
</g>
|
|
121
|
+
<g>
|
|
122
|
+
<polyline data-points="-2.3148566499999994,0.5512093000000002 1.7580660749999977,2.3025814000000002" data-type="line" data-label="" points="144.8008766226725,282.86977763412216 479.96357486113317,138.7485560227891" fill="none" stroke="hsl(73, 100%, 50%, 0.8)" stroke-width="1" stroke-dasharray="4 2" />
|
|
123
|
+
</g>
|
|
124
|
+
<g>
|
|
125
|
+
<polyline data-points="-1.4,-0.42500000000000004 -2.31430995,-0.5512093000000002" data-type="line" data-label="" points="220.08485425212754,363.20249325997025 144.84586481898717,373.58831503634275" fill="none" stroke="hsl(157, 100%, 50%, 0.8)" stroke-width="1" stroke-dasharray="4 2" />
|
|
126
|
+
</g>
|
|
127
|
+
<g>
|
|
128
|
+
<polyline data-points="1.4,0.5 1.757519574999999,1.2" data-type="line" data-label="" points="450.49815163863525,287.08381465907036 479.91860312291124,229.4804903124434" fill="none" stroke="hsl(304, 100%, 50%, 0.8)" stroke-width="1" stroke-dasharray="4 2" />
|
|
129
|
+
</g>
|
|
130
|
+
<g>
|
|
131
|
+
<polyline data-points="-1.4,0.42500000000000004 -1.8574283249999997,0.42500000000000004 -1.8574283249999997,0.7512093000000004 -2.3148566499999994,0.7512093000000004 -2.3148566499999994,0.5512093000000002" data-type="line" data-label="" points="220.08485425212754,293.25559941049465 182.44286543740003,293.25559941049465 182.44286543740003,266.4116849636573 144.8008766226725,266.4116849636573 144.8008766226725,282.86977763412216" fill="none" stroke="purple" stroke-width="1" />
|
|
132
|
+
</g>
|
|
133
|
+
<g>
|
|
134
|
+
<polyline data-points="1.4,-0.3 1.5790330374999988,-0.3 1.5790330374999988,2.5025814000000004 1.7580660749999977,2.5025814000000004 1.7580660749999977,2.3025814000000002" data-type="line" data-label="" points="450.49815163863525,352.9161853409297 465.23086324988424,352.9161853409297 465.23086324988424,122.29046335232425 479.96357486113317,122.29046335232425 479.96357486113317,138.7485560227891" fill="none" stroke="purple" stroke-width="1" />
|
|
135
|
+
</g>
|
|
136
|
+
<g>
|
|
137
|
+
<polyline data-points="1.4,-0.5 1.5999999999999999,-0.5 1.5999999999999999,-0.3 1.4,-0.3" data-type="line" data-label="" points="450.49815163863525,369.37427801139455 466.9562443091001,369.37427801139455 466.9562443091001,352.9161853409297 450.49815163863525,352.9161853409297" fill="none" stroke="purple" stroke-width="1" />
|
|
138
|
+
</g>
|
|
139
|
+
<g>
|
|
140
|
+
<polyline data-points="-2.31430995,-0.5512093000000002 -2.31430995,-0.7512093000000004 -1.857154975,-0.7512093000000004 -1.857154975,-0.42500000000000004 -1.4,-0.42500000000000004" data-type="line" data-label="" points="144.84586481898717,373.58831503634275 144.84586481898717,390.0464077068076 182.46535953555735,390.0464077068076 182.46535953555735,363.20249325997025 220.08485425212754,363.20249325997025" fill="none" stroke="purple" stroke-width="1" />
|
|
141
|
+
</g>
|
|
142
|
+
<g>
|
|
143
|
+
<polyline data-points="1.757519574999999,1.2 1.757519574999999,0.5 1.4,0.5" data-type="line" data-label="" points="479.91860312291124,229.4804903124434 479.91860312291124,287.08381465907036 450.49815163863525,287.08381465907036" fill="none" stroke="purple" stroke-width="1" />
|
|
144
|
+
</g>
|
|
145
|
+
<g>
|
|
146
|
+
<polyline data-points="1.757519574999999,-2.2 1.757519574999999,-2 -1.757519574999999,-2 -1.757519574999999,-2.2" data-type="line" data-label="" points="479.91860312291124,509.2680657103457 479.91860312291124,492.80997303988084 190.66440276785158,492.80997303988084 190.66440276785158,509.2680657103457" fill="none" stroke="purple" stroke-width="1" />
|
|
147
|
+
</g>
|
|
148
|
+
<g>
|
|
149
|
+
<rect data-type="rect" data-label="schematic_component_0" data-x="0" data-y="0" x="220.08485425212754" y="270.6257219886055" width="230.4132973865077" height="115.2066486932539" fill="hsl(24, 100%, 50%, 0.8)" stroke="black" stroke-width="0.012152076428571431" />
|
|
150
|
+
</g>
|
|
151
|
+
<g>
|
|
152
|
+
<rect data-type="rect" data-label="schematic_component_1" data-x="-2.3145833" data-y="0" x="123.05068836854284" y="282.86977763412216" width="43.545364704573984" height="90.71853740222059" fill="hsl(24, 100%, 50%, 0.8)" stroke="black" stroke-width="0.012152076428571431" />
|
|
153
|
+
</g>
|
|
154
|
+
<g>
|
|
155
|
+
<rect data-type="rect" data-label="schematic_component_2" data-x="1.7577928249999983" data-y="1.7512907000000002" x="466.95624430910016" y="138.7485560227891" width="25.96968936584409" height="90.7319342896543" fill="hsl(24, 100%, 50%, 0.8)" stroke="black" stroke-width="0.012152076428571431" />
|
|
156
|
+
</g>
|
|
157
|
+
<g>
|
|
158
|
+
<rect data-type="rect" data-label="schematic_component_3" data-x="-1.7577928249999983" data-y="-2.7512907" x="177.65707221581857" y="509.2680657103457" width="25.96968936584412" height="90.7319342896543" fill="hsl(24, 100%, 50%, 0.8)" stroke="black" stroke-width="0.012152076428571431" />
|
|
159
|
+
</g>
|
|
160
|
+
<g>
|
|
161
|
+
<rect data-type="rect" data-label="schematic_component_4" data-x="1.7577928249999983" data-y="-2.7512907" x="466.95624430910016" y="509.2680657103457" width="25.96968936584409" height="90.7319342896543" fill="hsl(24, 100%, 50%, 0.8)" stroke="black" stroke-width="0.012152076428571431" />
|
|
162
|
+
</g>
|
|
163
|
+
<g>
|
|
164
|
+
<rect data-type="rect" data-label="" data-x="-1.8574283249999997" data-y="1.2512093000000004" x="174.2138191021676" y="184.1212216113331" width="16.45809267046485" height="82.2904633523242" fill="hsl(40, 100%, 50%, 0.35)" stroke="black" stroke-width="0.012152076428571431" />
|
|
165
|
+
</g>
|
|
166
|
+
<g>
|
|
167
|
+
<rect data-type="rect" data-label="" data-x="1.5790330374999988" data-y="3.0025814000000004" x="457.0018169146518" y="40.00000000000006" width="16.45809267046485" height="82.2904633523242" fill="hsl(40, 100%, 50%, 0.35)" stroke="black" stroke-width="0.012152076428571431" />
|
|
168
|
+
</g>
|
|
169
|
+
<g>
|
|
170
|
+
<rect data-type="rect" data-label="" data-x="-2.31430995" data-y="-1.1512093000000005" x="136.61681848375474" y="390.0464077068076" width="16.45809267046485" height="65.83237068185935" fill="hsl(40, 100%, 50%, 0.35)" stroke="black" stroke-width="0.012152076428571431" />
|
|
171
|
+
</g>
|
|
172
|
+
<g>
|
|
173
|
+
<rect data-type="rect" data-label="" data-x="1.807519574999999" data-y="0.85" x="479.91860312291124" y="250.05310615052446" width="8.229046335232397" height="16.45809267046485" fill="hsl(40, 100%, 50%, 0.35)" stroke="black" stroke-width="0.012152076428571431" />
|
|
174
|
+
</g>
|
|
175
|
+
<g>
|
|
176
|
+
<rect data-type="rect" data-label="" data-x="1.982519574999999" data-y="-2" x="479.91860312291124" y="484.5809267046484" width="37.0307085085459" height="16.458092670464907" fill="hsl(40, 100%, 50%, 0.35)" stroke="black" stroke-width="0.012152076428571431" />
|
|
177
|
+
</g>
|
|
178
|
+
<g id="crosshair" style="display: none">
|
|
179
|
+
<line id="crosshair-h" y1="0" y2="640" stroke="#666" stroke-width="0.5" />
|
|
180
|
+
<line id="crosshair-v" x1="0" x2="640" stroke="#666" stroke-width="0.5" /><text id="coordinates" font-family="monospace" font-size="12" fill="#666"></text>
|
|
181
|
+
</g>
|
|
182
|
+
<script>
|
|
183
|
+
<![CDATA[
|
|
184
|
+
document.currentScript.parentElement.addEventListener('mousemove', (e) => {
|
|
185
|
+
const svg = e.currentTarget;
|
|
186
|
+
const rect = svg.getBoundingClientRect();
|
|
187
|
+
const x = e.clientX - rect.left;
|
|
188
|
+
const y = e.clientY - rect.top;
|
|
189
|
+
const crosshair = svg.getElementById('crosshair');
|
|
190
|
+
const h = svg.getElementById('crosshair-h');
|
|
191
|
+
const v = svg.getElementById('crosshair-v');
|
|
192
|
+
const coords = svg.getElementById('coordinates');
|
|
193
|
+
|
|
194
|
+
crosshair.style.display = 'block';
|
|
195
|
+
h.setAttribute('x1', '0');
|
|
196
|
+
h.setAttribute('x2', '640');
|
|
197
|
+
h.setAttribute('y1', y);
|
|
198
|
+
h.setAttribute('y2', y);
|
|
199
|
+
v.setAttribute('x1', x);
|
|
200
|
+
v.setAttribute('x2', x);
|
|
201
|
+
v.setAttribute('y1', '0');
|
|
202
|
+
v.setAttribute('y2', '640');
|
|
203
|
+
|
|
204
|
+
// Calculate real coordinates using inverse transformation
|
|
205
|
+
const matrix = {
|
|
206
|
+
"a": 82.2904633523242,
|
|
207
|
+
"c": 0,
|
|
208
|
+
"e": 335.2915029453814,
|
|
209
|
+
"b": 0,
|
|
210
|
+
"d": -82.2904633523242,
|
|
211
|
+
"f": 328.22904633523245
|
|
212
|
+
};
|
|
213
|
+
// Manually invert and apply the affine transform
|
|
214
|
+
// Since we only use translate and scale, we can directly compute:
|
|
215
|
+
// x' = (x - tx) / sx
|
|
216
|
+
// y' = (y - ty) / sy
|
|
217
|
+
const sx = matrix.a;
|
|
218
|
+
const sy = matrix.d;
|
|
219
|
+
const tx = matrix.e;
|
|
220
|
+
const ty = matrix.f;
|
|
221
|
+
const realPoint = {
|
|
222
|
+
x: (x - tx) / sx,
|
|
223
|
+
y: (y - ty) / sy // Flip y back since we used negative scale
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
coords.textContent = `(${realPoint.x.toFixed(2)}, ${realPoint.y.toFixed(2)})`;
|
|
227
|
+
coords.setAttribute('x', (x + 5).toString());
|
|
228
|
+
coords.setAttribute('y', (y - 5).toString());
|
|
229
|
+
});
|
|
230
|
+
document.currentScript.parentElement.addEventListener('mouseleave', () => {
|
|
231
|
+
document.currentScript.parentElement.getElementById('crosshair').style.display = 'none';
|
|
232
|
+
});
|
|
233
|
+
]]>
|
|
234
|
+
</script>
|
|
235
|
+
</svg>
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
import { expect } from "bun:test"
|
|
2
|
+
import { test } from "bun:test"
|
|
3
|
+
import { SchematicTracePipelineSolver, type InputProblem } from "lib/index"
|
|
4
|
+
import "tests/fixtures/matcher"
|
|
5
|
+
|
|
6
|
+
const inputProblem = {
|
|
7
|
+
chips: [
|
|
8
|
+
{
|
|
9
|
+
chipId: "schematic_component_0",
|
|
10
|
+
center: {
|
|
11
|
+
x: 0,
|
|
12
|
+
y: 0,
|
|
13
|
+
},
|
|
14
|
+
width: 2,
|
|
15
|
+
height: 1.4,
|
|
16
|
+
pins: [
|
|
17
|
+
{
|
|
18
|
+
pinId: "U3.8",
|
|
19
|
+
x: -1.4,
|
|
20
|
+
y: 0.42500000000000004,
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
pinId: "U3.4",
|
|
24
|
+
x: -1.4,
|
|
25
|
+
y: -0.42500000000000004,
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
pinId: "U3.1",
|
|
29
|
+
x: 1.4,
|
|
30
|
+
y: 0.5,
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
pinId: "U3.6",
|
|
34
|
+
x: 1.4,
|
|
35
|
+
y: 0.30000000000000004,
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
pinId: "U3.5",
|
|
39
|
+
x: 1.4,
|
|
40
|
+
y: 0.10000000000000009,
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
pinId: "U3.2",
|
|
44
|
+
x: 1.4,
|
|
45
|
+
y: -0.09999999999999998,
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
pinId: "U3.3",
|
|
49
|
+
x: 1.4,
|
|
50
|
+
y: -0.3,
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
pinId: "U3.7",
|
|
54
|
+
x: 1.4,
|
|
55
|
+
y: -0.5,
|
|
56
|
+
},
|
|
57
|
+
],
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
chipId: "schematic_component_1",
|
|
61
|
+
center: {
|
|
62
|
+
x: -2.3145833,
|
|
63
|
+
y: 0,
|
|
64
|
+
},
|
|
65
|
+
width: 0.5291665999999999,
|
|
66
|
+
height: 1.0583333000000001,
|
|
67
|
+
pins: [
|
|
68
|
+
{
|
|
69
|
+
pinId: "C20.1",
|
|
70
|
+
x: -2.3148566499999994,
|
|
71
|
+
y: 0.5512093000000002,
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
pinId: "C20.2",
|
|
75
|
+
x: -2.31430995,
|
|
76
|
+
y: -0.5512093000000002,
|
|
77
|
+
},
|
|
78
|
+
],
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
chipId: "schematic_component_2",
|
|
82
|
+
center: {
|
|
83
|
+
x: 1.7577928249999983,
|
|
84
|
+
y: 1.7512907000000002,
|
|
85
|
+
},
|
|
86
|
+
width: 0.3155856499999966,
|
|
87
|
+
height: 1.0583332999999997,
|
|
88
|
+
pins: [
|
|
89
|
+
{
|
|
90
|
+
pinId: "R11.1",
|
|
91
|
+
x: 1.7580660749999977,
|
|
92
|
+
y: 2.3025814000000002,
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
pinId: "R11.2",
|
|
96
|
+
x: 1.757519574999999,
|
|
97
|
+
y: 1.2,
|
|
98
|
+
},
|
|
99
|
+
],
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
chipId: "schematic_component_3",
|
|
103
|
+
center: {
|
|
104
|
+
x: -1.7577928249999983,
|
|
105
|
+
y: -2.7512907000000002,
|
|
106
|
+
},
|
|
107
|
+
width: 0.3155856499999966,
|
|
108
|
+
height: 1.0583332999999997,
|
|
109
|
+
pins: [
|
|
110
|
+
{
|
|
111
|
+
pinId: "R12.1",
|
|
112
|
+
x: -1.7580660749999977,
|
|
113
|
+
y: -3.3025814000000002,
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
pinId: "R12.2",
|
|
117
|
+
x: -1.757519574999999,
|
|
118
|
+
y: -2.2,
|
|
119
|
+
},
|
|
120
|
+
],
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
chipId: "schematic_component_4",
|
|
124
|
+
center: {
|
|
125
|
+
x: 1.7577928249999983,
|
|
126
|
+
y: -2.7512907000000002,
|
|
127
|
+
},
|
|
128
|
+
width: 0.3155856499999966,
|
|
129
|
+
height: 1.0583332999999997,
|
|
130
|
+
pins: [
|
|
131
|
+
{
|
|
132
|
+
pinId: "R13.1",
|
|
133
|
+
x: 1.7580660749999977,
|
|
134
|
+
y: -3.3025814000000002,
|
|
135
|
+
},
|
|
136
|
+
{
|
|
137
|
+
pinId: "R13.2",
|
|
138
|
+
x: 1.757519574999999,
|
|
139
|
+
y: -2.2,
|
|
140
|
+
},
|
|
141
|
+
],
|
|
142
|
+
},
|
|
143
|
+
],
|
|
144
|
+
directConnections: [
|
|
145
|
+
{
|
|
146
|
+
pinIds: ["C20.1", "U3.8"],
|
|
147
|
+
netId: "capacitor.C20 > port.pin1 to .U3 > .VDD",
|
|
148
|
+
},
|
|
149
|
+
{
|
|
150
|
+
pinIds: ["C20.2", "U3.4"],
|
|
151
|
+
netId: "capacitor.C20 > port.pin2 to .U3 > .GND",
|
|
152
|
+
},
|
|
153
|
+
{
|
|
154
|
+
pinIds: ["R11.2", "U3.1"],
|
|
155
|
+
netId: "resistor.R11 > port.pin2 to .U3 > .N_CS",
|
|
156
|
+
},
|
|
157
|
+
{
|
|
158
|
+
pinIds: ["R13.2", "R12.2"],
|
|
159
|
+
netId: "resistor.R11 > port.pin1 to resistor.R12 > port.pin1",
|
|
160
|
+
},
|
|
161
|
+
],
|
|
162
|
+
netConnections: [
|
|
163
|
+
{
|
|
164
|
+
netId: "V3_3",
|
|
165
|
+
pinIds: ["U3.8", "U3.3", "U3.7", "C20.1", "R11.1"],
|
|
166
|
+
netLabelWidth: 1,
|
|
167
|
+
},
|
|
168
|
+
{
|
|
169
|
+
netId: "GND",
|
|
170
|
+
pinIds: ["U3.4", "C20.2"],
|
|
171
|
+
netLabelWidth: 0.8,
|
|
172
|
+
},
|
|
173
|
+
{
|
|
174
|
+
netId: "FLASH_N_CS",
|
|
175
|
+
pinIds: ["U3.1", "R11.2"],
|
|
176
|
+
netLabelWidth: 0.1,
|
|
177
|
+
},
|
|
178
|
+
],
|
|
179
|
+
availableNetLabelOrientations: {
|
|
180
|
+
V3_3: ["y+"],
|
|
181
|
+
GND: ["y-"],
|
|
182
|
+
},
|
|
183
|
+
maxMspPairDistance: 5,
|
|
184
|
+
} as InputProblem
|
|
185
|
+
|
|
186
|
+
test("example20", () => {
|
|
187
|
+
const solver = new SchematicTracePipelineSolver(inputProblem)
|
|
188
|
+
solver.solve()
|
|
189
|
+
expect(solver).toMatchSolverSnapshot(import.meta.path)
|
|
190
|
+
})
|