@tscircuit/schematic-trace-solver 0.0.80 → 0.0.81
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 -1
- package/dist/index.js +50 -5
- package/lib/solvers/AvailableNetOrientationSolver/AvailableNetOrientationSolver.ts +64 -4
- package/lib/solvers/AvailableNetOrientationSolver/types.ts +1 -0
- package/package.json +1 -1
- package/tests/examples/__snapshots__/example46.snap.svg +4 -4
- package/tests/repros/__snapshots__/bugreport-001-gnd-overlap.snap.svg +219 -0
- package/tests/repros/assets/bugreport-001-gnd-overlap.input.json +163 -0
- package/tests/repros/bugreport-001-gnd-overlap.test.ts +16 -0
package/dist/index.d.ts
CHANGED
|
@@ -694,7 +694,7 @@ type CandidateLabel = {
|
|
|
694
694
|
width: number;
|
|
695
695
|
height: number;
|
|
696
696
|
};
|
|
697
|
-
type CandidateStatus$2 = "valid" | "chip-collision" | "text-collision" | "trace-collision" | "netlabel-collision";
|
|
697
|
+
type CandidateStatus$2 = "valid" | "chip-collision" | "text-collision" | "trace-collision" | "trace-clearance-violation" | "netlabel-collision";
|
|
698
698
|
type CandidatePhase = "rotate" | "shift" | "lateral-shift";
|
|
699
699
|
type EvaluatedCandidate = CandidateLabel & {
|
|
700
700
|
status: CandidateStatus$2;
|
|
@@ -758,6 +758,11 @@ declare class AvailableNetOrientationSolver extends BaseSolver {
|
|
|
758
758
|
private getNetLabelHeight;
|
|
759
759
|
private getCandidateStatus;
|
|
760
760
|
private getBoundsStatus;
|
|
761
|
+
private isTraceTooCloseToLabel;
|
|
762
|
+
private getLabelTraceClearanceBounds;
|
|
763
|
+
private shouldCheckTraceClearanceForLabel;
|
|
764
|
+
private hasRoutedLabelOnSameNet;
|
|
765
|
+
private isPortOnlyLabel;
|
|
761
766
|
private intersectsAnyOtherNetLabel;
|
|
762
767
|
private sharesChipBoundary;
|
|
763
768
|
private getChipSideForPoint;
|
package/dist/index.js
CHANGED
|
@@ -6167,6 +6167,7 @@ var ensureGraphicsArrays = (graphics) => {
|
|
|
6167
6167
|
};
|
|
6168
6168
|
|
|
6169
6169
|
// lib/solvers/AvailableNetOrientationSolver/AvailableNetOrientationSolver.ts
|
|
6170
|
+
var LABEL_TRACE_CLEARANCE = 0.1;
|
|
6170
6171
|
var AvailableNetOrientationSolver = class extends BaseSolver {
|
|
6171
6172
|
inputProblem;
|
|
6172
6173
|
traces;
|
|
@@ -6580,10 +6581,15 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
|
|
|
6580
6581
|
}
|
|
6581
6582
|
getCandidateStatus(params) {
|
|
6582
6583
|
const { candidate, label, labelIndex, phase } = params;
|
|
6583
|
-
const boundsStatus = this.getBoundsStatus(
|
|
6584
|
-
getRectBounds(
|
|
6585
|
-
|
|
6586
|
-
|
|
6584
|
+
const boundsStatus = this.getBoundsStatus({
|
|
6585
|
+
bounds: getRectBounds(
|
|
6586
|
+
candidate.center,
|
|
6587
|
+
candidate.width,
|
|
6588
|
+
candidate.height
|
|
6589
|
+
),
|
|
6590
|
+
labelIndex,
|
|
6591
|
+
label
|
|
6592
|
+
});
|
|
6587
6593
|
if (boundsStatus !== "valid") return boundsStatus;
|
|
6588
6594
|
const connectorTrace = this.getCandidateConnectorTrace(label, {
|
|
6589
6595
|
anchorPoint: candidate.anchorPoint,
|
|
@@ -6607,7 +6613,8 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
|
|
|
6607
6613
|
}
|
|
6608
6614
|
return "valid";
|
|
6609
6615
|
}
|
|
6610
|
-
getBoundsStatus(
|
|
6616
|
+
getBoundsStatus(candidateBoundsCheck) {
|
|
6617
|
+
const { bounds, labelIndex, label } = candidateBoundsCheck;
|
|
6611
6618
|
if (this.chipObstacleSpatialIndex.getChipsInBounds(bounds).length > 0) {
|
|
6612
6619
|
return "chip-collision";
|
|
6613
6620
|
}
|
|
@@ -6620,11 +6627,49 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
|
|
|
6620
6627
|
if (traceCrossesBoundsInterior(bounds, this.traceMap)) {
|
|
6621
6628
|
return "trace-collision";
|
|
6622
6629
|
}
|
|
6630
|
+
if (this.isTraceTooCloseToLabel(bounds, label)) {
|
|
6631
|
+
return "trace-clearance-violation";
|
|
6632
|
+
}
|
|
6623
6633
|
if (this.intersectsAnyOtherNetLabel(bounds, labelIndex)) {
|
|
6624
6634
|
return "netlabel-collision";
|
|
6625
6635
|
}
|
|
6626
6636
|
return "valid";
|
|
6627
6637
|
}
|
|
6638
|
+
isTraceTooCloseToLabel(bounds, label) {
|
|
6639
|
+
if (!this.shouldCheckTraceClearanceForLabel(label)) return false;
|
|
6640
|
+
const clearanceBounds = this.getLabelTraceClearanceBounds(bounds);
|
|
6641
|
+
for (const trace of Object.values(this.traceMap)) {
|
|
6642
|
+
if (trace.globalConnNetId === label.globalConnNetId) continue;
|
|
6643
|
+
if (tracePathIntersectsBounds(trace.tracePath, clearanceBounds)) {
|
|
6644
|
+
return true;
|
|
6645
|
+
}
|
|
6646
|
+
}
|
|
6647
|
+
return false;
|
|
6648
|
+
}
|
|
6649
|
+
getLabelTraceClearanceBounds(bounds) {
|
|
6650
|
+
return {
|
|
6651
|
+
minX: bounds.minX - LABEL_TRACE_CLEARANCE,
|
|
6652
|
+
minY: bounds.minY - LABEL_TRACE_CLEARANCE,
|
|
6653
|
+
maxX: bounds.maxX + LABEL_TRACE_CLEARANCE,
|
|
6654
|
+
maxY: bounds.maxY + LABEL_TRACE_CLEARANCE
|
|
6655
|
+
};
|
|
6656
|
+
}
|
|
6657
|
+
shouldCheckTraceClearanceForLabel(label) {
|
|
6658
|
+
if (!this.isPortOnlyLabel(label)) return false;
|
|
6659
|
+
if (!this.hasRoutedLabelOnSameNet(label)) return false;
|
|
6660
|
+
const orientations = this.getAvailableOrientations(label);
|
|
6661
|
+
return orientations.length === 1;
|
|
6662
|
+
}
|
|
6663
|
+
hasRoutedLabelOnSameNet(label) {
|
|
6664
|
+
for (const otherLabel of this.outputNetLabelPlacements) {
|
|
6665
|
+
if (otherLabel.globalConnNetId !== label.globalConnNetId) continue;
|
|
6666
|
+
if (otherLabel.mspConnectionPairIds.length > 0) return true;
|
|
6667
|
+
}
|
|
6668
|
+
return false;
|
|
6669
|
+
}
|
|
6670
|
+
isPortOnlyLabel(label) {
|
|
6671
|
+
return label.mspConnectionPairIds.length === 0;
|
|
6672
|
+
}
|
|
6628
6673
|
intersectsAnyOtherNetLabel(bounds, labelIndex) {
|
|
6629
6674
|
for (let i = 0; i < this.outputNetLabelPlacements.length; i++) {
|
|
6630
6675
|
if (i === labelIndex) continue;
|
|
@@ -38,6 +38,8 @@ import type {
|
|
|
38
38
|
import { visualizeAvailableNetOrientationSolver } from "./visualize"
|
|
39
39
|
import { rectIntersectsAnyTextBox } from "lib/utils/textBoxBounds"
|
|
40
40
|
|
|
41
|
+
const LABEL_TRACE_CLEARANCE = 0.1
|
|
42
|
+
|
|
41
43
|
export class AvailableNetOrientationSolver extends BaseSolver {
|
|
42
44
|
inputProblem: InputProblem
|
|
43
45
|
traces: SolvedTracePath[]
|
|
@@ -606,10 +608,15 @@ export class AvailableNetOrientationSolver extends BaseSolver {
|
|
|
606
608
|
phase: CandidatePhase
|
|
607
609
|
}) {
|
|
608
610
|
const { candidate, label, labelIndex, phase } = params
|
|
609
|
-
const boundsStatus = this.getBoundsStatus(
|
|
610
|
-
getRectBounds(
|
|
611
|
+
const boundsStatus = this.getBoundsStatus({
|
|
612
|
+
bounds: getRectBounds(
|
|
613
|
+
candidate.center,
|
|
614
|
+
candidate.width,
|
|
615
|
+
candidate.height,
|
|
616
|
+
),
|
|
611
617
|
labelIndex,
|
|
612
|
-
|
|
618
|
+
label,
|
|
619
|
+
})
|
|
613
620
|
if (boundsStatus !== "valid") return boundsStatus
|
|
614
621
|
|
|
615
622
|
const connectorTrace = this.getCandidateConnectorTrace(label, {
|
|
@@ -640,7 +647,13 @@ export class AvailableNetOrientationSolver extends BaseSolver {
|
|
|
640
647
|
return "valid"
|
|
641
648
|
}
|
|
642
649
|
|
|
643
|
-
private getBoundsStatus(
|
|
650
|
+
private getBoundsStatus(candidateBoundsCheck: {
|
|
651
|
+
bounds: Bounds
|
|
652
|
+
labelIndex: number
|
|
653
|
+
label: NetLabelPlacement
|
|
654
|
+
}): CandidateStatus {
|
|
655
|
+
const { bounds, labelIndex, label } = candidateBoundsCheck
|
|
656
|
+
|
|
644
657
|
if (this.chipObstacleSpatialIndex.getChipsInBounds(bounds).length > 0) {
|
|
645
658
|
return "chip-collision"
|
|
646
659
|
}
|
|
@@ -653,12 +666,59 @@ export class AvailableNetOrientationSolver extends BaseSolver {
|
|
|
653
666
|
if (traceCrossesBoundsInterior(bounds, this.traceMap)) {
|
|
654
667
|
return "trace-collision"
|
|
655
668
|
}
|
|
669
|
+
if (this.isTraceTooCloseToLabel(bounds, label)) {
|
|
670
|
+
return "trace-clearance-violation"
|
|
671
|
+
}
|
|
656
672
|
if (this.intersectsAnyOtherNetLabel(bounds, labelIndex)) {
|
|
657
673
|
return "netlabel-collision"
|
|
658
674
|
}
|
|
659
675
|
return "valid"
|
|
660
676
|
}
|
|
661
677
|
|
|
678
|
+
private isTraceTooCloseToLabel(bounds: Bounds, label: NetLabelPlacement) {
|
|
679
|
+
if (!this.shouldCheckTraceClearanceForLabel(label)) return false
|
|
680
|
+
|
|
681
|
+
const clearanceBounds = this.getLabelTraceClearanceBounds(bounds)
|
|
682
|
+
for (const trace of Object.values(this.traceMap)) {
|
|
683
|
+
if (trace.globalConnNetId === label.globalConnNetId) continue
|
|
684
|
+
if (tracePathIntersectsBounds(trace.tracePath, clearanceBounds)) {
|
|
685
|
+
return true
|
|
686
|
+
}
|
|
687
|
+
}
|
|
688
|
+
|
|
689
|
+
return false
|
|
690
|
+
}
|
|
691
|
+
|
|
692
|
+
private getLabelTraceClearanceBounds(bounds: Bounds): Bounds {
|
|
693
|
+
return {
|
|
694
|
+
minX: bounds.minX - LABEL_TRACE_CLEARANCE,
|
|
695
|
+
minY: bounds.minY - LABEL_TRACE_CLEARANCE,
|
|
696
|
+
maxX: bounds.maxX + LABEL_TRACE_CLEARANCE,
|
|
697
|
+
maxY: bounds.maxY + LABEL_TRACE_CLEARANCE,
|
|
698
|
+
}
|
|
699
|
+
}
|
|
700
|
+
|
|
701
|
+
private shouldCheckTraceClearanceForLabel(label: NetLabelPlacement) {
|
|
702
|
+
if (!this.isPortOnlyLabel(label)) return false
|
|
703
|
+
if (!this.hasRoutedLabelOnSameNet(label)) return false
|
|
704
|
+
|
|
705
|
+
const orientations = this.getAvailableOrientations(label)
|
|
706
|
+
return orientations.length === 1
|
|
707
|
+
}
|
|
708
|
+
|
|
709
|
+
private hasRoutedLabelOnSameNet(label: NetLabelPlacement) {
|
|
710
|
+
for (const otherLabel of this.outputNetLabelPlacements) {
|
|
711
|
+
if (otherLabel.globalConnNetId !== label.globalConnNetId) continue
|
|
712
|
+
if (otherLabel.mspConnectionPairIds.length > 0) return true
|
|
713
|
+
}
|
|
714
|
+
|
|
715
|
+
return false
|
|
716
|
+
}
|
|
717
|
+
|
|
718
|
+
private isPortOnlyLabel(label: NetLabelPlacement) {
|
|
719
|
+
return label.mspConnectionPairIds.length === 0
|
|
720
|
+
}
|
|
721
|
+
|
|
662
722
|
private intersectsAnyOtherNetLabel(bounds: Bounds, labelIndex: number) {
|
|
663
723
|
for (let i = 0; i < this.outputNetLabelPlacements.length; i++) {
|
|
664
724
|
if (i === labelIndex) continue
|
package/package.json
CHANGED
|
@@ -86,7 +86,7 @@ orientation: x-" data-x="-1.485" data-y="-0.2" cx="256.11911623439005" cy="288.2
|
|
|
86
86
|
</g>
|
|
87
87
|
<g>
|
|
88
88
|
<circle data-type="point" data-label="anchorPoint
|
|
89
|
-
orientation: y-" data-x="-1.3860000000000001" data-y="-0.
|
|
89
|
+
orientation: y-" data-x="-1.3860000000000001" data-y="-0.601" cx="261.4447646493756" cy="309.8328530259365" r="3" fill="hsl(40, 100%, 50%, 0.9)" />
|
|
90
90
|
</g>
|
|
91
91
|
<g>
|
|
92
92
|
<circle data-type="point" data-label="anchorPoint
|
|
@@ -218,10 +218,10 @@ orientation: x-" data-x="2.6749999999999994" data-y="-2.7362499999999996" cx="47
|
|
|
218
218
|
<polyline data-points="-1.2850000000000001,0.20000000000000018 -1.866,0.20000000000000018 -1.866,-4.440892098500626e-16 -2.87,-4.440892098500626e-16 -2.87,0.19999999999999973" data-type="line" data-label="" points="266.8780019212296,266.74351585014404 235.62343900096062,266.74351585014404 235.62343900096062,277.5024015369836 181.61383285302594,277.5024015369836 181.61383285302594,266.74351585014404" fill="none" stroke="purple" stroke-width="1" />
|
|
219
219
|
</g>
|
|
220
220
|
<g>
|
|
221
|
-
<polyline data-points="-1.2850000000000001,-0.2 -1.485,-0.2 -1.485,-0.
|
|
221
|
+
<polyline data-points="-1.2850000000000001,-0.2 -1.485,-0.2 -1.485,-0.5 -2.166,-0.5 -2.166,0.5 -1.485,0.5 -1.485,0.2 -1.2850000000000001,0.2" data-type="line" data-label="" points="266.8780019212296,288.26128722382316 256.11911623439005,288.26128722382316 256.11911623439005,304.39961575408256 219.48511047070127,304.39961575408256 219.48511047070127,250.60518731988466 256.11911623439005,250.60518731988466 256.11911623439005,266.74351585014404 266.8780019212296,266.74351585014404" fill="none" stroke="purple" stroke-width="1" />
|
|
222
222
|
</g>
|
|
223
223
|
<g>
|
|
224
|
-
<polyline data-points="-1.2850000000000001,0 -1.3860000000000001,0 -1.3860000000000001,-0.
|
|
224
|
+
<polyline data-points="-1.2850000000000001,0 -1.3860000000000001,0 -1.3860000000000001,-0.601" data-type="line" data-label="" points="266.8780019212296,277.5024015369836 261.4447646493756,277.5024015369836 261.4447646493756,309.8328530259365" fill="none" stroke="purple" stroke-width="1" />
|
|
225
225
|
</g>
|
|
226
226
|
<g>
|
|
227
227
|
<rect data-type="rect" data-label="schematic_component_0" data-x="-2.71" data-y="0.7199999999999998" x="167.08933717579254" y="210.79731027857824" width="46.26320845341016" height="55.9462055715658" fill="hsl(24, 100%, 50%, 0.8)" stroke="black" stroke-width="0.018589285714285714" />
|
|
@@ -257,7 +257,7 @@ globalConnNetId: connectivity_net1" data-x="-1.725" data-y="-0.2" x="230.2977905
|
|
|
257
257
|
</g>
|
|
258
258
|
<g>
|
|
259
259
|
<rect data-type="rect" data-label="netId: GND
|
|
260
|
-
globalConnNetId: connectivity_net2" data-x="-1.3860000000000001" data-y="-0.
|
|
260
|
+
globalConnNetId: connectivity_net2" data-x="-1.3860000000000001" data-y="-0.841" x="256.0653218059558" y="309.8328530259365" width="10.758885686839562" height="25.821325648414984" fill="#00000066" stroke="#000000" stroke-width="0.018589285714285714" />
|
|
261
261
|
</g>
|
|
262
262
|
<g>
|
|
263
263
|
<rect data-type="rect" data-label="netId: GND
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
<svg width="640" height="640" viewBox="0 0 640 640" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<rect width="100%" height="100%" fill="white" />
|
|
3
|
+
<g>
|
|
4
|
+
<circle data-type="point" data-label="BT1.1
|
|
5
|
+
x+" data-x="-2.6" data-y="2.2" cx="84.13793103448276" cy="230.89655172413794" r="3" fill="hsl(114, 100%, 50%, 0.8)" />
|
|
6
|
+
</g>
|
|
7
|
+
<g>
|
|
8
|
+
<circle data-type="point" data-label="BT1.2
|
|
9
|
+
x+" data-x="-2.6" data-y="1.8" cx="84.13793103448276" cy="252.9655172413793" r="3" fill="hsl(115, 100%, 50%, 0.8)" />
|
|
10
|
+
</g>
|
|
11
|
+
<g>
|
|
12
|
+
<circle data-type="point" data-label="SW1.1
|
|
13
|
+
x-" data-x="-0.5" data-y="2" cx="200" cy="241.93103448275863" r="3" fill="hsl(104, 100%, 50%, 0.8)" />
|
|
14
|
+
</g>
|
|
15
|
+
<g>
|
|
16
|
+
<circle data-type="point" data-label="SW1.2
|
|
17
|
+
x+" data-x="0.5" data-y="2" cx="255.17241379310343" cy="241.93103448275863" r="3" fill="hsl(105, 100%, 50%, 0.8)" />
|
|
18
|
+
</g>
|
|
19
|
+
<g>
|
|
20
|
+
<circle data-type="point" data-label="R1.1
|
|
21
|
+
x-" data-x="2.45" data-y="1" cx="362.7586206896552" cy="297.1034482758621" r="3" fill="hsl(226, 100%, 50%, 0.8)" />
|
|
22
|
+
</g>
|
|
23
|
+
<g>
|
|
24
|
+
<circle data-type="point" data-label="R1.2
|
|
25
|
+
x+" data-x="3.55" data-y="1" cx="423.44827586206895" cy="297.1034482758621" r="3" fill="hsl(227, 100%, 50%, 0.8)" />
|
|
26
|
+
</g>
|
|
27
|
+
<g>
|
|
28
|
+
<circle data-type="point" data-label="R2.1
|
|
29
|
+
x-" data-x="2.45" data-y="-1" cx="362.7586206896552" cy="407.44827586206895" r="3" fill="hsl(107, 100%, 50%, 0.8)" />
|
|
30
|
+
</g>
|
|
31
|
+
<g>
|
|
32
|
+
<circle data-type="point" data-label="R2.2
|
|
33
|
+
x+" data-x="3.55" data-y="-1" cx="423.44827586206895" cy="407.44827586206895" r="3" fill="hsl(108, 100%, 50%, 0.8)" />
|
|
34
|
+
</g>
|
|
35
|
+
<g>
|
|
36
|
+
<circle data-type="point" data-label="D1.1
|
|
37
|
+
x-" data-x="5.45" data-y="1" cx="528.2758620689655" cy="297.1034482758621" r="3" fill="hsl(32, 100%, 50%, 0.8)" />
|
|
38
|
+
</g>
|
|
39
|
+
<g>
|
|
40
|
+
<circle data-type="point" data-label="D1.2
|
|
41
|
+
x+" data-x="6.55" data-y="1" cx="588.9655172413793" cy="297.1034482758621" r="3" fill="hsl(33, 100%, 50%, 0.8)" />
|
|
42
|
+
</g>
|
|
43
|
+
<g>
|
|
44
|
+
<circle data-type="point" data-label="D2.1
|
|
45
|
+
x-" data-x="5.45" data-y="-1" cx="528.2758620689655" cy="407.44827586206895" r="3" fill="hsl(273, 100%, 50%, 0.8)" />
|
|
46
|
+
</g>
|
|
47
|
+
<g>
|
|
48
|
+
<circle data-type="point" data-label="D2.2
|
|
49
|
+
x+" data-x="6.55" data-y="-1" cx="588.9655172413793" cy="407.44827586206895" r="3" fill="hsl(274, 100%, 50%, 0.8)" />
|
|
50
|
+
</g>
|
|
51
|
+
<g>
|
|
52
|
+
<circle data-type="point" data-label="anchorPoint
|
|
53
|
+
orientation: y+" data-x="-2.075" data-y="2.2" cx="113.10344827586206" cy="230.89655172413794" r="3" fill="hsl(40, 100%, 50%, 0.9)" />
|
|
54
|
+
</g>
|
|
55
|
+
<g>
|
|
56
|
+
<circle data-type="point" data-label="anchorPoint
|
|
57
|
+
orientation: y-" data-x="-2.499" data-y="1.5990000000000002" cx="89.7103448275862" cy="264.0551724137931" r="3" fill="hsl(40, 100%, 50%, 0.9)" />
|
|
58
|
+
</g>
|
|
59
|
+
<g>
|
|
60
|
+
<circle data-type="point" data-label="anchorPoint
|
|
61
|
+
orientation: y-" data-x="6.65" data-y="-1" cx="594.4827586206897" cy="407.44827586206895" r="3" fill="hsl(40, 100%, 50%, 0.9)" />
|
|
62
|
+
</g>
|
|
63
|
+
<g>
|
|
64
|
+
<circle data-type="point" data-label="anchorPoint
|
|
65
|
+
orientation: y-" data-x="2.25" data-y="-1" cx="351.7241379310345" cy="407.44827586206895" r="3" fill="hsl(40, 100%, 50%, 0.9)" />
|
|
66
|
+
</g>
|
|
67
|
+
<g>
|
|
68
|
+
<circle data-type="point" data-label="anchorPoint
|
|
69
|
+
orientation: y+" data-x="4.5" data-y="1" cx="475.8620689655172" cy="297.1034482758621" r="3" fill="hsl(40, 100%, 50%, 0.9)" />
|
|
70
|
+
</g>
|
|
71
|
+
<g>
|
|
72
|
+
<circle data-type="point" data-label="anchorPoint
|
|
73
|
+
orientation: y+" data-x="4.5" data-y="-1" cx="475.8620689655172" cy="407.44827586206895" r="3" fill="hsl(40, 100%, 50%, 0.9)" />
|
|
74
|
+
</g>
|
|
75
|
+
<g>
|
|
76
|
+
<polyline data-points="-2.6,2.2 -0.5,2" data-type="line" data-label="" points="84.13793103448276,230.89655172413794 200,241.93103448275863" fill="none" stroke="hsl(0, 100%, 50%, 0.8)" stroke-width="1" />
|
|
77
|
+
</g>
|
|
78
|
+
<g>
|
|
79
|
+
<polyline data-points="0.5,2 2.45,1" data-type="line" data-label="" points="255.17241379310343,241.93103448275863 362.7586206896552,297.1034482758621" fill="none" stroke="hsl(304, 100%, 50%, 0.8)" stroke-width="1" />
|
|
80
|
+
</g>
|
|
81
|
+
<g>
|
|
82
|
+
<polyline data-points="0.5,2 2.45,-1" data-type="line" data-label="" points="255.17241379310343,241.93103448275863 362.7586206896552,407.44827586206895" fill="none" stroke="hsl(304, 100%, 50%, 0.8)" stroke-width="1" />
|
|
83
|
+
</g>
|
|
84
|
+
<g>
|
|
85
|
+
<polyline data-points="3.55,1 5.45,1" data-type="line" data-label="" points="423.44827586206895,297.1034482758621 528.2758620689655,297.1034482758621" fill="none" stroke="hsl(312, 100%, 50%, 0.8)" stroke-width="1" />
|
|
86
|
+
</g>
|
|
87
|
+
<g>
|
|
88
|
+
<polyline data-points="3.55,-1 5.45,-1" data-type="line" data-label="" points="423.44827586206895,407.44827586206895 528.2758620689655,407.44827586206895" fill="none" stroke="hsl(320, 100%, 50%, 0.8)" stroke-width="1" />
|
|
89
|
+
</g>
|
|
90
|
+
<g>
|
|
91
|
+
<polyline data-points="-2.6,1.8 6.55,1" data-type="line" data-label="" points="84.13793103448276,252.9655172413793 588.9655172413793,297.1034482758621" fill="none" stroke="hsl(157, 100%, 50%, 0.8)" stroke-width="1" stroke-dasharray="4 2" />
|
|
92
|
+
</g>
|
|
93
|
+
<g>
|
|
94
|
+
<polyline data-points="-2.6,1.8 6.55,-1" data-type="line" data-label="" points="84.13793103448276,252.9655172413793 588.9655172413793,407.44827586206895" fill="none" stroke="hsl(157, 100%, 50%, 0.8)" stroke-width="1" stroke-dasharray="4 2" />
|
|
95
|
+
</g>
|
|
96
|
+
<g>
|
|
97
|
+
<polyline data-points="6.55,1 6.55,-1" data-type="line" data-label="" points="588.9655172413793,297.1034482758621 588.9655172413793,407.44827586206895" fill="none" stroke="hsl(157, 100%, 50%, 0.8)" stroke-width="1" stroke-dasharray="4 2" />
|
|
98
|
+
</g>
|
|
99
|
+
<g>
|
|
100
|
+
<polyline data-points="-2.6,2.2 -1.55,2.2 -1.55,2 -0.5,2" data-type="line" data-label="" points="84.13793103448276,230.89655172413794 142.06896551724137,230.89655172413794 142.06896551724137,241.93103448275863 200,241.93103448275863" fill="none" stroke="purple" stroke-width="1" />
|
|
101
|
+
</g>
|
|
102
|
+
<g>
|
|
103
|
+
<polyline data-points="2.45,-1 2.25,-1 2.25,1 2.45,1" data-type="line" data-label="" points="362.7586206896552,407.44827586206895 351.7241379310345,407.44827586206895 351.7241379310345,297.1034482758621 362.7586206896552,297.1034482758621" fill="none" stroke="purple" stroke-width="1" />
|
|
104
|
+
</g>
|
|
105
|
+
<g>
|
|
106
|
+
<polyline data-points="0.5,2 1.475,2 1.475,1 2.45,1" data-type="line" data-label="" points="255.17241379310343,241.93103448275863 308.9655172413793,241.93103448275863 308.9655172413793,297.1034482758621 362.7586206896552,297.1034482758621" fill="none" stroke="purple" stroke-width="1" />
|
|
107
|
+
</g>
|
|
108
|
+
<g>
|
|
109
|
+
<polyline data-points="3.55,1 5.45,1" data-type="line" data-label="" points="423.44827586206895,297.1034482758621 528.2758620689655,297.1034482758621" fill="none" stroke="purple" stroke-width="1" />
|
|
110
|
+
</g>
|
|
111
|
+
<g>
|
|
112
|
+
<polyline data-points="3.55,-1 5.45,-1" data-type="line" data-label="" points="423.44827586206895,407.44827586206895 528.2758620689655,407.44827586206895" fill="none" stroke="purple" stroke-width="1" />
|
|
113
|
+
</g>
|
|
114
|
+
<g>
|
|
115
|
+
<polyline data-points="6.55,-1 6.75,-1 6.75,1 6.55,1" data-type="line" data-label="" points="588.9655172413793,407.44827586206895 600,407.44827586206895 600,297.1034482758621 588.9655172413793,297.1034482758621" fill="none" stroke="purple" stroke-width="1" />
|
|
116
|
+
</g>
|
|
117
|
+
<g>
|
|
118
|
+
<polyline data-points="-2.6,1.8 -2.499,1.8 -2.499,1.5990000000000002" data-type="line" data-label="" points="84.13793103448276,252.9655172413793 89.7103448275862,252.9655172413793 89.7103448275862,264.0551724137931" fill="none" stroke="purple" stroke-width="1" />
|
|
119
|
+
</g>
|
|
120
|
+
<g>
|
|
121
|
+
<rect data-type="rect" data-label="BT1" data-x="-3" data-y="2" x="40" y="219.86206896551727" width="44.13793103448276" height="44.13793103448273" fill="hsl(199, 100%, 50%, 0.8)" stroke="black" stroke-width="0.018125000000000002" />
|
|
122
|
+
</g>
|
|
123
|
+
<g>
|
|
124
|
+
<rect data-type="rect" data-label="SW1" data-x="0" data-y="2" x="200" y="219.86206896551727" width="55.17241379310343" height="44.13793103448273" fill="hsl(69, 100%, 50%, 0.8)" stroke="black" stroke-width="0.018125000000000002" />
|
|
125
|
+
</g>
|
|
126
|
+
<g>
|
|
127
|
+
<rect data-type="rect" data-label="R1" data-x="3" data-y="1" x="362.7586206896552" y="286.3748772413793" width="60.68965517241378" height="21.45714206896554" fill="hsl(71, 100%, 50%, 0.8)" stroke="black" stroke-width="0.018125000000000002" />
|
|
128
|
+
</g>
|
|
129
|
+
<g>
|
|
130
|
+
<rect data-type="rect" data-label="R2" data-x="3" data-y="-1" x="362.7586206896552" y="396.7197048275862" width="60.68965517241378" height="21.45714206896554" fill="hsl(72, 100%, 50%, 0.8)" stroke="black" stroke-width="0.018125000000000002" />
|
|
131
|
+
</g>
|
|
132
|
+
<g>
|
|
133
|
+
<rect data-type="rect" data-label="D1" data-x="6" data-y="1" x="528.2758620689655" y="286.3748772413793" width="60.689655172413836" height="21.45714206896554" fill="hsl(357, 100%, 50%, 0.8)" stroke="black" stroke-width="0.018125000000000002" />
|
|
134
|
+
</g>
|
|
135
|
+
<g>
|
|
136
|
+
<rect data-type="rect" data-label="D2" data-x="6" data-y="-1" x="528.2758620689655" y="396.7197048275862" width="60.689655172413836" height="21.45714206896554" fill="hsl(358, 100%, 50%, 0.8)" stroke="black" stroke-width="0.018125000000000002" />
|
|
137
|
+
</g>
|
|
138
|
+
<g>
|
|
139
|
+
<rect data-type="rect" data-label="netId: BT1.plus to SW1.in
|
|
140
|
+
globalConnNetId: connectivity_net0" data-x="-2.075" data-y="2.4250000000000003" x="107.5862068965517" y="206.06896551724137" width="11.034482758620712" height="24.82758620689657" fill="hsl(40, 100%, 50%, 0.35)" stroke="black" stroke-width="0.018125000000000002" />
|
|
141
|
+
</g>
|
|
142
|
+
<g>
|
|
143
|
+
<rect data-type="rect" data-label="netId: GND
|
|
144
|
+
globalConnNetId: connectivity_net4" data-x="-2.499" data-y="1.3590000000000002" x="84.19310344827585" y="264.0551724137931" width="11.034482758620697" height="26.48275862068965" fill="#00000066" stroke="#000000" stroke-width="0.018125000000000002" />
|
|
145
|
+
</g>
|
|
146
|
+
<g>
|
|
147
|
+
<rect data-type="rect" data-label="netId: GND
|
|
148
|
+
globalConnNetId: connectivity_net4" data-x="6.65" data-y="-1.24" x="588.9655172413793" y="407.44827586206895" width="11.034482758620697" height="26.48275862068965" fill="#00000066" stroke="#000000" stroke-width="0.018125000000000002" />
|
|
149
|
+
</g>
|
|
150
|
+
<g>
|
|
151
|
+
<rect data-type="rect" data-label="netId: SW1.out to R2.left
|
|
152
|
+
globalConnNetId: connectivity_net1" data-x="2.25" data-y="-1.225" x="346.2068965517241" y="407.44827586206895" width="11.034482758620697" height="24.82758620689657" fill="hsl(40, 100%, 50%, 0.35)" stroke="black" stroke-width="0.018125000000000002" />
|
|
153
|
+
</g>
|
|
154
|
+
<g>
|
|
155
|
+
<rect data-type="rect" data-label="netId: R1.right to D1.a
|
|
156
|
+
globalConnNetId: connectivity_net2" data-x="4.5" data-y="1.225" x="470.34482758620686" y="272.2758620689655" width="11.034482758620697" height="24.82758620689657" fill="hsl(40, 100%, 50%, 0.35)" stroke="black" stroke-width="0.018125000000000002" />
|
|
157
|
+
</g>
|
|
158
|
+
<g>
|
|
159
|
+
<rect data-type="rect" data-label="netId: R2.right to D2.a
|
|
160
|
+
globalConnNetId: connectivity_net3" data-x="4.5" data-y="-0.775" x="470.34482758620686" y="382.62068965517244" width="11.034482758620697" height="24.827586206896513" fill="hsl(40, 100%, 50%, 0.35)" stroke="black" stroke-width="0.018125000000000002" />
|
|
161
|
+
</g>
|
|
162
|
+
<g id="crosshair" style="display: none">
|
|
163
|
+
<line id="crosshair-h" y1="0" y2="640" stroke="#666" stroke-width="0.5" />
|
|
164
|
+
<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>
|
|
165
|
+
</g>
|
|
166
|
+
<script>
|
|
167
|
+
<![CDATA[
|
|
168
|
+
document.currentScript.parentElement.addEventListener('mousemove', (e) => {
|
|
169
|
+
const svg = e.currentTarget;
|
|
170
|
+
const rect = svg.getBoundingClientRect();
|
|
171
|
+
const x = e.clientX - rect.left;
|
|
172
|
+
const y = e.clientY - rect.top;
|
|
173
|
+
const crosshair = svg.getElementById('crosshair');
|
|
174
|
+
const h = svg.getElementById('crosshair-h');
|
|
175
|
+
const v = svg.getElementById('crosshair-v');
|
|
176
|
+
const coords = svg.getElementById('coordinates');
|
|
177
|
+
|
|
178
|
+
crosshair.style.display = 'block';
|
|
179
|
+
h.setAttribute('x1', '0');
|
|
180
|
+
h.setAttribute('x2', '640');
|
|
181
|
+
h.setAttribute('y1', y);
|
|
182
|
+
h.setAttribute('y2', y);
|
|
183
|
+
v.setAttribute('x1', x);
|
|
184
|
+
v.setAttribute('x2', x);
|
|
185
|
+
v.setAttribute('y1', '0');
|
|
186
|
+
v.setAttribute('y2', '640');
|
|
187
|
+
|
|
188
|
+
// Calculate real coordinates using inverse transformation
|
|
189
|
+
const matrix = {
|
|
190
|
+
"a": 55.172413793103445,
|
|
191
|
+
"c": 0,
|
|
192
|
+
"e": 227.58620689655172,
|
|
193
|
+
"b": 0,
|
|
194
|
+
"d": -55.172413793103445,
|
|
195
|
+
"f": 352.2758620689655
|
|
196
|
+
};
|
|
197
|
+
// Manually invert and apply the affine transform
|
|
198
|
+
// Since we only use translate and scale, we can directly compute:
|
|
199
|
+
// x' = (x - tx) / sx
|
|
200
|
+
// y' = (y - ty) / sy
|
|
201
|
+
const sx = matrix.a;
|
|
202
|
+
const sy = matrix.d;
|
|
203
|
+
const tx = matrix.e;
|
|
204
|
+
const ty = matrix.f;
|
|
205
|
+
const realPoint = {
|
|
206
|
+
x: (x - tx) / sx,
|
|
207
|
+
y: (y - ty) / sy // Flip y back since we used negative scale
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
coords.textContent = `(${realPoint.x.toFixed(2)}, ${realPoint.y.toFixed(2)})`;
|
|
211
|
+
coords.setAttribute('x', (x + 5).toString());
|
|
212
|
+
coords.setAttribute('y', (y - 5).toString());
|
|
213
|
+
});
|
|
214
|
+
document.currentScript.parentElement.addEventListener('mouseleave', () => {
|
|
215
|
+
document.currentScript.parentElement.getElementById('crosshair').style.display = 'none';
|
|
216
|
+
});
|
|
217
|
+
]]>
|
|
218
|
+
</script>
|
|
219
|
+
</svg>
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
{
|
|
2
|
+
"chips": [
|
|
3
|
+
{
|
|
4
|
+
"chipId": "BT1",
|
|
5
|
+
"center": {
|
|
6
|
+
"x": -3,
|
|
7
|
+
"y": 2
|
|
8
|
+
},
|
|
9
|
+
"width": 0.8,
|
|
10
|
+
"height": 0.8,
|
|
11
|
+
"pins": [
|
|
12
|
+
{
|
|
13
|
+
"pinId": "BT1.1",
|
|
14
|
+
"x": -2.6,
|
|
15
|
+
"y": 2.2
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"pinId": "BT1.2",
|
|
19
|
+
"x": -2.6,
|
|
20
|
+
"y": 1.8
|
|
21
|
+
}
|
|
22
|
+
]
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
"chipId": "SW1",
|
|
26
|
+
"center": {
|
|
27
|
+
"x": 0,
|
|
28
|
+
"y": 2
|
|
29
|
+
},
|
|
30
|
+
"width": 1,
|
|
31
|
+
"height": 0.8,
|
|
32
|
+
"pins": [
|
|
33
|
+
{
|
|
34
|
+
"pinId": "SW1.1",
|
|
35
|
+
"x": -0.5,
|
|
36
|
+
"y": 2
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
"pinId": "SW1.2",
|
|
40
|
+
"x": 0.5,
|
|
41
|
+
"y": 2
|
|
42
|
+
}
|
|
43
|
+
]
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
"chipId": "R1",
|
|
47
|
+
"center": {
|
|
48
|
+
"x": 3,
|
|
49
|
+
"y": 1
|
|
50
|
+
},
|
|
51
|
+
"width": 1.06,
|
|
52
|
+
"height": 0.3889107,
|
|
53
|
+
"pins": [
|
|
54
|
+
{
|
|
55
|
+
"pinId": "R1.1",
|
|
56
|
+
"x": 2.45,
|
|
57
|
+
"y": 1
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
"pinId": "R1.2",
|
|
61
|
+
"x": 3.55,
|
|
62
|
+
"y": 1
|
|
63
|
+
}
|
|
64
|
+
]
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
"chipId": "R2",
|
|
68
|
+
"center": {
|
|
69
|
+
"x": 3,
|
|
70
|
+
"y": -1
|
|
71
|
+
},
|
|
72
|
+
"width": 1.06,
|
|
73
|
+
"height": 0.3889107,
|
|
74
|
+
"pins": [
|
|
75
|
+
{
|
|
76
|
+
"pinId": "R2.1",
|
|
77
|
+
"x": 2.45,
|
|
78
|
+
"y": -1
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
"pinId": "R2.2",
|
|
82
|
+
"x": 3.55,
|
|
83
|
+
"y": -1
|
|
84
|
+
}
|
|
85
|
+
]
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
"chipId": "D1",
|
|
89
|
+
"center": {
|
|
90
|
+
"x": 6,
|
|
91
|
+
"y": 1
|
|
92
|
+
},
|
|
93
|
+
"width": 1.06,
|
|
94
|
+
"height": 0.3889107,
|
|
95
|
+
"pins": [
|
|
96
|
+
{
|
|
97
|
+
"pinId": "D1.1",
|
|
98
|
+
"x": 5.45,
|
|
99
|
+
"y": 1
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
"pinId": "D1.2",
|
|
103
|
+
"x": 6.55,
|
|
104
|
+
"y": 1
|
|
105
|
+
}
|
|
106
|
+
]
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
"chipId": "D2",
|
|
110
|
+
"center": {
|
|
111
|
+
"x": 6,
|
|
112
|
+
"y": -1
|
|
113
|
+
},
|
|
114
|
+
"width": 1.06,
|
|
115
|
+
"height": 0.3889107,
|
|
116
|
+
"pins": [
|
|
117
|
+
{
|
|
118
|
+
"pinId": "D2.1",
|
|
119
|
+
"x": 5.45,
|
|
120
|
+
"y": -1
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
"pinId": "D2.2",
|
|
124
|
+
"x": 6.55,
|
|
125
|
+
"y": -1
|
|
126
|
+
}
|
|
127
|
+
]
|
|
128
|
+
}
|
|
129
|
+
],
|
|
130
|
+
"directConnections": [
|
|
131
|
+
{
|
|
132
|
+
"pinIds": ["BT1.1", "SW1.1"],
|
|
133
|
+
"netId": "BT1.plus to SW1.in"
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
"pinIds": ["SW1.2", "R1.1"],
|
|
137
|
+
"netId": "SW1.out to R1.left"
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
"pinIds": ["SW1.2", "R2.1"],
|
|
141
|
+
"netId": "SW1.out to R2.left"
|
|
142
|
+
},
|
|
143
|
+
{
|
|
144
|
+
"pinIds": ["R1.2", "D1.1"],
|
|
145
|
+
"netId": "R1.right to D1.a"
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
"pinIds": ["R2.2", "D2.1"],
|
|
149
|
+
"netId": "R2.right to D2.a"
|
|
150
|
+
}
|
|
151
|
+
],
|
|
152
|
+
"netConnections": [
|
|
153
|
+
{
|
|
154
|
+
"netId": "GND",
|
|
155
|
+
"pinIds": ["BT1.2", "D1.2", "D2.2"],
|
|
156
|
+
"netLabelWidth": 0.48
|
|
157
|
+
}
|
|
158
|
+
],
|
|
159
|
+
"availableNetLabelOrientations": {
|
|
160
|
+
"GND": ["y-"]
|
|
161
|
+
},
|
|
162
|
+
"maxMspPairDistance": 8
|
|
163
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { expect, test } from "bun:test"
|
|
2
|
+
import { SchematicTracePipelineSolver } from "lib/solvers/SchematicTracePipelineSolver/SchematicTracePipelineSolver"
|
|
3
|
+
import inputProblem from "./assets/bugreport-001-gnd-overlap.input.json"
|
|
4
|
+
import "tests/fixtures/matcher"
|
|
5
|
+
|
|
6
|
+
test("bugreport-001-gnd-overlap", () => {
|
|
7
|
+
const solver = new SchematicTracePipelineSolver(inputProblem as any)
|
|
8
|
+
solver.solve()
|
|
9
|
+
|
|
10
|
+
expect(
|
|
11
|
+
solver.netLabelPlacementSolver!.netLabelPlacements.some(
|
|
12
|
+
(placement) => placement.netId === "GND",
|
|
13
|
+
),
|
|
14
|
+
).toBe(true)
|
|
15
|
+
expect(solver).toMatchSolverSnapshot(import.meta.path)
|
|
16
|
+
})
|