@tscircuit/schematic-trace-solver 0.0.97 → 0.0.98

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/dist/index.d.ts +9 -0
  2. package/dist/index.js +753 -285
  3. package/lib/solvers/SchematicTracePipelineSolver/SchematicTracePipelineSolver.ts +45 -1
  4. package/lib/solvers/TraceCleanupSolver/TraceCleanupSolver.ts +55 -13
  5. package/lib/solvers/TraceCleanupSolver/alignSameNetRails.ts +66 -0
  6. package/lib/solvers/TraceCleanupSolver/sameNetRailAlignment/evaluateRailGroup.ts +124 -0
  7. package/lib/solvers/TraceCleanupSolver/sameNetRailAlignment/geometry.ts +108 -0
  8. package/lib/solvers/TraceCleanupSolver/sameNetRailAlignment/getComponentSideRailSegments.ts +121 -0
  9. package/lib/solvers/TraceCleanupSolver/sameNetRailAlignment/getRailGroups.ts +114 -0
  10. package/lib/solvers/TraceCleanupSolver/sameNetRailAlignment/moveRailSegments.ts +27 -0
  11. package/lib/solvers/TraceCleanupSolver/sameNetRailAlignment/preservesLabelAnchors.ts +30 -0
  12. package/lib/solvers/TraceCleanupSolver/sameNetRailAlignment/scoreRailAlignment.ts +67 -0
  13. package/lib/solvers/TraceCleanupSolver/sameNetRailAlignment/types.ts +34 -0
  14. package/lib/solvers/TraceLabelOverlapAvoidanceSolver/sub-solvers/SingleOverlapSolver/SingleOverlapSolver.ts +1 -60
  15. package/lib/utils/doesPathCoincideWithTraces.ts +61 -0
  16. package/package.json +1 -1
  17. package/tests/bug-reports/bug-report-20260706T220324Z/__snapshots__/bug-report-20260706T220324Z.snap.svg +1 -1
  18. package/tests/bug-reports/bug-report-20260707T141025Z/__snapshots__/bug-report-20260707T141025Z.snap.svg +1 -1
  19. package/tests/examples/__snapshots__/example02.snap.svg +1 -1
  20. package/tests/examples/__snapshots__/example14.snap.svg +1 -1
  21. package/tests/examples/__snapshots__/example18.snap.svg +1 -1
  22. package/tests/examples/__snapshots__/example46.snap.svg +1 -1
  23. package/tests/repros/__snapshots__/repro-cc2340r5.snap.svg +1 -1
  24. package/tests/repros/__snapshots__/repro-rp2040-gamepad-trace-alignment.snap.svg +1 -1
  25. package/tests/repros/__snapshots__/repro130-bq27441-fuel-gauge-trace-through-c1.snap.svg +1 -1
  26. package/tests/repros/repro-rp2040-gamepad-trace-alignment.test.ts +24 -0
  27. package/tests/solvers/TraceCleanupSolver/alignSameNetRails-component-scope.test.ts +38 -0
  28. package/tests/solvers/TraceCleanupSolver/alignSameNetRails-eligible-traces.test.ts +28 -0
  29. package/tests/solvers/TraceCleanupSolver/alignSameNetRails-horizontal.test.ts +62 -0
  30. package/tests/solvers/TraceCleanupSolver/alignSameNetRails-label-anchor.test.ts +36 -0
  31. package/tests/solvers/TraceCleanupSolver/alignSameNetRails-label-junction.test.ts +42 -0
  32. package/tests/solvers/TraceCleanupSolver/alignSameNetRails-obstacle.test.ts +28 -0
  33. package/tests/solvers/TraceCleanupSolver/alignSameNetRails-pipeline-label-connector.test.ts +52 -0
  34. package/tests/solvers/TraceCleanupSolver/alignSameNetRails-vertical.test.ts +25 -0
  35. package/tests/solvers/TraceCleanupSolver/alignSameNetRails-visible-length.test.ts +40 -0
  36. package/tests/solvers/TraceCleanupSolver/fixtures/alignSameNetRails.ts +89 -0
@@ -1,4 +1,4 @@
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="-6.25,4.1 -5.1,4.1" data-type="line" data-label="" points="150.94205868102486,141.16802481267635 189.0266459894364,141.16802481267635" fill="none" stroke="hsl(320, 100%, 50%, 0.8)" stroke-width="1px"/></g><g><polyline data-points="6,4.1 7.15,4.1" data-type="line" data-label="" points="556.6257060967127,141.16802481267635 594.7102934051242,141.16802481267635" fill="none" stroke="hsl(216, 100%, 50%, 0.8)" stroke-width="1px"/></g><g><polyline data-points="-6.25,3 -2.6999999999999997,1.5" data-type="line" data-label="" points="150.94205868102486,177.596760498983 268.5075238504691,227.27230916212847" fill="none" stroke="hsl(248, 100%, 50%, 0.8)" stroke-width="1px"/></g><g><polyline data-points="-5.1,3 -2.6999999999999997,1.3" data-type="line" data-label="" points="189.0266459894364,177.596760498983 268.5075238504691,233.89571565054786" fill="none" stroke="hsl(336, 100%, 50%, 0.8)" stroke-width="1px"/></g><g><polyline data-points="6,3 2.6999999999999997,1.525" data-type="line" data-label="" points="556.6257060967127,177.596760498983 447.3394990377927,226.44438335107603" fill="none" stroke="hsl(72, 100%, 50%, 0.8)" stroke-width="1px"/></g><g><polyline data-points="7.15,3 2.6999999999999997,0.775" data-type="line" data-label="" points="594.7102934051242,177.596760498983 447.3394990377927,251.28215768264874" fill="none" stroke="hsl(304, 100%, 50%, 0.8)" stroke-width="1px"/></g><g><polyline data-points="-4.7,-0.8999999999999999 -2.6999999999999997,0.10000000000000009" data-type="line" data-label="" points="202.27345896627517,306.75318702316116 268.5075238504691,273.6361545810642" fill="none" stroke="hsl(304, 100%, 50%, 0.8)" stroke-width="1px"/></g><g><polyline data-points="-7.2,-4.6 -2.55,-5.1" data-type="line" data-label="" points="119.48087786103275,429.2862070589199 273.4750787167836,445.84472327996843" fill="none" stroke="hsl(160, 100%, 50%, 0.8)" stroke-width="1px"/></g><g><polyline data-points="-2.55,-5.1 -2.6999999999999997,-0.3999999999999999" data-type="line" data-label="" points="273.4750787167836,445.84472327996843 268.5075238504691,290.1946708021127" fill="none" stroke="hsl(88, 100%, 50%, 0.8)" stroke-width="1px"/></g><g><polyline data-points="-2.55,-5.1 3.8499999999999996,-4.8" data-type="line" data-label="" points="273.4750787167836,445.84472327996843 485.4240863462042,435.9096135473393" fill="none" stroke="hsl(168, 100%, 50%, 0.8)" stroke-width="1px"/></g><g><polyline data-points="3.8499999999999996,-4.8 2.6999999999999997,-0.17499999999999993" data-type="line" data-label="" points="485.4240863462042,435.9096135473393 447.3394990377927,282.7433385026409" fill="none" stroke="hsl(96, 100%, 50%, 0.8)" stroke-width="1px"/></g><g><polyline data-points="4.950000000000001,-4.8 2.6999999999999997,-0.42499999999999993" data-type="line" data-label="" points="521.8528220325109,435.9096135473393 447.3394990377927,291.0225966131651" fill="none" stroke="hsl(312, 100%, 50%, 0.8)" stroke-width="1px"/></g><g><polyline data-points="-2.6999999999999997,1.5 -6.25,3" data-type="line" data-label="" points="268.5075238504691,227.27230916212847 150.94205868102486,177.596760498983" fill="none" stroke="hsl(216, 100%, 50%, 0.8)" stroke-width="1px" stroke-dasharray="4 2"/></g><g><polyline data-points="-2.6999999999999997,1.3 -5.1,3" data-type="line" data-label="" points="268.5075238504691,233.89571565054786 189.0266459894364,177.596760498983" fill="none" stroke="hsl(196, 100%, 50%, 0.8)" stroke-width="1px" stroke-dasharray="4 2"/></g><g><polyline data-points="-2.6999999999999997,1.1 0,-1.3499999999999999" data-type="line" data-label="" points="268.5075238504691,240.51912213896725 357.9235114441309,321.6558516221048" fill="none" stroke="hsl(237, 100%, 50%, 0.8)" stroke-width="1px" stroke-dasharray="4 2"/></g><g><polyline data-points="-2.6999999999999997,1.1 -7.2,-5" data-type="line" data-label="" points="268.5075238504691,240.51912213896725 119.48087786103275,442.5330200357587" fill="none" stroke="hsl(237, 100%, 50%, 0.8)" stroke-width="1px" stroke-dasharray="4 2"/></g><g><polyline data-points="-2.6999999999999997,1.1 -4.7,-2" data-type="line" data-label="" points="268.5075238504691,240.51912213896725 202.27345896627517,343.1819227094678" fill="none" stroke="hsl(237, 100%, 50%, 0.8)" stroke-width="1px" stroke-dasharray="4 2"/></g><g><polyline data-points="-2.6999999999999997,1.1 -2.55,-6.200000000000001" data-type="line" data-label="" points="268.5075238504691,240.51912213896725 273.4750787167836,482.27345896627514" fill="none" stroke="hsl(237, 100%, 50%, 0.8)" stroke-width="1px" stroke-dasharray="4 2"/></g><g><polyline data-points="0,-1.3499999999999999 -7.2,-5" data-type="line" data-label="" points="357.9235114441309,321.6558516221048 119.48087786103275,442.5330200357587" fill="none" stroke="hsl(237, 100%, 50%, 0.8)" stroke-width="1px" stroke-dasharray="4 2"/></g><g><polyline data-points="0,-1.3499999999999999 -4.7,-2" data-type="line" data-label="" points="357.9235114441309,321.6558516221048 202.27345896627517,343.1819227094678" fill="none" stroke="hsl(237, 100%, 50%, 0.8)" stroke-width="1px" stroke-dasharray="4 2"/></g><g><polyline data-points="0,-1.3499999999999999 -2.55,-6.200000000000001" data-type="line" data-label="" points="357.9235114441309,321.6558516221048 273.4750787167836,482.27345896627514" fill="none" stroke="hsl(237, 100%, 50%, 0.8)" stroke-width="1px" stroke-dasharray="4 2"/></g><g><polyline data-points="-7.2,-5 -4.7,-2" data-type="line" data-label="" points="119.48087786103275,442.5330200357587 202.27345896627517,343.1819227094678" fill="none" stroke="hsl(237, 100%, 50%, 0.8)" stroke-width="1px" stroke-dasharray="4 2"/></g><g><polyline data-points="-7.2,-5 -2.55,-6.200000000000001" data-type="line" data-label="" points="119.48087786103275,442.5330200357587 273.4750787167836,482.27345896627514" fill="none" stroke="hsl(237, 100%, 50%, 0.8)" stroke-width="1px" stroke-dasharray="4 2"/></g><g><polyline data-points="-4.7,-2 -2.55,-6.200000000000001" data-type="line" data-label="" points="202.27345896627517,343.1819227094678 273.4750787167836,482.27345896627514" fill="none" stroke="hsl(237, 100%, 50%, 0.8)" stroke-width="1px" stroke-dasharray="4 2"/></g><g><polyline data-points="-2.6999999999999997,-0.3999999999999999 2.6999999999999997,-0.17499999999999993" data-type="line" data-label="" points="268.5075238504691,290.1946708021127 447.3394990377927,282.7433385026409" fill="none" stroke="hsl(127, 100%, 50%, 0.8)" stroke-width="1px" stroke-dasharray="4 2"/></g><g><polyline data-points="-2.6999999999999997,-0.3999999999999999 -7.2,-4.6" data-type="line" data-label="" points="268.5075238504691,290.1946708021127 119.48087786103275,429.2862070589199" fill="none" stroke="hsl(127, 100%, 50%, 0.8)" stroke-width="1px" stroke-dasharray="4 2"/></g><g><polyline data-points="-2.6999999999999997,-0.3999999999999999 3.8499999999999996,-4.8" data-type="line" data-label="" points="268.5075238504691,290.1946708021127 485.4240863462042,435.9096135473393" fill="none" stroke="hsl(127, 100%, 50%, 0.8)" stroke-width="1px" stroke-dasharray="4 2"/></g><g><polyline data-points="-2.6999999999999997,-0.3999999999999999 -2.55,-5.1" data-type="line" data-label="" points="268.5075238504691,290.1946708021127 273.4750787167836,445.84472327996843" fill="none" stroke="hsl(127, 100%, 50%, 0.8)" stroke-width="1px" stroke-dasharray="4 2"/></g><g><polyline data-points="2.6999999999999997,-0.17499999999999993 -7.2,-4.6" data-type="line" data-label="" points="447.3394990377927,282.7433385026409 119.48087786103275,429.2862070589199" fill="none" stroke="hsl(127, 100%, 50%, 0.8)" stroke-width="1px" stroke-dasharray="4 2"/></g><g><polyline data-points="2.6999999999999997,-0.17499999999999993 3.8499999999999996,-4.8" data-type="line" data-label="" points="447.3394990377927,282.7433385026409 485.4240863462042,435.9096135473393" fill="none" stroke="hsl(127, 100%, 50%, 0.8)" stroke-width="1px" stroke-dasharray="4 2"/></g><g><polyline data-points="2.6999999999999997,-0.17499999999999993 -2.55,-5.1" data-type="line" data-label="" points="447.3394990377927,282.7433385026409 273.4750787167836,445.84472327996843" fill="none" stroke="hsl(127, 100%, 50%, 0.8)" stroke-width="1px" stroke-dasharray="4 2"/></g><g><polyline data-points="-7.2,-4.6 3.8499999999999996,-4.8" data-type="line" data-label="" points="119.48087786103275,429.2862070589199 485.4240863462042,435.9096135473393" fill="none" stroke="hsl(127, 100%, 50%, 0.8)" stroke-width="1px" stroke-dasharray="4 2"/></g><g><polyline data-points="-7.2,-4.6 -2.55,-5.1" data-type="line" data-label="" points="119.48087786103275,429.2862070589199 273.4750787167836,445.84472327996843" fill="none" stroke="hsl(127, 100%, 50%, 0.8)" stroke-width="1px" stroke-dasharray="4 2"/></g><g><polyline data-points="3.8499999999999996,-4.8 -2.55,-5.1" data-type="line" data-label="" points="485.4240863462042,435.9096135473393 273.4750787167836,445.84472327996843" fill="none" stroke="hsl(127, 100%, 50%, 0.8)" stroke-width="1px" stroke-dasharray="4 2"/></g><g><polyline data-points="2.6999999999999997,-0.42499999999999993 4.950000000000001,-4.8" data-type="line" data-label="" points="447.3394990377927,291.0225966131651 521.8528220325109,435.9096135473393" fill="none" stroke="hsl(71, 100%, 50%, 0.8)" stroke-width="1px" stroke-dasharray="4 2"/></g><g><polyline data-points="2.6999999999999997,0.775 -7.2,-4.8" data-type="line" data-label="" points="447.3394990377927,251.28215768264874 119.48087786103275,435.9096135473393" fill="none" stroke="hsl(247, 100%, 50%, 0.8)" stroke-width="1px" stroke-dasharray="4 2"/></g><g><polyline data-points="2.6999999999999997,0.775 7.15,3" data-type="line" data-label="" points="447.3394990377927,251.28215768264874 594.7102934051242,177.596760498983" fill="none" stroke="hsl(247, 100%, 50%, 0.8)" stroke-width="1px" stroke-dasharray="4 2"/></g><g><polyline data-points="-7.2,-4.8 7.15,3" data-type="line" data-label="" points="119.48087786103275,435.9096135473393 594.7102934051242,177.596760498983" fill="none" stroke="hsl(247, 100%, 50%, 0.8)" stroke-width="1px" stroke-dasharray="4 2"/></g><g><polyline data-points="2.6999999999999997,1.525 6,3" data-type="line" data-label="" points="447.3394990377927,226.44438335107603 556.6257060967127,177.596760498983" fill="none" stroke="hsl(189, 100%, 50%, 0.8)" stroke-width="1px" stroke-dasharray="4 2"/></g><g><polyline data-points="-6.25,4.1 -6.25,4.3 -5.1,4.3 -5.1,4.1" data-type="line" data-label="" points="150.94205868102486,141.16802481267635 150.94205868102486,134.54461832425696 189.0266459894364,134.54461832425696 189.0266459894364,141.16802481267635" fill="none" stroke="purple" stroke-width="1px"/></g><g><polyline data-points="6,4.1 6,4.3 7.15,4.3 7.15,4.1" data-type="line" data-label="" points="556.6257060967127,141.16802481267635 556.6257060967127,134.54461832425696 594.7102934051242,134.54461832425696 594.7102934051242,141.16802481267635" fill="none" stroke="purple" stroke-width="1px"/></g><g><polyline data-points="-6.25,3 -6.25,1.5 -2.6999999999999997,1.5" data-type="line" data-label="" points="150.94205868102486,177.596760498983 150.94205868102486,227.27230916212847 268.5075238504691,227.27230916212847" fill="none" stroke="purple" stroke-width="1px"/></g><g><polyline data-points="-5.1,3 -5.1,1.2999999999999998 -2.6999999999999997,1.2999999999999998" data-type="line" data-label="" points="189.0266459894364,177.596760498983 189.0266459894364,233.89571565054786 268.5075238504691,233.89571565054786" fill="none" stroke="purple" stroke-width="1px"/></g><g><polyline data-points="6,3 6,1.525 2.6999999999999997,1.525" data-type="line" data-label="" points="556.6257060967127,177.596760498983 556.6257060967127,226.44438335107603 447.3394990377927,226.44438335107603" fill="none" stroke="purple" stroke-width="1px"/></g><g><polyline data-points="2.6999999999999997,0.775 2.9,0.775 2.9,-4.8 -7.2,-4.8" data-type="line" data-label="" points="447.3394990377927,251.28215768264874 453.96290552621207,251.28215768264874 453.96290552621207,435.9096135473393 119.48087786103275,435.9096135473393" fill="none" stroke="purple" stroke-width="1px"/></g><g><polyline data-points="7.15,3 7.15,0.775 2.6999999999999997,0.775" data-type="line" data-label="" points="594.7102934051242,177.596760498983 594.7102934051242,251.28215768264874 447.3394990377927,251.28215768264874" fill="none" stroke="purple" stroke-width="1px"/></g><g><polyline data-points="-4.7,-0.8999999999999999 -4.7,0.10000000000000009 -2.6999999999999997,0.10000000000000009" data-type="line" data-label="" points="202.27345896627517,306.75318702316116 202.27345896627517,273.6361545810642 268.5075238504691,273.6361545810642" fill="none" stroke="purple" stroke-width="1px"/></g><g><polyline data-points="-2.6999999999999997,-0.3999999999999999 -3,-0.3999999999999999 -3,-2.75 -2.55,-2.75 -2.55,-5.1" data-type="line" data-label="" points="268.5075238504691,290.1946708021127 258.57241411784,290.1946708021127 258.57241411784,368.01969704104056 273.4750787167836,368.01969704104056 273.4750787167836,445.84472327996843" fill="none" stroke="purple" stroke-width="1px"/></g><g><polyline data-points="-7.2,-4.6 -2.55,-4.6 -2.55,-5.1" data-type="line" data-label="" points="119.48087786103275,429.2862070589199 273.4750787167836,429.2862070589199 273.4750787167836,445.84472327996843" fill="none" stroke="purple" stroke-width="1px"/></g><g><polyline data-points="2.6999999999999997,-0.17499999999999993 3.2749999999999995,-0.17499999999999993 3.2749999999999995,-4.8 3.8499999999999996,-4.8" data-type="line" data-label="" points="447.3394990377927,282.7433385026409 466.38179269199844,282.7433385026409 466.38179269199844,435.9096135473393 485.4240863462042,435.9096135473393" fill="none" stroke="purple" stroke-width="1px"/></g><g><polyline data-points="4.950000000000001,-4.8 5.150000000000001,-4.8 5.150000000000001,-0.42499999999999993 2.6999999999999997,-0.42499999999999993" data-type="line" data-label="" points="521.8528220325109,435.9096135473393 528.4762285209304,435.9096135473393 528.4762285209304,291.0225966131651 447.3394990377927,291.0225966131651" fill="none" stroke="purple" stroke-width="1px"/></g><g><polyline data-points="-2.7,1.0999999999999996 -3.7,1.0999999999999996 -3.7,-2.2 -4.7,-2.2 -4.7,-2" data-type="line" data-label="" points="268.50752385046906,240.51912213896725 235.39049140837213,240.51912213896725 235.39049140837213,349.8053291978872 202.27345896627517,349.8053291978872 202.27345896627517,343.1819227094678" fill="none" stroke="purple" stroke-width="1px"/></g><g><polyline data-points="0,-1.3499999999999999 0,-1.5499999999999998 -2.8,-1.5499999999999998 -2.8,1.1 -2.6999999999999997,1.1" data-type="line" data-label="" points="357.9235114441309,321.6558516221048 357.9235114441309,328.2792581105242 265.1958206062594,328.2792581105242 265.1958206062594,240.51912213896725 268.5075238504691,240.51912213896725" fill="none" stroke="purple" stroke-width="1px"/></g><g><polyline data-points="-7.2,-5 -4.7,-5 -4.7,-2" data-type="line" data-label="" points="119.48087786103275,442.5330200357587 202.27345896627517,442.5330200357587 202.27345896627517,343.1819227094678" fill="none" stroke="purple" stroke-width="1px"/></g><g><polyline data-points="-2.55,-6.200000000000001 -2.55,-6.400000000000001 -4.875,-6.400000000000001 -4.875,-5 -7.2,-5" data-type="line" data-label="" points="273.4750787167836,482.27345896627514 273.4750787167836,488.89686545469453 196.4779782889082,488.89686545469453 196.4779782889082,442.5330200357587 119.48087786103275,442.5330200357587" fill="none" stroke="purple" stroke-width="1px"/></g><g><rect data-type="rect" data-label="schematic_component_0" data-x="0" data-y="0.55" x="268.5075238504691" y="195.8111283421363" width="178.83197518732356" height="125.84472327996849" fill="hsl(24, 100%, 50%, 0.8)" stroke="black" stroke-width="0.030195942276785723"/></g><g><rect data-type="rect" data-label="schematic_component_1" data-x="-8.4" data-y="-4.8" x="40.00000000000003" y="422.6628005705005" width="79.48087786103275" height="26.493625953677622" fill="hsl(24, 100%, 50%, 0.8)" stroke="black" stroke-width="0.030195942276785723"/></g><g><rect data-type="rect" data-label="schematic_component_2" data-x="4.4" data-y="-4.8" x="485.42408634620426" y="429.46982941285" width="36.42873568630665" height="12.879568268978574" fill="hsl(24, 100%, 50%, 0.8)" stroke="black" stroke-width="0.030195942276785723"/></g><g><rect data-type="rect" data-label="schematic_component_3" data-x="-6.25" data-y="3.55" x="145.65235208614916" y="141.16802481267635" width="10.57941318975142" height="36.42873568630665" fill="hsl(24, 100%, 50%, 0.8)" stroke="black" stroke-width="0.030195942276785723"/></g><g><rect data-type="rect" data-label="schematic_component_4" data-x="-5.1" data-y="3.55" x="183.73693939456066" y="141.16802481267635" width="10.579413189751449" height="36.42873568630665" fill="hsl(24, 100%, 50%, 0.8)" stroke="black" stroke-width="0.030195942276785723"/></g><g><rect data-type="rect" data-label="schematic_component_5" data-x="6" data-y="3.55" x="551.335999501837" y="141.16802481267635" width="10.579413189751335" height="36.42873568630665" fill="hsl(24, 100%, 50%, 0.8)" stroke="black" stroke-width="0.030195942276785723"/></g><g><rect data-type="rect" data-label="schematic_component_6" data-x="7.15" data-y="3.55" x="589.4205868102484" y="141.16802481267635" width="10.579413189751449" height="36.42873568630665" fill="hsl(24, 100%, 50%, 0.8)" stroke="black" stroke-width="0.030195942276785723"/></g><g><rect data-type="rect" data-label="schematic_component_7" data-x="-4.7" data-y="-1.45" x="193.49744536911948" y="306.7531870231612" width="17.552027194311364" height="36.42873568630665" fill="hsl(24, 100%, 50%, 0.8)" stroke="black" stroke-width="0.030195942276785723"/></g><g><rect data-type="rect" data-label="schematic_component_8" data-x="-2.55" data-y="-5.65" x="264.6990651196279" y="445.84472327996843" width="17.552027194311393" height="36.42873568630671" fill="hsl(24, 100%, 50%, 0.8)" stroke="black" stroke-width="0.030195942276785723"/></g><g><rect data-type="rect" data-label="netId: SDA
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="-6.25,4.1 -5.1,4.1" data-type="line" data-label="" points="150.94205868102486,141.16802481267635 189.0266459894364,141.16802481267635" fill="none" stroke="hsl(320, 100%, 50%, 0.8)" stroke-width="1px"/></g><g><polyline data-points="6,4.1 7.15,4.1" data-type="line" data-label="" points="556.6257060967127,141.16802481267635 594.7102934051242,141.16802481267635" fill="none" stroke="hsl(216, 100%, 50%, 0.8)" stroke-width="1px"/></g><g><polyline data-points="-6.25,3 -2.6999999999999997,1.5" data-type="line" data-label="" points="150.94205868102486,177.596760498983 268.5075238504691,227.27230916212847" fill="none" stroke="hsl(248, 100%, 50%, 0.8)" stroke-width="1px"/></g><g><polyline data-points="-5.1,3 -2.6999999999999997,1.3" data-type="line" data-label="" points="189.0266459894364,177.596760498983 268.5075238504691,233.89571565054786" fill="none" stroke="hsl(336, 100%, 50%, 0.8)" stroke-width="1px"/></g><g><polyline data-points="6,3 2.6999999999999997,1.525" data-type="line" data-label="" points="556.6257060967127,177.596760498983 447.3394990377927,226.44438335107603" fill="none" stroke="hsl(72, 100%, 50%, 0.8)" stroke-width="1px"/></g><g><polyline data-points="7.15,3 2.6999999999999997,0.775" data-type="line" data-label="" points="594.7102934051242,177.596760498983 447.3394990377927,251.28215768264874" fill="none" stroke="hsl(304, 100%, 50%, 0.8)" stroke-width="1px"/></g><g><polyline data-points="-4.7,-0.8999999999999999 -2.6999999999999997,0.10000000000000009" data-type="line" data-label="" points="202.27345896627517,306.75318702316116 268.5075238504691,273.6361545810642" fill="none" stroke="hsl(304, 100%, 50%, 0.8)" stroke-width="1px"/></g><g><polyline data-points="-7.2,-4.6 -2.55,-5.1" data-type="line" data-label="" points="119.48087786103275,429.2862070589199 273.4750787167836,445.84472327996843" fill="none" stroke="hsl(160, 100%, 50%, 0.8)" stroke-width="1px"/></g><g><polyline data-points="-2.55,-5.1 -2.6999999999999997,-0.3999999999999999" data-type="line" data-label="" points="273.4750787167836,445.84472327996843 268.5075238504691,290.1946708021127" fill="none" stroke="hsl(88, 100%, 50%, 0.8)" stroke-width="1px"/></g><g><polyline data-points="-2.55,-5.1 3.8499999999999996,-4.8" data-type="line" data-label="" points="273.4750787167836,445.84472327996843 485.4240863462042,435.9096135473393" fill="none" stroke="hsl(168, 100%, 50%, 0.8)" stroke-width="1px"/></g><g><polyline data-points="3.8499999999999996,-4.8 2.6999999999999997,-0.17499999999999993" data-type="line" data-label="" points="485.4240863462042,435.9096135473393 447.3394990377927,282.7433385026409" fill="none" stroke="hsl(96, 100%, 50%, 0.8)" stroke-width="1px"/></g><g><polyline data-points="4.950000000000001,-4.8 2.6999999999999997,-0.42499999999999993" data-type="line" data-label="" points="521.8528220325109,435.9096135473393 447.3394990377927,291.0225966131651" fill="none" stroke="hsl(312, 100%, 50%, 0.8)" stroke-width="1px"/></g><g><polyline data-points="-2.6999999999999997,1.5 -6.25,3" data-type="line" data-label="" points="268.5075238504691,227.27230916212847 150.94205868102486,177.596760498983" fill="none" stroke="hsl(216, 100%, 50%, 0.8)" stroke-width="1px" stroke-dasharray="4 2"/></g><g><polyline data-points="-2.6999999999999997,1.3 -5.1,3" data-type="line" data-label="" points="268.5075238504691,233.89571565054786 189.0266459894364,177.596760498983" fill="none" stroke="hsl(196, 100%, 50%, 0.8)" stroke-width="1px" stroke-dasharray="4 2"/></g><g><polyline data-points="-2.6999999999999997,1.1 0,-1.3499999999999999" data-type="line" data-label="" points="268.5075238504691,240.51912213896725 357.9235114441309,321.6558516221048" fill="none" stroke="hsl(237, 100%, 50%, 0.8)" stroke-width="1px" stroke-dasharray="4 2"/></g><g><polyline data-points="-2.6999999999999997,1.1 -7.2,-5" data-type="line" data-label="" points="268.5075238504691,240.51912213896725 119.48087786103275,442.5330200357587" fill="none" stroke="hsl(237, 100%, 50%, 0.8)" stroke-width="1px" stroke-dasharray="4 2"/></g><g><polyline data-points="-2.6999999999999997,1.1 -4.7,-2" data-type="line" data-label="" points="268.5075238504691,240.51912213896725 202.27345896627517,343.1819227094678" fill="none" stroke="hsl(237, 100%, 50%, 0.8)" stroke-width="1px" stroke-dasharray="4 2"/></g><g><polyline data-points="-2.6999999999999997,1.1 -2.55,-6.200000000000001" data-type="line" data-label="" points="268.5075238504691,240.51912213896725 273.4750787167836,482.27345896627514" fill="none" stroke="hsl(237, 100%, 50%, 0.8)" stroke-width="1px" stroke-dasharray="4 2"/></g><g><polyline data-points="0,-1.3499999999999999 -7.2,-5" data-type="line" data-label="" points="357.9235114441309,321.6558516221048 119.48087786103275,442.5330200357587" fill="none" stroke="hsl(237, 100%, 50%, 0.8)" stroke-width="1px" stroke-dasharray="4 2"/></g><g><polyline data-points="0,-1.3499999999999999 -4.7,-2" data-type="line" data-label="" points="357.9235114441309,321.6558516221048 202.27345896627517,343.1819227094678" fill="none" stroke="hsl(237, 100%, 50%, 0.8)" stroke-width="1px" stroke-dasharray="4 2"/></g><g><polyline data-points="0,-1.3499999999999999 -2.55,-6.200000000000001" data-type="line" data-label="" points="357.9235114441309,321.6558516221048 273.4750787167836,482.27345896627514" fill="none" stroke="hsl(237, 100%, 50%, 0.8)" stroke-width="1px" stroke-dasharray="4 2"/></g><g><polyline data-points="-7.2,-5 -4.7,-2" data-type="line" data-label="" points="119.48087786103275,442.5330200357587 202.27345896627517,343.1819227094678" fill="none" stroke="hsl(237, 100%, 50%, 0.8)" stroke-width="1px" stroke-dasharray="4 2"/></g><g><polyline data-points="-7.2,-5 -2.55,-6.200000000000001" data-type="line" data-label="" points="119.48087786103275,442.5330200357587 273.4750787167836,482.27345896627514" fill="none" stroke="hsl(237, 100%, 50%, 0.8)" stroke-width="1px" stroke-dasharray="4 2"/></g><g><polyline data-points="-4.7,-2 -2.55,-6.200000000000001" data-type="line" data-label="" points="202.27345896627517,343.1819227094678 273.4750787167836,482.27345896627514" fill="none" stroke="hsl(237, 100%, 50%, 0.8)" stroke-width="1px" stroke-dasharray="4 2"/></g><g><polyline data-points="-2.6999999999999997,-0.3999999999999999 2.6999999999999997,-0.17499999999999993" data-type="line" data-label="" points="268.5075238504691,290.1946708021127 447.3394990377927,282.7433385026409" fill="none" stroke="hsl(127, 100%, 50%, 0.8)" stroke-width="1px" stroke-dasharray="4 2"/></g><g><polyline data-points="-2.6999999999999997,-0.3999999999999999 -7.2,-4.6" data-type="line" data-label="" points="268.5075238504691,290.1946708021127 119.48087786103275,429.2862070589199" fill="none" stroke="hsl(127, 100%, 50%, 0.8)" stroke-width="1px" stroke-dasharray="4 2"/></g><g><polyline data-points="-2.6999999999999997,-0.3999999999999999 3.8499999999999996,-4.8" data-type="line" data-label="" points="268.5075238504691,290.1946708021127 485.4240863462042,435.9096135473393" fill="none" stroke="hsl(127, 100%, 50%, 0.8)" stroke-width="1px" stroke-dasharray="4 2"/></g><g><polyline data-points="-2.6999999999999997,-0.3999999999999999 -2.55,-5.1" data-type="line" data-label="" points="268.5075238504691,290.1946708021127 273.4750787167836,445.84472327996843" fill="none" stroke="hsl(127, 100%, 50%, 0.8)" stroke-width="1px" stroke-dasharray="4 2"/></g><g><polyline data-points="2.6999999999999997,-0.17499999999999993 -7.2,-4.6" data-type="line" data-label="" points="447.3394990377927,282.7433385026409 119.48087786103275,429.2862070589199" fill="none" stroke="hsl(127, 100%, 50%, 0.8)" stroke-width="1px" stroke-dasharray="4 2"/></g><g><polyline data-points="2.6999999999999997,-0.17499999999999993 3.8499999999999996,-4.8" data-type="line" data-label="" points="447.3394990377927,282.7433385026409 485.4240863462042,435.9096135473393" fill="none" stroke="hsl(127, 100%, 50%, 0.8)" stroke-width="1px" stroke-dasharray="4 2"/></g><g><polyline data-points="2.6999999999999997,-0.17499999999999993 -2.55,-5.1" data-type="line" data-label="" points="447.3394990377927,282.7433385026409 273.4750787167836,445.84472327996843" fill="none" stroke="hsl(127, 100%, 50%, 0.8)" stroke-width="1px" stroke-dasharray="4 2"/></g><g><polyline data-points="-7.2,-4.6 3.8499999999999996,-4.8" data-type="line" data-label="" points="119.48087786103275,429.2862070589199 485.4240863462042,435.9096135473393" fill="none" stroke="hsl(127, 100%, 50%, 0.8)" stroke-width="1px" stroke-dasharray="4 2"/></g><g><polyline data-points="-7.2,-4.6 -2.55,-5.1" data-type="line" data-label="" points="119.48087786103275,429.2862070589199 273.4750787167836,445.84472327996843" fill="none" stroke="hsl(127, 100%, 50%, 0.8)" stroke-width="1px" stroke-dasharray="4 2"/></g><g><polyline data-points="3.8499999999999996,-4.8 -2.55,-5.1" data-type="line" data-label="" points="485.4240863462042,435.9096135473393 273.4750787167836,445.84472327996843" fill="none" stroke="hsl(127, 100%, 50%, 0.8)" stroke-width="1px" stroke-dasharray="4 2"/></g><g><polyline data-points="2.6999999999999997,-0.42499999999999993 4.950000000000001,-4.8" data-type="line" data-label="" points="447.3394990377927,291.0225966131651 521.8528220325109,435.9096135473393" fill="none" stroke="hsl(71, 100%, 50%, 0.8)" stroke-width="1px" stroke-dasharray="4 2"/></g><g><polyline data-points="2.6999999999999997,0.775 -7.2,-4.8" data-type="line" data-label="" points="447.3394990377927,251.28215768264874 119.48087786103275,435.9096135473393" fill="none" stroke="hsl(247, 100%, 50%, 0.8)" stroke-width="1px" stroke-dasharray="4 2"/></g><g><polyline data-points="2.6999999999999997,0.775 7.15,3" data-type="line" data-label="" points="447.3394990377927,251.28215768264874 594.7102934051242,177.596760498983" fill="none" stroke="hsl(247, 100%, 50%, 0.8)" stroke-width="1px" stroke-dasharray="4 2"/></g><g><polyline data-points="-7.2,-4.8 7.15,3" data-type="line" data-label="" points="119.48087786103275,435.9096135473393 594.7102934051242,177.596760498983" fill="none" stroke="hsl(247, 100%, 50%, 0.8)" stroke-width="1px" stroke-dasharray="4 2"/></g><g><polyline data-points="2.6999999999999997,1.525 6,3" data-type="line" data-label="" points="447.3394990377927,226.44438335107603 556.6257060967127,177.596760498983" fill="none" stroke="hsl(189, 100%, 50%, 0.8)" stroke-width="1px" stroke-dasharray="4 2"/></g><g><polyline data-points="-6.25,4.1 -6.25,4.3 -5.1,4.3 -5.1,4.1" data-type="line" data-label="" points="150.94205868102486,141.16802481267635 150.94205868102486,134.54461832425696 189.0266459894364,134.54461832425696 189.0266459894364,141.16802481267635" fill="none" stroke="purple" stroke-width="1px"/></g><g><polyline data-points="6,4.1 6,4.3 7.15,4.3 7.15,4.1" data-type="line" data-label="" points="556.6257060967127,141.16802481267635 556.6257060967127,134.54461832425696 594.7102934051242,134.54461832425696 594.7102934051242,141.16802481267635" fill="none" stroke="purple" stroke-width="1px"/></g><g><polyline data-points="-6.25,3 -6.25,1.5 -2.6999999999999997,1.5" data-type="line" data-label="" points="150.94205868102486,177.596760498983 150.94205868102486,227.27230916212847 268.5075238504691,227.27230916212847" fill="none" stroke="purple" stroke-width="1px"/></g><g><polyline data-points="-5.1,3 -5.1,1.2999999999999998 -2.6999999999999997,1.2999999999999998" data-type="line" data-label="" points="189.0266459894364,177.596760498983 189.0266459894364,233.89571565054786 268.5075238504691,233.89571565054786" fill="none" stroke="purple" stroke-width="1px"/></g><g><polyline data-points="6,3 6,1.525 2.6999999999999997,1.525" data-type="line" data-label="" points="556.6257060967127,177.596760498983 556.6257060967127,226.44438335107603 447.3394990377927,226.44438335107603" fill="none" stroke="purple" stroke-width="1px"/></g><g><polyline data-points="2.6999999999999997,0.775 2.9,0.775 2.9,-4.8 -7.2,-4.8" data-type="line" data-label="" points="447.3394990377927,251.28215768264874 453.96290552621207,251.28215768264874 453.96290552621207,435.9096135473393 119.48087786103275,435.9096135473393" fill="none" stroke="purple" stroke-width="1px"/></g><g><polyline data-points="7.15,3 7.15,0.775 2.6999999999999997,0.775" data-type="line" data-label="" points="594.7102934051242,177.596760498983 594.7102934051242,251.28215768264874 447.3394990377927,251.28215768264874" fill="none" stroke="purple" stroke-width="1px"/></g><g><polyline data-points="-4.7,-0.8999999999999999 -4.7,0.10000000000000009 -2.6999999999999997,0.10000000000000009" data-type="line" data-label="" points="202.27345896627517,306.75318702316116 202.27345896627517,273.6361545810642 268.5075238504691,273.6361545810642" fill="none" stroke="purple" stroke-width="1px"/></g><g><polyline data-points="-2.6999999999999997,-0.3999999999999999 -3,-0.3999999999999999 -3,-2.75 -2.55,-2.75 -2.55,-5.1" data-type="line" data-label="" points="268.5075238504691,290.1946708021127 258.57241411784,290.1946708021127 258.57241411784,368.01969704104056 273.4750787167836,368.01969704104056 273.4750787167836,445.84472327996843" fill="none" stroke="purple" stroke-width="1px"/></g><g><polyline data-points="-7.2,-4.6 -2.55,-4.6 -2.55,-5.1" data-type="line" data-label="" points="119.48087786103275,429.2862070589199 273.4750787167836,429.2862070589199 273.4750787167836,445.84472327996843" fill="none" stroke="purple" stroke-width="1px"/></g><g><polyline data-points="2.6999999999999997,-0.17499999999999993 3.2749999999999995,-0.17499999999999993 3.2749999999999995,-4.8 3.8499999999999996,-4.8" data-type="line" data-label="" points="447.3394990377927,282.7433385026409 466.38179269199844,282.7433385026409 466.38179269199844,435.9096135473393 485.4240863462042,435.9096135473393" fill="none" stroke="purple" stroke-width="1px"/></g><g><polyline data-points="4.950000000000001,-4.8 5.150000000000001,-4.8 5.150000000000001,-0.42499999999999993 2.6999999999999997,-0.42499999999999993" data-type="line" data-label="" points="521.8528220325109,435.9096135473393 528.4762285209304,435.9096135473393 528.4762285209304,291.0225966131651 447.3394990377927,291.0225966131651" fill="none" stroke="purple" stroke-width="1px"/></g><g><polyline data-points="-2.7,1.0999999999999996 -3.7,1.0999999999999996 -3.7,-2.2 -4.7,-2.2 -4.7,-2" data-type="line" data-label="" points="268.50752385046906,240.51912213896725 235.39049140837213,240.51912213896725 235.39049140837213,349.8053291978872 202.27345896627517,349.8053291978872 202.27345896627517,343.1819227094678" fill="none" stroke="purple" stroke-width="1px"/></g><g><polyline data-points="0,-1.3499999999999999 0,-1.5499999999999998 -3.7,-1.5499999999999998 -3.7,1.1 -2.6999999999999997,1.1" data-type="line" data-label="" points="357.9235114441309,321.6558516221048 357.9235114441309,328.2792581105242 235.39049140837213,328.2792581105242 235.39049140837213,240.51912213896725 268.5075238504691,240.51912213896725" fill="none" stroke="purple" stroke-width="1px"/></g><g><polyline data-points="-7.2,-5 -4.7,-5 -4.7,-2" data-type="line" data-label="" points="119.48087786103275,442.5330200357587 202.27345896627517,442.5330200357587 202.27345896627517,343.1819227094678" fill="none" stroke="purple" stroke-width="1px"/></g><g><polyline data-points="-2.55,-6.200000000000001 -2.55,-6.400000000000001 -4.875,-6.400000000000001 -4.875,-5 -7.2,-5" data-type="line" data-label="" points="273.4750787167836,482.27345896627514 273.4750787167836,488.89686545469453 196.4779782889082,488.89686545469453 196.4779782889082,442.5330200357587 119.48087786103275,442.5330200357587" fill="none" stroke="purple" stroke-width="1px"/></g><g><rect data-type="rect" data-label="schematic_component_0" data-x="0" data-y="0.55" x="268.5075238504691" y="195.8111283421363" width="178.83197518732356" height="125.84472327996849" fill="hsl(24, 100%, 50%, 0.8)" stroke="black" stroke-width="0.030195942276785723"/></g><g><rect data-type="rect" data-label="schematic_component_1" data-x="-8.4" data-y="-4.8" x="40.00000000000003" y="422.6628005705005" width="79.48087786103275" height="26.493625953677622" fill="hsl(24, 100%, 50%, 0.8)" stroke="black" stroke-width="0.030195942276785723"/></g><g><rect data-type="rect" data-label="schematic_component_2" data-x="4.4" data-y="-4.8" x="485.42408634620426" y="429.46982941285" width="36.42873568630665" height="12.879568268978574" fill="hsl(24, 100%, 50%, 0.8)" stroke="black" stroke-width="0.030195942276785723"/></g><g><rect data-type="rect" data-label="schematic_component_3" data-x="-6.25" data-y="3.55" x="145.65235208614916" y="141.16802481267635" width="10.57941318975142" height="36.42873568630665" fill="hsl(24, 100%, 50%, 0.8)" stroke="black" stroke-width="0.030195942276785723"/></g><g><rect data-type="rect" data-label="schematic_component_4" data-x="-5.1" data-y="3.55" x="183.73693939456066" y="141.16802481267635" width="10.579413189751449" height="36.42873568630665" fill="hsl(24, 100%, 50%, 0.8)" stroke="black" stroke-width="0.030195942276785723"/></g><g><rect data-type="rect" data-label="schematic_component_5" data-x="6" data-y="3.55" x="551.335999501837" y="141.16802481267635" width="10.579413189751335" height="36.42873568630665" fill="hsl(24, 100%, 50%, 0.8)" stroke="black" stroke-width="0.030195942276785723"/></g><g><rect data-type="rect" data-label="schematic_component_6" data-x="7.15" data-y="3.55" x="589.4205868102484" y="141.16802481267635" width="10.579413189751449" height="36.42873568630665" fill="hsl(24, 100%, 50%, 0.8)" stroke="black" stroke-width="0.030195942276785723"/></g><g><rect data-type="rect" data-label="schematic_component_7" data-x="-4.7" data-y="-1.45" x="193.49744536911948" y="306.7531870231612" width="17.552027194311364" height="36.42873568630665" fill="hsl(24, 100%, 50%, 0.8)" stroke="black" stroke-width="0.030195942276785723"/></g><g><rect data-type="rect" data-label="schematic_component_8" data-x="-2.55" data-y="-5.65" x="264.6990651196279" y="445.84472327996843" width="17.552027194311393" height="36.42873568630671" fill="hsl(24, 100%, 50%, 0.8)" stroke="black" stroke-width="0.030195942276785723"/></g><g><rect data-type="rect" data-label="netId: SDA
2
2
  globalConnNetId: connectivity_net2" data-x="-6.49" data-y="2.25" x="135.04588310881832" y="199.12283158634602" width="15.896175572206545" height="6.623406488419391" fill="hsl(40, 100%, 50%, 0.35)" stroke="black" stroke-width="0.030195942276785723"/></g><g><rect data-type="rect" data-label="netId: SCL
3
3
  globalConnNetId: connectivity_net3" data-x="-5.34" data-y="2.15" x="173.13047041722984" y="202.43453483055572" width="15.896175572206545" height="6.623406488419391" fill="hsl(40, 100%, 50%, 0.35)" stroke="black" stroke-width="0.030195942276785723"/></g><g><rect data-type="rect" data-label="netId: PGND
4
4
  globalConnNetId: connectivity_net9" data-x="-2.55" data-y="-6.700000000000001" x="270.16337547257393" y="488.8968654546945" width="6.623406488419391" height="19.870219465258174" fill="#00000066" stroke="#000000" stroke-width="0.030195942276785723"/></g><g><rect data-type="rect" data-label="netId: C1.pin1 to U1.VDD
@@ -10,5 +10,29 @@ test("reproduces RP2040 gamepad trace routing", () => {
10
10
 
11
11
  solver.solve()
12
12
 
13
+ const finalTraces = solver
14
+ .netLabelTraceCollisionSolver!.getOutput()
15
+ .traces.filter((trace) => trace.userNetId === "GND")
16
+ const leftRailXs = new Set<number>()
17
+ const rightRailXs = new Set<number>()
18
+ for (const trace of finalTraces) {
19
+ for (let i = 0; i < trace.tracePath.length - 1; i++) {
20
+ const start = trace.tracePath[i]!
21
+ const end = trace.tracePath[i + 1]!
22
+ if (Math.abs(start.x - end.x) > 1e-6) continue
23
+ if (start.x < -1.778 - 1e-6) leftRailXs.add(start.x)
24
+ if (start.x > 1.778 + 1e-6) rightRailXs.add(start.x)
25
+ }
26
+ }
27
+
28
+ expect(leftRailXs.size).toBe(1)
29
+ expect(rightRailXs.size).toBe(1)
30
+ expect(
31
+ solver.traceCleanupSolver2!.stats.alignedRailGroupCount,
32
+ ).toBeGreaterThanOrEqual(2)
33
+ expect(
34
+ solver.traceCleanupSolver2!.stats.alignedTraceCount,
35
+ ).toBeGreaterThanOrEqual(8)
36
+
13
37
  expect(solver).toMatchSolverSnapshot(import.meta.path)
14
38
  })
@@ -0,0 +1,38 @@
1
+ import { expect, test } from "bun:test"
2
+ import type { SolvedTracePath } from "lib/solvers/SchematicTraceLinesSolver/SchematicTraceLinesSolver"
3
+ import type { InputProblem } from "lib/types/InputProblem"
4
+ import {
5
+ align,
6
+ getVerticalRailTraces,
7
+ verticalProblem,
8
+ } from "./fixtures/alignSameNetRails"
9
+
10
+ test("does not combine rails from different component sides", () => {
11
+ const traces = getVerticalRailTraces()
12
+ traces[1] = {
13
+ ...traces[1]!,
14
+ pins: traces[1]!.pins.map((item) => ({ ...item, chipId: "U2" })) as [
15
+ SolvedTracePath["pins"][0],
16
+ SolvedTracePath["pins"][1],
17
+ ],
18
+ }
19
+ const inputProblem: InputProblem = {
20
+ ...verticalProblem,
21
+ chips: [
22
+ ...verticalProblem.chips,
23
+ {
24
+ ...verticalProblem.chips[0]!,
25
+ chipId: "U2",
26
+ pins: verticalProblem.chips[0]!.pins.map((item) => ({
27
+ ...item,
28
+ pinId: item.pinId.replace("U1", "U2"),
29
+ })),
30
+ },
31
+ ],
32
+ }
33
+
34
+ const result = align(traces, { inputProblem })
35
+
36
+ expect(result.alignedRailGroupCount).toBe(0)
37
+ expect(result.traces).toEqual(traces)
38
+ })
@@ -0,0 +1,28 @@
1
+ import { expect, test } from "bun:test"
2
+ import {
3
+ align,
4
+ createTrace,
5
+ getVerticalPin,
6
+ getVerticalRailTraces,
7
+ } from "./fixtures/alignSameNetRails"
8
+
9
+ test("uses routed-trace provenance to exclude generated label connectors", () => {
10
+ const realTrace = getVerticalRailTraces()[0]!
11
+ const connector = createTrace(
12
+ "label-connector",
13
+ [
14
+ { x: -1, y: 0 },
15
+ { x: -5, y: 0 },
16
+ { x: -5, y: -2 },
17
+ { x: -1, y: -2 },
18
+ ],
19
+ [getVerticalPin("U1.2"), getVerticalPin("U1.3")],
20
+ )
21
+
22
+ const result = align([realTrace, connector], {
23
+ eligibleTraceIds: new Set([realTrace.mspPairId]),
24
+ })
25
+
26
+ expect(result.alignedRailGroupCount).toBe(0)
27
+ expect(result.traces).toEqual([realTrace, connector])
28
+ })
@@ -0,0 +1,62 @@
1
+ import { expect, test } from "bun:test"
2
+ import type { InputProblem } from "lib/types/InputProblem"
3
+ import {
4
+ align,
5
+ createTrace,
6
+ verticalProblem,
7
+ } from "./fixtures/alignSameNetRails"
8
+
9
+ test("applies the same component-side rule to horizontal rails", () => {
10
+ const inputProblem: InputProblem = {
11
+ ...verticalProblem,
12
+ chips: [
13
+ {
14
+ chipId: "U2",
15
+ center: { x: 0, y: 0 },
16
+ width: 6,
17
+ height: 2,
18
+ pins: [
19
+ { pinId: "U2.1", x: -2, y: 1, _facingDirection: "y+" },
20
+ { pinId: "U2.2", x: 0, y: 1, _facingDirection: "y+" },
21
+ { pinId: "U2.3", x: 2, y: 1, _facingDirection: "y+" },
22
+ ],
23
+ },
24
+ ],
25
+ }
26
+ const inputPins = inputProblem.chips[0]!.pins.map((inputPin) => ({
27
+ ...inputPin,
28
+ chipId: "U2",
29
+ }))
30
+ const traces = [
31
+ createTrace(
32
+ "left",
33
+ [
34
+ { x: -2, y: 1 },
35
+ { x: -2, y: 2 },
36
+ { x: 0, y: 2 },
37
+ { x: 0, y: 1 },
38
+ ],
39
+ [inputPins[0]!, inputPins[1]!],
40
+ ),
41
+ createTrace(
42
+ "right",
43
+ [
44
+ { x: 0, y: 1 },
45
+ { x: 0, y: 3 },
46
+ { x: 2, y: 3 },
47
+ { x: 2, y: 1 },
48
+ ],
49
+ [inputPins[1]!, inputPins[2]!],
50
+ ),
51
+ ]
52
+
53
+ const result = align(traces, { inputProblem })
54
+
55
+ expect(result.alignedRailGroupCount).toBe(1)
56
+ expect(result.traces[1]!.tracePath).toEqual([
57
+ { x: 0, y: 1 },
58
+ { x: 0, y: 2 },
59
+ { x: 2, y: 2 },
60
+ { x: 2, y: 1 },
61
+ ])
62
+ })
@@ -0,0 +1,36 @@
1
+ import { expect, test } from "bun:test"
2
+ import type { NetLabelPlacement } from "lib/solvers/NetLabelPlacementSolver/NetLabelPlacementSolver"
3
+ import { align, getVerticalRailTraces } from "./fixtures/alignSameNetRails"
4
+
5
+ test("preserves existing label anchors", () => {
6
+ const traces = getVerticalRailTraces()
7
+ const labels: NetLabelPlacement[] = [
8
+ {
9
+ globalConnNetId: "power-net",
10
+ netId: "POWER",
11
+ mspConnectionPairIds: ["upper"],
12
+ pinIds: ["U1.1", "U1.2"],
13
+ orientation: "x+",
14
+ anchorPoint: { x: -2, y: 1 },
15
+ center: { x: -1.8, y: 1 },
16
+ width: 0.4,
17
+ height: 0.2,
18
+ },
19
+ {
20
+ globalConnNetId: "power-net",
21
+ netId: "POWER",
22
+ mspConnectionPairIds: ["lower"],
23
+ pinIds: ["U1.2", "U1.3"],
24
+ orientation: "x+",
25
+ anchorPoint: { x: -3, y: -1 },
26
+ center: { x: -2.8, y: -1 },
27
+ width: 0.4,
28
+ height: 0.2,
29
+ },
30
+ ]
31
+
32
+ const result = align(traces, { netLabelPlacements: labels })
33
+
34
+ expect(result.alignedRailGroupCount).toBe(0)
35
+ expect(result.traces).toEqual(traces)
36
+ })
@@ -0,0 +1,42 @@
1
+ import { expect, test } from "bun:test"
2
+ import type { NetLabelPlacement } from "lib/solvers/NetLabelPlacementSolver/NetLabelPlacementSolver"
3
+ import {
4
+ align,
5
+ createTrace,
6
+ getVerticalRailTraces,
7
+ } from "./fixtures/alignSameNetRails"
8
+
9
+ test("preserves every trace joined at a net-label anchor", () => {
10
+ const rails = getVerticalRailTraces()
11
+ const anchorKeeper = createTrace(
12
+ "anchor-keeper",
13
+ [
14
+ { x: -3, y: -1 },
15
+ { x: -4, y: -1 },
16
+ ],
17
+ [
18
+ { pinId: "X1.1", chipId: "X1", x: -3, y: -1 },
19
+ { pinId: "X2.1", chipId: "X2", x: -4, y: -1 },
20
+ ],
21
+ )
22
+ const traces = [...rails, anchorKeeper]
23
+ const label: NetLabelPlacement = {
24
+ globalConnNetId: "power-net",
25
+ netId: "POWER",
26
+ mspConnectionPairIds: [anchorKeeper.mspPairId],
27
+ pinIds: anchorKeeper.pinIds,
28
+ orientation: "x-",
29
+ anchorPoint: { x: -3, y: -1 },
30
+ center: { x: -3.2, y: -1 },
31
+ width: 0.4,
32
+ height: 0.2,
33
+ }
34
+
35
+ const result = align(traces, {
36
+ netLabelPlacements: [label],
37
+ eligibleTraceIds: new Set(rails.map((trace) => trace.mspPairId)),
38
+ })
39
+
40
+ expect(result.alignedRailGroupCount).toBe(0)
41
+ expect(result.traces).toEqual(traces)
42
+ })
@@ -0,0 +1,28 @@
1
+ import { expect, test } from "bun:test"
2
+ import {
3
+ align,
4
+ getVerticalRailTraces,
5
+ verticalProblem,
6
+ } from "./fixtures/alignSameNetRails"
7
+
8
+ test("does not align through an obstacle", () => {
9
+ const traces = getVerticalRailTraces()
10
+ const result = align(traces, {
11
+ inputProblem: {
12
+ ...verticalProblem,
13
+ chips: [
14
+ ...verticalProblem.chips,
15
+ {
16
+ chipId: "barrier",
17
+ center: { x: -2.5, y: 0 },
18
+ width: 0.4,
19
+ height: 0.4,
20
+ pins: [],
21
+ },
22
+ ],
23
+ },
24
+ })
25
+
26
+ expect(result.alignedRailGroupCount).toBe(0)
27
+ expect(result.traces).toEqual(traces)
28
+ })
@@ -0,0 +1,52 @@
1
+ import { expect, test } from "bun:test"
2
+ import { SchematicTracePipelineSolver } from "lib/solvers/SchematicTracePipelineSolver/SchematicTracePipelineSolver"
3
+ import type { InputProblem } from "lib/types/InputProblem"
4
+
5
+ test("pipeline does not stretch a real loop toward a generated label connector", () => {
6
+ const inputProblem: InputProblem = {
7
+ chips: [
8
+ {
9
+ chipId: "U3",
10
+ center: { x: 0, y: 0 },
11
+ width: 2.8,
12
+ height: 1.4,
13
+ pins: [
14
+ { pinId: "U3.3", x: 1.4, y: -0.3 },
15
+ { pinId: "U3.7", x: 1.4, y: -0.5 },
16
+ ],
17
+ },
18
+ ],
19
+ directConnections: [],
20
+ netConnections: [
21
+ {
22
+ netId: "V3_3",
23
+ pinIds: ["U3.3", "U3.7"],
24
+ netLabelWidth: 0.42,
25
+ netLabelHeight: 0.6,
26
+ },
27
+ ],
28
+ textBoxes: [],
29
+ availableNetLabelOrientations: { V3_3: ["y+"] },
30
+ maxMspPairDistance: 2.4,
31
+ }
32
+ const solver = new SchematicTracePipelineSolver(inputProblem)
33
+
34
+ solver.solve()
35
+
36
+ const traces = solver.traceCleanupSolver2!.getOutput().traces
37
+ const realTrace = traces.find((trace) => trace.mspPairId === "U3.3-U3.7")!
38
+ const labelConnector = traces.find((trace) =>
39
+ trace.mspPairId.startsWith("available-net-orientation-"),
40
+ )!
41
+ expect(realTrace.tracePath).toEqual([
42
+ { x: 1.4, y: -0.3 },
43
+ { x: 1.5999999999999999, y: -0.3 },
44
+ { x: 1.5999999999999999, y: -0.5 },
45
+ { x: 1.4, y: -0.5 },
46
+ ])
47
+ expect(labelConnector.mspPairId).toBe("available-net-orientation-0-V3_3")
48
+ expect(solver.traceCleanupSolver2!.stats).toMatchObject({
49
+ alignedRailGroupCount: 0,
50
+ alignedTraceCount: 0,
51
+ })
52
+ })
@@ -0,0 +1,25 @@
1
+ import { expect, test } from "bun:test"
2
+ import { align, getVerticalRailTraces } from "./fixtures/alignSameNetRails"
3
+
4
+ test("aligns same-net rails on one component side", () => {
5
+ const result = align(getVerticalRailTraces())
6
+
7
+ expect(result).toMatchObject({
8
+ alignedRailGroupCount: 1,
9
+ alignedTraceCount: 1,
10
+ })
11
+ expect(result.traces.map((trace) => trace.tracePath)).toEqual([
12
+ [
13
+ { x: -1, y: 2 },
14
+ { x: -2, y: 2 },
15
+ { x: -2, y: 0 },
16
+ { x: -1, y: 0 },
17
+ ],
18
+ [
19
+ { x: -1, y: 0 },
20
+ { x: -2, y: 0 },
21
+ { x: -2, y: -2 },
22
+ { x: -1, y: -2 },
23
+ ],
24
+ ])
25
+ })
@@ -0,0 +1,40 @@
1
+ import { expect, test } from "bun:test"
2
+ import {
3
+ align,
4
+ createTrace,
5
+ getVerticalPin,
6
+ getVerticalRailTraces,
7
+ verticalProblem,
8
+ } from "./fixtures/alignSameNetRails"
9
+
10
+ test("keeps the baseline when alignment would only lengthen visible geometry", () => {
11
+ const traces = getVerticalRailTraces()
12
+ traces[1] = createTrace(
13
+ "lower",
14
+ [
15
+ { x: -1, y: 0 },
16
+ { x: -10, y: 0 },
17
+ { x: -10, y: -2 },
18
+ { x: -1, y: -2 },
19
+ ],
20
+ [getVerticalPin("U1.2"), getVerticalPin("U1.3")],
21
+ )
22
+ const result = align(traces, {
23
+ inputProblem: {
24
+ ...verticalProblem,
25
+ chips: [
26
+ ...verticalProblem.chips,
27
+ {
28
+ chipId: "blocks-short-candidate",
29
+ center: { x: -2, y: -1 },
30
+ width: 0.2,
31
+ height: 0.4,
32
+ pins: [],
33
+ },
34
+ ],
35
+ },
36
+ })
37
+
38
+ expect(result.alignedRailGroupCount).toBe(0)
39
+ expect(result.traces).toEqual(traces)
40
+ })
@@ -0,0 +1,89 @@
1
+ import type { NetLabelPlacement } from "lib/solvers/NetLabelPlacementSolver/NetLabelPlacementSolver"
2
+ import type { SolvedTracePath } from "lib/solvers/SchematicTraceLinesSolver/SchematicTraceLinesSolver"
3
+ import { alignSameNetRails } from "lib/solvers/TraceCleanupSolver/alignSameNetRails"
4
+ import type { InputPin, InputProblem } from "lib/types/InputProblem"
5
+
6
+ export const verticalProblem: InputProblem = {
7
+ chips: [
8
+ {
9
+ chipId: "U1",
10
+ center: { x: 0, y: 0 },
11
+ width: 2,
12
+ height: 6,
13
+ pins: [
14
+ { pinId: "U1.1", x: -1, y: 2, _facingDirection: "x-" },
15
+ { pinId: "U1.2", x: -1, y: 0, _facingDirection: "x-" },
16
+ { pinId: "U1.3", x: -1, y: -2, _facingDirection: "x-" },
17
+ ],
18
+ },
19
+ ],
20
+ directConnections: [],
21
+ netConnections: [],
22
+ textBoxes: [],
23
+ availableNetLabelOrientations: {},
24
+ }
25
+
26
+ export const getVerticalPin = (
27
+ pinId: string,
28
+ ): InputPin & { chipId: string } => {
29
+ const inputPin = verticalProblem.chips[0]!.pins.find(
30
+ (candidate) => candidate.pinId === pinId,
31
+ )!
32
+ return { ...inputPin, chipId: "U1" }
33
+ }
34
+
35
+ export const createTrace = (
36
+ mspPairId: string,
37
+ tracePath: Array<{ x: number; y: number }>,
38
+ pins: SolvedTracePath["pins"],
39
+ globalConnNetId = "power-net",
40
+ ): SolvedTracePath => ({
41
+ mspPairId,
42
+ globalConnNetId,
43
+ dcConnNetId: mspPairId,
44
+ userNetId: "POWER",
45
+ pins,
46
+ tracePath,
47
+ mspConnectionPairIds: [mspPairId],
48
+ pinIds: pins.map((item) => item.pinId),
49
+ })
50
+
51
+ export const getVerticalRailTraces = () => [
52
+ createTrace(
53
+ "upper",
54
+ [
55
+ { x: -1, y: 2 },
56
+ { x: -2, y: 2 },
57
+ { x: -2, y: 0 },
58
+ { x: -1, y: 0 },
59
+ ],
60
+ [getVerticalPin("U1.1"), getVerticalPin("U1.2")],
61
+ ),
62
+ createTrace(
63
+ "lower",
64
+ [
65
+ { x: -1, y: 0 },
66
+ { x: -3, y: 0 },
67
+ { x: -3, y: -2 },
68
+ { x: -1, y: -2 },
69
+ ],
70
+ [getVerticalPin("U1.2"), getVerticalPin("U1.3")],
71
+ ),
72
+ ]
73
+
74
+ export const align = (
75
+ traces: SolvedTracePath[],
76
+ options: {
77
+ inputProblem?: InputProblem
78
+ netLabelPlacements?: NetLabelPlacement[]
79
+ eligibleTraceIds?: ReadonlySet<string>
80
+ } = {},
81
+ ) =>
82
+ alignSameNetRails({
83
+ inputProblem: options.inputProblem ?? verticalProblem,
84
+ traces,
85
+ netLabelPlacements: options.netLabelPlacements ?? [],
86
+ eligibleTraceIds:
87
+ options.eligibleTraceIds ??
88
+ new Set(traces.map((trace) => trace.mspPairId)),
89
+ })