@tscircuit/schematic-trace-solver 0.0.40 → 0.0.42

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 (57) hide show
  1. package/dist/index.d.ts +155 -9
  2. package/dist/index.js +998 -479
  3. package/lib/solvers/LongDistancePairSolver/LongDistancePairSolver.ts +238 -0
  4. package/lib/solvers/SchematicTracePipelineSolver/SchematicTracePipelineSolver.ts +61 -26
  5. package/lib/solvers/TraceLabelOverlapAvoidanceSolver/TraceLabelOverlapAvoidanceSolver.ts +94 -192
  6. package/lib/solvers/TraceLabelOverlapAvoidanceSolver/rerouteCollidingTrace.ts +13 -24
  7. package/lib/solvers/TraceLabelOverlapAvoidanceSolver/sub-solvers/LabelMergingSolver/LabelMergingSolver.ts +205 -0
  8. package/lib/solvers/TraceLabelOverlapAvoidanceSolver/sub-solvers/OverlapAvoidanceStepSolver/OverlapAvoidanceStepSolver.ts +144 -0
  9. package/lib/solvers/TraceLabelOverlapAvoidanceSolver/sub-solvers/SingleOverlapSolver/SingleOverlapSolver.ts +117 -0
  10. package/lib/solvers/TraceLabelOverlapAvoidanceSolver/sub-solvers/TraceCleanupSolver/TraceCleanupSolver.ts +132 -0
  11. package/lib/solvers/TraceLabelOverlapAvoidanceSolver/{balanceLShapes.ts → sub-solvers/TraceCleanupSolver/balanceLShapes.ts} +12 -10
  12. package/lib/solvers/TraceLabelOverlapAvoidanceSolver/{hasCollisions.ts → sub-solvers/TraceCleanupSolver/hasCollisions.ts} +1 -1
  13. package/lib/solvers/TraceLabelOverlapAvoidanceSolver/{hasCollisionsWithLabels.ts → sub-solvers/TraceCleanupSolver/hasCollisionsWithLabels.ts} +1 -1
  14. package/lib/solvers/TraceLabelOverlapAvoidanceSolver/{minimizeTurnsWithFilteredLabels.ts → sub-solvers/TraceCleanupSolver/minimizeTurnsWithFilteredLabels.ts} +6 -6
  15. package/lib/solvers/TraceLabelOverlapAvoidanceSolver/{simplifyPath.ts → sub-solvers/TraceCleanupSolver/simplifyPath.ts} +1 -1
  16. package/lib/solvers/TraceLabelOverlapAvoidanceSolver/{turnMinimization.ts → sub-solvers/TraceCleanupSolver/turnMinimization.ts} +0 -2
  17. package/lib/solvers/TraceLabelOverlapAvoidanceSolver/tryFourPointDetour.ts +104 -0
  18. package/lib/solvers/TraceLabelOverlapAvoidanceSolver/trySnipAndReconnect.ts +24 -154
  19. package/lib/utils/does-trace-overlap-with-existing-traces.ts +33 -0
  20. package/package.json +1 -1
  21. package/site/examples/example25.page.tsx +4 -0
  22. package/tests/assets/1.input.json +379 -0
  23. package/tests/assets/2.input.json +330 -0
  24. package/tests/assets/3.input.json +388 -0
  25. package/tests/assets/MergedNetLabelObstacles.test.input.json +154 -0
  26. package/tests/assets/OverlapAvoidanceStepSolver.test.input.json +682 -0
  27. package/tests/assets/SingleOverlapSolver.test.input.json +170 -0
  28. package/tests/assets/TraceCleanupSolver.test.input.json +216 -0
  29. package/tests/assets/TraceLabelOverlapAvoidanceSolver.test.input.json +424 -0
  30. package/tests/assets/example25.json +96 -0
  31. package/tests/examples/__snapshots__/example03.snap.svg +67 -76
  32. package/tests/examples/__snapshots__/example10.snap.svg +24 -30
  33. package/tests/examples/__snapshots__/example13.snap.svg +81 -84
  34. package/tests/examples/__snapshots__/example15.snap.svg +5 -8
  35. package/tests/examples/__snapshots__/example21.snap.svg +68 -74
  36. package/tests/examples/__snapshots__/example25.snap.svg +3 -3
  37. package/tests/examples/__snapshots__/example26.snap.svg +3 -3
  38. package/tests/examples/__snapshots__/example28.snap.svg +273 -0
  39. package/tests/examples/example28.test.ts +13 -0
  40. package/tests/solvers/TraceLabelOverlapAvoidanceSolver/TraceLabelOverlapAvoidanceSolver.test.ts +18 -0
  41. package/tests/solvers/TraceLabelOverlapAvoidanceSolver/__snapshots__/TraceLabelOverlapAvoidanceSolver.snap.svg +243 -0
  42. package/tests/solvers/TraceLabelOverlapAvoidanceSolver/renderComparisonView/__snapshots__/renderComparisonView01.snap.svg +223 -0
  43. package/tests/solvers/TraceLabelOverlapAvoidanceSolver/renderComparisonView/__snapshots__/renderComparisonView02.snap.svg +205 -0
  44. package/tests/solvers/TraceLabelOverlapAvoidanceSolver/renderComparisonView/__snapshots__/renderComparisonView03.snap.svg +184 -0
  45. package/tests/solvers/TraceLabelOverlapAvoidanceSolver/renderComparisonView/renderComparisonView01.test.ts +29 -0
  46. package/tests/solvers/TraceLabelOverlapAvoidanceSolver/renderComparisonView/renderComparisonView02.test.ts +27 -0
  47. package/tests/solvers/TraceLabelOverlapAvoidanceSolver/renderComparisonView/renderComparisonView03.test.ts +39 -0
  48. package/tests/solvers/TraceLabelOverlapAvoidanceSolver/sub-solver/MergedNetLabelObstacles.test.ts +14 -0
  49. package/tests/solvers/TraceLabelOverlapAvoidanceSolver/sub-solver/OverlapAvoidanceStepSolver.test.ts +20 -0
  50. package/tests/solvers/TraceLabelOverlapAvoidanceSolver/sub-solver/SingleOverlapSolver.test.ts +10 -0
  51. package/tests/solvers/TraceLabelOverlapAvoidanceSolver/sub-solver/TraceCleanupSolver.test.ts +19 -0
  52. package/tests/solvers/TraceLabelOverlapAvoidanceSolver/sub-solver/__snapshots__/MergedNetLabelObstacles.snap.svg +140 -0
  53. package/tests/solvers/TraceLabelOverlapAvoidanceSolver/sub-solver/__snapshots__/OverlapAvoidanceStepSolver.snap.svg +216 -0
  54. package/tests/solvers/TraceLabelOverlapAvoidanceSolver/sub-solver/__snapshots__/SingleOverlapSolver.snap.svg +125 -0
  55. package/tests/solvers/TraceLabelOverlapAvoidanceSolver/sub-solver/__snapshots__/TraceCleanupSolver.snap.svg +119 -0
  56. /package/lib/solvers/TraceLabelOverlapAvoidanceSolver/{countTurns.ts → sub-solvers/TraceCleanupSolver/countTurns.ts} +0 -0
  57. /package/lib/solvers/TraceLabelOverlapAvoidanceSolver/{tryConnectPoints.ts → sub-solvers/TraceCleanupSolver/tryConnectPoints.ts} +0 -0
@@ -1,32 +1,26 @@
1
1
  import type { Point } from "@tscircuit/math-utils"
2
- import { getRectBounds } from "../NetLabelPlacementSolver/SingleNetLabelPlacementSolver/geometry"
3
2
  import type { SolvedTracePath } from "../SchematicTraceLinesSolver/SchematicTraceLinesSolver"
4
- import {
5
- isPathCollidingWithObstacles,
6
- isVertical,
7
- segmentIntersectsRect,
8
- } from "../SchematicTraceLinesSolver/SchematicTraceSingleLineSolver2/collisions"
9
- import type { NetLabelPlacement } from "../NetLabelPlacementSolver/NetLabelPlacementSolver"
10
- import { simplifyPath } from "./simplifyPath"
11
3
 
12
- export const trySnipAndReconnect = ({
4
+ export const generateSnipAndReconnectCandidates = ({
13
5
  initialTrace,
14
6
  firstInsideIndex,
15
7
  lastInsideIndex,
16
8
  labelBounds,
17
- obstacles,
9
+ paddingBuffer,
10
+ detourCount,
18
11
  }: {
19
12
  initialTrace: SolvedTracePath
20
13
  firstInsideIndex: number
21
14
  lastInsideIndex: number
22
15
  labelBounds: any
23
- obstacles: any[]
24
- }): SolvedTracePath | null => {
16
+ paddingBuffer: number
17
+ detourCount: number
18
+ }): Point[][] => {
25
19
  if (
26
20
  firstInsideIndex <= 0 ||
27
21
  lastInsideIndex >= initialTrace.tracePath.length - 1
28
22
  ) {
29
- return null
23
+ return []
30
24
  }
31
25
 
32
26
  const entryPoint = initialTrace.tracePath[firstInsideIndex - 1]
@@ -35,32 +29,19 @@ export const trySnipAndReconnect = ({
35
29
  const pathToEntry = initialTrace.tracePath.slice(0, firstInsideIndex)
36
30
  const pathFromExit = initialTrace.tracePath.slice(lastInsideIndex + 1)
37
31
 
38
- const candidateDetours: Point[][] = []
32
+ const allCandidateDetours: Point[][] = []
39
33
 
34
+ // Candidate type 1: simple elbow
40
35
  if (entryPoint.x !== exitPoint.x && entryPoint.y !== exitPoint.y) {
41
- candidateDetours.push([{ x: exitPoint.x, y: entryPoint.y }])
42
- candidateDetours.push([{ x: entryPoint.x, y: exitPoint.y }])
36
+ allCandidateDetours.push([{ x: exitPoint.x, y: entryPoint.y }])
37
+ allCandidateDetours.push([{ x: entryPoint.x, y: exitPoint.y }])
43
38
  } else if (entryPoint.x === exitPoint.x || entryPoint.y === exitPoint.y) {
44
- const newPath = [...pathToEntry, ...pathFromExit]
45
- const simplified = simplifyPath(newPath)
46
- if (!isPathCollidingWithObstacles(simplified, obstacles)) {
47
- return { ...initialTrace, tracePath: simplified }
48
- }
39
+ // Candidate type 2: direct connection (if points are aligned)
40
+ allCandidateDetours.push([]) // No detour points needed
49
41
  }
50
42
 
51
- for (let i = 0; i < candidateDetours.length; i++) {
52
- const detour = candidateDetours[i]
53
- const newFullPath = [...pathToEntry, ...detour, ...pathFromExit]
54
- const simplified = simplifyPath(newFullPath)
55
-
56
- if (!isPathCollidingWithObstacles(simplified, obstacles)) {
57
- return { ...initialTrace, tracePath: simplified }
58
- }
59
- }
60
-
61
- candidateDetours.length = 0
62
-
63
- const buffer = 0.1
43
+ // Candidate type 3: routing around the label bounds
44
+ const buffer = paddingBuffer + detourCount * paddingBuffer
64
45
  const leftX = labelBounds.minX - buffer
65
46
  const rightX = labelBounds.maxX + buffer
66
47
  const topY = labelBounds.maxY + buffer
@@ -71,7 +52,7 @@ export const trySnipAndReconnect = ({
71
52
  entryPoint.x < labelBounds.maxX &&
72
53
  exitPoint.x < labelBounds.maxX
73
54
  ) {
74
- candidateDetours.push([
55
+ allCandidateDetours.push([
75
56
  { x: leftX, y: entryPoint.y },
76
57
  { x: leftX, y: exitPoint.y },
77
58
  ])
@@ -82,7 +63,7 @@ export const trySnipAndReconnect = ({
82
63
  entryPoint.x > labelBounds.minX &&
83
64
  exitPoint.x > labelBounds.minX
84
65
  ) {
85
- candidateDetours.push([
66
+ allCandidateDetours.push([
86
67
  { x: rightX, y: entryPoint.y },
87
68
  { x: rightX, y: exitPoint.y },
88
69
  ])
@@ -93,7 +74,7 @@ export const trySnipAndReconnect = ({
93
74
  entryPoint.y > labelBounds.minY &&
94
75
  exitPoint.y > labelBounds.minY
95
76
  ) {
96
- candidateDetours.push([
77
+ allCandidateDetours.push([
97
78
  { x: entryPoint.x, y: topY },
98
79
  { x: exitPoint.x, y: topY },
99
80
  ])
@@ -104,126 +85,15 @@ export const trySnipAndReconnect = ({
104
85
  entryPoint.y < labelBounds.maxY &&
105
86
  exitPoint.y < labelBounds.maxY
106
87
  ) {
107
- candidateDetours.push([
88
+ allCandidateDetours.push([
108
89
  { x: entryPoint.x, y: bottomY },
109
90
  { x: exitPoint.x, y: bottomY },
110
91
  ])
111
92
  }
112
93
 
113
- for (let i = 0; i < candidateDetours.length; i++) {
114
- const detour = candidateDetours[i]
115
- const newFullPath = [...pathToEntry, ...detour, ...pathFromExit]
116
- const simplified = simplifyPath(newFullPath)
117
-
118
- if (!isPathCollidingWithObstacles(simplified, obstacles)) {
119
- return { ...initialTrace, tracePath: simplified }
120
- }
121
- }
122
-
123
- return null
124
- }
125
-
126
- export const tryFourPointDetour = ({
127
- initialTrace,
128
- label,
129
- labelBounds,
130
- obstacles,
131
- paddingBuffer,
132
- detourCount,
133
- }: {
134
- initialTrace: SolvedTracePath
135
- label: NetLabelPlacement
136
- labelBounds: any
137
- obstacles: any[]
138
- paddingBuffer: number
139
- detourCount: number
140
- }): SolvedTracePath | null => {
141
- let collidingSegIndex = -1
142
- for (let i = 0; i < initialTrace.tracePath.length - 1; i++) {
143
- if (
144
- segmentIntersectsRect(
145
- initialTrace.tracePath[i],
146
- initialTrace.tracePath[i + 1],
147
- labelBounds,
148
- )
149
- ) {
150
- collidingSegIndex = i
151
- break
152
- }
153
- }
154
-
155
- if (collidingSegIndex === -1) return initialTrace
156
-
157
- const pA = initialTrace.tracePath[collidingSegIndex]
158
- const pB = initialTrace.tracePath[collidingSegIndex + 1]
159
-
160
- if (!pA || !pB) return null
161
-
162
- const candidateDetours: Point[][] = []
163
- const paddedLabelBounds = getRectBounds(
164
- label.center,
165
- label.width,
166
- label.height,
167
- )
168
-
169
- const effectivePadding = paddingBuffer + detourCount * paddingBuffer
170
-
171
- if (isVertical(pA, pB)) {
172
- const xCandidates = [
173
- paddedLabelBounds.maxX + effectivePadding,
174
- paddedLabelBounds.minX - effectivePadding,
175
- ]
176
- for (const newX of xCandidates) {
177
- candidateDetours.push(
178
- pB.y > pA.y
179
- ? [
180
- { x: pA.x, y: paddedLabelBounds.minY - effectivePadding },
181
- { x: newX, y: paddedLabelBounds.minY - effectivePadding },
182
- { x: newX, y: paddedLabelBounds.maxY + effectivePadding },
183
- { x: pB.x, y: paddedLabelBounds.maxY + effectivePadding },
184
- ]
185
- : [
186
- { x: pA.x, y: paddedLabelBounds.maxY + effectivePadding },
187
- { x: newX, y: paddedLabelBounds.maxY + effectivePadding },
188
- { x: newX, y: paddedLabelBounds.minY - effectivePadding },
189
- { x: pB.x, y: paddedLabelBounds.minY - effectivePadding },
190
- ],
191
- )
192
- }
193
- } else {
194
- const yCandidates = [
195
- paddedLabelBounds.maxY + effectivePadding,
196
- paddedLabelBounds.minY - effectivePadding,
197
- ]
198
- for (const newY of yCandidates) {
199
- candidateDetours.push(
200
- pB.x > pA.x
201
- ? [
202
- { x: paddedLabelBounds.minX - effectivePadding, y: pA.y },
203
- { x: paddedLabelBounds.minX - effectivePadding, y: newY },
204
- { x: paddedLabelBounds.maxX + effectivePadding, y: newY },
205
- { x: paddedLabelBounds.maxX + effectivePadding, y: pB.y },
206
- ]
207
- : [
208
- { x: paddedLabelBounds.maxX + effectivePadding, y: pA.y },
209
- { x: paddedLabelBounds.maxX + effectivePadding, y: newY },
210
- { x: paddedLabelBounds.minX - effectivePadding, y: newY },
211
- { x: paddedLabelBounds.minX - effectivePadding, y: pB.y },
212
- ],
213
- )
214
- }
215
- }
216
-
217
- for (const detourPoints of candidateDetours) {
218
- const finalPath = [
219
- ...initialTrace.tracePath.slice(0, collidingSegIndex + 1),
220
- ...detourPoints,
221
- ...initialTrace.tracePath.slice(collidingSegIndex + 1),
222
- ]
223
- const simplifiedFinalPath = simplifyPath(finalPath)
224
- if (!isPathCollidingWithObstacles(simplifiedFinalPath, obstacles)) {
225
- return { ...initialTrace, tracePath: simplifiedFinalPath }
226
- }
227
- }
228
- return null
94
+ return allCandidateDetours.map((detour) => [
95
+ ...pathToEntry,
96
+ ...detour,
97
+ ...pathFromExit,
98
+ ])
229
99
  }
@@ -0,0 +1,33 @@
1
+ import type { Point } from "@tscircuit/math-utils"
2
+ import type { SolvedTracePath } from "../solvers/SchematicTraceLinesSolver/SchematicTraceLinesSolver"
3
+ import { doSegmentsIntersect } from "@tscircuit/math-utils"
4
+
5
+ export function doesTraceOverlapWithExistingTraces(
6
+ newTracePath: Point[],
7
+ existingTraces: SolvedTracePath[],
8
+ ): boolean {
9
+ for (let i = 0; i < newTracePath.length - 1; i++) {
10
+ const newSegmentP1 = newTracePath[i]
11
+ const newSegmentP2 = newTracePath[i + 1]
12
+
13
+ for (const existingTrace of existingTraces) {
14
+ for (let j = 0; j < existingTrace.tracePath.length - 1; j++) {
15
+ const existingSegmentP1 = existingTrace.tracePath[j]
16
+ const existingSegmentP2 = existingTrace.tracePath[j + 1]
17
+
18
+ if (
19
+ doSegmentsIntersect(
20
+ newSegmentP1,
21
+ newSegmentP2,
22
+ existingSegmentP1,
23
+ existingSegmentP2,
24
+ )
25
+ ) {
26
+ return true // Found an intersection
27
+ }
28
+ }
29
+ }
30
+ }
31
+
32
+ return false // No intersections found
33
+ }
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.40",
4
+ "version": "0.0.42",
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/example25.json"
3
+
4
+ export default () => <PipelineDebugger inputProblem={inputProblem as any} />
@@ -0,0 +1,379 @@
1
+ {
2
+ "mergedNetLabelObstacleSolver": {
3
+ "netLabelPlacements": [
4
+ {
5
+ "globalConnNetId": "connectivity_net0",
6
+ "dcConnNetId": "connectivity_net0",
7
+ "netId": "GND",
8
+ "mspConnectionPairIds": ["U1.1-J1.3"],
9
+ "pinIds": ["U1.1", "J1.3"],
10
+ "orientation": "y-",
11
+ "anchorPoint": {
12
+ "x": 1.4000000000000001,
13
+ "y": -2.295
14
+ },
15
+ "width": 0.2,
16
+ "height": 0.45,
17
+ "center": {
18
+ "x": 1.4000000000000001,
19
+ "y": -2.52
20
+ }
21
+ },
22
+ {
23
+ "globalConnNetId": "connectivity_net1",
24
+ "netId": "VCC",
25
+ "mspConnectionPairIds": [],
26
+ "pinIds": ["U1.8"],
27
+ "orientation": "x+",
28
+ "anchorPoint": {
29
+ "x": 1.2000000000000002,
30
+ "y": 0.30000000000000004
31
+ },
32
+ "width": 0.45,
33
+ "height": 0.2,
34
+ "center": {
35
+ "x": 1.4260000000000002,
36
+ "y": 0.30000000000000004
37
+ }
38
+ },
39
+ {
40
+ "globalConnNetId": "connectivity_net1",
41
+ "netId": "VCC",
42
+ "mspConnectionPairIds": [],
43
+ "pinIds": ["J1.1"],
44
+ "orientation": "x-",
45
+ "anchorPoint": {
46
+ "x": 1.6,
47
+ "y": -1.895
48
+ },
49
+ "width": 0.45,
50
+ "height": 0.2,
51
+ "center": {
52
+ "x": 1.374,
53
+ "y": -1.895
54
+ }
55
+ },
56
+ {
57
+ "globalConnNetId": "connectivity_net2",
58
+ "netId": "MMM",
59
+ "mspConnectionPairIds": [],
60
+ "pinIds": ["J1.2"],
61
+ "orientation": "x-",
62
+ "anchorPoint": {
63
+ "x": 1.6,
64
+ "y": -2.095
65
+ },
66
+ "width": 0.45,
67
+ "height": 0.2,
68
+ "center": {
69
+ "x": 1.374,
70
+ "y": -2.095
71
+ }
72
+ }
73
+ ],
74
+ "inputProblem": {
75
+ "chips": [
76
+ {
77
+ "chipId": "schematic_component_0",
78
+ "center": {
79
+ "x": 0,
80
+ "y": 0
81
+ },
82
+ "width": 2.4000000000000004,
83
+ "height": 1,
84
+ "pins": [
85
+ {
86
+ "pinId": "U1.1",
87
+ "x": 1.2000000000000002,
88
+ "y": -0.30000000000000004
89
+ },
90
+ {
91
+ "pinId": "U1.2",
92
+ "x": -1.2000000000000002,
93
+ "y": -0.30000000000000004
94
+ },
95
+ {
96
+ "pinId": "U1.3",
97
+ "x": 1.2000000000000002,
98
+ "y": 0.09999999999999998
99
+ },
100
+ {
101
+ "pinId": "U1.4",
102
+ "x": -1.2000000000000002,
103
+ "y": 0.30000000000000004
104
+ },
105
+ {
106
+ "pinId": "U1.5",
107
+ "x": -1.2000000000000002,
108
+ "y": 0.10000000000000003
109
+ },
110
+ {
111
+ "pinId": "U1.6",
112
+ "x": -1.2000000000000002,
113
+ "y": -0.09999999999999998
114
+ },
115
+ {
116
+ "pinId": "U1.7",
117
+ "x": 1.2000000000000002,
118
+ "y": -0.10000000000000003
119
+ },
120
+ {
121
+ "pinId": "U1.8",
122
+ "x": 1.2000000000000002,
123
+ "y": 0.30000000000000004
124
+ }
125
+ ]
126
+ },
127
+ {
128
+ "chipId": "schematic_component_1",
129
+ "center": {
130
+ "x": 2.7,
131
+ "y": -2.095
132
+ },
133
+ "width": 2.2,
134
+ "height": 0.8,
135
+ "pins": [
136
+ {
137
+ "pinId": "J1.1",
138
+ "x": 1.6,
139
+ "y": -1.895
140
+ },
141
+ {
142
+ "pinId": "J1.2",
143
+ "x": 1.6,
144
+ "y": -2.095
145
+ },
146
+ {
147
+ "pinId": "J1.3",
148
+ "x": 1.6,
149
+ "y": -2.295
150
+ }
151
+ ]
152
+ }
153
+ ],
154
+ "directConnections": [],
155
+ "netConnections": [
156
+ {
157
+ "netId": "GND",
158
+ "pinIds": ["U1.1", "J1.3"]
159
+ },
160
+ {
161
+ "netId": "VCC",
162
+ "pinIds": ["U1.8", "J1.1"]
163
+ },
164
+ {
165
+ "netId": "MMM",
166
+ "pinIds": ["J1.2"]
167
+ }
168
+ ],
169
+ "availableNetLabelOrientations": {
170
+ "VCC": ["y-"],
171
+ "OUT": ["x-", "x+"],
172
+ "GND": ["y-"],
173
+ "MMM": ["x+", "x-"]
174
+ },
175
+ "maxMspPairDistance": 2.4
176
+ },
177
+ "traces": [
178
+ {
179
+ "mspPairId": "U1.1-J1.3",
180
+ "dcConnNetId": "connectivity_net0",
181
+ "globalConnNetId": "connectivity_net0",
182
+ "userNetId": "GND",
183
+ "pins": [
184
+ {
185
+ "pinId": "U1.1",
186
+ "x": 1.2000000000000002,
187
+ "y": -0.30000000000000004,
188
+ "chipId": "schematic_component_0",
189
+ "_facingDirection": "x+"
190
+ },
191
+ {
192
+ "pinId": "J1.3",
193
+ "x": 1.6,
194
+ "y": -2.295,
195
+ "chipId": "schematic_component_1",
196
+ "_facingDirection": "x-"
197
+ }
198
+ ],
199
+ "tracePath": [
200
+ {
201
+ "x": 1.2000000000000002,
202
+ "y": -0.30000000000000004
203
+ },
204
+ {
205
+ "x": 1.4000000000000001,
206
+ "y": -0.30000000000000004
207
+ },
208
+ {
209
+ "x": 1.4000000000000001,
210
+ "y": -1.2974999999999999
211
+ },
212
+ {
213
+ "x": 1.4000000000000001,
214
+ "y": -2.295
215
+ },
216
+ {
217
+ "x": 1.6,
218
+ "y": -2.295
219
+ }
220
+ ],
221
+ "mspConnectionPairIds": ["U1.1-J1.3"],
222
+ "pinIds": ["U1.1", "J1.3"]
223
+ }
224
+ ]
225
+ },
226
+ "netLabelPlacementSolver": {
227
+ "inputProblem": {
228
+ "chips": [
229
+ {
230
+ "chipId": "schematic_component_0",
231
+ "center": {
232
+ "x": 0,
233
+ "y": 0
234
+ },
235
+ "width": 2.4000000000000004,
236
+ "height": 1,
237
+ "pins": [
238
+ {
239
+ "pinId": "U1.1",
240
+ "x": 1.2000000000000002,
241
+ "y": -0.30000000000000004
242
+ },
243
+ {
244
+ "pinId": "U1.2",
245
+ "x": -1.2000000000000002,
246
+ "y": -0.30000000000000004
247
+ },
248
+ {
249
+ "pinId": "U1.3",
250
+ "x": 1.2000000000000002,
251
+ "y": 0.09999999999999998
252
+ },
253
+ {
254
+ "pinId": "U1.4",
255
+ "x": -1.2000000000000002,
256
+ "y": 0.30000000000000004
257
+ },
258
+ {
259
+ "pinId": "U1.5",
260
+ "x": -1.2000000000000002,
261
+ "y": 0.10000000000000003
262
+ },
263
+ {
264
+ "pinId": "U1.6",
265
+ "x": -1.2000000000000002,
266
+ "y": -0.09999999999999998
267
+ },
268
+ {
269
+ "pinId": "U1.7",
270
+ "x": 1.2000000000000002,
271
+ "y": -0.10000000000000003
272
+ },
273
+ {
274
+ "pinId": "U1.8",
275
+ "x": 1.2000000000000002,
276
+ "y": 0.30000000000000004
277
+ }
278
+ ]
279
+ },
280
+ {
281
+ "chipId": "schematic_component_1",
282
+ "center": {
283
+ "x": 2.7,
284
+ "y": -2.095
285
+ },
286
+ "width": 2.2,
287
+ "height": 0.8,
288
+ "pins": [
289
+ {
290
+ "pinId": "J1.1",
291
+ "x": 1.6,
292
+ "y": -1.895
293
+ },
294
+ {
295
+ "pinId": "J1.2",
296
+ "x": 1.6,
297
+ "y": -2.095
298
+ },
299
+ {
300
+ "pinId": "J1.3",
301
+ "x": 1.6,
302
+ "y": -2.295
303
+ }
304
+ ]
305
+ }
306
+ ],
307
+ "directConnections": [],
308
+ "netConnections": [
309
+ {
310
+ "netId": "GND",
311
+ "pinIds": ["U1.1", "J1.3"]
312
+ },
313
+ {
314
+ "netId": "VCC",
315
+ "pinIds": ["U1.8", "J1.1"]
316
+ },
317
+ {
318
+ "netId": "MMM",
319
+ "pinIds": ["J1.2"]
320
+ }
321
+ ],
322
+ "availableNetLabelOrientations": {
323
+ "VCC": ["y-"],
324
+ "OUT": ["x-", "x+"],
325
+ "GND": ["y-"],
326
+ "MMM": ["x+", "x-"]
327
+ },
328
+ "maxMspPairDistance": 2.4
329
+ },
330
+ "inputTraceMap": {
331
+ "U1.1-J1.3": {
332
+ "mspPairId": "U1.1-J1.3",
333
+ "dcConnNetId": "connectivity_net0",
334
+ "globalConnNetId": "connectivity_net0",
335
+ "userNetId": "GND",
336
+ "pins": [
337
+ {
338
+ "pinId": "U1.1",
339
+ "x": 1.2000000000000002,
340
+ "y": -0.30000000000000004,
341
+ "chipId": "schematic_component_0",
342
+ "_facingDirection": "x+"
343
+ },
344
+ {
345
+ "pinId": "J1.3",
346
+ "x": 1.6,
347
+ "y": -2.295,
348
+ "chipId": "schematic_component_1",
349
+ "_facingDirection": "x-"
350
+ }
351
+ ],
352
+ "tracePath": [
353
+ {
354
+ "x": 1.2000000000000002,
355
+ "y": -0.30000000000000004
356
+ },
357
+ {
358
+ "x": 1.4000000000000001,
359
+ "y": -0.30000000000000004
360
+ },
361
+ {
362
+ "x": 1.4000000000000001,
363
+ "y": -1.2974999999999999
364
+ },
365
+ {
366
+ "x": 1.4000000000000001,
367
+ "y": -2.295
368
+ },
369
+ {
370
+ "x": 1.6,
371
+ "y": -2.295
372
+ }
373
+ ],
374
+ "mspConnectionPairIds": ["U1.1-J1.3"],
375
+ "pinIds": ["U1.1", "J1.3"]
376
+ }
377
+ }
378
+ }
379
+ }