@tscircuit/schematic-trace-solver 0.0.159 → 0.0.161

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.
Files changed (71) hide show
  1. package/dist/index.d.ts +43 -9
  2. package/dist/index.js +807 -115
  3. package/lib/solvers/AvailableNetOrientationSolver/AvailableNetOrientationSolver.ts +210 -6
  4. package/lib/solvers/InlineNetLabelSolver/InlineNetLabelSolver.ts +536 -94
  5. package/lib/solvers/InlineNetLabelSolver/pushAnchoredNetLabelsAwayFromInlineLabels.ts +9 -7
  6. package/lib/solvers/InlineNetLabelSolver/pushInlineTerminalLabelsAwayFromAnchoredLabels.ts +295 -0
  7. package/lib/solvers/NetLabelPlacementSolver/NetLabelPlacementSolver.ts +7 -35
  8. package/lib/solvers/SchematicTraceLinesSolver/getTraceConnectedPinComponents.ts +60 -0
  9. package/lib/solvers/TraceCleanupSolver/sameNetRailAlignment/getFixedLabelCoordinate.ts +44 -13
  10. package/lib/types/InputProblem.ts +5 -4
  11. package/package.json +1 -1
  12. package/tests/bug-reports/bug-report-20260706T220324Z/__snapshots__/bug-report-20260706T220324Z.snap.svg +1 -1
  13. package/tests/bug-reports/bug-report-20260728T144234Z/__snapshots__/bug-report-20260728T144234Z.snap.svg +1 -1
  14. package/tests/bug-reports/bug-report-20260728T225606Z/__snapshots__/bug-report-20260728T225606Z.snap.svg +79 -79
  15. package/tests/bug-reports/bug-report-20260730T061837Z/__snapshots__/bug-report-20260730T061837Z.snap.svg +85 -85
  16. package/tests/bug-reports/bug-report-20260731T052229Z/__snapshots__/bug-report-20260731T052229Z.snap.svg +1 -1
  17. package/tests/bug-reports/bug-report-20260804T095800Z/__snapshots__/bug-report-20260804T095800Z.snap.svg +163 -163
  18. package/tests/bug-reports/bug-report-20260804T171919Z/__snapshots__/bug-report-20260804T171919Z.snap.svg +547 -547
  19. package/tests/bug-reports/bug-report-20260804T225912Z/__snapshots__/bug-report-20260804T225912Z.snap.svg +13 -13
  20. package/tests/bug-reports/bug-report-20260805T061316Z/__snapshots__/bug-report-20260805T061316Z.snap.svg +267 -267
  21. package/tests/bug-reports/bug-report-20260806T061548Z/__snapshots__/bug-report-20260806T061548Z.snap.svg +267 -267
  22. package/tests/bug-reports/bug-report-20260806T093501Z/__snapshots__/bug-report-20260806T093501Z.snap.svg +109 -109
  23. package/tests/bug-reports/bug-report-20260811T075142Z/__snapshots__/bug-report-20260811T075142Z.snap.svg +1 -1
  24. package/tests/bug-reports/bug-report-20260815T073240Z/__snapshots__/bug-report-20260815T073240Z.snap.svg +49 -49
  25. package/tests/bug-reports/bug-report-20260819T091818Z/__snapshots__/bug-report-20260819T091818Z.snap.svg +1 -1
  26. package/tests/bug-reports/bug-report-20260825T045913Z/__snapshots__/bug-report-20260825T045913Z.snap.svg +103 -103
  27. package/tests/bug-reports/bug-report-20260825T103621Z/__snapshots__/bug-report-20260825T103621Z.snap.svg +103 -103
  28. package/tests/bug-reports/bug-report-20260826T072956Z/__snapshots__/bug-report-20260826T072956Z.snap.svg +600 -792
  29. package/tests/bug-reports/bug-report-20260826T072956Z/bug-report-20260826T072956Z.test.ts +66 -1
  30. package/tests/examples/__snapshots__/example51.snap.svg +568 -568
  31. package/tests/fixtures/convertSolverOutputToCircuitJson.test.ts +16 -1
  32. package/tests/fixtures/convertSolverOutputToCircuitJson.ts +23 -12
  33. package/tests/repros/__snapshots__/board-1273-trace-overlap-cycle.snap.svg +736 -736
  34. package/tests/repros/__snapshots__/board-15984-same-net-junction.snap.svg +79 -79
  35. package/tests/repros/__snapshots__/board1096-usb-label-overlap-iteration.snap.svg +127 -127
  36. package/tests/repros/__snapshots__/repro-bluetooth-controller-ground-decoupling-groups.snap.svg +106 -0
  37. package/tests/repros/__snapshots__/repro-board-589-regulator-section.snap.svg +31 -31
  38. package/tests/repros/__snapshots__/repro-board-648-esp12f-section.snap.svg +121 -121
  39. package/tests/repros/__snapshots__/repro-bq25895-cross-net-trace-overlap.snap.svg +43 -43
  40. package/tests/repros/__snapshots__/repro-core-555-power-cross-net-overlap.snap.svg +19 -19
  41. package/tests/repros/__snapshots__/repro-core-ground-inline-label-fallback.snap.svg +277 -0
  42. package/tests/repros/__snapshots__/repro-core-subcircuit-missing-ground.snap.svg +19 -19
  43. package/tests/repros/__snapshots__/repro-core-tb67s579ftg-inline-label-routing.snap.svg +7 -7
  44. package/tests/repros/__snapshots__/repro-dc-power-isolated-routing.snap.svg +37 -37
  45. package/tests/repros/__snapshots__/repro-hdc2080-ground-label-alignment.snap.svg +137 -0
  46. package/tests/repros/__snapshots__/repro-nrf52810-clock-routing.snap.svg +61 -61
  47. package/tests/repros/__snapshots__/repro-pga300-redundant-ground-traces.snap.svg +115 -115
  48. package/tests/repros/__snapshots__/repro-pmp11282-isolated-dcdc.snap.svg +743 -743
  49. package/tests/repros/__snapshots__/repro-rp2040-usb-cc2-ground-overlap.snap.svg +43 -43
  50. package/tests/repros/__snapshots__/repro-ti-power-output-section.snap.svg +1 -1
  51. package/tests/repros/__snapshots__/repro-tida010076-j4-ground-bus.snap.svg +17 -17
  52. package/tests/repros/__snapshots__/repro-tida010076-page02.snap.svg +1131 -1131
  53. package/tests/repros/__snapshots__/repro-type-c-16pin-self-connection.snap.svg +7 -7
  54. package/tests/repros/__snapshots__/repro-type-c-16pin-to-resistor.snap.svg +7 -7
  55. package/tests/repros/__snapshots__/repro-usb-power-vbus-label-detour.snap.svg +666 -666
  56. package/tests/repros/__snapshots__/repro161-power-section-autolayout.snap.svg +73 -73
  57. package/tests/repros/__snapshots__/repro48-555-timer-vcc-rail-label.snap.svg +73 -73
  58. package/tests/repros/assets/repro-bluetooth-controller-ground-decoupling-groups.input.json +214 -0
  59. package/tests/repros/assets/repro-core-ground-inline-label-fallback.input.json +863 -0
  60. package/tests/repros/repro-bluetooth-controller-ground-decoupling-groups.test.ts +18 -0
  61. package/tests/repros/repro-core-ground-inline-label-fallback.test.ts +34 -0
  62. package/tests/repros/repro-hdc2080-ground-label-alignment.test.ts +239 -0
  63. package/tests/repros/repro-tida010076-j4-ground-bus.test.ts +14 -10
  64. package/tests/repros/repro-tida010076-page02.test.ts +2 -2
  65. package/tests/repros/repro-usb-power-vbus-label-detour.test.ts +14 -0
  66. package/tests/solvers/InlineNetLabelSolver/__snapshots__/inline-net-label02.snap.svg +1 -1
  67. package/tests/solvers/InlineNetLabelSolver/multi-pin-connected-components.test.ts +252 -0
  68. package/tests/solvers/InlineNetLabelSolver/opposite-side-placement.test.ts +71 -0
  69. package/tests/solvers/InlineNetLabelSolver/push-anchored-net-labels-away.test.ts +8 -2
  70. package/tests/solvers/InlineNetLabelSolver/push-inline-terminal-labels-away.test.ts +91 -0
  71. package/tests/solvers/InlineNetLabelSolver/two-pin-terminal-stubs-atomic.test.ts +7 -1
@@ -0,0 +1,252 @@
1
+ import { expect, test } from "bun:test"
2
+ import { InlineNetLabelSolver } from "lib/solvers/InlineNetLabelSolver/InlineNetLabelSolver"
3
+ import type { NetLabelPlacement } from "lib/solvers/NetLabelPlacementSolver/NetLabelPlacementSolver"
4
+ import type { SolvedTracePath } from "lib/solvers/SchematicTraceLinesSolver/SchematicTraceLinesSolver"
5
+ import type { InputProblem } from "lib/types/InputProblem"
6
+
7
+ test("a multi-pin net labels routed and disconnected components inline", () => {
8
+ const inputProblem: InputProblem = {
9
+ chips: [
10
+ {
11
+ chipId: "J1",
12
+ center: { x: 0, y: 0 },
13
+ width: 1,
14
+ height: 1,
15
+ pins: [
16
+ {
17
+ pinId: "J1.1",
18
+ x: -0.5,
19
+ y: 0.2,
20
+ _facingDirection: "x-",
21
+ },
22
+ {
23
+ pinId: "J1.2",
24
+ x: -0.5,
25
+ y: -0.2,
26
+ _facingDirection: "x-",
27
+ },
28
+ ],
29
+ },
30
+ {
31
+ chipId: "U1",
32
+ center: { x: 2, y: 0 },
33
+ width: 1,
34
+ height: 1,
35
+ pins: [
36
+ {
37
+ pinId: "U1.1",
38
+ x: 2.5,
39
+ y: 0,
40
+ _facingDirection: "x+",
41
+ },
42
+ ],
43
+ },
44
+ ],
45
+ directConnections: [],
46
+ netConnections: [
47
+ {
48
+ netId: "MOTOR",
49
+ pinIds: ["J1.1", "J1.2", "U1.1"],
50
+ allowInlineNetLabel: true,
51
+ inlineNetLabelWidth: 0.6,
52
+ inlineNetLabelHeight: 0.12,
53
+ },
54
+ ],
55
+ availableNetLabelOrientations: { MOTOR: ["x-", "x+"] },
56
+ }
57
+ const shortConnectorTrace: SolvedTracePath = {
58
+ mspPairId: "J1.1-J1.2",
59
+ mspConnectionPairIds: ["J1.1-J1.2"],
60
+ dcConnNetId: "MOTOR",
61
+ globalConnNetId: "MOTOR",
62
+ userNetId: "MOTOR",
63
+ pins: [
64
+ { pinId: "J1.1", chipId: "J1", x: -0.5, y: 0.2 },
65
+ { pinId: "J1.2", chipId: "J1", x: -0.5, y: -0.2 },
66
+ ],
67
+ pinIds: ["J1.1", "J1.2"],
68
+ tracePath: [
69
+ { x: -0.5, y: 0.2 },
70
+ { x: -0.8, y: 0.2 },
71
+ { x: -0.8, y: -0.2 },
72
+ { x: -0.5, y: -0.2 },
73
+ ],
74
+ }
75
+
76
+ const solver = new InlineNetLabelSolver({
77
+ inputProblem,
78
+ traces: [shortConnectorTrace],
79
+ netLabelPlacements: [],
80
+ })
81
+ solver.solve()
82
+
83
+ const output = solver.getOutput()
84
+ expect(output.inlineNetLabelPlacements).toHaveLength(3)
85
+ expect(
86
+ output.inlineNetLabelPlacements.every(
87
+ (placement) => placement.stubTracePath !== undefined,
88
+ ),
89
+ ).toBe(true)
90
+ expect(output.traces).toHaveLength(0)
91
+ expect(output.netLabelPlacements).toHaveLength(0)
92
+ })
93
+
94
+ test("a short routed component is retained when replacing it would strand an intermediate pin", () => {
95
+ const inputProblem: InputProblem = {
96
+ chips: [
97
+ {
98
+ chipId: "J1",
99
+ center: { x: 0, y: 0 },
100
+ width: 1,
101
+ height: 1,
102
+ pins: [
103
+ { pinId: "J1.1", x: -0.5, y: 0.2, _facingDirection: "x-" },
104
+ { pinId: "J1.2", x: -0.5, y: -0.2, _facingDirection: "x-" },
105
+ ],
106
+ },
107
+ {
108
+ chipId: "U1",
109
+ center: { x: 2, y: 0 },
110
+ width: 1,
111
+ height: 1,
112
+ pins: [{ pinId: "U1.1", x: 2.5, y: 0, _facingDirection: "x+" }],
113
+ },
114
+ ],
115
+ directConnections: [{ pinIds: ["J1.1", "J1.2"] }],
116
+ netConnections: [
117
+ {
118
+ netId: "MOTOR",
119
+ pinIds: ["J1.1", "U1.1"],
120
+ allowInlineNetLabel: true,
121
+ inlineNetLabelWidth: 0.6,
122
+ inlineNetLabelHeight: 0.12,
123
+ },
124
+ ],
125
+ availableNetLabelOrientations: { MOTOR: ["x-", "x+"] },
126
+ }
127
+ const shortTrace: SolvedTracePath = {
128
+ mspPairId: "J1.1-J1.2",
129
+ mspConnectionPairIds: ["J1.1-J1.2"],
130
+ dcConnNetId: "MOTOR",
131
+ globalConnNetId: "MOTOR",
132
+ userNetId: "MOTOR",
133
+ pins: [
134
+ { pinId: "J1.1", chipId: "J1", x: -0.5, y: 0.2 },
135
+ { pinId: "J1.2", chipId: "J1", x: -0.5, y: -0.2 },
136
+ ],
137
+ pinIds: ["J1.1", "J1.2"],
138
+ tracePath: [
139
+ { x: -0.5, y: 0.2 },
140
+ { x: -0.8, y: 0.2 },
141
+ { x: -0.8, y: -0.2 },
142
+ { x: -0.5, y: -0.2 },
143
+ ],
144
+ }
145
+ const anchoredLabels: NetLabelPlacement[] = [
146
+ {
147
+ globalConnNetId: "MOTOR",
148
+ netId: "MOTOR",
149
+ mspConnectionPairIds: ["J1.1-J1.2"],
150
+ pinIds: ["J1.1", "J1.2"],
151
+ orientation: "x-",
152
+ anchorPoint: { x: -0.8, y: 0 },
153
+ center: { x: -1.2, y: 0 },
154
+ width: 0.6,
155
+ height: 0.12,
156
+ },
157
+ {
158
+ globalConnNetId: "MOTOR",
159
+ netId: "MOTOR",
160
+ mspConnectionPairIds: [],
161
+ pinIds: ["U1.1"],
162
+ orientation: "x+",
163
+ anchorPoint: { x: 2.5, y: 0 },
164
+ center: { x: 2.9, y: 0 },
165
+ width: 0.6,
166
+ height: 0.12,
167
+ },
168
+ ]
169
+
170
+ const solver = new InlineNetLabelSolver({
171
+ inputProblem,
172
+ traces: [shortTrace],
173
+ netLabelPlacements: anchoredLabels,
174
+ })
175
+ solver.solve()
176
+
177
+ const output = solver.getOutput()
178
+ expect(output.inlineNetLabelPlacements).toHaveLength(0)
179
+ expect(output.traces).toEqual([shortTrace])
180
+ expect(output.netLabelPlacements).toEqual(anchoredLabels)
181
+ })
182
+
183
+ test("a generated anchored-label connector becomes an inline terminal stub", () => {
184
+ const inputProblem: InputProblem = {
185
+ chips: [
186
+ {
187
+ chipId: "U1",
188
+ center: { x: 0, y: 0 },
189
+ width: 1,
190
+ height: 1,
191
+ pins: [{ pinId: "U1.1", x: -0.5, y: 0, _facingDirection: "x-" }],
192
+ },
193
+ {
194
+ chipId: "U2",
195
+ center: { x: 3, y: 0 },
196
+ width: 1,
197
+ height: 1,
198
+ pins: [{ pinId: "U2.1", x: 2.5, y: 0, _facingDirection: "x-" }],
199
+ },
200
+ {
201
+ chipId: "U3",
202
+ center: { x: 6, y: 0 },
203
+ width: 1,
204
+ height: 1,
205
+ pins: [{ pinId: "U3.1", x: 5.5, y: 0, _facingDirection: "x-" }],
206
+ },
207
+ ],
208
+ directConnections: [],
209
+ netConnections: [
210
+ {
211
+ netId: "SIGNAL",
212
+ pinIds: ["U1.1", "U2.1", "U3.1"],
213
+ allowInlineNetLabel: true,
214
+ inlineNetLabelWidth: 0.6,
215
+ inlineNetLabelHeight: 0.12,
216
+ },
217
+ ],
218
+ availableNetLabelOrientations: { SIGNAL: ["x-"] },
219
+ }
220
+ const generatedLabelConnector: SolvedTracePath = {
221
+ mspPairId: "available-net-orientation-0-SIGNAL",
222
+ mspConnectionPairIds: ["available-net-orientation-0-SIGNAL"],
223
+ dcConnNetId: "SIGNAL",
224
+ globalConnNetId: "SIGNAL",
225
+ userNetId: "SIGNAL",
226
+ pins: [
227
+ { pinId: "U1.1", chipId: "U1", x: -0.5, y: 0 },
228
+ { pinId: "U1.1", chipId: "U1", x: -0.5, y: 0 },
229
+ ],
230
+ pinIds: ["U1.1"],
231
+ tracePath: [
232
+ { x: -0.5, y: 0 },
233
+ { x: -1.5, y: 0 },
234
+ ],
235
+ }
236
+
237
+ const solver = new InlineNetLabelSolver({
238
+ inputProblem,
239
+ traces: [generatedLabelConnector],
240
+ netLabelPlacements: [],
241
+ })
242
+ solver.solve()
243
+
244
+ const output = solver.getOutput()
245
+ expect(output.inlineNetLabelPlacements).toHaveLength(3)
246
+ expect(
247
+ output.inlineNetLabelPlacements.every(
248
+ (placement) => placement.stubTracePath !== undefined,
249
+ ),
250
+ ).toBe(true)
251
+ expect(output.traces).toHaveLength(0)
252
+ })
@@ -0,0 +1,71 @@
1
+ import { expect, test } from "bun:test"
2
+ import { InlineNetLabelSolver } from "lib/solvers/InlineNetLabelSolver/InlineNetLabelSolver"
3
+ import type { SolvedTracePath } from "lib/solvers/SchematicTraceLinesSolver/SchematicTraceLinesSolver"
4
+ import type { InputProblem } from "lib/types/InputProblem"
5
+
6
+ test("an inline label tries the opposite side when the preferred side is blocked", () => {
7
+ const inputProblem: InputProblem = {
8
+ chips: [
9
+ {
10
+ chipId: "U1",
11
+ center: { x: -2, y: 0 },
12
+ width: 1,
13
+ height: 1,
14
+ pins: [{ pinId: "U1.1", x: -1.5, y: 0 }],
15
+ },
16
+ {
17
+ chipId: "U2",
18
+ center: { x: 2, y: 0 },
19
+ width: 1,
20
+ height: 1,
21
+ pins: [{ pinId: "U2.1", x: 1.5, y: 0 }],
22
+ },
23
+ ],
24
+ directConnections: [
25
+ {
26
+ netId: "SIGNAL",
27
+ pinIds: ["U1.1", "U2.1"],
28
+ allowInlineNetLabel: true,
29
+ inlineNetLabelWidth: 0.8,
30
+ inlineNetLabelHeight: 0.12,
31
+ },
32
+ ],
33
+ netConnections: [],
34
+ textBoxes: [
35
+ {
36
+ center: { x: 0, y: 0.11 },
37
+ width: 3,
38
+ height: 0.12,
39
+ text: "preferred-side obstacle",
40
+ },
41
+ ],
42
+ availableNetLabelOrientations: { SIGNAL: ["x-", "x+"] },
43
+ }
44
+ const trace: SolvedTracePath = {
45
+ mspPairId: "U1.1-U2.1",
46
+ mspConnectionPairIds: ["U1.1-U2.1"],
47
+ dcConnNetId: "SIGNAL",
48
+ globalConnNetId: "SIGNAL",
49
+ userNetId: "SIGNAL",
50
+ pins: [
51
+ { pinId: "U1.1", chipId: "U1", x: -1.5, y: 0 },
52
+ { pinId: "U2.1", chipId: "U2", x: 1.5, y: 0 },
53
+ ],
54
+ pinIds: ["U1.1", "U2.1"],
55
+ tracePath: [
56
+ { x: -1.5, y: 0 },
57
+ { x: 1.5, y: 0 },
58
+ ],
59
+ }
60
+
61
+ const solver = new InlineNetLabelSolver({
62
+ inputProblem,
63
+ traces: [trace],
64
+ netLabelPlacements: [],
65
+ })
66
+ solver.solve()
67
+
68
+ expect(solver.inlineNetLabelPlacements).toHaveLength(1)
69
+ expect(solver.inlineNetLabelPlacements[0]!.side).toBe("y-")
70
+ expect(solver.inlineNetLabelPlacements[0]!.center.y).toBeLessThan(0)
71
+ })
@@ -11,9 +11,15 @@ test("pushes a regular endpoint label and its wick past nearby inline text", ()
11
11
  {
12
12
  chipId: "U1",
13
13
  center: { x: 0, y: 0 },
14
- width: 1,
14
+ // The routing box includes component text, so the real pins can sit
15
+ // inside it. A generated connector may legitimately cross that
16
+ // expanded owner box on its way out from the pin.
17
+ width: 2,
15
18
  height: 1,
16
- pins: [],
19
+ pins: [
20
+ { pinId: "U1.1", x: -0.5, y: 0.2, _facingDirection: "x-" },
21
+ { pinId: "U1.2", x: -0.5, y: 0, _facingDirection: "x-" },
22
+ ],
17
23
  },
18
24
  ],
19
25
  directConnections: [],
@@ -0,0 +1,91 @@
1
+ import { expect, test } from "bun:test"
2
+ import type { InlineNetLabelPlacement } from "lib/solvers/InlineNetLabelSolver/InlineNetLabelSolver"
3
+ import { pushInlineTerminalLabelsAwayFromAnchoredLabels } from "lib/solvers/InlineNetLabelSolver/pushInlineTerminalLabelsAwayFromAnchoredLabels"
4
+ import type { NetLabelPlacement } from "lib/solvers/NetLabelPlacementSolver/NetLabelPlacementSolver"
5
+ import type { InputProblem } from "lib/types/InputProblem"
6
+
7
+ test("moves an inline terminal row outward past a retained anchored label", () => {
8
+ const inputProblem: InputProblem = {
9
+ chips: [
10
+ {
11
+ chipId: "J1",
12
+ center: { x: 0, y: 0 },
13
+ width: 1,
14
+ height: 1,
15
+ pins: [
16
+ { pinId: "J1.A0", x: -0.5, y: 0.2, _facingDirection: "x-" },
17
+ { pinId: "J1.SCLK", x: -0.5, y: 0, _facingDirection: "x-" },
18
+ { pinId: "J1.MISO", x: -0.5, y: -0.2, _facingDirection: "x-" },
19
+ ],
20
+ },
21
+ ],
22
+ directConnections: [],
23
+ netConnections: [],
24
+ availableNetLabelOrientations: {},
25
+ }
26
+ const anchoredNetLabelPlacements: NetLabelPlacement[] = [
27
+ {
28
+ globalConnNetId: "A0",
29
+ netId: "A0",
30
+ mspConnectionPairIds: [],
31
+ pinIds: ["J1.A0"],
32
+ orientation: "x-",
33
+ anchorPoint: { x: -0.5, y: 0.2 },
34
+ center: { x: -0.75, y: 0.2 },
35
+ width: 0.5,
36
+ height: 0.2,
37
+ },
38
+ ]
39
+ const inlineNetLabelPlacements: InlineNetLabelPlacement[] = [
40
+ {
41
+ globalConnNetId: "SCLK",
42
+ netId: "SCLK",
43
+ pinIds: ["J1.SCLK"],
44
+ stubTracePath: [
45
+ { x: -0.5, y: 0 },
46
+ { x: -1.1, y: 0 },
47
+ ],
48
+ axis: "x",
49
+ anchorPoint: { x: -0.8, y: 0 },
50
+ center: { x: -0.8, y: 0.11 },
51
+ width: 0.4,
52
+ height: 0.12,
53
+ side: "y+",
54
+ },
55
+ {
56
+ globalConnNetId: "MISO",
57
+ netId: "MISO",
58
+ pinIds: ["J1.MISO"],
59
+ stubTracePath: [
60
+ { x: -0.5, y: -0.2 },
61
+ { x: -1.1, y: -0.2 },
62
+ ],
63
+ axis: "x",
64
+ anchorPoint: { x: -0.8, y: -0.2 },
65
+ center: { x: -0.8, y: -0.09 },
66
+ width: 0.4,
67
+ height: 0.12,
68
+ side: "y+",
69
+ },
70
+ ]
71
+
72
+ const output = pushInlineTerminalLabelsAwayFromAnchoredLabels({
73
+ inputProblem,
74
+ traces: [],
75
+ anchoredNetLabelPlacements,
76
+ inlineNetLabelPlacements,
77
+ })
78
+
79
+ expect(output.movedGroupCount).toBe(1)
80
+ expect(output.inlineNetLabelPlacements[0]!.center.x).toBeLessThan(-0.8)
81
+ expect(output.inlineNetLabelPlacements[1]!.center.x).toBe(
82
+ output.inlineNetLabelPlacements[0]!.center.x,
83
+ )
84
+ expect(output.inlineNetLabelPlacements[0]!.stubTracePath![0]).toEqual({
85
+ x: -0.5,
86
+ y: 0,
87
+ })
88
+ expect(output.inlineNetLabelPlacements[0]!.stubTracePath![1]!.x).toBeLessThan(
89
+ -1.1,
90
+ )
91
+ })
@@ -36,7 +36,13 @@ test("two-pin terminal stubs fall back atomically when one endpoint is obstructe
36
36
  center: { x: -0.85, y: 0.11 },
37
37
  width: 1.1,
38
38
  height: 0.12,
39
- text: "obstacle",
39
+ text: "upper obstacle",
40
+ },
41
+ {
42
+ center: { x: -0.85, y: -0.11 },
43
+ width: 1.1,
44
+ height: 0.12,
45
+ text: "lower obstacle",
40
46
  },
41
47
  ],
42
48
  availableNetLabelOrientations: { NET_SIGNAL: ["x-", "x+"] },