@tscircuit/schematic-trace-solver 0.0.57 → 0.0.60
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 +266 -128
- package/lib/solvers/AvailableNetOrientationSolver/AvailableNetOrientationSolver.ts +19 -3
- package/lib/solvers/Example28Solver/reroute.ts +137 -17
- package/lib/solvers/Example28Solver/types.ts +1 -0
- package/lib/solvers/NetLabelPlacementSolver/NetLabelPlacementSolver.ts +32 -10
- package/lib/solvers/TraceAnchoredNetLabelOverlapSolver/candidates.ts +17 -5
- package/lib/solvers/TraceCleanupSolver/is4PointRectangle.ts +7 -2
- package/lib/types/InputProblem.ts +1 -0
- package/package.json +1 -1
- package/site/examples/example35.page.tsx +4 -0
- package/site/examples/example36.page.tsx +4 -0
- package/tests/assets/example35.json +127 -0
- package/tests/assets/example36.json +124 -0
- package/tests/examples/__snapshots__/example35.snap.svg +177 -0
- package/tests/examples/__snapshots__/example36.snap.svg +160 -0
- package/tests/examples/example35.test.ts +12 -0
- package/tests/examples/example36.test.ts +12 -0
|
@@ -431,9 +431,25 @@ export class AvailableNetOrientationSolver extends BaseSolver {
|
|
|
431
431
|
}
|
|
432
432
|
|
|
433
433
|
private getNetLabelWidth(label: NetLabelPlacement) {
|
|
434
|
-
if (
|
|
435
|
-
|
|
436
|
-
|
|
434
|
+
if (label.netId) {
|
|
435
|
+
const ncWidth = this.inputProblem.netConnections.find(
|
|
436
|
+
(connection) => connection.netId === label.netId,
|
|
437
|
+
)?.netLabelWidth
|
|
438
|
+
if (ncWidth !== undefined) return ncWidth
|
|
439
|
+
|
|
440
|
+
const dcWidthByNetId = this.inputProblem.directConnections.find(
|
|
441
|
+
(dc) => dc.netId === label.netId,
|
|
442
|
+
)?.netLabelWidth
|
|
443
|
+
if (dcWidthByNetId !== undefined) return dcWidthByNetId
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
const dcWidthByPinId = this.inputProblem.directConnections.find((dc) =>
|
|
447
|
+
dc.pinIds.some((pid) => label.pinIds.includes(pid)),
|
|
448
|
+
)?.netLabelWidth
|
|
449
|
+
if (dcWidthByPinId !== undefined) return dcWidthByPinId
|
|
450
|
+
|
|
451
|
+
return this.inputProblem.netConnections.find((nc) =>
|
|
452
|
+
nc.pinIds.some((pid) => label.pinIds.includes(pid)),
|
|
437
453
|
)?.netLabelWidth
|
|
438
454
|
}
|
|
439
455
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { Point } from "@tscircuit/math-utils"
|
|
2
2
|
import type { NetLabelPlacement } from "lib/solvers/NetLabelPlacementSolver/NetLabelPlacementSolver"
|
|
3
|
+
import { segmentIntersectsRect as segmentIntersectsLabelRect } from "lib/solvers/NetLabelPlacementSolver/SingleNetLabelPlacementSolver/collisions"
|
|
3
4
|
import { getRectBounds } from "lib/solvers/NetLabelPlacementSolver/SingleNetLabelPlacementSolver/geometry"
|
|
4
5
|
import type { SolvedTracePath } from "lib/solvers/SchematicTraceLinesSolver/SchematicTraceLinesSolver"
|
|
5
6
|
import { simplifyPath } from "lib/solvers/TraceCleanupSolver/simplifyPath"
|
|
@@ -73,9 +74,39 @@ export const generateRerouteCandidateResults = ({
|
|
|
73
74
|
outputNetLabelPlacements: NetLabelPlacement[]
|
|
74
75
|
chipObstacles: ChipObstacle[]
|
|
75
76
|
}) => {
|
|
76
|
-
const rawCandidates = generateCandidatePaths(trace, label, inputProblem)
|
|
77
77
|
const seen = new Set<string>()
|
|
78
78
|
const candidateResults: RerouteCandidateResult[] = []
|
|
79
|
+
const horizontalSegmentPushCandidate = generateHorizontalSegmentPushCandidate(
|
|
80
|
+
trace,
|
|
81
|
+
label,
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
if (horizontalSegmentPushCandidate) {
|
|
85
|
+
candidateResults.push(
|
|
86
|
+
createCandidateResult({
|
|
87
|
+
trace,
|
|
88
|
+
obstacleLabel: label,
|
|
89
|
+
path: horizontalSegmentPushCandidate,
|
|
90
|
+
seen,
|
|
91
|
+
outputTraces,
|
|
92
|
+
outputNetLabelPlacements,
|
|
93
|
+
chipObstacles,
|
|
94
|
+
usesHorizontalSegmentPush: true,
|
|
95
|
+
}),
|
|
96
|
+
)
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const rawCandidates = [
|
|
100
|
+
...generateLabelHugCandidates(trace, label),
|
|
101
|
+
...generateRerouteCandidates({
|
|
102
|
+
trace,
|
|
103
|
+
label,
|
|
104
|
+
problem: inputProblem,
|
|
105
|
+
paddingBuffer: LABEL_SIDE_CLEARANCE,
|
|
106
|
+
detourCount: 0,
|
|
107
|
+
}),
|
|
108
|
+
...generateEndpointDetourCandidates(trace, label),
|
|
109
|
+
]
|
|
79
110
|
|
|
80
111
|
for (const rawCandidate of rawCandidates) {
|
|
81
112
|
candidateResults.push(
|
|
@@ -94,22 +125,6 @@ export const generateRerouteCandidateResults = ({
|
|
|
94
125
|
return candidateResults
|
|
95
126
|
}
|
|
96
127
|
|
|
97
|
-
const generateCandidatePaths = (
|
|
98
|
-
trace: SolvedTracePath,
|
|
99
|
-
label: NetLabelPlacement,
|
|
100
|
-
inputProblem: InputProblem,
|
|
101
|
-
) => [
|
|
102
|
-
...generateLabelHugCandidates(trace, label),
|
|
103
|
-
...generateRerouteCandidates({
|
|
104
|
-
trace,
|
|
105
|
-
label,
|
|
106
|
-
problem: inputProblem,
|
|
107
|
-
paddingBuffer: LABEL_SIDE_CLEARANCE,
|
|
108
|
-
detourCount: 0,
|
|
109
|
-
}),
|
|
110
|
-
...generateEndpointDetourCandidates(trace, label),
|
|
111
|
-
]
|
|
112
|
-
|
|
113
128
|
const createCandidateResult = ({
|
|
114
129
|
trace,
|
|
115
130
|
obstacleLabel,
|
|
@@ -118,6 +133,7 @@ const createCandidateResult = ({
|
|
|
118
133
|
outputTraces,
|
|
119
134
|
outputNetLabelPlacements,
|
|
120
135
|
chipObstacles,
|
|
136
|
+
usesHorizontalSegmentPush,
|
|
121
137
|
}: {
|
|
122
138
|
trace: SolvedTracePath
|
|
123
139
|
obstacleLabel: NetLabelPlacement
|
|
@@ -126,6 +142,7 @@ const createCandidateResult = ({
|
|
|
126
142
|
outputTraces: SolvedTracePath[]
|
|
127
143
|
outputNetLabelPlacements: NetLabelPlacement[]
|
|
128
144
|
chipObstacles: ChipObstacle[]
|
|
145
|
+
usesHorizontalSegmentPush?: boolean
|
|
129
146
|
}): RerouteCandidateResult => {
|
|
130
147
|
const key = getPathKey(path)
|
|
131
148
|
|
|
@@ -133,6 +150,7 @@ const createCandidateResult = ({
|
|
|
133
150
|
return {
|
|
134
151
|
path,
|
|
135
152
|
status: "duplicate",
|
|
153
|
+
usesHorizontalSegmentPush,
|
|
136
154
|
selected: false,
|
|
137
155
|
}
|
|
138
156
|
}
|
|
@@ -143,6 +161,7 @@ const createCandidateResult = ({
|
|
|
143
161
|
return {
|
|
144
162
|
path,
|
|
145
163
|
status: "chip-collision",
|
|
164
|
+
usesHorizontalSegmentPush,
|
|
146
165
|
selected: false,
|
|
147
166
|
}
|
|
148
167
|
}
|
|
@@ -157,6 +176,7 @@ const createCandidateResult = ({
|
|
|
157
176
|
outputNetLabelPlacements,
|
|
158
177
|
}),
|
|
159
178
|
status: "valid",
|
|
179
|
+
usesHorizontalSegmentPush,
|
|
160
180
|
selected: false,
|
|
161
181
|
}
|
|
162
182
|
}
|
|
@@ -259,6 +279,13 @@ const selectBestReroutePath = ({
|
|
|
259
279
|
outputNetLabelPlacements: NetLabelPlacement[]
|
|
260
280
|
candidateResults: RerouteCandidateResult[]
|
|
261
281
|
}) => {
|
|
282
|
+
for (const candidate of candidateResults) {
|
|
283
|
+
if (!candidate.usesHorizontalSegmentPush) continue
|
|
284
|
+
if (candidate.status !== "valid") continue
|
|
285
|
+
if (!candidate.score) continue
|
|
286
|
+
return candidate.path
|
|
287
|
+
}
|
|
288
|
+
|
|
262
289
|
let bestPath: Point[] | null = null
|
|
263
290
|
let bestScore = scoreTracePath({
|
|
264
291
|
trace,
|
|
@@ -279,6 +306,99 @@ const selectBestReroutePath = ({
|
|
|
279
306
|
return bestPath
|
|
280
307
|
}
|
|
281
308
|
|
|
309
|
+
const generateHorizontalSegmentPushCandidate = (
|
|
310
|
+
trace: SolvedTracePath,
|
|
311
|
+
label: NetLabelPlacement,
|
|
312
|
+
): Point[] | null => {
|
|
313
|
+
const labelDirection = dir(label.orientation)
|
|
314
|
+
if (labelDirection.x === 0) return null
|
|
315
|
+
|
|
316
|
+
const path = trace.tracePath
|
|
317
|
+
const bounds = getRectBounds(label.center, label.width, label.height)
|
|
318
|
+
const collidingVerticalSegmentIndex = path.findIndex((start, index) => {
|
|
319
|
+
const end = path[index + 1]
|
|
320
|
+
if (!end) return false
|
|
321
|
+
if (Math.abs(start.x - end.x) >= 1e-9) return false
|
|
322
|
+
return segmentIntersectsLabelRect(start, end, bounds)
|
|
323
|
+
})
|
|
324
|
+
|
|
325
|
+
if (
|
|
326
|
+
collidingVerticalSegmentIndex <= 0 ||
|
|
327
|
+
collidingVerticalSegmentIndex >= path.length - 2
|
|
328
|
+
) {
|
|
329
|
+
return null
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
const previousAnchor = path[collidingVerticalSegmentIndex - 1]!
|
|
333
|
+
const verticalStart = path[collidingVerticalSegmentIndex]!
|
|
334
|
+
const verticalEnd = path[collidingVerticalSegmentIndex + 1]!
|
|
335
|
+
const nextAnchor = path[collidingVerticalSegmentIndex + 2]!
|
|
336
|
+
|
|
337
|
+
if (
|
|
338
|
+
Math.abs(previousAnchor.y - verticalStart.y) >= 1e-9 ||
|
|
339
|
+
Math.abs(verticalEnd.y - nextAnchor.y) >= 1e-9
|
|
340
|
+
) {
|
|
341
|
+
return null
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
let segmentPushX = bounds.minX - LABEL_SIDE_CLEARANCE
|
|
345
|
+
if (labelDirection.x > 0) {
|
|
346
|
+
segmentPushX = bounds.maxX + LABEL_SIDE_CLEARANCE
|
|
347
|
+
}
|
|
348
|
+
const segmentPushStartY = getClearedHorizontalY({
|
|
349
|
+
start: previousAnchor,
|
|
350
|
+
end: { x: segmentPushX, y: verticalStart.y },
|
|
351
|
+
labelBounds: bounds,
|
|
352
|
+
})
|
|
353
|
+
const segmentPushEndY = getClearedHorizontalY({
|
|
354
|
+
start: { x: segmentPushX, y: verticalEnd.y },
|
|
355
|
+
end: nextAnchor,
|
|
356
|
+
labelBounds: bounds,
|
|
357
|
+
})
|
|
358
|
+
|
|
359
|
+
const segmentPushPath: Point[] = [
|
|
360
|
+
...path.slice(0, collidingVerticalSegmentIndex - 1),
|
|
361
|
+
previousAnchor,
|
|
362
|
+
]
|
|
363
|
+
|
|
364
|
+
if (Math.abs(previousAnchor.y - segmentPushStartY) >= 1e-9) {
|
|
365
|
+
segmentPushPath.push({ x: previousAnchor.x, y: segmentPushStartY })
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
segmentPushPath.push({ x: segmentPushX, y: segmentPushStartY })
|
|
369
|
+
segmentPushPath.push({ x: segmentPushX, y: segmentPushEndY })
|
|
370
|
+
|
|
371
|
+
if (Math.abs(nextAnchor.y - segmentPushEndY) >= 1e-9) {
|
|
372
|
+
segmentPushPath.push({ x: nextAnchor.x, y: segmentPushEndY })
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
segmentPushPath.push(
|
|
376
|
+
nextAnchor,
|
|
377
|
+
...path.slice(collidingVerticalSegmentIndex + 3),
|
|
378
|
+
)
|
|
379
|
+
|
|
380
|
+
return simplifyPath(segmentPushPath)
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
const getClearedHorizontalY = ({
|
|
384
|
+
start,
|
|
385
|
+
end,
|
|
386
|
+
labelBounds,
|
|
387
|
+
}: {
|
|
388
|
+
start: Point
|
|
389
|
+
end: Point
|
|
390
|
+
labelBounds: { minX: number; minY: number; maxX: number; maxY: number }
|
|
391
|
+
}) => {
|
|
392
|
+
if (!segmentIntersectsLabelRect(start, end, labelBounds)) return start.y
|
|
393
|
+
|
|
394
|
+
const labelCenterY = (labelBounds.minY + labelBounds.maxY) / 2
|
|
395
|
+
if (start.y >= labelCenterY) {
|
|
396
|
+
return labelBounds.maxY + LABEL_HUG_CLEARANCE
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
return labelBounds.minY - LABEL_HUG_CLEARANCE
|
|
400
|
+
}
|
|
401
|
+
|
|
282
402
|
const markSelectedCandidate = (
|
|
283
403
|
candidateResults: RerouteCandidateResult[],
|
|
284
404
|
bestPath: Point[] | null,
|
|
@@ -250,6 +250,36 @@ export class NetLabelPlacementSolver extends BaseSolver {
|
|
|
250
250
|
return groups
|
|
251
251
|
}
|
|
252
252
|
|
|
253
|
+
private getNetLabelWidthForGroup(
|
|
254
|
+
group: OverlappingSameNetTraceGroup,
|
|
255
|
+
): number | undefined {
|
|
256
|
+
if (group.netId) {
|
|
257
|
+
const ncWidth = this.inputProblem.netConnections.find(
|
|
258
|
+
(nc) => nc.netId === group.netId,
|
|
259
|
+
)?.netLabelWidth
|
|
260
|
+
if (ncWidth !== undefined) return ncWidth
|
|
261
|
+
|
|
262
|
+
const dcWidthByNetId = this.inputProblem.directConnections.find(
|
|
263
|
+
(dc) => dc.netId === group.netId,
|
|
264
|
+
)?.netLabelWidth
|
|
265
|
+
if (dcWidthByNetId !== undefined) return dcWidthByNetId
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
const pinIds = group.overlappingTraces?.pins.map((p) => p.pinId) ?? []
|
|
269
|
+
if (group.portOnlyPinId) {
|
|
270
|
+
pinIds.push(group.portOnlyPinId)
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
const dcWidthByPinId = this.inputProblem.directConnections.find((dc) =>
|
|
274
|
+
dc.pinIds.some((pid) => pinIds.includes(pid)),
|
|
275
|
+
)?.netLabelWidth
|
|
276
|
+
if (dcWidthByPinId !== undefined) return dcWidthByPinId
|
|
277
|
+
|
|
278
|
+
return this.inputProblem.netConnections.find((nc) =>
|
|
279
|
+
nc.pinIds.some((pid) => pinIds.includes(pid)),
|
|
280
|
+
)?.netLabelWidth
|
|
281
|
+
}
|
|
282
|
+
|
|
253
283
|
override _step() {
|
|
254
284
|
if (this.activeSubSolver?.solved) {
|
|
255
285
|
this.netLabelPlacements.push(this.activeSubSolver.netLabelPlacement!)
|
|
@@ -273,11 +303,7 @@ export class NetLabelPlacementSolver extends BaseSolver {
|
|
|
273
303
|
this.currentGroup
|
|
274
304
|
) {
|
|
275
305
|
this.triedAnyOrientationFallbackForCurrentGroup = true
|
|
276
|
-
const netLabelWidth = this.currentGroup
|
|
277
|
-
? this.inputProblem.netConnections.find(
|
|
278
|
-
(nc) => nc.netId === this.currentGroup!.netId,
|
|
279
|
-
)?.netLabelWidth
|
|
280
|
-
: undefined
|
|
306
|
+
const netLabelWidth = this.getNetLabelWidthForGroup(this.currentGroup)
|
|
281
307
|
this.activeSubSolver = new SingleNetLabelPlacementSolver({
|
|
282
308
|
inputProblem: this.inputProblem,
|
|
283
309
|
inputTraceMap: this.inputTraceMap,
|
|
@@ -313,11 +339,7 @@ export class NetLabelPlacementSolver extends BaseSolver {
|
|
|
313
339
|
this.currentGroup = nextOverlappingSameNetTraceGroup
|
|
314
340
|
this.triedAnyOrientationFallbackForCurrentGroup = false
|
|
315
341
|
|
|
316
|
-
const netLabelWidth = this.currentGroup
|
|
317
|
-
? this.inputProblem.netConnections.find(
|
|
318
|
-
(nc) => nc.netId === this.currentGroup!.netId,
|
|
319
|
-
)?.netLabelWidth
|
|
320
|
-
: undefined
|
|
342
|
+
const netLabelWidth = this.getNetLabelWidthForGroup(this.currentGroup)
|
|
321
343
|
|
|
322
344
|
this.activeSubSolver = new SingleNetLabelPlacementSolver({
|
|
323
345
|
inputProblem: this.inputProblem,
|
|
@@ -338,14 +338,26 @@ const getNetLabelWidth = (
|
|
|
338
338
|
inputProblem: InputProblem,
|
|
339
339
|
label: NetLabelPlacement,
|
|
340
340
|
) => {
|
|
341
|
-
const
|
|
341
|
+
const ncWidthByNetId = inputProblem.netConnections.find(
|
|
342
342
|
(connection) => connection.netId === label.netId,
|
|
343
343
|
)?.netLabelWidth
|
|
344
|
-
if (
|
|
344
|
+
if (ncWidthByNetId !== undefined) return ncWidthByNetId
|
|
345
345
|
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
346
|
+
const dcWidth = inputProblem.directConnections.find((dc) =>
|
|
347
|
+
dc.pinIds.some((pid) => label.pinIds.includes(pid)),
|
|
348
|
+
)?.netLabelWidth
|
|
349
|
+
if (dcWidth !== undefined) return dcWidth
|
|
350
|
+
|
|
351
|
+
const ncWidthByPinId = inputProblem.netConnections.find((nc) =>
|
|
352
|
+
nc.pinIds.some((pid) => label.pinIds.includes(pid)),
|
|
353
|
+
)?.netLabelWidth
|
|
354
|
+
if (ncWidthByPinId !== undefined) return ncWidthByPinId
|
|
355
|
+
|
|
356
|
+
if (label.orientation === "y+" || label.orientation === "y-") {
|
|
357
|
+
return label.height
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
return label.width
|
|
349
361
|
}
|
|
350
362
|
|
|
351
363
|
const roundDistance = (distance: number) => Number(distance.toFixed(6))
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import type { Point } from "@tscircuit/math-utils"
|
|
2
2
|
|
|
3
|
+
const EPS = 1e-6
|
|
4
|
+
|
|
5
|
+
const sameX = (a: Point, b: Point) => Math.abs(a.x - b.x) <= EPS
|
|
6
|
+
const sameY = (a: Point, b: Point) => Math.abs(a.y - b.y) <= EPS
|
|
7
|
+
|
|
3
8
|
/**
|
|
4
9
|
* Checks if a given path of four points forms a rectangle with horizontal and vertical segments.
|
|
5
10
|
* It verifies if the path forms either an H-V-H "C" shape or a V-H-V "C" shape.
|
|
@@ -9,9 +14,9 @@ export const is4PointRectangle = (path: Point[]): boolean => {
|
|
|
9
14
|
const [p0, p1, p2, p3] = path
|
|
10
15
|
// H-V-H "C" shape
|
|
11
16
|
const isHVHC =
|
|
12
|
-
p0
|
|
17
|
+
sameY(p0, p1) && sameX(p1, p2) && sameY(p2, p3) && sameX(p0, p3)
|
|
13
18
|
// V-H-V "C" shape
|
|
14
19
|
const isVHVC =
|
|
15
|
-
p0
|
|
20
|
+
sameX(p0, p1) && sameY(p1, p2) && sameX(p2, p3) && sameY(p0, p3)
|
|
16
21
|
return isHVHC || isVHVC
|
|
17
22
|
}
|
package/package.json
CHANGED
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
{
|
|
2
|
+
"chips": [
|
|
3
|
+
{
|
|
4
|
+
"chipId": "schematic_component_0",
|
|
5
|
+
"center": {
|
|
6
|
+
"x": 0,
|
|
7
|
+
"y": 0
|
|
8
|
+
},
|
|
9
|
+
"width": 1.3,
|
|
10
|
+
"height": 1,
|
|
11
|
+
"pins": [
|
|
12
|
+
{
|
|
13
|
+
"pinId": "U1.1",
|
|
14
|
+
"x": -1.05,
|
|
15
|
+
"y": 0.30000000000000004
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"pinId": "U1.2",
|
|
19
|
+
"x": -1.05,
|
|
20
|
+
"y": 0.10000000000000003
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
"pinId": "U1.3",
|
|
24
|
+
"x": -1.05,
|
|
25
|
+
"y": -0.09999999999999998
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
"pinId": "U1.4",
|
|
29
|
+
"x": -1.05,
|
|
30
|
+
"y": -0.30000000000000004
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
"pinId": "U1.5",
|
|
34
|
+
"x": 1.05,
|
|
35
|
+
"y": -0.30000000000000004
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
"pinId": "U1.6",
|
|
39
|
+
"x": 1.05,
|
|
40
|
+
"y": -0.10000000000000003
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
"pinId": "U1.7",
|
|
44
|
+
"x": 1.05,
|
|
45
|
+
"y": 0.09999999999999998
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
"pinId": "U1.8",
|
|
49
|
+
"x": 1.05,
|
|
50
|
+
"y": 0.30000000000000004
|
|
51
|
+
}
|
|
52
|
+
]
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
"chipId": "schematic_component_1",
|
|
56
|
+
"center": {
|
|
57
|
+
"x": 2,
|
|
58
|
+
"y": 2
|
|
59
|
+
},
|
|
60
|
+
"width": 1.3,
|
|
61
|
+
"height": 1,
|
|
62
|
+
"pins": [
|
|
63
|
+
{
|
|
64
|
+
"pinId": "U2.1",
|
|
65
|
+
"x": 0.95,
|
|
66
|
+
"y": 2.3
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
"pinId": "U2.2",
|
|
70
|
+
"x": 0.95,
|
|
71
|
+
"y": 2.1
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
"pinId": "U2.3",
|
|
75
|
+
"x": 0.95,
|
|
76
|
+
"y": 1.9
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
"pinId": "U2.4",
|
|
80
|
+
"x": 0.95,
|
|
81
|
+
"y": 1.7
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
"pinId": "U2.5",
|
|
85
|
+
"x": 3.05,
|
|
86
|
+
"y": 1.7
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
"pinId": "U2.6",
|
|
90
|
+
"x": 3.05,
|
|
91
|
+
"y": 1.9
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
"pinId": "U2.7",
|
|
95
|
+
"x": 3.05,
|
|
96
|
+
"y": 2.1
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
"pinId": "U2.8",
|
|
100
|
+
"x": 3.05,
|
|
101
|
+
"y": 2.3
|
|
102
|
+
}
|
|
103
|
+
]
|
|
104
|
+
}
|
|
105
|
+
],
|
|
106
|
+
"directConnections": [
|
|
107
|
+
{
|
|
108
|
+
"pinIds": ["U1.7", "U2.7"],
|
|
109
|
+
"netId": "U1.IO3 to U2.IO3"
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
"pinIds": ["U1.6", "U2.8"],
|
|
113
|
+
"netId": "U1.CLK to U2.VCC"
|
|
114
|
+
}
|
|
115
|
+
],
|
|
116
|
+
"netConnections": [
|
|
117
|
+
{
|
|
118
|
+
"netId": "VCC",
|
|
119
|
+
"pinIds": ["U1.5", "U1.8"],
|
|
120
|
+
"netLabelWidth": 0.48
|
|
121
|
+
}
|
|
122
|
+
],
|
|
123
|
+
"availableNetLabelOrientations": {
|
|
124
|
+
"VCC": ["y+"]
|
|
125
|
+
},
|
|
126
|
+
"maxMspPairDistance": 2.4
|
|
127
|
+
}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
{
|
|
2
|
+
"chips": [
|
|
3
|
+
{
|
|
4
|
+
"chipId": "schematic_component_0",
|
|
5
|
+
"center": {
|
|
6
|
+
"x": 0,
|
|
7
|
+
"y": 0
|
|
8
|
+
},
|
|
9
|
+
"width": 1.3,
|
|
10
|
+
"height": 1,
|
|
11
|
+
"pins": [
|
|
12
|
+
{
|
|
13
|
+
"pinId": "U1.1",
|
|
14
|
+
"x": -1.05,
|
|
15
|
+
"y": 0.30000000000000004
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"pinId": "U1.2",
|
|
19
|
+
"x": -1.05,
|
|
20
|
+
"y": 0.10000000000000003
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
"pinId": "U1.3",
|
|
24
|
+
"x": -1.05,
|
|
25
|
+
"y": -0.09999999999999998
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
"pinId": "U1.4",
|
|
29
|
+
"x": -1.05,
|
|
30
|
+
"y": -0.30000000000000004
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
"pinId": "U1.5",
|
|
34
|
+
"x": 1.05,
|
|
35
|
+
"y": -0.30000000000000004
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
"pinId": "U1.6",
|
|
39
|
+
"x": 1.05,
|
|
40
|
+
"y": -0.10000000000000003
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
"pinId": "U1.7",
|
|
44
|
+
"x": 1.05,
|
|
45
|
+
"y": 0.09999999999999998
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
"pinId": "U1.8",
|
|
49
|
+
"x": 1.05,
|
|
50
|
+
"y": 0.30000000000000004
|
|
51
|
+
}
|
|
52
|
+
]
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
"chipId": "schematic_component_1",
|
|
56
|
+
"center": {
|
|
57
|
+
"x": 2,
|
|
58
|
+
"y": 2
|
|
59
|
+
},
|
|
60
|
+
"width": 1.3,
|
|
61
|
+
"height": 1,
|
|
62
|
+
"pins": [
|
|
63
|
+
{
|
|
64
|
+
"pinId": "U2.1",
|
|
65
|
+
"x": 0.95,
|
|
66
|
+
"y": 2.3
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
"pinId": "U2.2",
|
|
70
|
+
"x": 0.95,
|
|
71
|
+
"y": 2.1
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
"pinId": "U2.3",
|
|
75
|
+
"x": 0.95,
|
|
76
|
+
"y": 1.9
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
"pinId": "U2.4",
|
|
80
|
+
"x": 0.95,
|
|
81
|
+
"y": 1.7
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
"pinId": "U2.5",
|
|
85
|
+
"x": 3.05,
|
|
86
|
+
"y": 1.7
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
"pinId": "U2.6",
|
|
90
|
+
"x": 3.05,
|
|
91
|
+
"y": 1.9
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
"pinId": "U2.7",
|
|
95
|
+
"x": 3.05,
|
|
96
|
+
"y": 2.1
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
"pinId": "U2.8",
|
|
100
|
+
"x": 3.05,
|
|
101
|
+
"y": 2.3
|
|
102
|
+
}
|
|
103
|
+
]
|
|
104
|
+
}
|
|
105
|
+
],
|
|
106
|
+
"directConnections": [
|
|
107
|
+
{
|
|
108
|
+
"pinIds": ["U1.6", "U2.8"],
|
|
109
|
+
"netId": "U1.CLK to U2.VCC",
|
|
110
|
+
"netLabelWidth": 1
|
|
111
|
+
}
|
|
112
|
+
],
|
|
113
|
+
"netConnections": [
|
|
114
|
+
{
|
|
115
|
+
"netId": "VCC",
|
|
116
|
+
"pinIds": ["U1.5", "U1.8"],
|
|
117
|
+
"netLabelWidth": 0.48
|
|
118
|
+
}
|
|
119
|
+
],
|
|
120
|
+
"availableNetLabelOrientations": {
|
|
121
|
+
"VCC": ["y+"]
|
|
122
|
+
},
|
|
123
|
+
"maxMspPairDistance": 2.4
|
|
124
|
+
}
|