@tscircuit/schematic-trace-solver 0.0.77 → 0.0.79

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 (40) hide show
  1. package/.github/ISSUE_TEMPLATE/json-bug-report.yml +24 -0
  2. package/.github/scripts/import-json-bug-report.ts +483 -0
  3. package/.github/workflows/json-bug-report.yml +154 -0
  4. package/dist/index.d.ts +37 -10
  5. package/dist/index.js +281 -74
  6. package/lib/solvers/AvailableNetOrientationSolver/AvailableNetOrientationSolver.ts +4 -0
  7. package/lib/solvers/AvailableNetOrientationSolver/types.ts +1 -0
  8. package/lib/solvers/NetLabelNetLabelCollisionSolver/NetLabelNetLabelCollisionSolver.ts +6 -0
  9. package/lib/solvers/NetLabelPlacementSolver/SingleNetLabelPlacementSolver/SingleNetLabelPlacementSolver.ts +21 -1
  10. package/lib/solvers/NetLabelPlacementSolver/SingleNetLabelPlacementSolver/SingleNetLabelPlacementSolver_visualize.ts +9 -3
  11. package/lib/solvers/NetLabelPlacementSolver/SingleNetLabelPlacementSolver/solvePortOnlyPin.ts +27 -2
  12. package/lib/solvers/NetLabelTraceCollisionSolver/NetLabelTraceCollisionSolver.ts +87 -1
  13. package/lib/solvers/SchematicTraceLinesSolver/SchematicTraceLinesSolver.ts +1 -0
  14. package/lib/solvers/SchematicTraceLinesSolver/SchematicTraceSingleLineSolver2/SchematicTraceSingleLineSolver2.ts +121 -30
  15. package/lib/solvers/SchematicTraceLinesSolver/SchematicTraceSingleLineSolver2/collisions.ts +10 -10
  16. package/lib/solvers/SchematicTraceLinesSolver/SchematicTraceSingleLineSolver2/mid.ts +5 -8
  17. package/lib/solvers/SchematicTraceLinesSolver/SchematicTraceSingleLineSolver2/rect.ts +31 -6
  18. package/lib/solvers/TraceAnchoredNetLabelOverlapSolver/TraceAnchoredNetLabelOverlapSolver.ts +3 -0
  19. package/lib/solvers/TraceAnchoredNetLabelOverlapSolver/types.ts +1 -0
  20. package/lib/solvers/VccNetLabelCornerPlacementSolver/VccNetLabelCornerPlacementSolver.ts +3 -0
  21. package/lib/solvers/VccNetLabelCornerPlacementSolver/types.ts +1 -0
  22. package/lib/utils/textBoxBounds.ts +40 -0
  23. package/package.json +1 -1
  24. package/site/examples/example46.page.tsx +4 -0
  25. package/site/examples/example47.page.tsx +4 -0
  26. package/site/examples/example48.page.tsx +4 -0
  27. package/site/examples/example49.page.tsx +4 -0
  28. package/tests/assets/example46.json +236 -0
  29. package/tests/assets/example47.json +206 -0
  30. package/tests/assets/example48.json +104 -0
  31. package/tests/assets/example49.json +390 -0
  32. package/tests/examples/__snapshots__/example46.snap.svg +343 -0
  33. package/tests/examples/__snapshots__/example47.snap.svg +324 -0
  34. package/tests/examples/__snapshots__/example48.snap.svg +168 -0
  35. package/tests/examples/__snapshots__/example49.snap.svg +566 -0
  36. package/tests/examples/example46.test.ts +12 -0
  37. package/tests/examples/example47.test.ts +12 -0
  38. package/tests/examples/example48.test.ts +12 -0
  39. package/tests/examples/example49.test.ts +12 -0
  40. package/tests/repros/__snapshots__/manufacturePartNumber-text-box.snap.svg +12 -12
@@ -1,19 +1,44 @@
1
1
  import type { InputChip, InputProblem } from "lib/types/InputProblem"
2
2
  import { getInputChipBounds } from "lib/solvers/GuidelinesSolver/getInputChipBounds"
3
+ import { getTextBoxBounds, type RectPadding } from "lib/utils/textBoxBounds"
3
4
 
4
- export type ChipWithBounds = {
5
- chipId: string
5
+ export type RectBounds = {
6
6
  minX: number
7
7
  minY: number
8
8
  maxX: number
9
9
  maxY: number
10
10
  }
11
11
 
12
- export const chipToRect = (chip: InputChip): ChipWithBounds => {
12
+ export type ChipObstacleRect = RectBounds & {
13
+ kind: "chip"
14
+ chipId: string
15
+ }
16
+
17
+ export type TextBoxObstacleRect = RectBounds & {
18
+ kind: "text_box"
19
+ textBox: NonNullable<InputProblem["textBoxes"]>[number]
20
+ }
21
+
22
+ export type ObstacleRect = ChipObstacleRect | TextBoxObstacleRect
23
+
24
+ export const chipToRect = (chip: InputChip): ChipObstacleRect => {
13
25
  const b = getInputChipBounds(chip)
14
- return { chipId: chip.chipId, ...b }
26
+ return { kind: "chip", chipId: chip.chipId, ...b }
15
27
  }
16
28
 
17
- export const getObstacleRects = (problem: InputProblem): ChipWithBounds[] => {
18
- return problem.chips.map(chipToRect)
29
+ export const getObstacleRects = (
30
+ problem: InputProblem,
31
+ opts: { textBoxPadding?: RectPadding } = {},
32
+ ): ObstacleRect[] => {
33
+ const chipRects = problem.chips.map(chipToRect)
34
+ const textBoxRects = (problem.textBoxes ?? []).map((textBox) => {
35
+ const b = getTextBoxBounds(textBox, opts.textBoxPadding)
36
+ return {
37
+ kind: "text_box" as const,
38
+ textBox,
39
+ ...b,
40
+ }
41
+ })
42
+
43
+ return [...chipRects, ...textBoxRects]
19
44
  }
@@ -20,6 +20,7 @@ import type {
20
20
  TraceAnchoredNetLabelOverlapSolverParams,
21
21
  } from "./types"
22
22
  import { visualizeTraceAnchoredNetLabelOverlapSolver } from "./visualize"
23
+ import { rectIntersectsAnyTextBox } from "lib/utils/textBoxBounds"
23
24
 
24
25
  type ActiveOverlapSearch = {
25
26
  overlap: LabelOverlap
@@ -227,6 +228,8 @@ export class TraceAnchoredNetLabelOverlapSolver extends BaseSolver {
227
228
  ): CandidateStatus {
228
229
  const bounds = getLabelBounds(candidate)
229
230
  if (this.intersectsAnyChip(bounds)) return "chip-collision"
231
+ if (rectIntersectsAnyTextBox(bounds, this.inputProblem))
232
+ return "text-collision"
230
233
  if (traceCrossesBoundsInterior(bounds, this.traces))
231
234
  return "trace-collision"
232
235
  if (this.intersectsAnyOtherLabel(bounds, labelIndex)) {
@@ -30,6 +30,7 @@ export type TraceLocation = {
30
30
  export type CandidateStatus =
31
31
  | "valid"
32
32
  | "chip-collision"
33
+ | "text-collision"
33
34
  | "trace-collision"
34
35
  | "netlabel-collision"
35
36
 
@@ -23,6 +23,7 @@ import type {
23
23
  VccNetLabelCornerPlacementSolverParams,
24
24
  } from "./types"
25
25
  import { visualizeVccNetLabelCornerPlacementSolver } from "./visualize"
26
+ import { rectIntersectsAnyTextBox } from "lib/utils/textBoxBounds"
26
27
 
27
28
  export class VccNetLabelCornerPlacementSolver extends BaseSolver {
28
29
  inputProblem: InputProblem
@@ -171,6 +172,8 @@ export class VccNetLabelCornerPlacementSolver extends BaseSolver {
171
172
  labelIndex: number,
172
173
  ): CornerCandidateStatus {
173
174
  if (this.intersectsAnyChip(bounds)) return "chip-collision"
175
+ if (rectIntersectsAnyTextBox(bounds, this.inputProblem))
176
+ return "text-collision"
174
177
  if (traceCrossesBoundsInterior(bounds, this.traceMap)) {
175
178
  return "trace-collision"
176
179
  }
@@ -25,6 +25,7 @@ export type TraceCornerCandidate = {
25
25
  export type CornerCandidateStatus =
26
26
  | "valid"
27
27
  | "chip-collision"
28
+ | "text-collision"
28
29
  | "trace-collision"
29
30
  | "netlabel-collision"
30
31
 
@@ -0,0 +1,40 @@
1
+ import type { Bounds } from "@tscircuit/math-utils"
2
+ import type { InputProblem, TextBoxes } from "lib/types/InputProblem"
3
+
4
+ export type RectPadding = {
5
+ minX?: number
6
+ minY?: number
7
+ maxX?: number
8
+ maxY?: number
9
+ }
10
+
11
+ export function getTextBoxBounds(
12
+ textBox: TextBoxes,
13
+ padding: RectPadding = {},
14
+ ): Bounds {
15
+ return {
16
+ minX: textBox.center.x - textBox.width / 2 - (padding.minX ?? 0),
17
+ minY: textBox.center.y - textBox.height / 2 - (padding.minY ?? 0),
18
+ maxX: textBox.center.x + textBox.width / 2 + (padding.maxX ?? 0),
19
+ maxY: textBox.center.y + textBox.height / 2 + (padding.maxY ?? 0),
20
+ }
21
+ }
22
+
23
+ export function boundsOverlap(a: Bounds, b: Bounds, eps = 1e-9): boolean {
24
+ return (
25
+ a.minX < b.maxX - eps &&
26
+ a.maxX > b.minX + eps &&
27
+ a.minY < b.maxY - eps &&
28
+ a.maxY > b.minY + eps
29
+ )
30
+ }
31
+
32
+ export function rectIntersectsAnyTextBox(
33
+ bounds: Bounds,
34
+ inputProblem: InputProblem,
35
+ ): boolean {
36
+ for (const textBox of inputProblem.textBoxes ?? []) {
37
+ if (boundsOverlap(bounds, getTextBoxBounds(textBox))) return true
38
+ }
39
+ return false
40
+ }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@tscircuit/schematic-trace-solver",
3
3
  "main": "dist/index.js",
4
- "version": "0.0.77",
4
+ "version": "0.0.79",
5
5
  "type": "module",
6
6
  "scripts": {
7
7
  "start": "cosmos",
@@ -0,0 +1,4 @@
1
+ import { PipelineDebugger } from "site/components/PipelineDebugger"
2
+ import inputProblem from "../../tests/assets/example46.json"
3
+
4
+ export default () => <PipelineDebugger inputProblem={inputProblem as any} />
@@ -0,0 +1,4 @@
1
+ import { PipelineDebugger } from "site/components/PipelineDebugger"
2
+ import inputProblem from "../../tests/assets/example47.json"
3
+
4
+ export default () => <PipelineDebugger inputProblem={inputProblem as any} />
@@ -0,0 +1,4 @@
1
+ import { PipelineDebugger } from "site/components/PipelineDebugger"
2
+ import inputProblem from "../../tests/assets/example48.json"
3
+
4
+ export default () => <PipelineDebugger inputProblem={inputProblem as any} />
@@ -0,0 +1,4 @@
1
+ import { PipelineDebugger } from "site/components/PipelineDebugger"
2
+ import inputProblem from "../../tests/assets/example49.json"
3
+
4
+ export default () => <PipelineDebugger inputProblem={inputProblem as any} />
@@ -0,0 +1,236 @@
1
+ {
2
+ "chips": [
3
+ {
4
+ "chipId": "schematic_component_0",
5
+ "center": {
6
+ "x": -2.71,
7
+ "y": 0.7199999999999998
8
+ },
9
+ "width": 0.8599999999999999,
10
+ "height": 1.04,
11
+ "pins": [
12
+ {
13
+ "pinId": "DPROT.1",
14
+ "x": -2.87,
15
+ "y": 1.2399999999999998
16
+ },
17
+ {
18
+ "pinId": "DPROT.2",
19
+ "x": -2.87,
20
+ "y": 0.19999999999999973
21
+ }
22
+ ],
23
+ "sectionId": "pwr"
24
+ },
25
+ {
26
+ "chipId": "schematic_component_1",
27
+ "center": {
28
+ "x": -3.25,
29
+ "y": 3.05
30
+ },
31
+ "width": 1.8800000000000003,
32
+ "height": 1.13,
33
+ "pins": [
34
+ {
35
+ "pinId": "F1.1",
36
+ "x": -2.87,
37
+ "y": 3.58
38
+ },
39
+ {
40
+ "pinId": "F1.2",
41
+ "x": -2.87,
42
+ "y": 2.5199999999999996
43
+ }
44
+ ],
45
+ "sectionId": "pwr"
46
+ },
47
+ {
48
+ "chipId": "schematic_component_2",
49
+ "center": {
50
+ "x": 0,
51
+ "y": 0
52
+ },
53
+ "width": 1.77,
54
+ "height": 0.6,
55
+ "pins": [
56
+ {
57
+ "pinId": "U2.1",
58
+ "x": -1.2850000000000001,
59
+ "y": 0.2
60
+ },
61
+ {
62
+ "pinId": "U2.2",
63
+ "x": -1.2850000000000001,
64
+ "y": 0
65
+ },
66
+ {
67
+ "pinId": "U2.3",
68
+ "x": -1.2850000000000001,
69
+ "y": -0.2
70
+ },
71
+ {
72
+ "pinId": "U2.4",
73
+ "x": 1.2850000000000001,
74
+ "y": -0.1
75
+ },
76
+ {
77
+ "pinId": "U2.5",
78
+ "x": 1.2850000000000001,
79
+ "y": 0.1
80
+ }
81
+ ],
82
+ "sectionId": "pwr"
83
+ },
84
+ {
85
+ "chipId": "schematic_component_3",
86
+ "center": {
87
+ "x": -2.755,
88
+ "y": -1.56
89
+ },
90
+ "width": 0.9600000000000004,
91
+ "height": 1.1000000000000003,
92
+ "pins": [
93
+ {
94
+ "pinId": "C1.1",
95
+ "x": -2.97,
96
+ "y": -1.01
97
+ },
98
+ {
99
+ "pinId": "C1.2",
100
+ "x": -2.97,
101
+ "y": -2.1100000000000003
102
+ }
103
+ ],
104
+ "sectionId": "pwr"
105
+ },
106
+ {
107
+ "chipId": "schematic_component_4",
108
+ "center": {
109
+ "x": -0.5950000000000002,
110
+ "y": -2.4550000000000005
111
+ },
112
+ "width": 0.9599999999999999,
113
+ "height": 1.1000000000000003,
114
+ "pins": [
115
+ {
116
+ "pinId": "C4.1",
117
+ "x": -0.8100000000000003,
118
+ "y": -1.9050000000000005
119
+ },
120
+ {
121
+ "pinId": "C4.2",
122
+ "x": -0.8100000000000003,
123
+ "y": -3.005000000000001
124
+ }
125
+ ],
126
+ "sectionId": "pwr"
127
+ },
128
+ {
129
+ "chipId": "schematic_component_5",
130
+ "center": {
131
+ "x": 2.9724999999999997,
132
+ "y": -1.8699999999999997
133
+ },
134
+ "width": 1.245,
135
+ "height": 1.13,
136
+ "pins": [
137
+ {
138
+ "pinId": "DPWR.1",
139
+ "x": 2.675,
140
+ "y": -1.3299999999999996
141
+ },
142
+ {
143
+ "pinId": "DPWR.2",
144
+ "x": 2.675,
145
+ "y": -2.4099999999999997
146
+ }
147
+ ],
148
+ "sectionId": "pwr"
149
+ },
150
+ {
151
+ "chipId": "schematic_component_6",
152
+ "center": {
153
+ "x": 1.5519553499999992,
154
+ "y": -4.1899999999999995
155
+ },
156
+ "width": 0.9739106999999991,
157
+ "height": 1.0999999999999996,
158
+ "pins": [
159
+ {
160
+ "pinId": "R1.1",
161
+ "x": 1.2594553499999992,
162
+ "y": -3.6399999999999997
163
+ },
164
+ {
165
+ "pinId": "R1.2",
166
+ "x": 1.2594553499999992,
167
+ "y": -4.739999999999999
168
+ }
169
+ ],
170
+ "sectionId": "pwr"
171
+ },
172
+ {
173
+ "chipId": "schematic_component_7",
174
+ "center": {
175
+ "x": -0.5950000000000001,
176
+ "y": -4.765000000000001
177
+ },
178
+ "width": 0.8400000000000001,
179
+ "height": 1.0999999999999996,
180
+ "pins": [
181
+ {
182
+ "pinId": "C18.1",
183
+ "x": -0.75,
184
+ "y": -4.215000000000001
185
+ },
186
+ {
187
+ "pinId": "C18.2",
188
+ "x": -0.75,
189
+ "y": -5.315
190
+ }
191
+ ],
192
+ "sectionId": "pwr"
193
+ }
194
+ ],
195
+ "directConnections": [
196
+ {
197
+ "pinIds": ["F1.2", "DPROT.1"],
198
+ "netId": ".F1 > .pin2 to .DPROT > .anode"
199
+ }
200
+ ],
201
+ "netConnections": [
202
+ {
203
+ "netId": "VBUS",
204
+ "pinIds": ["DPROT.1", "F1.1", "F1.2"],
205
+ "netLabelWidth": 0.6
206
+ },
207
+ {
208
+ "netId": "RAW",
209
+ "pinIds": ["DPROT.2", "U2.1", "U2.3", "C1.1"],
210
+ "netLabelWidth": 0.48
211
+ },
212
+ {
213
+ "netId": "GND",
214
+ "pinIds": ["U2.2", "C1.2", "C4.2", "R1.2", "C18.2"],
215
+ "netLabelWidth": 0.48
216
+ },
217
+ {
218
+ "netId": "V3V3",
219
+ "pinIds": ["U2.5", "C4.1", "DPWR.1", "C18.1"],
220
+ "netLabelWidth": 0.6
221
+ },
222
+ {
223
+ "netId": "PWR_LED_K",
224
+ "pinIds": ["DPWR.2", "R1.1"],
225
+ "netLabelWidth": 1.2
226
+ }
227
+ ],
228
+ "availableNetLabelOrientations": {
229
+ "VBUS": ["y+"],
230
+ "RAW": ["x-", "x+", "y+", "y-"],
231
+ "V3V3": ["y+"],
232
+ "GND": ["y-"],
233
+ "PWR_LED_K": ["x-", "x+", "y+", "y-"]
234
+ },
235
+ "maxMspPairDistance": 2.4
236
+ }
@@ -0,0 +1,206 @@
1
+ {
2
+ "chips": [
3
+ {
4
+ "chipId": "schematic_component_0",
5
+ "center": {
6
+ "x": -0.5899999999999996,
7
+ "y": 0.315272325
8
+ },
9
+ "width": 1.6,
10
+ "height": 1,
11
+ "pins": [
12
+ {
13
+ "pinId": "U1.1",
14
+ "x": 0.6100000000000005,
15
+ "y": 0.015272324999999976
16
+ },
17
+ {
18
+ "pinId": "U1.2",
19
+ "x": -1.7899999999999998,
20
+ "y": 0.015272324999999976
21
+ },
22
+ {
23
+ "pinId": "U1.3",
24
+ "x": 0.6100000000000005,
25
+ "y": 0.415272325
26
+ },
27
+ {
28
+ "pinId": "U1.4",
29
+ "x": -1.7899999999999998,
30
+ "y": 0.6152723250000001
31
+ },
32
+ {
33
+ "pinId": "U1.5",
34
+ "x": -1.7899999999999998,
35
+ "y": 0.41527232500000005
36
+ },
37
+ {
38
+ "pinId": "U1.6",
39
+ "x": -1.7899999999999998,
40
+ "y": 0.21527232500000004
41
+ },
42
+ {
43
+ "pinId": "U1.7",
44
+ "x": 0.6100000000000005,
45
+ "y": 0.215272325
46
+ },
47
+ {
48
+ "pinId": "U1.8",
49
+ "x": 0.6100000000000005,
50
+ "y": 0.6152723250000001
51
+ }
52
+ ]
53
+ },
54
+ {
55
+ "chipId": "schematic_component_1",
56
+ "center": {
57
+ "x": 1.88195535,
58
+ "y": 1.8047276749999999
59
+ },
60
+ "width": 0.8539106999999988,
61
+ "height": 1.1,
62
+ "pins": [
63
+ {
64
+ "pinId": "R1.1",
65
+ "x": 1.64945535,
66
+ "y": 2.354727675
67
+ },
68
+ {
69
+ "pinId": "R1.2",
70
+ "x": 1.64945535,
71
+ "y": 1.2547276749999998
72
+ }
73
+ ]
74
+ },
75
+ {
76
+ "chipId": "schematic_component_2",
77
+ "center": {
78
+ "x": 1.8600000000000005,
79
+ "y": 0.21527232500000035
80
+ },
81
+ "width": 1.1,
82
+ "height": 0.7789106999999988,
83
+ "pins": [
84
+ {
85
+ "pinId": "R2.1",
86
+ "x": 1.3100000000000005,
87
+ "y": 0.21527232500000038
88
+ },
89
+ {
90
+ "pinId": "R2.2",
91
+ "x": 2.4100000000000006,
92
+ "y": 0.21527232500000038
93
+ }
94
+ ]
95
+ },
96
+ {
97
+ "chipId": "schematic_component_3",
98
+ "center": {
99
+ "x": -1.8774999999999997,
100
+ "y": 4.109727674999999
101
+ },
102
+ "width": 1.1149999999999998,
103
+ "height": 1.0999999999999996,
104
+ "pins": [
105
+ {
106
+ "pinId": "C1.1",
107
+ "x": -2.0149999999999997,
108
+ "y": 4.659727674999999
109
+ },
110
+ {
111
+ "pinId": "C1.2",
112
+ "x": -2.0149999999999997,
113
+ "y": 3.5597276749999995
114
+ }
115
+ ]
116
+ },
117
+ {
118
+ "chipId": "schematic_component_4",
119
+ "center": {
120
+ "x": -1.6525000000000003,
121
+ "y": -1.804727675
122
+ },
123
+ "width": 1.1150000000000002,
124
+ "height": 1.1000000000000003,
125
+ "pins": [
126
+ {
127
+ "pinId": "C2.1",
128
+ "x": -1.7900000000000003,
129
+ "y": -1.254727675
130
+ },
131
+ {
132
+ "pinId": "C2.2",
133
+ "x": -1.7900000000000003,
134
+ "y": -2.3547276750000004
135
+ }
136
+ ]
137
+ },
138
+ {
139
+ "chipId": "schematic_component_5",
140
+ "center": {
141
+ "x": 0.9100000000000001,
142
+ "y": 4.3547276749999995
143
+ },
144
+ "width": 1.4000000000000004,
145
+ "height": 0.8000000000000003,
146
+ "pins": [
147
+ {
148
+ "pinId": "J1.1",
149
+ "x": -0.18999999999999995,
150
+ "y": 4.554727675
151
+ },
152
+ {
153
+ "pinId": "J1.2",
154
+ "x": -0.18999999999999995,
155
+ "y": 4.3547276749999995
156
+ },
157
+ {
158
+ "pinId": "J1.3",
159
+ "x": -0.18999999999999995,
160
+ "y": 4.154727674999999
161
+ }
162
+ ]
163
+ }
164
+ ],
165
+ "directConnections": [
166
+ {
167
+ "pinIds": ["U1.5", "C2.1"],
168
+ "netId": "U1.CTRL to C2.pin1"
169
+ },
170
+ {
171
+ "pinIds": ["R1.2", "U1.7"],
172
+ "netId": "R1.pin2 to U1.DISCH"
173
+ },
174
+ {
175
+ "pinIds": ["U1.7", "R2.1"],
176
+ "netId": "U1.DISCH to R2.pin1"
177
+ }
178
+ ],
179
+ "netConnections": [
180
+ {
181
+ "netId": "GND",
182
+ "pinIds": ["U1.1", "C1.2", "C2.2", "J1.3"],
183
+ "netLabelWidth": 0.48
184
+ },
185
+ {
186
+ "netId": "NODE",
187
+ "pinIds": ["U1.2", "U1.6", "R2.2", "C1.1"],
188
+ "netLabelWidth": 0.6
189
+ },
190
+ {
191
+ "netId": "OUT",
192
+ "pinIds": ["U1.3", "J1.2"],
193
+ "netLabelWidth": 0.48
194
+ },
195
+ {
196
+ "netId": "VCC",
197
+ "pinIds": ["U1.4", "U1.8", "R1.1", "J1.1"],
198
+ "netLabelWidth": 0.48
199
+ }
200
+ ],
201
+ "availableNetLabelOrientations": {
202
+ "VCC": ["y+"],
203
+ "GND": ["y-"]
204
+ },
205
+ "maxMspPairDistance": 2.4
206
+ }