@tscircuit/schematic-trace-solver 0.0.201 → 0.0.202
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 +6 -0
- package/dist/index.js +68 -5
- package/lib/solvers/InlineNetLabelSolver/InlineNetLabelSolver.ts +1 -0
- package/lib/solvers/InlineNetLabelSolver/getLocalTraceLabelShifts.ts +37 -2
- package/lib/solvers/NetLabelNetLabelCollisionSolver/NetLabelNetLabelCollisionSolver.ts +66 -0
- package/lib/solvers/SchematicTracePipelineSolver/SchematicTracePipelineSolver.ts +1 -0
- package/package.json +1 -1
- package/tests/repros/__snapshots__/repro-mouse-switch-ground-unnecessary-jog.snap.svg +15 -22
- package/tests/repros/__snapshots__/repro-trace-endpoints-stop-at-component-boundary.snap.svg +94 -0
- package/tests/repros/assets/repro-trace-endpoints-stop-at-component-boundary.input.json +82 -0
- package/tests/repros/repro-mouse-switch-ground-unnecessary-jog.test.ts +15 -0
- package/tests/repros/repro-trace-endpoints-stop-at-component-boundary.test.ts +21 -0
package/dist/index.d.ts
CHANGED
|
@@ -1149,6 +1149,8 @@ type Candidate = {
|
|
|
1149
1149
|
status: CandidateStatus | null;
|
|
1150
1150
|
};
|
|
1151
1151
|
interface NetLabelNetLabelCollisionSolverParams {
|
|
1152
|
+
/** Move temporary port-only inline labels before moving their neighbors. */
|
|
1153
|
+
preserveNonInlineLabelsAgainstInlineEligibleCollisions?: boolean;
|
|
1152
1154
|
/** Use the final horizontal tag envelope after inline conversion. */
|
|
1153
1155
|
useRenderedLabelBounds?: boolean;
|
|
1154
1156
|
/** Already placed labels that are obstacles, but must not be moved. */
|
|
@@ -1181,6 +1183,10 @@ declare class NetLabelNetLabelCollisionSolver extends BaseSolver {
|
|
|
1181
1183
|
};
|
|
1182
1184
|
private labelBounds;
|
|
1183
1185
|
private collisionKey;
|
|
1186
|
+
private isSingleTerminalInlineEligible;
|
|
1187
|
+
private hasSatisfiedSingleOrientation;
|
|
1188
|
+
private isAlignedWithHostTrace;
|
|
1189
|
+
private isProtectedAgainstTemporaryInlineCollision;
|
|
1184
1190
|
private findNextCollidingPair;
|
|
1185
1191
|
private netLabelWidthOf;
|
|
1186
1192
|
private netLabelHeightOf;
|
package/dist/index.js
CHANGED
|
@@ -12776,7 +12776,8 @@ var NetLabelNetLabelCollisionSolver = class extends BaseSolver {
|
|
|
12776
12776
|
traces: this.traces,
|
|
12777
12777
|
netLabelPlacements: this.netLabelPlacements,
|
|
12778
12778
|
fixedNetLabelPlacements: this.params.fixedNetLabelPlacements,
|
|
12779
|
-
useRenderedLabelBounds: this.params.useRenderedLabelBounds
|
|
12779
|
+
useRenderedLabelBounds: this.params.useRenderedLabelBounds,
|
|
12780
|
+
preserveNonInlineLabelsAgainstInlineEligibleCollisions: this.params.preserveNonInlineLabelsAgainstInlineEligibleCollisions
|
|
12780
12781
|
};
|
|
12781
12782
|
}
|
|
12782
12783
|
getOutput() {
|
|
@@ -12790,6 +12791,36 @@ var NetLabelNetLabelCollisionSolver = class extends BaseSolver {
|
|
|
12790
12791
|
collisionKey(a, b) {
|
|
12791
12792
|
return [a.globalConnNetId, b.globalConnNetId].sort().join("::");
|
|
12792
12793
|
}
|
|
12794
|
+
isSingleTerminalInlineEligible(label) {
|
|
12795
|
+
if (!label.netId) return false;
|
|
12796
|
+
return [
|
|
12797
|
+
...this.inputProblem.netConnections,
|
|
12798
|
+
...this.inputProblem.directConnections
|
|
12799
|
+
].some(
|
|
12800
|
+
(connection) => connection.allowInlineNetLabel && connection.pinIds.length === 1 && connection.netId === label.netId && label.pinIds.every((pinId) => connection.pinIds.includes(pinId))
|
|
12801
|
+
);
|
|
12802
|
+
}
|
|
12803
|
+
hasSatisfiedSingleOrientation(label) {
|
|
12804
|
+
if (!label.netId) return false;
|
|
12805
|
+
const orientations = this.inputProblem.availableNetLabelOrientations[label.netId];
|
|
12806
|
+
return orientations?.length === 1 && orientations[0] === label.orientation;
|
|
12807
|
+
}
|
|
12808
|
+
isAlignedWithHostTrace(label) {
|
|
12809
|
+
const orientationAxis = label.orientation.startsWith("x") ? "x" : "y";
|
|
12810
|
+
return label.mspConnectionPairIds.some((mspPairId) => {
|
|
12811
|
+
const trace = this.traceMap[mspPairId];
|
|
12812
|
+
return trace?.tracePath.slice(1).some((end, index) => {
|
|
12813
|
+
const start = trace.tracePath[index];
|
|
12814
|
+
if (!tracePathContainsPoint([start, end], label.anchorPoint))
|
|
12815
|
+
return false;
|
|
12816
|
+
const segmentAxis = Math.abs(start.x - end.x) < SEGMENT_PARALLEL_EPS ? "y" : "x";
|
|
12817
|
+
return segmentAxis === orientationAxis;
|
|
12818
|
+
});
|
|
12819
|
+
});
|
|
12820
|
+
}
|
|
12821
|
+
isProtectedAgainstTemporaryInlineCollision(label) {
|
|
12822
|
+
return !this.isSingleTerminalInlineEligible(label) && this.hasSatisfiedSingleOrientation(label) && this.isAlignedWithHostTrace(label);
|
|
12823
|
+
}
|
|
12793
12824
|
findNextCollidingPair() {
|
|
12794
12825
|
const labels = [
|
|
12795
12826
|
...this.outputNetLabelPlacements,
|
|
@@ -12962,6 +12993,18 @@ var NetLabelNetLabelCollisionSolver = class extends BaseSolver {
|
|
|
12962
12993
|
this.labelsToTry = [pair[1], pair[0]].filter(
|
|
12963
12994
|
(label) => !(this.params.fixedNetLabelPlacements ?? []).includes(label)
|
|
12964
12995
|
);
|
|
12996
|
+
if (this.params.preserveNonInlineLabelsAgainstInlineEligibleCollisions && pair.some((label) => this.isSingleTerminalInlineEligible(label)) && pair.some(
|
|
12997
|
+
(label) => this.isProtectedAgainstTemporaryInlineCollision(label)
|
|
12998
|
+
)) {
|
|
12999
|
+
this.labelsToTry = this.labelsToTry.filter(
|
|
13000
|
+
(label) => this.isSingleTerminalInlineEligible(label) || !this.isProtectedAgainstTemporaryInlineCollision(label)
|
|
13001
|
+
);
|
|
13002
|
+
}
|
|
13003
|
+
if (this.labelsToTry.length === 0) {
|
|
13004
|
+
this.skippedCollisionKeys.add(this.collisionKey(pair[0], pair[1]));
|
|
13005
|
+
this.clearActiveSearch();
|
|
13006
|
+
return;
|
|
13007
|
+
}
|
|
12965
13008
|
this.beginSearchForLabel(this.labelsToTry.shift());
|
|
12966
13009
|
return;
|
|
12967
13010
|
}
|
|
@@ -15628,6 +15671,11 @@ function* getLocalTraceLabelShifts(inputProblem, output, pendingInlinePlacements
|
|
|
15628
15671
|
minY: label.center.y - label.height / 2,
|
|
15629
15672
|
maxY: label.center.y + label.height / 2
|
|
15630
15673
|
}));
|
|
15674
|
+
const pendingReplacementBounds = output.netLabelPlacements.filter(
|
|
15675
|
+
(label) => pendingInlinePlacements.some(
|
|
15676
|
+
(placement) => placement.globalConnNetId === label.globalConnNetId && placement.pinIds.length === label.pinIds.length && placement.pinIds.every((pinId) => label.pinIds.includes(pinId))
|
|
15677
|
+
)
|
|
15678
|
+
).map(getAnchoredNetLabelRenderedBounds);
|
|
15631
15679
|
const pinPositions = [
|
|
15632
15680
|
...inputProblem.chips.flatMap((chip) => chip.pins),
|
|
15633
15681
|
...output.traces.flatMap((trace) => trace.pins)
|
|
@@ -15639,13 +15687,26 @@ function* getLocalTraceLabelShifts(inputProblem, output, pendingInlinePlacements
|
|
|
15639
15687
|
const axis = Math.abs(a.x - b.x) < EPS16 ? "x" : "y";
|
|
15640
15688
|
const along = axis === "x" ? "y" : "x";
|
|
15641
15689
|
if (Math.abs(a[axis] - b[axis]) > EPS16 || same(a, b)) continue;
|
|
15642
|
-
const
|
|
15690
|
+
const candidateObstacles = [
|
|
15643
15691
|
...output.netLabelPlacements.filter((label) => label.globalConnNetId !== trace.globalConnNetId).map(getAnchoredNetLabelRenderedBounds),
|
|
15644
15692
|
...inlineBounds,
|
|
15645
15693
|
...terminalBounds.filter(
|
|
15646
15694
|
({ label }) => !trace.pinIds.some((pinId) => label.pinIds.includes(pinId))
|
|
15647
15695
|
).map(({ bounds }) => bounds)
|
|
15648
|
-
]
|
|
15696
|
+
];
|
|
15697
|
+
const attachedLabelBounds = output.netLabelPlacements.filter(
|
|
15698
|
+
(label) => label.globalConnNetId === trace.globalConnNetId && label.netId != null && inputProblem.availableNetLabelOrientations[label.netId]?.length === 1 && inputProblem.availableNetLabelOrientations[label.netId]?.[0] === label.orientation && (axis === "x" ? label.orientation === "y+" || label.orientation === "y-" : label.orientation === "x+" || label.orientation === "x-") && tracePathContainsPoint([a, b], label.anchorPoint)
|
|
15699
|
+
).map(getAnchoredNetLabelRenderedBounds);
|
|
15700
|
+
const blocking = [
|
|
15701
|
+
...candidateObstacles.filter(
|
|
15702
|
+
(bounds) => segmentIntersectsRect(a, b, bounds)
|
|
15703
|
+
),
|
|
15704
|
+
...pendingReplacementBounds.filter(
|
|
15705
|
+
(bounds) => attachedLabelBounds.some(
|
|
15706
|
+
(labelBounds) => boundsOverlap(labelBounds, bounds)
|
|
15707
|
+
)
|
|
15708
|
+
)
|
|
15709
|
+
];
|
|
15649
15710
|
if (!blocking.length) continue;
|
|
15650
15711
|
let low = Math.min(a[along], b[along]);
|
|
15651
15712
|
let high = Math.max(a[along], b[along]);
|
|
@@ -17559,7 +17620,8 @@ var InlineNetLabelSolver = class _InlineNetLabelSolver extends BaseSolver {
|
|
|
17559
17620
|
netLabelPlacements: retainedNetLabelPlacements,
|
|
17560
17621
|
fixedNetLabelPlacements: fixedLabels,
|
|
17561
17622
|
netLabelConnectorTraceIds: this.netLabelConnectorTraceIds,
|
|
17562
|
-
useRenderedLabelBounds: activeInlinePlacements.length > 0
|
|
17623
|
+
useRenderedLabelBounds: activeInlinePlacements.length > 0,
|
|
17624
|
+
preserveNonInlineLabelsAgainstInlineEligibleCollisions: true
|
|
17563
17625
|
});
|
|
17564
17626
|
if (activeInlinePlacements.length > 0) labelCollisionSolver.solve();
|
|
17565
17627
|
const pushed = pushAnchoredNetLabelsAwayFromInlineLabels({
|
|
@@ -19010,7 +19072,8 @@ var SchematicTracePipelineSolver = class extends BaseSolver {
|
|
|
19010
19072
|
{
|
|
19011
19073
|
inputProblem: instance.inputProblem,
|
|
19012
19074
|
traces: simplificationOutput.traces,
|
|
19013
|
-
netLabelPlacements: simplificationOutput.netLabelPlacements
|
|
19075
|
+
netLabelPlacements: simplificationOutput.netLabelPlacements,
|
|
19076
|
+
preserveNonInlineLabelsAgainstInlineEligibleCollisions: true
|
|
19014
19077
|
}
|
|
19015
19078
|
];
|
|
19016
19079
|
}
|
|
@@ -1195,6 +1195,7 @@ export class InlineNetLabelSolver extends BaseSolver {
|
|
|
1195
1195
|
fixedNetLabelPlacements: fixedLabels,
|
|
1196
1196
|
netLabelConnectorTraceIds: this.netLabelConnectorTraceIds,
|
|
1197
1197
|
useRenderedLabelBounds: activeInlinePlacements.length > 0,
|
|
1198
|
+
preserveNonInlineLabelsAgainstInlineEligibleCollisions: true,
|
|
1198
1199
|
})
|
|
1199
1200
|
if (activeInlinePlacements.length > 0) labelCollisionSolver.solve()
|
|
1200
1201
|
const pushed = pushAnchoredNetLabelsAwayFromInlineLabels({
|
|
@@ -75,6 +75,16 @@ export function* getLocalTraceLabelShifts(
|
|
|
75
75
|
minY: label.center.y - label.height / 2,
|
|
76
76
|
maxY: label.center.y + label.height / 2,
|
|
77
77
|
}))
|
|
78
|
+
const pendingReplacementBounds = output.netLabelPlacements
|
|
79
|
+
.filter((label) =>
|
|
80
|
+
pendingInlinePlacements.some(
|
|
81
|
+
(placement) =>
|
|
82
|
+
placement.globalConnNetId === label.globalConnNetId &&
|
|
83
|
+
placement.pinIds.length === label.pinIds.length &&
|
|
84
|
+
placement.pinIds.every((pinId) => label.pinIds.includes(pinId)),
|
|
85
|
+
),
|
|
86
|
+
)
|
|
87
|
+
.map(getAnchoredNetLabelRenderedBounds)
|
|
78
88
|
const pinPositions = [
|
|
79
89
|
...inputProblem.chips.flatMap((chip) => chip.pins),
|
|
80
90
|
...output.traces.flatMap((trace) => trace.pins),
|
|
@@ -87,7 +97,7 @@ export function* getLocalTraceLabelShifts(
|
|
|
87
97
|
const axis = Math.abs(a.x - b.x) < EPS ? "x" : "y"
|
|
88
98
|
const along = axis === "x" ? "y" : "x"
|
|
89
99
|
if (Math.abs(a[axis] - b[axis]) > EPS || same(a, b)) continue
|
|
90
|
-
const
|
|
100
|
+
const candidateObstacles = [
|
|
91
101
|
...output.netLabelPlacements
|
|
92
102
|
.filter((label) => label.globalConnNetId !== trace.globalConnNetId)
|
|
93
103
|
.map(getAnchoredNetLabelRenderedBounds),
|
|
@@ -98,7 +108,32 @@ export function* getLocalTraceLabelShifts(
|
|
|
98
108
|
!trace.pinIds.some((pinId) => label.pinIds.includes(pinId)),
|
|
99
109
|
)
|
|
100
110
|
.map(({ bounds }) => bounds),
|
|
101
|
-
]
|
|
111
|
+
]
|
|
112
|
+
const attachedLabelBounds = output.netLabelPlacements
|
|
113
|
+
.filter(
|
|
114
|
+
(label) =>
|
|
115
|
+
label.globalConnNetId === trace.globalConnNetId &&
|
|
116
|
+
label.netId != null &&
|
|
117
|
+
inputProblem.availableNetLabelOrientations[label.netId]?.length ===
|
|
118
|
+
1 &&
|
|
119
|
+
inputProblem.availableNetLabelOrientations[label.netId]?.[0] ===
|
|
120
|
+
label.orientation &&
|
|
121
|
+
(axis === "x"
|
|
122
|
+
? label.orientation === "y+" || label.orientation === "y-"
|
|
123
|
+
: label.orientation === "x+" || label.orientation === "x-") &&
|
|
124
|
+
tracePathContainsPoint([a, b], label.anchorPoint),
|
|
125
|
+
)
|
|
126
|
+
.map(getAnchoredNetLabelRenderedBounds)
|
|
127
|
+
const blocking = [
|
|
128
|
+
...candidateObstacles.filter((bounds) =>
|
|
129
|
+
segmentIntersectsRect(a, b, bounds),
|
|
130
|
+
),
|
|
131
|
+
...pendingReplacementBounds.filter((bounds) =>
|
|
132
|
+
attachedLabelBounds.some((labelBounds) =>
|
|
133
|
+
boundsOverlap(labelBounds, bounds),
|
|
134
|
+
),
|
|
135
|
+
),
|
|
136
|
+
]
|
|
102
137
|
if (!blocking.length) continue
|
|
103
138
|
// Cleanup can split one rail across several trace records, including a
|
|
104
139
|
// branch that starts at a junction instead of at its pin. Shift the
|
|
@@ -93,6 +93,8 @@ function sampleAnchorsAlongSegment(
|
|
|
93
93
|
}
|
|
94
94
|
|
|
95
95
|
export interface NetLabelNetLabelCollisionSolverParams {
|
|
96
|
+
/** Move temporary port-only inline labels before moving their neighbors. */
|
|
97
|
+
preserveNonInlineLabelsAgainstInlineEligibleCollisions?: boolean
|
|
96
98
|
/** Use the final horizontal tag envelope after inline conversion. */
|
|
97
99
|
useRenderedLabelBounds?: boolean
|
|
98
100
|
/** Already placed labels that are obstacles, but must not be moved. */
|
|
@@ -148,6 +150,8 @@ export class NetLabelNetLabelCollisionSolver extends BaseSolver {
|
|
|
148
150
|
netLabelPlacements: this.netLabelPlacements,
|
|
149
151
|
fixedNetLabelPlacements: this.params.fixedNetLabelPlacements,
|
|
150
152
|
useRenderedLabelBounds: this.params.useRenderedLabelBounds,
|
|
153
|
+
preserveNonInlineLabelsAgainstInlineEligibleCollisions:
|
|
154
|
+
this.params.preserveNonInlineLabelsAgainstInlineEligibleCollisions,
|
|
151
155
|
}
|
|
152
156
|
}
|
|
153
157
|
|
|
@@ -168,6 +172,50 @@ export class NetLabelNetLabelCollisionSolver extends BaseSolver {
|
|
|
168
172
|
return [a.globalConnNetId, b.globalConnNetId].sort().join("::")
|
|
169
173
|
}
|
|
170
174
|
|
|
175
|
+
private isSingleTerminalInlineEligible(label: NetLabelPlacement) {
|
|
176
|
+
if (!label.netId) return false
|
|
177
|
+
return [
|
|
178
|
+
...this.inputProblem.netConnections,
|
|
179
|
+
...this.inputProblem.directConnections,
|
|
180
|
+
].some(
|
|
181
|
+
(connection) =>
|
|
182
|
+
connection.allowInlineNetLabel &&
|
|
183
|
+
connection.pinIds.length === 1 &&
|
|
184
|
+
connection.netId === label.netId &&
|
|
185
|
+
label.pinIds.every((pinId) => connection.pinIds.includes(pinId)),
|
|
186
|
+
)
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
private hasSatisfiedSingleOrientation(label: NetLabelPlacement) {
|
|
190
|
+
if (!label.netId) return false
|
|
191
|
+
const orientations =
|
|
192
|
+
this.inputProblem.availableNetLabelOrientations[label.netId]
|
|
193
|
+
return orientations?.length === 1 && orientations[0] === label.orientation
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
private isAlignedWithHostTrace(label: NetLabelPlacement) {
|
|
197
|
+
const orientationAxis = label.orientation.startsWith("x") ? "x" : "y"
|
|
198
|
+
return label.mspConnectionPairIds.some((mspPairId) => {
|
|
199
|
+
const trace = this.traceMap[mspPairId]
|
|
200
|
+
return trace?.tracePath.slice(1).some((end, index) => {
|
|
201
|
+
const start = trace.tracePath[index]!
|
|
202
|
+
if (!tracePathContainsPoint([start, end], label.anchorPoint))
|
|
203
|
+
return false
|
|
204
|
+
const segmentAxis =
|
|
205
|
+
Math.abs(start.x - end.x) < SEGMENT_PARALLEL_EPS ? "y" : "x"
|
|
206
|
+
return segmentAxis === orientationAxis
|
|
207
|
+
})
|
|
208
|
+
})
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
private isProtectedAgainstTemporaryInlineCollision(label: NetLabelPlacement) {
|
|
212
|
+
return (
|
|
213
|
+
!this.isSingleTerminalInlineEligible(label) &&
|
|
214
|
+
this.hasSatisfiedSingleOrientation(label) &&
|
|
215
|
+
this.isAlignedWithHostTrace(label)
|
|
216
|
+
)
|
|
217
|
+
}
|
|
218
|
+
|
|
171
219
|
private findNextCollidingPair():
|
|
172
220
|
| [NetLabelPlacement, NetLabelPlacement]
|
|
173
221
|
| null {
|
|
@@ -394,6 +442,24 @@ export class NetLabelNetLabelCollisionSolver extends BaseSolver {
|
|
|
394
442
|
this.labelsToTry = [pair[1], pair[0]].filter(
|
|
395
443
|
(label) => !(this.params.fixedNetLabelPlacements ?? []).includes(label),
|
|
396
444
|
)
|
|
445
|
+
if (
|
|
446
|
+
this.params.preserveNonInlineLabelsAgainstInlineEligibleCollisions &&
|
|
447
|
+
pair.some((label) => this.isSingleTerminalInlineEligible(label)) &&
|
|
448
|
+
pair.some((label) =>
|
|
449
|
+
this.isProtectedAgainstTemporaryInlineCollision(label),
|
|
450
|
+
)
|
|
451
|
+
) {
|
|
452
|
+
this.labelsToTry = this.labelsToTry.filter(
|
|
453
|
+
(label) =>
|
|
454
|
+
this.isSingleTerminalInlineEligible(label) ||
|
|
455
|
+
!this.isProtectedAgainstTemporaryInlineCollision(label),
|
|
456
|
+
)
|
|
457
|
+
}
|
|
458
|
+
if (this.labelsToTry.length === 0) {
|
|
459
|
+
this.skippedCollisionKeys.add(this.collisionKey(pair[0], pair[1]))
|
|
460
|
+
this.clearActiveSearch()
|
|
461
|
+
return
|
|
462
|
+
}
|
|
397
463
|
this.beginSearchForLabel(this.labelsToTry.shift()!)
|
|
398
464
|
return
|
|
399
465
|
}
|
|
@@ -559,6 +559,7 @@ export class SchematicTracePipelineSolver extends BaseSolver {
|
|
|
559
559
|
inputProblem: instance.inputProblem,
|
|
560
560
|
traces: simplificationOutput.traces,
|
|
561
561
|
netLabelPlacements: simplificationOutput.netLabelPlacements,
|
|
562
|
+
preserveNonInlineLabelsAgainstInlineEligibleCollisions: true,
|
|
562
563
|
},
|
|
563
564
|
]
|
|
564
565
|
},
|
package/package.json
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
<svg width="1200" height="2016" viewBox="0 0 1200 2016" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="Solver debug visualization on top and Circuit JSON schematic on the bottom">
|
|
2
2
|
<g transform="translate(0, 0) scale(1.875, 1.875) translate(0, 0)">
|
|
3
|
-
<rect width="100%" height="100%" fill="white"/><g><polyline data-points="-8.690000000000001,4.1 -9.35,-3.9" data-type="line" data-label="" points="
|
|
4
|
-
globalConnNetId: connectivity_net0" data-x="-
|
|
3
|
+
<rect width="100%" height="100%" fill="white"/><g><polyline data-points="-8.690000000000001,4.1 -9.35,-3.9" data-type="line" data-label="" points="314.62753950338595,61.489841986455986 272.9119638826186,567.1331828442438" fill="none" stroke="hsl(157, 100%, 50%, 0.8)" stroke-width="1px" stroke-dasharray="4 2"/></g><g><polyline data-points="-8.690000000000001,4.1 -10.359999999999998,4.1 -10.359999999999998,-3.9 -9.35,-3.9" data-type="line" data-label="" points="314.62753950338595,61.489841986455986 209.07449209932292,61.489841986455986 209.07449209932292,567.1331828442438 272.9119638826186,567.1331828442438" fill="none" stroke="purple" stroke-width="1px"/></g><g><polyline data-points="-8.690000000000001,3.9 -9.530000000000001,3.9" data-type="line" data-label="" points="314.62753950338595,74.13092550790068 261.53498871331817,74.13092550790068" fill="none" stroke="purple" stroke-width="1px"/></g><g><polyline data-points="-9.35,-4.1 -10.03,-4.1" data-type="line" data-label="" points="272.9119638826186,579.7742663656885 229.9322799097066,579.7742663656885" fill="none" stroke="purple" stroke-width="1px"/></g><g><rect data-type="rect" data-label="schematic_component_0" data-x="-7.690000000000001" data-y="4" x="314.62753950338595" y="55.16930022573361" width="126.41083521444699" height="25.282167042889427" fill="hsl(24, 100%, 50%, 0.8)" stroke="black" stroke-width="0.01582142857142857"/></g><g><rect data-type="rect" data-label="schematic_component_1" data-x="-8.35" data-y="-4" x="272.9119638826186" y="560.8126410835214" width="126.41083521444693" height="25.282167042889455" fill="hsl(24, 100%, 50%, 0.8)" stroke="black" stroke-width="0.01582142857142857"/></g><g><rect data-type="rect" data-label="D2FC-F-7N(20M)" data-x="-7.450000000000001" data-y="3.67" x="339.9097065462754" y="82.97968397291196" width="106.18510158013538" height="11.37697516930021" fill="rgba(160, 0, 220, 0.14)" stroke="black" stroke-width="0.01582142857142857"/></g><g><rect data-type="rect" data-label="SW_LEFT" data-x="-7.870000000000001" data-y="4.3149999999999995" x="336.11738148984193" y="40.00000000000003" width="60.6772009029346" height="15.801354401805895" fill="rgba(160, 0, 220, 0.14)" stroke="black" stroke-width="0.01582142857142857"/></g><g><rect data-type="rect" data-label="D2FC-F-7N(20M)" data-x="-8.11" data-y="-4.33" x="298.1941309255079" y="588.6230248306997" width="106.1851015801355" height="11.37697516930018" fill="rgba(160, 0, 220, 0.14)" stroke="black" stroke-width="0.01582142857142857"/></g><g><rect data-type="rect" data-label="SW_RIGHT" data-x="-8.469999999999999" data-y="-3.6849999999999996" x="294.40180586907456" y="545.6433408577878" width="68.26185101580126" height="15.801354401805838" fill="rgba(160, 0, 220, 0.14)" stroke="black" stroke-width="0.01582142857142857"/></g><g><rect data-type="rect" data-label="netId: GND
|
|
4
|
+
globalConnNetId: connectivity_net0" data-x="-10.359999999999998" data-y="-4.11" x="193.90519187358927" y="567.133182844244" width="30.3386004514673" height="26.54627539503383" fill="#00000066" stroke="#000000" stroke-width="0.01582142857142857"/></g><g><rect data-type="rect" data-label="INLINE netId: LEFT_SW
|
|
5
5
|
axis: x
|
|
6
|
-
side: y+" data-x="-9.110000000000001" data-y="4.01" x="
|
|
6
|
+
side: y+" data-x="-9.110000000000001" data-y="4.01" x="267.85553047404056" y="63.386004514672706" width="40.451467268623105" height="7.584650112866797" fill="hsl(40, 100%, 50%, 0.35)" stroke="black" stroke-width="0.01582142857142857"/></g><g><rect data-type="rect" data-label="INLINE netId: RIGHT
|
|
7
7
|
axis: x
|
|
8
|
-
side: y+" data-x="-9.69" data-y="-3.9899999999999998" x="
|
|
9
|
-
x-" data-x="-8.690000000000001" data-y="4.1" cx="
|
|
10
|
-
x-" data-x="-8.690000000000001" data-y="3.9" cx="
|
|
11
|
-
x+" data-x="-6.69" data-y="4" cx="
|
|
12
|
-
x-" data-x="-9.35" data-y="-3.9" cx="
|
|
13
|
-
x-" data-x="-9.35" data-y="-4.1" cx="
|
|
14
|
-
x+" data-x="-7.35" data-y="-4" cx="
|
|
15
|
-
orientation: y
|
|
16
|
-
LEFT_SW" data-x="-9.110000000000001" data-y="3.9" cx="
|
|
17
|
-
RIGHT" data-x="-9.69" data-y="-4.1" cx="
|
|
8
|
+
side: y+" data-x="-9.69" data-y="-3.9899999999999998" x="236.25282167042894" y="569.0293453724605" width="30.3386004514673" height="7.584650112866825" fill="hsl(40, 100%, 50%, 0.35)" stroke="black" stroke-width="0.01582142857142857"/></g><text data-type="text" data-label="LEFT_SW" data-x="-8.790000000000001" data-y="4.01" x="308.3069977426636" y="67.1783295711061" fill="green" font-size="7.584650112866817" font-family="sans-serif" text-anchor="end" dominant-baseline="central">LEFT_SW</text><text data-type="text" data-label="RIGHT" data-x="-9.45" data-y="-3.9899999999999998" x="266.59142212189624" y="572.8216704288939" fill="green" font-size="7.584650112866817" font-family="sans-serif" text-anchor="end" dominant-baseline="central">RIGHT</text><g><circle data-type="point" data-label="1
|
|
9
|
+
x-" data-x="-8.690000000000001" data-y="4.1" cx="314.62753950338595" cy="61.489841986455986" r="3" fill="hsl(248, 100%, 50%, 0.8)"/></g><g><circle data-type="point" data-label="2
|
|
10
|
+
x-" data-x="-8.690000000000001" data-y="3.9" cx="314.62753950338595" cy="74.13092550790068" r="3" fill="hsl(248, 100%, 50%, 0.8)"/></g><g><circle data-type="point" data-label="3
|
|
11
|
+
x+" data-x="-6.69" data-y="4" cx="441.03837471783294" cy="67.81038374717832" r="3" fill="hsl(248, 100%, 50%, 0.8)"/></g><g><circle data-type="point" data-label="1
|
|
12
|
+
x-" data-x="-9.35" data-y="-3.9" cx="272.9119638826186" cy="567.1331828442438" r="3" fill="hsl(248, 100%, 50%, 0.8)"/></g><g><circle data-type="point" data-label="2
|
|
13
|
+
x-" data-x="-9.35" data-y="-4.1" cx="272.9119638826186" cy="579.7742663656885" r="3" fill="hsl(248, 100%, 50%, 0.8)"/></g><g><circle data-type="point" data-label="3
|
|
14
|
+
x+" data-x="-7.35" data-y="-4" cx="399.3227990970655" cy="573.4537246049662" r="3" fill="hsl(248, 100%, 50%, 0.8)"/></g><g><circle data-type="point" data-label="anchorPoint
|
|
15
|
+
orientation: y-" data-x="-10.359999999999998" data-y="-3.9" cx="209.07449209932292" cy="567.1331828442438" r="3" fill="hsl(40, 100%, 50%, 0.9)"/></g><g><circle data-type="point" data-label="inline anchor
|
|
16
|
+
LEFT_SW" data-x="-9.110000000000001" data-y="3.9" cx="288.0812641083521" cy="74.13092550790068" r="3" fill="green"/></g><g><circle data-type="point" data-label="inline anchor
|
|
17
|
+
RIGHT" data-x="-9.69" data-y="-4.1" cx="251.4221218961626" cy="579.7742663656885" r="3" fill="green"/></g><g id="crosshair" style="display: none"><line id="crosshair-h" y1="0" y2="640" stroke="#666" stroke-width="0.5"/><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></g><script><![CDATA[
|
|
18
18
|
document.currentScript.parentElement.addEventListener('mousemove', (e) => {
|
|
19
19
|
const svg = e.currentTarget;
|
|
20
20
|
const rect = svg.getBoundingClientRect();
|
|
@@ -36,7 +36,7 @@ RIGHT" data-x="-9.69" data-y="-4.1" cx="234.3750000000001" cy="580" r="3" fill="
|
|
|
36
36
|
v.setAttribute('y2', '640');
|
|
37
37
|
|
|
38
38
|
// Calculate real coordinates using inverse transformation
|
|
39
|
-
const matrix = {"a":
|
|
39
|
+
const matrix = {"a":63.20541760722348,"c":0,"e":863.8826185101581,"b":0,"d":-63.20541760722348,"f":320.63205417607224};
|
|
40
40
|
// Manually invert and apply the affine transform
|
|
41
41
|
// Since we only use translate and scale, we can directly compute:
|
|
42
42
|
// x' = (x - tx) / sx
|
|
@@ -71,13 +71,6 @@ RIGHT" data-x="-9.69" data-y="-4.1" cx="234.3750000000001" cy="580" r="3" fill="
|
|
|
71
71
|
.port-label { fill: rgb(0, 100, 100); }
|
|
72
72
|
.component-name { fill: rgb(0, 100, 100); }
|
|
73
73
|
|
|
74
|
-
</style><rect class="boundary" x="0" y="0" width="1200" height="800"/><g class="trace sch-trace" data-layer="base" data-circuit-json-type="schematic_trace" data-schematic-trace-id="schematic_trace_0__stack1"><path d="M 555.3177571657768 73.81291826693001 L 469.89819023462815 73.81291826693001 L 469.89819023462815 717.88128344053 L 502.18211703895497 717.88128344053" class="trace-invisible-hover-outline sch-trace-hitbox" stroke="rgb(0, 150, 0)" fill="none" stroke-width="12.881367303472px" stroke-linecap="round" opacity="0" stroke-linejoin="round"/><path class="sch-trace-path" d="M 555.3177571657768 73.81291826693001 L 469.89819023462815 73.81291826693001 L 469.89819023462815 717.88128344053 L 502.18211703895497 717.88128344053" stroke="rgb(0, 150, 0)" fill="none" stroke-width="1.610170912934px" stroke-linecap="round" stroke-linejoin="round"/></g><g class="trace sch-trace" data-layer="base" data-circuit-json-type="schematic_trace" data-schematic-trace-id="schematic_trace_1__stack1"><path d="M 532.0215116390998 73.81291826693001 L 532.0215116390998 72.21079820856067" class="trace-invisible-hover-outline sch-trace-hitbox" stroke="rgb(0, 150, 0)" fill="none" stroke-width="12.881367303472px" stroke-linecap="round" opacity="0" stroke-linejoin="round"/><path class="sch-trace-path" d="M 532.0215116390998 73.81291826693001 L 532.0215116390998 72.21079820856067" stroke="rgb(0, 150, 0)" fill="none" stroke-width="1.610170912934px" stroke-linecap="round" stroke-linejoin="round"/></g><g class="trace sch-trace" data-layer="base" data-circuit-json-type="schematic_trace" data-schematic-trace-id="schematic_trace_2__stack1"><path d="M 555.3177571657768 89.91462739627002 L 487.6905788225488 89.91462739627002" class="trace-invisible-hover-outline sch-trace-hitbox" stroke="rgb(0, 150, 0)" fill="none" stroke-width="12.881367303472px" stroke-linecap="round" opacity="0" stroke-linejoin="round"/><path class="sch-trace-path" d="M 555.3177571657768 89.91462739627002 L 487.6905788225488 89.91462739627002" stroke="rgb(0, 150, 0)" fill="none" stroke-width="1.610170912934px" stroke-linecap="round" stroke-linejoin="round"/></g><g class="trace sch-trace" data-layer="base" data-circuit-json-type="schematic_trace" data-schematic-trace-id="schematic_trace_3__stack1"><path d="M 502.18211703895497 733.98299256987 L 447.436305999199 733.98299256987" class="trace-invisible-hover-outline sch-trace-hitbox" stroke="rgb(0, 150, 0)" fill="none" stroke-width="12.881367303472px" stroke-linecap="round" opacity="0" stroke-linejoin="round"/><path class="sch-trace-path" d="M 502.18211703895497 733.98299256987 L 447.436305999199 733.98299256987" stroke="rgb(0, 150, 0)" fill="none" stroke-width="1.610170912934px" stroke-linecap="round" stroke-linejoin="round"/></g><g class="trace-overlays sch-trace-overlays" data-layer="overlay" data-circuit-json-type="schematic_trace" data-schematic-trace-id="schematic_trace_0__stack1"/><g class="trace-overlays sch-trace-overlays" data-layer="overlay" data-circuit-json-type="schematic_trace" data-schematic-trace-id="schematic_trace_1__stack1"/><g class="trace-overlays sch-trace-overlays" data-layer="overlay" data-circuit-json-type="schematic_trace" data-schematic-trace-id="schematic_trace_2__stack1"/><g class="trace-overlays sch-trace-overlays" data-layer="overlay" data-circuit-json-type="schematic_trace" data-schematic-trace-id="schematic_trace_3__stack1"/><g class="sch-component" data-circuit-json-type="schematic_component" data-schematic-component-id="schematic_component_0__stack1"><rect class="component chip sch-component-body" x="587.5211754244567" y="65.76206370225998" width="96.61025477604016" height="32.20341825868002" stroke-width="1.610170912934px" fill="rgb(255, 255, 194)" stroke="rgb(132, 0, 0)"/><rect class="component-overlay sch-component-overlay" x="587.5211754244567" y="65.76206370225998" width="96.61025477604016" height="32.20341825868002" fill="transparent"/><line class="component-pin sch-component-pin sch-port-line" x1="587.5211754244567" y1="73.81291826693001" x2="555.3177571657768" y2="73.81291826693001" stroke-width="1.610170912934px"/><g class="sch-port" data-schematic-port-id="source_port_0_0__stack1"><rect x="553.7075862528428" y="72.20274735399602" width="3.220341825868" height="3.220341825868" opacity="0"/></g><text class="pin-number sch-pin-number" x="571.4194662951168" y="72.20274735399607" style="font-family: sans-serif;" fill="rgb(169, 0, 0)" text-anchor="middle" dominant-baseline="auto" font-size="12.076281847005px" transform="">1</text><line class="component-pin sch-component-pin sch-port-line" x1="587.5211754244567" y1="89.91462739627002" x2="555.3177571657768" y2="89.91462739627002" stroke-width="1.610170912934px"/><g class="sch-port" data-schematic-port-id="source_port_0_1__stack1"><rect x="553.7075862528428" y="88.30445648333603" width="3.220341825868" height="3.220341825868" opacity="0"/></g><text class="pin-number sch-pin-number" x="571.4194662951168" y="88.30445648333597" style="font-family: sans-serif;" fill="rgb(169, 0, 0)" text-anchor="middle" dominant-baseline="auto" font-size="12.076281847005px" transform="">2</text><line class="component-pin sch-component-pin sch-port-line" x1="684.1314302004969" y1="81.86377283159999" x2="714.7246775462429" y2="81.86377283159999" stroke-width="1.610170912934px"/><g class="sch-port" data-schematic-port-id="source_port_0_2__stack1"><circle class="component-pin sch-component-pin sch-port-terminal" cx="716.3348484591769" cy="81.86377283159999" r="1.610170912934" stroke-width="1.610170912934px"/><rect x="714.7246775462429" y="80.25360191866599" width="3.220341825868" height="3.220341825868" opacity="0"/></g><text class="pin-number sch-pin-number" x="700.2331393298368" y="80.25360191866605" style="font-family: sans-serif;" fill="rgb(169, 0, 0)" text-anchor="middle" dominant-baseline="auto" font-size="12.076281847005px" transform="">3</text></g><g class="sch-component" data-circuit-json-type="schematic_component" data-schematic-component-id="schematic_component_1__stack1"><rect class="component chip sch-component-body" x="534.385535297635" y="709.83042887586" width="96.61025477603994" height="32.20341825868002" stroke-width="1.610170912934px" fill="rgb(255, 255, 194)" stroke="rgb(132, 0, 0)"/><rect class="component-overlay sch-component-overlay" x="534.385535297635" y="709.83042887586" width="96.61025477603994" height="32.20341825868002" fill="transparent"/><line class="component-pin sch-component-pin sch-port-line" x1="534.385535297635" y1="717.88128344053" x2="502.18211703895497" y2="717.88128344053" stroke-width="1.610170912934px"/><g class="sch-port" data-schematic-port-id="source_port_1_0__stack1"><rect x="500.571946126021" y="716.271112527596" width="3.220341825868" height="3.220341825868" opacity="0"/></g><text class="pin-number sch-pin-number" x="518.2838261682949" y="716.271112527596" style="font-family: sans-serif;" fill="rgb(169, 0, 0)" text-anchor="middle" dominant-baseline="auto" font-size="12.076281847005px" transform="">1</text><line class="component-pin sch-component-pin sch-port-line" x1="534.385535297635" y1="733.98299256987" x2="502.18211703895497" y2="733.98299256987" stroke-width="1.610170912934px"/><g class="sch-port" data-schematic-port-id="source_port_1_1__stack1"><rect x="500.571946126021" y="732.372821656936" width="3.220341825868" height="3.220341825868" opacity="0"/></g><text class="pin-number sch-pin-number" x="518.2838261682949" y="732.3728216569359" style="font-family: sans-serif;" fill="rgb(169, 0, 0)" text-anchor="middle" dominant-baseline="auto" font-size="12.076281847005px" transform="">2</text><line class="component-pin sch-component-pin sch-port-line" x1="630.9957900736749" y1="725.9321380051999" x2="661.589037419421" y2="725.9321380051999" stroke-width="1.610170912934px"/><g class="sch-port" data-schematic-port-id="source_port_1_2__stack1"><circle class="component-pin sch-component-pin sch-port-terminal" cx="663.1992083323549" cy="725.9321380051999" r="1.610170912934" stroke-width="1.610170912934px"/><rect x="661.589037419421" y="724.3219670922659" width="3.220341825868" height="3.220341825868" opacity="0"/></g><text class="pin-number sch-pin-number" x="647.097499203015" y="724.321967092266" style="font-family: sans-serif;" fill="rgb(169, 0, 0)" text-anchor="middle" dominant-baseline="auto" font-size="12.076281847005px" transform="">3</text></g><g class="schematic-port-hover sch-port-hover" data-schematic-port-id="source_port_0_0__stack1"><circle cx="555.3177571657768" cy="73.81291826693001" r="3.220341825868" fill="red" opacity="0"/></g><g class="schematic-port-hover sch-port-hover" data-schematic-port-id="source_port_0_1__stack1"><circle cx="555.3177571657768" cy="89.91462739627002" r="3.220341825868" fill="red" opacity="0"/></g><g class="schematic-port-hover sch-port-hover" data-schematic-port-id="source_port_0_2__stack1"><circle cx="716.3348484591769" cy="81.86377283159999" r="3.220341825868" fill="red" opacity="0"/></g><g class="schematic-port-hover sch-port-hover" data-schematic-port-id="source_port_1_0__stack1"><circle cx="502.18211703895497" cy="717.88128344053" r="3.220341825868" fill="red" opacity="0"/></g><g class="schematic-port-hover sch-port-hover" data-schematic-port-id="source_port_1_1__stack1"><circle cx="502.18211703895497" cy="733.98299256987" r="3.220341825868" fill="red" opacity="0"/></g><g class="schematic-port-hover sch-port-hover" data-schematic-port-id="source_port_1_2__stack1"><circle cx="663.1992083323549" cy="725.9321380051999" r="3.220341825868" fill="red" opacity="0"/></g><path class="net-label sch-net-label" data-circuit-json-type="schematic_net_label" data-schematic-net-label-id="schematic_net_label_0__stack1" d="
|
|
75
|
-
M 532.0215116390998,72.21079820856067
|
|
76
|
-
L 523.9706570744298,67.86333674363887
|
|
77
|
-
L 523.9706570744298,40.254272823197226
|
|
78
|
-
L 540.0723662037698,40.254272823197226
|
|
79
|
-
L 540.0723662037698,67.86333674363888
|
|
80
|
-
Z
|
|
81
|
-
" fill="rgba(255, 255, 255, 0.6)" stroke="rgb(132, 0, 0)" stroke-width="1.610170912934px"/><text class="net-label-text sch-net-label-text" data-circuit-json-type="schematic_net_label" data-schematic-net-label-id="schematic_net_label_0__stack1" x="532.0215116390998" y="64.96502910035767" fill="rgb(132, 0, 0)" text-anchor="start" dominant-baseline="central" font-family="sans-serif" font-variant-numeric="tabular-nums" font-size="14.491538216406px" transform="rotate(-90 532.0215116390998 64.96502910035767)">XX</text><text class="sch-text" x="655.1483537676849" y="108.43159289501102" fill="#7e22ce" text-anchor="middle" dominant-baseline="middle" font-family="sans-serif" font-size="14.491538216405978px" transform="rotate(0, 655.1483537676849, 108.43159289501102)">D2FC-F-7N(20M)</text><text class="sch-text" x="621.3347645960708" y="56.503580952889536" fill="#7e22ce" text-anchor="middle" dominant-baseline="middle" font-family="sans-serif" font-size="14.491538216406px" transform="rotate(0, 621.3347645960708, 56.503580952889536)">SW_LEFT</text><text class="sch-text" x="602.012713640863" y="752.499958068611" fill="#7e22ce" text-anchor="middle" dominant-baseline="middle" font-family="sans-serif" font-size="14.491538216405978px" transform="rotate(0, 602.012713640863, 752.499958068611)">D2FC-F-7N(20M)</text><text class="sch-text" x="573.029637208051" y="700.5719461264895" fill="#7e22ce" text-anchor="middle" dominant-baseline="middle" font-family="sans-serif" font-size="14.491538216406px" transform="rotate(0, 573.029637208051, 700.5719461264895)">SW_RIGHT</text><text class="sch-text" x="521.5041679941628" y="81.05868737513299" fill="#047857" text-anchor="middle" dominant-baseline="middle" font-family="sans-serif" font-size="9.661025477604px" transform="rotate(0, 521.5041679941628, 81.05868737513299)">XXXXXXX</text><text class="sch-text" x="474.80921151907694" y="725.127052548733" fill="#047857" text-anchor="middle" dominant-baseline="middle" font-family="sans-serif" font-size="9.661025477604px" transform="rotate(0, 474.80921151907694, 725.127052548733)">XXXXX</text><rect class="schematic-box sch-box" x="587.5211754244568" y="101.18582378680799" width="135.25435668645605" height="14.491538216406013" stroke-width="1.610170912934px" stroke="rgb(132, 0, 0)" fill="transparent" stroke-dasharray="12.881367303472 6.440683651736"/><rect class="schematic-box sch-box" x="582.6906626856548" y="46.440012747052094" width="77.288203820832" height="20.12713641167494" stroke-width="1.610170912934px" stroke="rgb(132, 0, 0)" fill="transparent" stroke-dasharray="12.881367303472 6.440683651736"/><rect class="schematic-box sch-box" x="534.385535297635" y="745.254188960408" width="135.25435668645594" height="14.491538216405957" stroke-width="1.610170912934px" stroke="rgb(132, 0, 0)" fill="transparent" stroke-dasharray="12.881367303472 6.440683651736"/><rect class="schematic-box sch-box" x="529.5550225588331" y="690.508377920652" width="86.94922929843597" height="20.127136411674883" stroke-width="1.610170912934px" stroke="rgb(132, 0, 0)" fill="transparent" stroke-dasharray="12.881367303472 6.440683651736"/>
|
|
74
|
+
</style><rect class="boundary" x="0" y="0" width="1200" height="800"/><g class="trace sch-trace" data-layer="base" data-circuit-json-type="schematic_trace" data-schematic-trace-id="schematic_trace_0__stack1"><path d="M 570.3853955376389 68.15415821511004 L 434.88843813401627 68.15415821511004 L 434.88843813401627 717.24137931031 L 516.8356997972851 717.24137931031" class="trace-invisible-hover-outline sch-trace-hitbox" stroke="rgb(0, 150, 0)" fill="none" stroke-width="12.981744421904px" stroke-linecap="round" opacity="0" stroke-linejoin="round"/><path class="sch-trace-path" d="M 570.3853955376389 68.15415821511004 L 434.88843813401627 68.15415821511004 L 434.88843813401627 717.24137931031 L 516.8356997972851 717.24137931031" stroke="rgb(0, 150, 0)" fill="none" stroke-width="1.622718052738px" stroke-linecap="round" stroke-linejoin="round"/></g><g class="trace sch-trace" data-layer="base" data-circuit-json-type="schematic_trace" data-schematic-trace-id="schematic_trace_1__stack1"><path d="M 570.3853955376389 84.38133874249002 L 502.231237322643 84.38133874249002" class="trace-invisible-hover-outline sch-trace-hitbox" stroke="rgb(0, 150, 0)" fill="none" stroke-width="12.981744421904px" stroke-linecap="round" opacity="0" stroke-linejoin="round"/><path class="sch-trace-path" d="M 570.3853955376389 84.38133874249002 L 502.231237322643 84.38133874249002" stroke="rgb(0, 150, 0)" fill="none" stroke-width="1.622718052738px" stroke-linecap="round" stroke-linejoin="round"/></g><g class="trace sch-trace" data-layer="base" data-circuit-json-type="schematic_trace" data-schematic-trace-id="schematic_trace_2__stack1"><path d="M 516.8356997972851 733.46855983769 L 461.6632860041931 733.46855983769" class="trace-invisible-hover-outline sch-trace-hitbox" stroke="rgb(0, 150, 0)" fill="none" stroke-width="12.981744421904px" stroke-linecap="round" opacity="0" stroke-linejoin="round"/><path class="sch-trace-path" d="M 516.8356997972851 733.46855983769 L 461.6632860041931 733.46855983769" stroke="rgb(0, 150, 0)" fill="none" stroke-width="1.622718052738px" stroke-linecap="round" stroke-linejoin="round"/></g><g class="trace-overlays sch-trace-overlays" data-layer="overlay" data-circuit-json-type="schematic_trace" data-schematic-trace-id="schematic_trace_0__stack1"/><g class="trace-overlays sch-trace-overlays" data-layer="overlay" data-circuit-json-type="schematic_trace" data-schematic-trace-id="schematic_trace_1__stack1"/><g class="trace-overlays sch-trace-overlays" data-layer="overlay" data-circuit-json-type="schematic_trace" data-schematic-trace-id="schematic_trace_2__stack1"/><g class="sch-component" data-circuit-json-type="schematic_component" data-schematic-component-id="schematic_component_0__stack1"><rect class="component chip sch-component-body" x="602.8397565923989" y="60.04056795141997" width="97.36308316428017" height="32.45436105476006" stroke-width="1.622718052738px" fill="rgb(255, 255, 194)" stroke="rgb(132, 0, 0)"/><rect class="component-overlay sch-component-overlay" x="602.8397565923989" y="60.04056795141997" width="97.36308316428017" height="32.45436105476006" fill="transparent"/><line class="component-pin sch-component-pin sch-port-line" x1="602.8397565923989" y1="68.15415821511004" x2="570.3853955376389" y2="68.15415821511004" stroke-width="1.622718052738px"/><g class="sch-port" data-schematic-port-id="source_port_0_0__stack1"><rect x="568.7626774849009" y="66.53144016237205" width="3.245436105476" height="3.245436105476" opacity="0"/></g><text class="pin-number sch-pin-number" x="586.612576065019" y="66.53144016237206" style="font-family: sans-serif;" fill="rgb(169, 0, 0)" text-anchor="middle" dominant-baseline="auto" font-size="12.170385395535px" transform="">1</text><line class="component-pin sch-component-pin sch-port-line" x1="602.8397565923989" y1="84.38133874249002" x2="570.3853955376389" y2="84.38133874249002" stroke-width="1.622718052738px"/><g class="sch-port" data-schematic-port-id="source_port_0_1__stack1"><rect x="568.7626774849009" y="82.75862068975202" width="3.245436105476" height="3.245436105476" opacity="0"/></g><text class="pin-number sch-pin-number" x="586.612576065019" y="82.75862068975204" style="font-family: sans-serif;" fill="rgb(169, 0, 0)" text-anchor="middle" dominant-baseline="auto" font-size="12.170385395535px" transform="">2</text><line class="component-pin sch-component-pin sch-port-line" x1="700.202839756679" y1="76.2677484788" x2="731.0344827587011" y2="76.2677484788" stroke-width="1.622718052738px"/><g class="sch-port" data-schematic-port-id="source_port_0_2__stack1"><circle class="component-pin sch-component-pin sch-port-terminal" cx="732.657200811439" cy="76.2677484788" r="1.622718052738" stroke-width="1.622718052738px"/><rect x="731.034482758701" y="74.64503042606201" width="3.245436105476" height="3.245436105476" opacity="0"/></g><text class="pin-number sch-pin-number" x="716.4300202840591" y="74.64503042606202" style="font-family: sans-serif;" fill="rgb(169, 0, 0)" text-anchor="middle" dominant-baseline="auto" font-size="12.170385395535px" transform="">3</text></g><g class="sch-component" data-circuit-json-type="schematic_component" data-schematic-component-id="schematic_component_1__stack1"><rect class="component chip sch-component-body" x="549.2900608520451" y="709.1277890466199" width="97.36308316427994" height="32.45436105476006" stroke-width="1.622718052738px" fill="rgb(255, 255, 194)" stroke="rgb(132, 0, 0)"/><rect class="component-overlay sch-component-overlay" x="549.2900608520451" y="709.1277890466199" width="97.36308316427994" height="32.45436105476006" fill="transparent"/><line class="component-pin sch-component-pin sch-port-line" x1="549.2900608520451" y1="717.24137931031" x2="516.8356997972851" y2="717.24137931031" stroke-width="1.622718052738px"/><g class="sch-port" data-schematic-port-id="source_port_1_0__stack1"><rect x="515.212981744547" y="715.618661257572" width="3.245436105476" height="3.245436105476" opacity="0"/></g><text class="pin-number sch-pin-number" x="533.062880324665" y="715.6186612575721" style="font-family: sans-serif;" fill="rgb(169, 0, 0)" text-anchor="middle" dominant-baseline="auto" font-size="12.170385395535px" transform="">1</text><line class="component-pin sch-component-pin sch-port-line" x1="549.2900608520451" y1="733.46855983769" x2="516.8356997972851" y2="733.46855983769" stroke-width="1.622718052738px"/><g class="sch-port" data-schematic-port-id="source_port_1_1__stack1"><rect x="515.212981744547" y="731.845841784952" width="3.245436105476" height="3.245436105476" opacity="0"/></g><text class="pin-number sch-pin-number" x="533.062880324665" y="731.845841784952" style="font-family: sans-serif;" fill="rgb(169, 0, 0)" text-anchor="middle" dominant-baseline="auto" font-size="12.170385395535px" transform="">2</text><line class="component-pin sch-component-pin sch-port-line" x1="646.6531440163251" y1="725.354969574" x2="677.4847870183471" y2="725.354969574" stroke-width="1.622718052738px"/><g class="sch-port" data-schematic-port-id="source_port_1_2__stack1"><circle class="component-pin sch-component-pin sch-port-terminal" cx="679.1075050710851" cy="725.354969574" r="1.622718052738" stroke-width="1.622718052738px"/><rect x="677.4847870183471" y="723.732251521262" width="3.245436105476" height="3.245436105476" opacity="0"/></g><text class="pin-number sch-pin-number" x="662.8803245437051" y="723.732251521262" style="font-family: sans-serif;" fill="rgb(169, 0, 0)" text-anchor="middle" dominant-baseline="auto" font-size="12.170385395535px" transform="">3</text></g><g class="schematic-port-hover sch-port-hover" data-schematic-port-id="source_port_0_0__stack1"><circle cx="570.3853955376389" cy="68.15415821511004" r="3.245436105476" fill="red" opacity="0"/></g><g class="schematic-port-hover sch-port-hover" data-schematic-port-id="source_port_0_1__stack1"><circle cx="570.3853955376389" cy="84.38133874249002" r="3.245436105476" fill="red" opacity="0"/></g><g class="schematic-port-hover sch-port-hover" data-schematic-port-id="source_port_0_2__stack1"><circle cx="732.657200811439" cy="76.2677484788" r="3.245436105476" fill="red" opacity="0"/></g><g class="schematic-port-hover sch-port-hover" data-schematic-port-id="source_port_1_0__stack1"><circle cx="516.8356997972851" cy="717.24137931031" r="3.245436105476" fill="red" opacity="0"/></g><g class="schematic-port-hover sch-port-hover" data-schematic-port-id="source_port_1_1__stack1"><circle cx="516.8356997972851" cy="733.46855983769" r="3.245436105476" fill="red" opacity="0"/></g><g class="schematic-port-hover sch-port-hover" data-schematic-port-id="source_port_1_2__stack1"><circle cx="679.1075050710851" cy="725.354969574" r="3.245436105476" fill="red" opacity="0"/></g><rect class="component-overlay sch-component-overlay sch-net-label-overlay" data-circuit-json-type="schematic_net_label" data-schematic-net-label-id="schematic_net_label_0__stack1" x="425.1521298175883" y="717.24137931031" width="19.47261663285599" height="14.604462474642105" fill="transparent"/><path class="sch-net-label-symbol-path" data-circuit-json-type="schematic_net_label" data-schematic-net-label-id="schematic_net_label_0__stack1" d="M 425.1521298175883 731.8458417849521 L 444.62474645044426 731.8458417849521" stroke="rgb(132, 0, 0)" fill="none" stroke-width="1.622718052738px" stroke-linecap="round"/><path class="sch-net-label-symbol-path" data-circuit-json-type="schematic_net_label" data-schematic-net-label-id="schematic_net_label_0__stack1" d="M 434.88843813401627 731.8458417849521 L 434.88843813401627 717.24137931031" stroke="rgb(132, 0, 0)" fill="none" stroke-width="1.622718052738px" stroke-linecap="round"/><text class="sch-net-label-symbol-text" data-circuit-json-type="schematic_net_label" data-schematic-net-label-id="schematic_net_label_0__stack1" x="434.88843813401627" y="735.9026369167971" fill="rgb(15, 15, 15)" font-family="sans-serif" text-anchor="middle" dominant-baseline="hanging" font-size="14.604462474641998px">XX</text><text class="sch-text" x="670.993914807395" y="103.04259634897699" fill="#7e22ce" text-anchor="middle" dominant-baseline="middle" font-family="sans-serif" font-size="14.604462474641977px" transform="rotate(0, 670.993914807395, 103.04259634897699)">D2FC-F-7N(20M)</text><text class="sch-text" x="636.916835699897" y="50.709939148176545" fill="#7e22ce" text-anchor="middle" dominant-baseline="middle" font-family="sans-serif" font-size="14.604462474641998px" transform="rotate(0, 636.916835699897, 50.709939148176545)">SW_LEFT</text><text class="sch-text" x="617.4442190670411" y="752.129817444177" fill="#7e22ce" text-anchor="middle" dominant-baseline="middle" font-family="sans-serif" font-size="14.604462474641977px" transform="rotate(0, 617.4442190670411, 752.129817444177)">D2FC-F-7N(20M)</text><text class="sch-text" x="588.2352941177571" y="699.7971602433765" fill="#7e22ce" text-anchor="middle" dominant-baseline="middle" font-family="sans-serif" font-size="14.604462474641998px" transform="rotate(0, 588.2352941177571, 699.7971602433765)">SW_RIGHT</text><text class="sch-text" x="536.308316430141" y="75.45638945243104" fill="#047857" text-anchor="middle" dominant-baseline="middle" font-family="sans-serif" font-size="9.736308316428px" transform="rotate(0, 536.308316430141, 75.45638945243104)">XXXXXXX</text><text class="sch-text" x="489.24949290073914" y="724.543610547631" fill="#047857" text-anchor="middle" dominant-baseline="middle" font-family="sans-serif" font-size="9.736308316428px" transform="rotate(0, 489.24949290073914, 724.543610547631)">XXXXX</text><rect class="schematic-box sch-box" x="602.839756592399" y="95.74036511165605" width="136.30831642999203" height="14.604462474641934" stroke-width="1.622718052738px" stroke="rgb(132, 0, 0)" fill="transparent" stroke-dasharray="12.981744421904 6.490872210952"/><rect class="schematic-box sch-box" x="597.971602434185" y="40.5679513185641" width="77.89046653142395" height="20.28397565922495" stroke-width="1.622718052738px" stroke="rgb(132, 0, 0)" fill="transparent" stroke-dasharray="12.981744421904 6.490872210952"/><rect class="schematic-box sch-box" x="549.2900608520451" y="744.827586206856" width="136.30831642999192" height="14.604462474641878" stroke-width="1.622718052738px" stroke="rgb(132, 0, 0)" fill="transparent" stroke-dasharray="12.981744421904 6.490872210952"/><rect class="schematic-box sch-box" x="544.4219066938313" y="689.6551724137639" width="87.62677484785195" height="20.283975659225007" stroke-width="1.622718052738px" stroke="rgb(132, 0, 0)" fill="transparent" stroke-dasharray="12.981744421904 6.490872210952"/>
|
|
82
75
|
</g>
|
|
83
76
|
</svg>
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
<svg width="1200" height="2016" viewBox="0 0 1200 2016" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="Solver debug visualization on top and Circuit JSON schematic on the bottom">
|
|
2
|
+
<g transform="translate(0, 0) scale(1.875, 1.875) translate(0, 0)">
|
|
3
|
+
<rect width="100%" height="100%" fill="white"/><g><polyline data-points="-14.05,6 -14.25,6 -14.25,5.72 -10.399999999999999,5.72 -10.399999999999999,5.92" data-type="line" data-label="" points="69.52029520295173,203.3948339483395 49.840098400983834,203.3948339483395 49.840098400983834,230.9471094710948 428.6838868388685,230.9471094710948 428.6838868388685,211.26691266912678" fill="none" stroke="purple" stroke-width="1px"/></g><g><polyline data-points="-9.6,6 -8.659,6 -8.659,3.180000000000001 -10.4,3.180000000000001 -10.4,3.3800000000000003" data-type="line" data-label="" points="507.4046740467404,203.3948339483395 599.9999999999999,203.3948339483395 599.9999999999999,480.88560885608854 428.68388683886826,480.88560885608854 428.68388683886826,461.2054120541206" fill="none" stroke="purple" stroke-width="1px"/></g><g><rect data-type="rect" data-label="J1" data-x="-13" data-y="6" x="69.52029520295173" y="183.71463714637144" width="206.64206642066438" height="39.36039360393613" fill="hsl(183, 100%, 50%, 0.8)" stroke="black" stroke-width="0.010162499999999998"/></g><g><rect data-type="rect" data-label="F1" data-x="-10.17" data-y="6.115" x="395.2275522755226" y="172.89052890528905" width="112.1771217712178" height="38.37638376383768" fill="hsl(59, 100%, 50%, 0.8)" stroke="black" stroke-width="0.010162499999999998"/></g><g><rect data-type="rect" data-label="RV1" data-x="-10.195" data-y="3.615" x="390.3075030750306" y="414.9569495694958" width="117.09717097170983" height="46.24846248462478" fill="hsl(157, 100%, 50%, 0.8)" stroke="black" stroke-width="0.010162499999999998"/></g><g><rect data-type="rect" data-label="netId: LINE
|
|
4
|
+
globalConnNetId: connectivity_net0" data-x="-14.25" data-y="6.225" x="39.999999999999886" y="159.11439114391163" width="19.680196801967895" height="44.280442804427935" fill="hsl(40, 100%, 50%, 0.35)" stroke="black" stroke-width="0.010162499999999998"/></g><g><rect data-type="rect" data-label="netId: LINE_FUSED
|
|
5
|
+
globalConnNetId: connectivity_net1" data-x="-9.1295" data-y="6.225" x="543.8622386223863" y="159.11439114391163" width="19.68019680196801" height="44.280442804427935" fill="hsl(40, 100%, 50%, 0.35)" stroke="black" stroke-width="0.010162499999999998"/></g><g><rect data-type="rect" data-label="netId: NEUTRAL
|
|
6
|
+
globalConnNetId: connectivity_net2" data-x="-9.179" data-y="3.5" x="507.50307503075015" y="439.55719557195584" width="82.65682656826573" height="19.680196801968066" fill="hsl(40, 100%, 50%, 0.35)" stroke="black" stroke-width="0.010162499999999998"/></g><g><circle data-type="point" data-label="J1.1
|
|
7
|
+
x-" data-x="-14.05" data-y="6" cx="69.52029520295173" cy="203.3948339483395" r="3" fill="hsl(218, 100%, 50%, 0.8)"/></g><g><circle data-type="point" data-label="F1.1
|
|
8
|
+
y-" data-x="-10.4" data-y="5.92" cx="428.68388683886826" cy="211.26691266912678" r="3" fill="hsl(214, 100%, 50%, 0.8)"/></g><g><circle data-type="point" data-label="F1.2
|
|
9
|
+
x+" data-x="-9.6" data-y="6" cx="507.4046740467404" cy="203.3948339483395" r="3" fill="hsl(215, 100%, 50%, 0.8)"/></g><g><circle data-type="point" data-label="RV1.1
|
|
10
|
+
y-" data-x="-10.4" data-y="3.3800000000000003" cx="428.68388683886826" cy="461.2054120541206" r="3" fill="hsl(72, 100%, 50%, 0.8)"/></g><g><circle data-type="point" data-label="RV1.2
|
|
11
|
+
x+" data-x="-9.6" data-y="3.5" cx="507.4046740467404" cy="449.39729397293985" r="3" fill="hsl(73, 100%, 50%, 0.8)"/></g><g><circle data-type="point" data-label="anchorPoint
|
|
12
|
+
orientation: y+" data-x="-14.25" data-y="6" cx="49.840098400983834" cy="203.3948339483395" r="3" fill="hsl(40, 100%, 50%, 0.9)"/></g><g><circle data-type="point" data-label="anchorPoint
|
|
13
|
+
orientation: y+" data-x="-9.1295" data-y="6" cx="553.7023370233702" cy="203.3948339483395" r="3" fill="hsl(40, 100%, 50%, 0.9)"/></g><g><circle data-type="point" data-label="anchorPoint
|
|
14
|
+
orientation: x+" data-x="-9.6" data-y="3.5" cx="507.4046740467404" cy="449.39729397293985" r="3" fill="hsl(40, 100%, 50%, 0.9)"/></g><g id="crosshair" style="display: none"><line id="crosshair-h" y1="0" y2="640" stroke="#666" stroke-width="0.5"/><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></g><script><![CDATA[
|
|
15
|
+
document.currentScript.parentElement.addEventListener('mousemove', (e) => {
|
|
16
|
+
const svg = e.currentTarget;
|
|
17
|
+
const rect = svg.getBoundingClientRect();
|
|
18
|
+
const x = e.clientX - rect.left;
|
|
19
|
+
const y = e.clientY - rect.top;
|
|
20
|
+
const crosshair = svg.getElementById('crosshair');
|
|
21
|
+
const h = svg.getElementById('crosshair-h');
|
|
22
|
+
const v = svg.getElementById('crosshair-v');
|
|
23
|
+
const coords = svg.getElementById('coordinates');
|
|
24
|
+
|
|
25
|
+
crosshair.style.display = 'block';
|
|
26
|
+
h.setAttribute('x1', '0');
|
|
27
|
+
h.setAttribute('x2', '640');
|
|
28
|
+
h.setAttribute('y1', y);
|
|
29
|
+
h.setAttribute('y2', y);
|
|
30
|
+
v.setAttribute('x1', x);
|
|
31
|
+
v.setAttribute('x2', x);
|
|
32
|
+
v.setAttribute('y1', '0');
|
|
33
|
+
v.setAttribute('y2', '640');
|
|
34
|
+
|
|
35
|
+
// Calculate real coordinates using inverse transformation
|
|
36
|
+
const matrix = {"a":98.40098400984012,"c":0,"e":1452.0541205412055,"b":0,"d":-98.40098400984012,"f":793.8007380073802};
|
|
37
|
+
// Manually invert and apply the affine transform
|
|
38
|
+
// Since we only use translate and scale, we can directly compute:
|
|
39
|
+
// x' = (x - tx) / sx
|
|
40
|
+
// y' = (y - ty) / sy
|
|
41
|
+
const sx = matrix.a;
|
|
42
|
+
const sy = matrix.d;
|
|
43
|
+
const tx = matrix.e;
|
|
44
|
+
const ty = matrix.f;
|
|
45
|
+
const realPoint = {
|
|
46
|
+
x: (x - tx) / sx,
|
|
47
|
+
y: (y - ty) / sy // Flip y back since we used negative scale
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
coords.textContent = `(${realPoint.x.toFixed(2)}, ${realPoint.y.toFixed(2)})`;
|
|
51
|
+
coords.setAttribute('x', (x + 5).toString());
|
|
52
|
+
coords.setAttribute('y', (y - 5).toString());
|
|
53
|
+
});
|
|
54
|
+
document.currentScript.parentElement.addEventListener('mouseleave', () => {
|
|
55
|
+
document.currentScript.parentElement.getElementById('crosshair').style.display = 'none';
|
|
56
|
+
});
|
|
57
|
+
]]></script>
|
|
58
|
+
</g>
|
|
59
|
+
<g transform="translate(0, 1216)">
|
|
60
|
+
<style>
|
|
61
|
+
.boundary { fill: rgb(245, 241, 237); }
|
|
62
|
+
.schematic-boundary { fill: none; stroke: #fff; }
|
|
63
|
+
.component { fill: none; stroke: rgb(132, 0, 0); }
|
|
64
|
+
.chip { fill: rgb(255, 255, 194); stroke: rgb(132, 0, 0); }
|
|
65
|
+
.component-pin { fill: none; stroke: rgb(132, 0, 0); }
|
|
66
|
+
.text { font-family: sans-serif; fill: rgb(0, 150, 0); }
|
|
67
|
+
.pin-number { fill: rgb(169, 0, 0); }
|
|
68
|
+
.port-label { fill: rgb(0, 100, 100); }
|
|
69
|
+
.component-name { fill: rgb(0, 100, 100); }
|
|
70
|
+
|
|
71
|
+
</style><rect class="boundary" x="0" y="0" width="1200" height="800"/><g class="trace sch-trace" data-layer="base" data-circuit-json-type="schematic_trace" data-schematic-trace-id="schematic_trace_0__stack1"><path d="M 142.41210502838976 179.8783563267002 L 106.80907877114987 179.8783563267002 L 106.80907877114987 229.72259308683624 L 792.1673342230201 229.72259308683624 L 792.1673342230201 194.11956682959612" class="trace-invisible-hover-outline sch-trace-hitbox" stroke="rgb(0, 150, 0)" fill="none" stroke-width="28.482421005792px" stroke-linecap="round" opacity="0" stroke-linejoin="round"/><path class="sch-trace-path" d="M 142.41210502838976 179.8783563267002 L 106.80907877114987 179.8783563267002 L 106.80907877114987 229.72259308683624 L 792.1673342230201 229.72259308683624 L 792.1673342230201 194.11956682959612" stroke="rgb(0, 150, 0)" fill="none" stroke-width="3.560302625724px" stroke-linecap="round" stroke-linejoin="round"/></g><g class="trace sch-trace" data-layer="base" data-circuit-json-type="schematic_trace" data-schematic-trace-id="schematic_trace_1__stack1"><path d="M 934.5794392519799 179.8783563267002 L 1102.091677792294 179.8783563267002 L 1102.091677792294 681.881026553784 L 792.1673342230199 681.881026553784 L 792.1673342230199 646.2780002965441" class="trace-invisible-hover-outline sch-trace-hitbox" stroke="rgb(0, 150, 0)" fill="none" stroke-width="28.482421005792px" stroke-linecap="round" opacity="0" stroke-linejoin="round"/><path class="sch-trace-path" d="M 934.5794392519799 179.8783563267002 L 1102.091677792294 179.8783563267002 L 1102.091677792294 681.881026553784 L 792.1673342230199 681.881026553784 L 792.1673342230199 646.2780002965441" stroke="rgb(0, 150, 0)" fill="none" stroke-width="3.560302625724px" stroke-linecap="round" stroke-linejoin="round"/></g><g class="trace-overlays sch-trace-overlays" data-layer="overlay" data-circuit-json-type="schematic_trace" data-schematic-trace-id="schematic_trace_0__stack1"/><g class="trace-overlays sch-trace-overlays" data-layer="overlay" data-circuit-json-type="schematic_trace" data-schematic-trace-id="schematic_trace_1__stack1"/><g class="sch-component" data-circuit-json-type="schematic_component" data-schematic-component-id="schematic_component_0__stack1"><rect class="component chip sch-component-body" x="213.61815754287" y="144.2753300694601" width="231.41967067205996" height="71.20605251448" stroke-width="3.560302625724px" fill="rgb(255, 255, 194)" stroke="rgb(132, 0, 0)"/><rect class="component-overlay sch-component-overlay" x="213.61815754287" y="144.2753300694601" width="231.41967067205996" height="71.20605251448" fill="transparent"/><text class="sch-text" x="329.3279928789002" y="179.8783563267002" fill="#0f172a" text-anchor="middle" dominant-baseline="middle" font-family="sans-serif" font-size="23.73535083816px" transform="rotate(0, 329.3279928789002, 179.8783563267002)">J1</text><line class="component-pin sch-component-pin sch-port-line" x1="213.61815754287" y1="179.8783563267002" x2="142.41210502838976" y2="179.8783563267002" stroke-width="3.560302625724px"/><g class="sch-port" data-schematic-port-id="source_port_0_0__stack1"><rect x="138.85180240266575" y="176.3180537009762" width="7.120605251448" height="7.120605251448" opacity="0"/></g><text class="pin-number sch-pin-number" x="178.01513128562965" y="176.31805370097618" style="font-family: sans-serif;" fill="rgb(169, 0, 0)" text-anchor="middle" dominant-baseline="auto" font-size="26.70226969293px" transform="">1</text></g><g class="sch-component" data-circuit-json-type="schematic_component" data-schematic-component-id="schematic_component_1__stack1"><rect class="component-overlay sch-component-overlay" x="791.4570450036748" y="162.32560986228535" width="143.12239424830545" height="36.45570419532308" fill="transparent"/><path class="sch-component-symbol-path" d="M 791.4570450036748 179.87835632670016 L 934.5794392519803 179.87835632670016" stroke="rgb(132, 0, 0)" fill="none" stroke-width="3.560302625724px" stroke-linecap="round"/><path class="sch-component-symbol-path" d="M 863.0182421278275 162.32560986228535 L 899.4739463231506 162.32560986228535 L 899.4739463231506 198.78131405760843 L 827.9127491989979 198.78131405760843 L 827.9127491989979 162.32560986228535 L 863.0182421278275 162.32560986228535" stroke="rgb(132, 0, 0)" fill="none" stroke-width="3.560302625724px" stroke-linecap="round"/><text class="sch-component-name sch-component-text" x="861.668030861334" y="152.8741309968312" stroke="rgb(245, 241, 237)" stroke-width="3.560302625724px" paint-order="stroke" fill="rgb(15, 15, 15)" font-family="sans-serif" text-anchor="middle" dominant-baseline="ideographic" font-size="32.042723631516px">F1</text><text class="sch-component-text" x="863.0182421278275" y="212.28342672254288" fill="rgb(15, 15, 15)" font-family="sans-serif" text-anchor="middle" dominant-baseline="hanging" font-size="32.042723631516px"></text></g><g class="sch-component" data-circuit-json-type="schematic_component" data-schematic-component-id="schematic_component_2__stack1"><rect class="component-overlay sch-component-overlay" x="790.5802827469805" y="594.2496975087281" width="143.9991565049993" height="62.66629959013858" fill="transparent"/><path class="sch-component-symbol-path" d="M 790.5802827469805 626.2495100653946 L 827.9133973964248 626.2495100653946" stroke="rgb(132, 0, 0)" fill="none" stroke-width="3.560302625724px" stroke-linecap="round"/><path class="sch-component-symbol-path" d="M 898.57965012573 626.2495100653946 L 934.5794392519798 624.9161845422002" stroke="rgb(132, 0, 0)" fill="none" stroke-width="3.560302625724px" stroke-linecap="round"/><path class="sch-component-symbol-path" d="M 898.57965012573 656.9159970988667 L 827.9133973964248 594.2496975087281" stroke="rgb(132, 0, 0)" fill="none" stroke-width="3.560302625724px" stroke-linecap="round"/><path class="sch-component-symbol-path" d="M 913.2462308808688 656.9159970988667 L 898.57965012573 656.9159970988667" stroke="rgb(132, 0, 0)" fill="none" stroke-width="3.560302625724px" stroke-linecap="round"/><path class="sch-component-symbol-path" d="M 862.5798609994802 607.5829527406725 L 898.57965012573 607.5829527406725 L 898.57965012573 643.5827418669223 L 827.9133973964248 643.5827418669223 L 827.9133973964248 607.5829527406725 L 862.5798609994802 607.5829527406725" stroke="rgb(132, 0, 0)" fill="none" stroke-width="3.560302625724px" stroke-linecap="round"/><text class="sch-component-name sch-component-text" x="854.5799078603135" y="592.9163719855336" stroke="rgb(245, 241, 237)" stroke-width="3.560302625724px" paint-order="stroke" fill="rgb(15, 15, 15)" font-family="sans-serif" text-anchor="start" dominant-baseline="middle" font-size="32.042723631516px">RV1</text><text class="sch-component-text" x="863.9131865226746" y="659.5826481452556" fill="rgb(15, 15, 15)" font-family="sans-serif" text-anchor="end" dominant-baseline="middle" font-size="32.042723631516px"></text><circle class="component-pin sch-component-pin" cx="934.5794392519798" cy="624.9161845422002" r="3.560302625724px" stroke-width="3.560302625724px" fill="none" stroke="rgb(132, 0, 0)"/></g><g class="schematic-port-hover sch-port-hover" data-schematic-port-id="source_port_0_0__stack1"><circle cx="142.41210502838976" cy="179.8783563267002" r="7.120605251448" fill="red" opacity="0"/></g><g class="schematic-port-hover sch-port-hover" data-schematic-port-id="source_port_1_0__stack1"><circle cx="814.9541566805533" cy="192.399806644122" r="7.120605251448" fill="red" opacity="0"/></g><g class="schematic-port-hover sch-port-hover" data-schematic-port-id="source_port_1_1__stack1"><circle cx="957.3662617095133" cy="178.15859614122587" r="7.120605251448" fill="red" opacity="0"/></g><g class="schematic-port-hover sch-port-hover" data-schematic-port-id="source_port_2_0__stack1"><circle cx="816.2959268650682" cy="645.8311745068766" r="7.120605251448" fill="red" opacity="0"/></g><g class="schematic-port-hover sch-port-hover" data-schematic-port-id="source_port_2_1__stack1"><circle cx="958.7080318940282" cy="624.4693587525326" r="7.120605251448" fill="red" opacity="0"/></g><path class="net-label sch-net-label" data-circuit-json-type="schematic_net_label" data-schematic-net-label-id="schematic_net_label_0__stack1" d="
|
|
72
|
+
M 106.80907877114987,179.8783563267002
|
|
73
|
+
L 89.00756564252987,170.2655392372454
|
|
74
|
+
L 89.00756564252987,109.2182168814979
|
|
75
|
+
L 124.61059189976987,109.2182168814979
|
|
76
|
+
L 124.61059189976987,170.2655392372454
|
|
77
|
+
Z
|
|
78
|
+
" fill="rgba(255, 255, 255, 0.6)" stroke="rgb(132, 0, 0)" stroke-width="3.560302625724px"/><text class="net-label-text sch-net-label-text" data-circuit-json-type="schematic_net_label" data-schematic-net-label-id="schematic_net_label_0__stack1" x="106.80907877114987" y="163.85699451094223" fill="rgb(132, 0, 0)" text-anchor="start" dominant-baseline="central" font-family="sans-serif" font-variant-numeric="tabular-nums" font-size="32.042723631516px" transform="rotate(-90 106.80907877114987 163.85699451094223)">XX</text><path class="net-label sch-net-label" data-circuit-json-type="schematic_net_label" data-schematic-net-label-id="schematic_net_label_1__stack1" d="
|
|
79
|
+
M 1018.335558522137,179.8783563267002
|
|
80
|
+
L 1000.5340453935171,170.2655392372454
|
|
81
|
+
L 1000.5340453935171,109.2182168814979
|
|
82
|
+
L 1036.137071650757,109.2182168814979
|
|
83
|
+
L 1036.137071650757,170.2655392372454
|
|
84
|
+
Z
|
|
85
|
+
" fill="rgba(255, 255, 255, 0.6)" stroke="rgb(132, 0, 0)" stroke-width="3.560302625724px"/><text class="net-label-text sch-net-label-text" data-circuit-json-type="schematic_net_label" data-schematic-net-label-id="schematic_net_label_1__stack1" x="1018.335558522137" y="163.85699451094223" fill="rgb(132, 0, 0)" text-anchor="start" dominant-baseline="central" font-family="sans-serif" font-variant-numeric="tabular-nums" font-size="32.042723631516px" transform="rotate(-90 1018.335558522137 163.85699451094223)">XX</text><path class="net-label sch-net-label" data-circuit-json-type="schematic_net_label" data-schematic-net-label-id="schematic_net_label_2__stack1" d="
|
|
86
|
+
M 934.5794392519799,624.9161845422001
|
|
87
|
+
L 944.1922563414347,607.1146714135801
|
|
88
|
+
L 1108.607031597369,607.1146714135801
|
|
89
|
+
L 1108.607031597369,642.71769767082
|
|
90
|
+
L 944.1922563414347,642.71769767082
|
|
91
|
+
Z
|
|
92
|
+
" fill="rgba(255, 255, 255, 0.6)" stroke="rgb(132, 0, 0)" stroke-width="3.560302625724px"/><text class="net-label-text sch-net-label-text" data-circuit-json-type="schematic_net_label" data-schematic-net-label-id="schematic_net_label_2__stack1" x="950.600801067738" y="624.9161845422001" fill="rgb(132, 0, 0)" text-anchor="start" dominant-baseline="central" font-family="sans-serif" font-variant-numeric="tabular-nums" font-size="32.042723631516px" transform="">NEUTRAL</text>
|
|
93
|
+
</g>
|
|
94
|
+
</svg>
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
{
|
|
2
|
+
"chips": [
|
|
3
|
+
{
|
|
4
|
+
"chipId": "J1",
|
|
5
|
+
"center": { "x": -13, "y": 6 },
|
|
6
|
+
"width": 1.3,
|
|
7
|
+
"height": 0.4,
|
|
8
|
+
"pins": [
|
|
9
|
+
{
|
|
10
|
+
"pinId": "J1.1",
|
|
11
|
+
"x": -14.05,
|
|
12
|
+
"y": 6,
|
|
13
|
+
"_facingDirection": "x-"
|
|
14
|
+
}
|
|
15
|
+
]
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"chipId": "F1",
|
|
19
|
+
"symbolName": "fuse_horz",
|
|
20
|
+
"center": { "x": -10.17, "y": 6.115 },
|
|
21
|
+
"width": 0.74,
|
|
22
|
+
"height": 0.39,
|
|
23
|
+
"pins": [
|
|
24
|
+
{
|
|
25
|
+
"pinId": "F1.1",
|
|
26
|
+
"x": -10.4,
|
|
27
|
+
"y": 6,
|
|
28
|
+
"_facingDirection": "x-"
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
"pinId": "F1.2",
|
|
32
|
+
"x": -9.6,
|
|
33
|
+
"y": 6,
|
|
34
|
+
"_facingDirection": "x+"
|
|
35
|
+
}
|
|
36
|
+
]
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
"chipId": "RV1",
|
|
40
|
+
"symbolName": "varistor_horz",
|
|
41
|
+
"center": { "x": -10.195, "y": 3.615 },
|
|
42
|
+
"width": 0.79,
|
|
43
|
+
"height": 0.47,
|
|
44
|
+
"pins": [
|
|
45
|
+
{
|
|
46
|
+
"pinId": "RV1.1",
|
|
47
|
+
"x": -10.4,
|
|
48
|
+
"y": 3.5,
|
|
49
|
+
"_facingDirection": "x-"
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
"pinId": "RV1.2",
|
|
53
|
+
"x": -9.6,
|
|
54
|
+
"y": 3.5,
|
|
55
|
+
"_facingDirection": "x+"
|
|
56
|
+
}
|
|
57
|
+
]
|
|
58
|
+
}
|
|
59
|
+
],
|
|
60
|
+
"directConnections": [
|
|
61
|
+
{
|
|
62
|
+
"netId": "LINE",
|
|
63
|
+
"pinIds": ["J1.1", "F1.1"]
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
"netId": "LINE_FUSED",
|
|
67
|
+
"pinIds": ["F1.2", "RV1.1"]
|
|
68
|
+
}
|
|
69
|
+
],
|
|
70
|
+
"netConnections": [
|
|
71
|
+
{
|
|
72
|
+
"netId": "NEUTRAL",
|
|
73
|
+
"netLabelText": "NEUTRAL",
|
|
74
|
+
"netLabelWidth": 0.84,
|
|
75
|
+
"pinIds": ["RV1.2"]
|
|
76
|
+
}
|
|
77
|
+
],
|
|
78
|
+
"availableNetLabelOrientations": {
|
|
79
|
+
"NEUTRAL": ["x+"]
|
|
80
|
+
},
|
|
81
|
+
"maxMspPairDistance": 100
|
|
82
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { expect, test } from "bun:test"
|
|
2
|
+
import { getOutputLabelCollisions } from "lib/solvers/InlineNetLabelSolver/getOutputLabelCollisions"
|
|
2
3
|
import { SchematicTracePipelineSolver } from "lib/solvers/SchematicTracePipelineSolver/SchematicTracePipelineSolver"
|
|
3
4
|
import "tests/fixtures/matcher"
|
|
4
5
|
import inputProblem from "./assets/repro-mouse-switch-ground-unnecessary-jog.input.json"
|
|
@@ -11,5 +12,19 @@ test("repro unnecessary jog in mouse switch ground trunk", () => {
|
|
|
11
12
|
|
|
12
13
|
solver.solve()
|
|
13
14
|
|
|
15
|
+
const inlineOutput = solver.inlineNetLabelSolver!.getOutput()
|
|
16
|
+
const groundLabel = inlineOutput.netLabelPlacements.find(
|
|
17
|
+
(label) => label.netId === "GND",
|
|
18
|
+
)
|
|
19
|
+
expect(groundLabel?.orientation).toBe("y-")
|
|
20
|
+
expect(
|
|
21
|
+
inlineOutput.inlineNetLabelPlacements.some(
|
|
22
|
+
(label) => label.netId === "RIGHT",
|
|
23
|
+
),
|
|
24
|
+
).toBe(true)
|
|
25
|
+
expect(
|
|
26
|
+
inlineOutput.netLabelPlacements.some((label) => label.netId === "RIGHT"),
|
|
27
|
+
).toBe(false)
|
|
28
|
+
expect(getOutputLabelCollisions(inlineOutput)).toEqual([])
|
|
14
29
|
expect(solver).toMatchSolverSnapshot(import.meta.path)
|
|
15
30
|
})
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { expect, test } from "bun:test"
|
|
2
|
+
import { SchematicTracePipelineSolver } from "lib/solvers/SchematicTracePipelineSolver/SchematicTracePipelineSolver"
|
|
3
|
+
import type { InputProblem } from "lib/types/InputProblem"
|
|
4
|
+
import "tests/fixtures/matcher"
|
|
5
|
+
import inputProblemJson from "./assets/repro-trace-endpoints-stop-at-component-boundary.input.json"
|
|
6
|
+
|
|
7
|
+
const inputProblem: InputProblem = JSON.parse(JSON.stringify(inputProblemJson))
|
|
8
|
+
|
|
9
|
+
// F1 and RV1 have ports inside their text-expanded component bounds. The
|
|
10
|
+
// routed traces currently stop at the lower bounds instead of reaching the
|
|
11
|
+
// original left-facing port coordinates.
|
|
12
|
+
test("trace endpoints stop at component boundaries before reaching target ports", () => {
|
|
13
|
+
const solver = new SchematicTracePipelineSolver(inputProblem, {
|
|
14
|
+
hideRatsNet: true,
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
solver.solve()
|
|
18
|
+
|
|
19
|
+
expect(solver.schematicTraceLinesSolver!.solvedTracePaths).toHaveLength(2)
|
|
20
|
+
expect(solver).toMatchSolverSnapshot(import.meta.path)
|
|
21
|
+
})
|