@tscircuit/schematic-trace-solver 0.0.101 → 0.0.103
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 +14 -6
- package/dist/index.js +251 -66
- package/lib/solvers/AvailableNetOrientationSolver/AvailableNetOrientationSolver.ts +58 -3
- package/lib/solvers/SchematicTraceLinesSolver/SchematicTraceSingleLineSolver2/SchematicTraceSingleLineSolver2.ts +13 -5
- package/lib/solvers/TraceOverlapShiftSolver/TraceOverlapIssueSolver/TraceOverlapIssueSolver.ts +168 -24
- package/lib/solvers/TraceOverlapShiftSolver/TraceOverlapShiftSolver.ts +128 -48
- package/package.json +1 -1
- package/site/bug-reports/bug-report-20260716T144856Z.page.tsx +4 -0
- package/site/bug-reports/bug-report-20260717T022934Z.page.tsx +4 -0
- package/site/bug-reports/bug-report-20260717T031704Z.page.tsx +4 -0
- package/site/bug-reports/bug-report-20260717T042845Z.page.tsx +4 -0
- package/tests/bug-reports/bug-report-20260706T213649Z/__snapshots__/bug-report-20260706T213649Z.snap.svg +3 -3
- package/tests/bug-reports/bug-report-20260706T220324Z/__snapshots__/bug-report-20260706T220324Z.snap.svg +3 -3
- package/tests/bug-reports/bug-report-20260707T092615Z/__snapshots__/bug-report-20260707T092615Z.snap.svg +5 -5
- package/tests/bug-reports/bug-report-20260707T140410Z/__snapshots__/bug-report-20260707T140410Z.snap.svg +3 -3
- package/tests/bug-reports/bug-report-20260716T144856Z/__snapshots__/bug-report-20260716T144856Z.snap.svg +149 -0
- package/tests/bug-reports/bug-report-20260716T144856Z/bug-report-20260716T144856Z.json +693 -0
- package/tests/bug-reports/bug-report-20260716T144856Z/bug-report-20260716T144856Z.test.ts +12 -0
- package/tests/bug-reports/bug-report-20260717T022934Z/__snapshots__/bug-report-20260717T022934Z.snap.svg +130 -0
- package/tests/bug-reports/bug-report-20260717T022934Z/bug-report-20260717T022934Z.json +543 -0
- package/tests/bug-reports/bug-report-20260717T022934Z/bug-report-20260717T022934Z.test.ts +12 -0
- package/tests/bug-reports/bug-report-20260717T031704Z/__snapshots__/bug-report-20260717T031704Z.snap.svg +48 -0
- package/tests/bug-reports/bug-report-20260717T031704Z/bug-report-20260717T031704Z.json +77 -0
- package/tests/bug-reports/bug-report-20260717T031704Z/bug-report-20260717T031704Z.test.ts +12 -0
- package/tests/bug-reports/bug-report-20260717T042845Z/__snapshots__/bug-report-20260717T042845Z.snap.svg +54 -0
- package/tests/bug-reports/bug-report-20260717T042845Z/bug-report-20260717T042845Z.json +113 -0
- package/tests/bug-reports/bug-report-20260717T042845Z/bug-report-20260717T042845Z.test.ts +12 -0
- package/tests/examples/__snapshots__/example11.snap.svg +19 -19
- package/tests/examples/__snapshots__/example19.snap.svg +3 -5
- package/tests/examples/__snapshots__/example29.snap.svg +13 -13
- package/tests/examples/__snapshots__/example37.snap.svg +4 -2
- package/tests/examples/example16.test.ts +22 -0
- package/tests/repros/__snapshots__/repro-rp2040-gamepad-trace-alignment.snap.svg +2 -8
- package/tests/repros/__snapshots__/repro47-endpoint-obstacle-detour.snap.svg +19 -19
- package/tests/repros/__snapshots__/trace-overlap-box-resistor.snap.svg +10 -10
- package/tests/repros/repro47-endpoint-obstacle-detour.test.ts +30 -0
- package/tests/solvers/TraceOverlapShiftSolver/TraceOverlapShiftSolver.test.ts +174 -0
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
<svg width="640" height="640" viewBox="0 0 640 640" xmlns="http://www.w3.org/2000/svg"><rect width="100%" height="100%" fill="white"/><g><polyline data-points="0.6499999999999999,0.825 -0.6499999999999999,-0.825" data-type="line" data-label="" points="
|
|
2
|
-
globalConnNetId: connectivity_net2" data-x="0.
|
|
3
|
-
globalConnNetId: connectivity_net3" data-x="1.5999999999999999" data-y="-0.95" x="
|
|
4
|
-
globalConnNetId: connectivity_net0" data-x="0.
|
|
5
|
-
globalConnNetId: connectivity_net1" data-x="1.4500000000000002" data-y="1.05" x="
|
|
6
|
-
x-" data-x="-1.25" data-y="0.825" cx="
|
|
7
|
-
x+" data-x="-0.6499999999999999" data-y="0.825" cx="
|
|
8
|
-
x-" data-x="0.6499999999999999" data-y="0.825" cx="
|
|
9
|
-
x+" data-x="1.25" data-y="0.825" cx="
|
|
10
|
-
x-" data-x="-1.25" data-y="-0.825" cx="
|
|
11
|
-
x+" data-x="-0.6499999999999999" data-y="-0.825" cx="
|
|
12
|
-
x-" data-x="0.49999999999999994" data-y="-0.725" cx="
|
|
13
|
-
y-" data-x="0.95" data-y="-1.1028787352499998" cx="
|
|
14
|
-
x+" data-x="1.4" data-y="-0.725" cx="
|
|
15
|
-
orientation: y+" data-x="0.
|
|
16
|
-
orientation: y-" data-x="1.5999999999999999" data-y="-0.725" cx="582.
|
|
17
|
-
orientation: y+" data-x="0.
|
|
18
|
-
orientation: y+" data-x="1.4500000000000002" data-y="0.825" cx="
|
|
1
|
+
<svg width="640" height="640" viewBox="0 0 640 640" xmlns="http://www.w3.org/2000/svg"><rect width="100%" height="100%" fill="white"/><g><polyline data-points="0.6499999999999999,0.825 -0.6499999999999999,-0.825" data-type="line" data-label="" points="419.0769230769231,177.84615384615384 195.0769230769231,462.1538461538462" fill="none" stroke="hsl(224, 100%, 50%, 0.8)" stroke-width="1px"/></g><g><polyline data-points="1.25,0.825 -1.25,-0.825" data-type="line" data-label="" points="522.4615384615386,177.84615384615384 91.69230769230768,462.1538461538462" fill="none" stroke="hsl(224, 100%, 50%, 0.8)" stroke-width="1px"/></g><g><polyline data-points="0.49999999999999994,-0.725 -1.25,0.825" data-type="line" data-label="" points="393.2307692307692,444.9230769230769 91.69230769230768,177.84615384615384" fill="none" stroke="hsl(168, 100%, 50%, 0.8)" stroke-width="1px"/></g><g><polyline data-points="1.4,-0.725 -0.6499999999999999,0.825" data-type="line" data-label="" points="548.3076923076924,444.9230769230769 195.0769230769231,177.84615384615384" fill="none" stroke="hsl(168, 100%, 50%, 0.8)" stroke-width="1px"/></g><g><polyline data-points="0.6499999999999999,0.825 0,0.825 0,-0.825 -0.6499999999999999,-0.825" data-type="line" data-label="" points="419.0769230769231,177.84615384615384 307.0769230769231,177.84615384615384 307.0769230769231,462.1538461538462 195.0769230769231,462.1538461538462" fill="none" stroke="purple" stroke-width="1px"/></g><g><polyline data-points="1.25,0.825 1.4500000000000002,0.825 1.4500000000000002,0 -1.3499999999999999,0 -1.3499999999999999,-0.825 -1.25,-0.825" data-type="line" data-label="" points="522.4615384615386,177.84615384615384 556.923076923077,177.84615384615384 556.923076923077,320 74.46153846153848,320 74.46153846153848,462.1538461538462 91.69230769230768,462.1538461538462" fill="none" stroke="purple" stroke-width="1px"/></g><g><polyline data-points="0.5,-0.725 0.2,-0.725 0.2,-1.365 -1.55,-1.365 -1.55,0.825 -1.25,0.825" data-type="line" data-label="" points="393.2307692307693,444.9230769230769 341.53846153846155,444.9230769230769 341.53846153846155,555.2 40,555.2 40,177.84615384615384 91.69230769230768,177.84615384615384" fill="none" stroke="purple" stroke-width="1px"/></g><g><polyline data-points="1.4,-0.725 1.5999999999999999,-0.725 1.5999999999999999,1.365 -0.1,1.365 -0.1,0.825 -0.6499999999999999,0.825" data-type="line" data-label="" points="548.3076923076924,444.9230769230769 582.7692307692307,444.9230769230769 582.7692307692307,84.79999999999998 289.84615384615387,84.79999999999998 289.84615384615387,177.84615384615384 195.0769230769231,177.84615384615384" fill="none" stroke="purple" stroke-width="1px"/></g><g><rect data-type="rect" data-label="schematic_component_0" data-x="-0.95" data-y="0.825" x="91.69230769230768" y="119.26153846153844" width="103.38461538461542" height="117.16923076923081" fill="hsl(24, 100%, 50%, 0.8)" stroke="black" stroke-width="0.005803571428571428"/></g><g><rect data-type="rect" data-label="schematic_component_1" data-x="0.95" data-y="0.825" x="419.0769230769231" y="119.26153846153844" width="103.38461538461547" height="117.16923076923081" fill="hsl(24, 100%, 50%, 0.8)" stroke="black" stroke-width="0.005803571428571428"/></g><g><rect data-type="rect" data-label="schematic_component_2" data-x="-0.95" data-y="-0.825" x="91.69230769230768" y="403.5692307692308" width="103.38461538461542" height="117.16923076923081" fill="hsl(24, 100%, 50%, 0.8)" stroke="black" stroke-width="0.005803571428571428"/></g><g><rect data-type="rect" data-label="schematic_component_3" data-x="0.95" data-y="-0.825" x="393.2307692307693" y="414.2732025415385" width="155.07692307692315" height="95.76128722461533" fill="hsl(24, 100%, 50%, 0.8)" stroke="black" stroke-width="0.005803571428571428"/></g><g><rect data-type="rect" data-label="netId: .J1 > .pin1 to .R1 > .pin1
|
|
2
|
+
globalConnNetId: connectivity_net2" data-x="0.35" data-y="-0.5" x="350.1538461538462" y="367.3846153846155" width="34.46153846153845" height="77.53846153846149" fill="hsl(40, 100%, 50%, 0.35)" stroke="black" stroke-width="0.005803571428571428"/></g><g><rect data-type="rect" data-label="netId: .J1 > .pin3 to .R1 > .pin2
|
|
3
|
+
globalConnNetId: connectivity_net3" data-x="1.5999999999999999" data-y="-0.95" x="565.5384615384614" y="444.92307692307696" width="34.46153846153845" height="77.53846153846155" fill="hsl(40, 100%, 50%, 0.35)" stroke="black" stroke-width="0.005803571428571428"/></g><g><rect data-type="rect" data-label="netId: .R2 > .pin1 to .R3 > .pin2
|
|
4
|
+
globalConnNetId: connectivity_net0" data-x="0.32499999999999996" data-y="1.05" x="345.84615384615387" y="100.30769230769229" width="34.46153846153845" height="77.53846153846155" fill="hsl(40, 100%, 50%, 0.35)" stroke="black" stroke-width="0.005803571428571428"/></g><g><rect data-type="rect" data-label="netId: .R2 > .pin2 to .R3 > .pin1
|
|
5
|
+
globalConnNetId: connectivity_net1" data-x="1.4500000000000002" data-y="1.05" x="539.6923076923078" y="100.30769230769229" width="34.46153846153845" height="77.53846153846155" fill="hsl(40, 100%, 50%, 0.35)" stroke="black" stroke-width="0.005803571428571428"/></g><g><circle data-type="point" data-label="R1.1
|
|
6
|
+
x-" data-x="-1.25" data-y="0.825" cx="91.69230769230768" cy="177.84615384615384" r="3" fill="hsl(226, 100%, 50%, 0.8)"/></g><g><circle data-type="point" data-label="R1.2
|
|
7
|
+
x+" data-x="-0.6499999999999999" data-y="0.825" cx="195.0769230769231" cy="177.84615384615384" r="3" fill="hsl(227, 100%, 50%, 0.8)"/></g><g><circle data-type="point" data-label="R2.1
|
|
8
|
+
x-" data-x="0.6499999999999999" data-y="0.825" cx="419.0769230769231" cy="177.84615384615384" r="3" fill="hsl(107, 100%, 50%, 0.8)"/></g><g><circle data-type="point" data-label="R2.2
|
|
9
|
+
x+" data-x="1.25" data-y="0.825" cx="522.4615384615386" cy="177.84615384615384" r="3" fill="hsl(108, 100%, 50%, 0.8)"/></g><g><circle data-type="point" data-label="R3.1
|
|
10
|
+
x-" data-x="-1.25" data-y="-0.825" cx="91.69230769230768" cy="462.1538461538462" r="3" fill="hsl(348, 100%, 50%, 0.8)"/></g><g><circle data-type="point" data-label="R3.2
|
|
11
|
+
x+" data-x="-0.6499999999999999" data-y="-0.825" cx="195.0769230769231" cy="462.1538461538462" r="3" fill="hsl(349, 100%, 50%, 0.8)"/></g><g><circle data-type="point" data-label="J1.1
|
|
12
|
+
x-" data-x="0.49999999999999994" data-y="-0.725" cx="393.2307692307692" cy="444.9230769230769" r="3" fill="hsl(218, 100%, 50%, 0.8)"/></g><g><circle data-type="point" data-label="J1.2
|
|
13
|
+
y-" data-x="0.95" data-y="-1.1028787352499998" cx="470.76923076923083" cy="510.0344897661538" r="3" fill="hsl(219, 100%, 50%, 0.8)"/></g><g><circle data-type="point" data-label="J1.3
|
|
14
|
+
x+" data-x="1.4" data-y="-0.725" cx="548.3076923076924" cy="444.9230769230769" r="3" fill="hsl(220, 100%, 50%, 0.8)"/></g><g><circle data-type="point" data-label="anchorPoint
|
|
15
|
+
orientation: y+" data-x="0.35" data-y="-0.725" cx="367.3846153846154" cy="444.9230769230769" r="3" fill="hsl(40, 100%, 50%, 0.9)"/></g><g><circle data-type="point" data-label="anchorPoint
|
|
16
|
+
orientation: y-" data-x="1.5999999999999999" data-y="-0.725" cx="582.7692307692307" cy="444.9230769230769" r="3" fill="hsl(40, 100%, 50%, 0.9)"/></g><g><circle data-type="point" data-label="anchorPoint
|
|
17
|
+
orientation: y+" data-x="0.32499999999999996" data-y="0.825" cx="363.0769230769231" cy="177.84615384615384" r="3" fill="hsl(40, 100%, 50%, 0.9)"/></g><g><circle data-type="point" data-label="anchorPoint
|
|
18
|
+
orientation: y+" data-x="1.4500000000000002" data-y="0.825" cx="556.923076923077" cy="177.84615384615384" 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[
|
|
19
19
|
document.currentScript.parentElement.addEventListener('mousemove', (e) => {
|
|
20
20
|
const svg = e.currentTarget;
|
|
21
21
|
const rect = svg.getBoundingClientRect();
|
|
@@ -37,7 +37,7 @@ orientation: y+" data-x="1.4500000000000002" data-y="0.825" cx="555.555555555555
|
|
|
37
37
|
v.setAttribute('y2', '640');
|
|
38
38
|
|
|
39
39
|
// Calculate real coordinates using inverse transformation
|
|
40
|
-
const matrix = {"a":
|
|
40
|
+
const matrix = {"a":172.30769230769232,"c":0,"e":307.0769230769231,"b":0,"d":-172.30769230769232,"f":320};
|
|
41
41
|
// Manually invert and apply the affine transform
|
|
42
42
|
// Since we only use translate and scale, we can directly compute:
|
|
43
43
|
// x' = (x - tx) / sx
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
<svg width="640" height="640" viewBox="0 0 640 640" xmlns="http://www.w3.org/2000/svg"><rect width="100%" height="100%" fill="white"/><g><polyline data-points="1.7999999999999998,-0.32499999999999996 2.25,-0.9" data-type="line" data-label="" points="
|
|
2
|
-
globalConnNetId: connectivity_net1" data-x="2.25" data-y="-3.0900000000000007" x="
|
|
3
|
-
globalConnNetId: connectivity_net0" data-x="
|
|
4
|
-
x+" data-x="1.7999999999999998" data-y="-0.975" cx="
|
|
5
|
-
x+" data-x="1.7999999999999998" data-y="-0.32499999999999996" cx="
|
|
6
|
-
y-" data-x="2.25" data-y="-0.9" cx="
|
|
7
|
-
y-" data-x="2.25" data-y="-2.6500000000000004" cx="
|
|
8
|
-
orientation: y-" data-x="2.25" data-y="-2.8500000000000005" cx="
|
|
9
|
-
orientation:
|
|
1
|
+
<svg width="640" height="640" viewBox="0 0 640 640" xmlns="http://www.w3.org/2000/svg"><rect width="100%" height="100%" fill="white"/><g><polyline data-points="1.7999999999999998,-0.32499999999999996 2.25,-0.9" data-type="line" data-label="" points="445.37313432835816,320.9286898839137 487.16417910447757,374.3283582089552" fill="none" stroke="hsl(112, 100%, 50%, 0.8)" stroke-width="1px"/></g><g><polyline data-points="1.7999999999999998,-0.975 2.25,-2.6500000000000004" data-type="line" data-label="" points="445.37313432835816,381.2935323383084 487.16417910447757,536.849087893864" fill="none" stroke="hsl(157, 100%, 50%, 0.8)" stroke-width="1px" stroke-dasharray="4 2"/></g><g><polyline data-points="1.7999999999999998,-0.32499999999999996 1.9902723250000003,-0.32499999999999996 1.9902723250000003,-1.1 2.25,-1.1 2.25,-0.9" data-type="line" data-label="" points="445.37313432835816,320.9286898839137 463.0435326699834,320.9286898839137 463.0435326699834,392.9021558872305 487.16417910447757,392.9021558872305 487.16417910447757,374.3283582089552" fill="none" stroke="purple" stroke-width="1px"/></g><g><polyline data-points="1.7999999999999998,-0.975 1.9249999999999998,-0.975 1.9249999999999998,-2.8500000000000005 2.25,-2.8500000000000005 2.25,-2.6500000000000004" data-type="line" data-label="" points="445.37313432835816,381.2935323383084 456.9817578772802,381.2935323383084 456.9817578772802,555.4228855721392 487.16417910447757,555.4228855721392 487.16417910447757,536.849087893864" fill="none" stroke="purple" stroke-width="1px"/></g><g><rect data-type="rect" data-label="schematic_component_0" data-x="0" data-y="0" x="111.04477611940302" y="40" width="334.32835820895514" height="501.49253731343276" fill="hsl(24, 100%, 50%, 0.8)" stroke="black" stroke-width="0.010767857142857145"/></g><g><rect data-type="rect" data-label="schematic_component_4" data-x="2.25" data-y="-0.35" x="472.33043150912107" y="272.1724709784411" width="29.667495190712998" height="102.15588723051411" fill="hsl(24, 100%, 50%, 0.8)" stroke="black" stroke-width="0.010767857142857145"/></g><g><rect data-type="rect" data-label="schematic_component_5" data-x="2.25" data-y="-2.1" x="472.33043150912107" y="434.6932006633499" width="29.667495190712998" height="102.15588723051405" fill="hsl(24, 100%, 50%, 0.8)" stroke="black" stroke-width="0.010767857142857145"/></g><g><rect data-type="rect" data-label="netId: GND
|
|
2
|
+
globalConnNetId: connectivity_net1" data-x="2.25" data-y="-3.0900000000000007" x="477.8772802653399" y="555.4228855721393" width="18.573797678275355" height="44.577114427860806" fill="#00000066" stroke="#000000" stroke-width="0.010767857142857145"/></g><g><rect data-type="rect" data-label="netId: U1.FB to R1.pin2
|
|
3
|
+
globalConnNetId: connectivity_net0" data-x="2.475" data-y="-1.1" x="487.1641791044775" y="383.6152570480929" width="41.79104477611946" height="18.573797678275298" fill="hsl(40, 100%, 50%, 0.35)" stroke="black" stroke-width="0.010767857142857145"/></g><g><circle data-type="point" data-label="U1.3
|
|
4
|
+
x+" data-x="1.7999999999999998" data-y="-0.975" cx="445.37313432835816" cy="381.2935323383084" r="3" fill="hsl(321, 100%, 50%, 0.8)"/></g><g><circle data-type="point" data-label="U1.4
|
|
5
|
+
x+" data-x="1.7999999999999998" data-y="-0.32499999999999996" cx="445.37313432835816" cy="320.9286898839137" r="3" fill="hsl(322, 100%, 50%, 0.8)"/></g><g><circle data-type="point" data-label="R1.2
|
|
6
|
+
y-" data-x="2.25" data-y="-0.9" cx="487.16417910447757" cy="374.3283582089552" r="3" fill="hsl(227, 100%, 50%, 0.8)"/></g><g><circle data-type="point" data-label="R2.2
|
|
7
|
+
y-" data-x="2.25" data-y="-2.6500000000000004" cx="487.16417910447757" cy="536.849087893864" r="3" fill="hsl(108, 100%, 50%, 0.8)"/></g><g><circle data-type="point" data-label="anchorPoint
|
|
8
|
+
orientation: y-" data-x="2.25" data-y="-2.8500000000000005" cx="487.16417910447757" cy="555.4228855721392" r="3" fill="hsl(40, 100%, 50%, 0.9)"/></g><g><circle data-type="point" data-label="anchorPoint
|
|
9
|
+
orientation: x+" data-x="2.25" data-y="-1.1" cx="487.16417910447757" cy="392.9021558872305" 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[
|
|
10
10
|
document.currentScript.parentElement.addEventListener('mousemove', (e) => {
|
|
11
11
|
const svg = e.currentTarget;
|
|
12
12
|
const rect = svg.getBoundingClientRect();
|
|
@@ -28,7 +28,7 @@ orientation: y+" data-x="1.9249999999999998" data-y="-0.32499999999999996" cx="4
|
|
|
28
28
|
v.setAttribute('y2', '640');
|
|
29
29
|
|
|
30
30
|
// Calculate real coordinates using inverse transformation
|
|
31
|
-
const matrix = {"a":92.86898839137643,"c":0,"e":
|
|
31
|
+
const matrix = {"a":92.86898839137643,"c":0,"e":278.2089552238806,"b":0,"d":-92.86898839137643,"f":290.7462686567164};
|
|
32
32
|
// Manually invert and apply the affine transform
|
|
33
33
|
// Since we only use translate and scale, we can directly compute:
|
|
34
34
|
// x' = (x - tx) / sx
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { expect, test } from "bun:test"
|
|
2
2
|
import { SchematicTracePipelineSolver } from "lib/solvers/SchematicTracePipelineSolver/SchematicTracePipelineSolver"
|
|
3
|
+
import { countPathIntersections } from "lib/solvers/Example28Solver/geometry"
|
|
3
4
|
import "tests/fixtures/matcher"
|
|
4
5
|
import inputProblem from "./assets/repro47-endpoint-obstacle-detour.input.json"
|
|
5
6
|
|
|
@@ -15,5 +16,34 @@ test("repro47: endpoint obstacle detours route around nearby components", () =>
|
|
|
15
16
|
)
|
|
16
17
|
.sort(),
|
|
17
18
|
).toEqual([])
|
|
19
|
+
|
|
20
|
+
const j1Pin1Trace = solver.schematicTraceLinesSolver!.solvedTracePaths.find(
|
|
21
|
+
(trace) => trace.mspPairId === "J1.1-R1.1",
|
|
22
|
+
)
|
|
23
|
+
const bottomChipEdge = Math.min(
|
|
24
|
+
...inputProblem.chips.map((chip) => chip.center.y - chip.height / 2),
|
|
25
|
+
)
|
|
26
|
+
expect(j1Pin1Trace).toBeDefined()
|
|
27
|
+
expect(
|
|
28
|
+
Math.min(...j1Pin1Trace!.tracePath.map((point) => point.y)),
|
|
29
|
+
).toBeLessThan(bottomChipEdge)
|
|
30
|
+
|
|
31
|
+
const finalTraces = solver.netLabelTraceCollisionSolver!.getOutput().traces
|
|
32
|
+
const traceById = new Map(
|
|
33
|
+
finalTraces.map((trace) => [trace.mspPairId, trace]),
|
|
34
|
+
)
|
|
35
|
+
expect(
|
|
36
|
+
countPathIntersections(
|
|
37
|
+
traceById.get("J1.1-R1.1")!.tracePath,
|
|
38
|
+
traceById.get("R2.2-R3.1")!.tracePath,
|
|
39
|
+
),
|
|
40
|
+
).toBe(0)
|
|
41
|
+
expect(
|
|
42
|
+
countPathIntersections(
|
|
43
|
+
traceById.get("J1.3-R1.2")!.tracePath,
|
|
44
|
+
traceById.get("R2.1-R3.2")!.tracePath,
|
|
45
|
+
),
|
|
46
|
+
).toBe(0)
|
|
47
|
+
|
|
18
48
|
expect(solver).toMatchSolverSnapshot(import.meta.path)
|
|
19
49
|
})
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
import type { Point } from "@tscircuit/math-utils"
|
|
2
|
+
import { expect, test } from "bun:test"
|
|
3
|
+
import { countPathIntersections } from "lib/solvers/Example28Solver/geometry"
|
|
4
|
+
import type { SolvedTracePath } from "lib/solvers/SchematicTraceLinesSolver/SchematicTraceLinesSolver"
|
|
5
|
+
import { TraceOverlapShiftSolver } from "lib/solvers/TraceOverlapShiftSolver/TraceOverlapShiftSolver"
|
|
6
|
+
import type { InputProblem } from "lib/types/InputProblem"
|
|
7
|
+
|
|
8
|
+
const inputProblem: InputProblem = {
|
|
9
|
+
chips: [],
|
|
10
|
+
directConnections: [],
|
|
11
|
+
netConnections: [],
|
|
12
|
+
availableNetLabelOrientations: {},
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const makeTrace = (
|
|
16
|
+
mspPairId: string,
|
|
17
|
+
globalConnNetId: string,
|
|
18
|
+
tracePath: Point[],
|
|
19
|
+
) =>
|
|
20
|
+
({
|
|
21
|
+
mspPairId,
|
|
22
|
+
globalConnNetId,
|
|
23
|
+
tracePath,
|
|
24
|
+
}) as SolvedTracePath
|
|
25
|
+
|
|
26
|
+
const createSolver = (inputTracePaths: SolvedTracePath[]) =>
|
|
27
|
+
new TraceOverlapShiftSolver({
|
|
28
|
+
inputProblem,
|
|
29
|
+
inputTracePaths,
|
|
30
|
+
globalConnMap: {} as any,
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
test("separates a collinear point contact using internal rails", () => {
|
|
34
|
+
const traceA = makeTrace("trace-a", "net-a", [
|
|
35
|
+
{ x: 0.65, y: 0.825 },
|
|
36
|
+
{ x: 0.45, y: 0.825 },
|
|
37
|
+
{ x: 0, y: 0.825 },
|
|
38
|
+
{ x: 0, y: -0.825 },
|
|
39
|
+
{ x: -0.45, y: -0.825 },
|
|
40
|
+
{ x: -0.65, y: -0.825 },
|
|
41
|
+
])
|
|
42
|
+
const traceB = makeTrace("trace-b", "net-b", [
|
|
43
|
+
{ x: 1.4, y: -0.725 },
|
|
44
|
+
{ x: 1.6, y: -0.725 },
|
|
45
|
+
{ x: 1.6, y: 1.365 },
|
|
46
|
+
{ x: 0, y: 1.365 },
|
|
47
|
+
{ x: 0, y: 0.825 },
|
|
48
|
+
{ x: -0.65, y: 0.825 },
|
|
49
|
+
])
|
|
50
|
+
const solver = createSolver([traceA, traceB])
|
|
51
|
+
|
|
52
|
+
expect(
|
|
53
|
+
solver
|
|
54
|
+
.findNextOverlapIssue()!
|
|
55
|
+
.overlappingTraceSegments.map(
|
|
56
|
+
(group) => group.pathsWithOverlap[0]!.traceSegmentIndex,
|
|
57
|
+
),
|
|
58
|
+
).toEqual([2, 3])
|
|
59
|
+
|
|
60
|
+
solver.solve()
|
|
61
|
+
|
|
62
|
+
const correctedA = solver.correctedTraceMap[traceA.mspPairId]!
|
|
63
|
+
const correctedB = solver.correctedTraceMap[traceB.mspPairId]!
|
|
64
|
+
expect(
|
|
65
|
+
countPathIntersections(correctedA.tracePath, correctedB.tracePath),
|
|
66
|
+
).toBe(0)
|
|
67
|
+
expect(correctedA.tracePath[2]!.x).toBeCloseTo(0)
|
|
68
|
+
expect(correctedB.tracePath[3]!.x).toBeCloseTo(-0.1)
|
|
69
|
+
})
|
|
70
|
+
|
|
71
|
+
test("preserves deterministic separation for a compound overlap", () => {
|
|
72
|
+
const lowerTrace = makeTrace("lower", "lower-net", [
|
|
73
|
+
{ x: 0, y: 0 },
|
|
74
|
+
{ x: 1, y: 0 },
|
|
75
|
+
{ x: 1, y: 1 },
|
|
76
|
+
{ x: 1, y: 2 },
|
|
77
|
+
{ x: 2, y: 2 },
|
|
78
|
+
])
|
|
79
|
+
const upperTrace = makeTrace("upper", "upper-net", [
|
|
80
|
+
{ x: 0, y: 0.2 },
|
|
81
|
+
{ x: 1, y: 0.2 },
|
|
82
|
+
{ x: 1, y: 1.2 },
|
|
83
|
+
{ x: 1, y: 2.2 },
|
|
84
|
+
{ x: 2, y: 2.2 },
|
|
85
|
+
])
|
|
86
|
+
const solver = createSolver([lowerTrace, upperTrace])
|
|
87
|
+
|
|
88
|
+
const issue = solver.findNextOverlapIssue()
|
|
89
|
+
expect(issue?.interactionKind).toBe("overlap")
|
|
90
|
+
expect(
|
|
91
|
+
issue?.overlappingTraceSegments.map(
|
|
92
|
+
(group) => group.pathsWithOverlap.length,
|
|
93
|
+
),
|
|
94
|
+
).toEqual([2, 2])
|
|
95
|
+
|
|
96
|
+
solver.solve()
|
|
97
|
+
|
|
98
|
+
const correctedLower = solver.correctedTraceMap[lowerTrace.mspPairId]!
|
|
99
|
+
const correctedUpper = solver.correctedTraceMap[upperTrace.mspPairId]!
|
|
100
|
+
expect(correctedLower.tracePath.slice(1, 4).map((point) => point.x)).toEqual([
|
|
101
|
+
0.9, 0.9, 0.9,
|
|
102
|
+
])
|
|
103
|
+
expect(correctedUpper.tracePath.slice(1, 4).map((point) => point.x)).toEqual([
|
|
104
|
+
1.1, 1.1, 1.1,
|
|
105
|
+
])
|
|
106
|
+
})
|
|
107
|
+
|
|
108
|
+
test("chooses the simple-overlap separation with fewer intersections", () => {
|
|
109
|
+
const outerTrace = makeTrace("outer", "outer-net", [
|
|
110
|
+
{ x: -1, y: -1 },
|
|
111
|
+
{ x: 0, y: -1 },
|
|
112
|
+
{ x: 0, y: 1 },
|
|
113
|
+
{ x: 1, y: 1 },
|
|
114
|
+
])
|
|
115
|
+
const innerTrace = makeTrace("inner", "inner-net", [
|
|
116
|
+
{ x: -1, y: -0.5 },
|
|
117
|
+
{ x: 0, y: -0.5 },
|
|
118
|
+
{ x: 0, y: 0.5 },
|
|
119
|
+
{ x: -1, y: 0.5 },
|
|
120
|
+
])
|
|
121
|
+
const solver = createSolver([outerTrace, innerTrace])
|
|
122
|
+
|
|
123
|
+
const issue = solver.findNextOverlapIssue()
|
|
124
|
+
expect(issue?.interactionKind).toBe("overlap")
|
|
125
|
+
expect(
|
|
126
|
+
issue?.overlappingTraceSegments.map(
|
|
127
|
+
(group) => group.pathsWithOverlap.length,
|
|
128
|
+
),
|
|
129
|
+
).toEqual([1, 1])
|
|
130
|
+
|
|
131
|
+
solver.solve()
|
|
132
|
+
|
|
133
|
+
const correctedOuter = solver.correctedTraceMap[outerTrace.mspPairId]!
|
|
134
|
+
const correctedInner = solver.correctedTraceMap[innerTrace.mspPairId]!
|
|
135
|
+
expect(
|
|
136
|
+
countPathIntersections(correctedOuter.tracePath, correctedInner.tracePath),
|
|
137
|
+
).toBe(0)
|
|
138
|
+
expect(correctedOuter.tracePath[1]!.x).toBeCloseTo(0.1)
|
|
139
|
+
expect(correctedInner.tracePath[1]!.x).toBeCloseTo(-0.1)
|
|
140
|
+
})
|
|
141
|
+
|
|
142
|
+
test("chooses the point-contact separation direction with fewer intersections", () => {
|
|
143
|
+
const innerTrace = makeTrace("inner", "inner-net", [
|
|
144
|
+
{ x: 1.25, y: 0.825 },
|
|
145
|
+
{ x: 1.45, y: 0.825 },
|
|
146
|
+
{ x: 1.45, y: 0 },
|
|
147
|
+
{ x: -1.45, y: 0 },
|
|
148
|
+
{ x: -1.45, y: -0.825 },
|
|
149
|
+
{ x: -1.25, y: -0.825 },
|
|
150
|
+
])
|
|
151
|
+
const exteriorTrace = makeTrace("exterior", "exterior-net", [
|
|
152
|
+
{ x: 0.5, y: -0.725 },
|
|
153
|
+
{ x: -0.075, y: -0.725 },
|
|
154
|
+
{ x: -0.075, y: -1.365 },
|
|
155
|
+
{ x: -1.45, y: -1.365 },
|
|
156
|
+
{ x: -1.45, y: -0.825 },
|
|
157
|
+
{ x: -1.65, y: -0.825 },
|
|
158
|
+
])
|
|
159
|
+
const solver = createSolver([innerTrace, exteriorTrace])
|
|
160
|
+
|
|
161
|
+
solver.solve()
|
|
162
|
+
|
|
163
|
+
const correctedInner = solver.correctedTraceMap[innerTrace.mspPairId]!
|
|
164
|
+
const correctedExterior = solver.correctedTraceMap[exteriorTrace.mspPairId]!
|
|
165
|
+
expect(
|
|
166
|
+
countPathIntersections(
|
|
167
|
+
correctedInner.tracePath,
|
|
168
|
+
correctedExterior.tracePath,
|
|
169
|
+
),
|
|
170
|
+
).toBe(0)
|
|
171
|
+
expect(correctedExterior.tracePath[3]!.x).toBeLessThan(
|
|
172
|
+
correctedInner.tracePath[3]!.x,
|
|
173
|
+
)
|
|
174
|
+
})
|