@tscircuit/schematic-trace-solver 0.0.179 → 0.0.181

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 (142) hide show
  1. package/dist/index.d.ts +2 -2
  2. package/dist/index.js +88 -11
  3. package/lib/solvers/AvailableNetOrientationSolver/AvailableNetOrientationSolver.ts +63 -4
  4. package/lib/solvers/AvailableNetOrientationSolver/traces.ts +36 -0
  5. package/lib/solvers/AvailableNetOrientationSolver/types.ts +1 -0
  6. package/lib/solvers/SameNetJunctionAlignmentSolver/alignSameNetJunctions.ts +29 -11
  7. package/package.json +1 -1
  8. package/tests/bug-reports/bug-report-20260706T213649Z/__snapshots__/bug-report-20260706T213649Z.snap.svg +2 -114
  9. package/tests/bug-reports/bug-report-20260706T213649Z/bug-report-20260706T213649Z.json +1 -0
  10. package/tests/bug-reports/bug-report-20260706T220324Z/__snapshots__/bug-report-20260706T220324Z.snap.svg +3 -94
  11. package/tests/bug-reports/bug-report-20260706T220324Z/bug-report-20260706T220324Z.json +1 -0
  12. package/tests/bug-reports/bug-report-20260707T092615Z/__snapshots__/bug-report-20260707T092615Z.snap.svg +533 -578
  13. package/tests/bug-reports/bug-report-20260707T092615Z/bug-report-20260707T092615Z.json +1 -0
  14. package/tests/bug-reports/bug-report-20260707T134549Z/__snapshots__/bug-report-20260707T134549Z.snap.svg +2 -37
  15. package/tests/bug-reports/bug-report-20260707T134549Z/bug-report-20260707T134549Z.json +1 -0
  16. package/tests/bug-reports/bug-report-20260707T134722Z/__snapshots__/bug-report-20260707T134722Z.snap.svg +4 -25
  17. package/tests/bug-reports/bug-report-20260707T134722Z/bug-report-20260707T134722Z.json +1 -0
  18. package/tests/bug-reports/bug-report-20260707T140410Z/__snapshots__/bug-report-20260707T140410Z.snap.svg +1 -50
  19. package/tests/bug-reports/bug-report-20260707T140410Z/bug-report-20260707T140410Z.json +1 -0
  20. package/tests/bug-reports/bug-report-20260707T141025Z/__snapshots__/bug-report-20260707T141025Z.snap.svg +1 -15
  21. package/tests/bug-reports/bug-report-20260707T141025Z/bug-report-20260707T141025Z.json +1 -0
  22. package/tests/bug-reports/bug-report-20260707T141421Z/__snapshots__/bug-report-20260707T141421Z.snap.svg +5 -33
  23. package/tests/bug-reports/bug-report-20260707T141421Z/bug-report-20260707T141421Z.json +1 -0
  24. package/tests/bug-reports/bug-report-20260707T230831Z/__snapshots__/bug-report-20260707T230831Z.snap.svg +1 -15
  25. package/tests/bug-reports/bug-report-20260707T230831Z/bug-report-20260707T230831Z.json +1 -0
  26. package/tests/bug-reports/bug-report-20260708T055430Z/__snapshots__/bug-report-20260708T055430Z.snap.svg +65 -79
  27. package/tests/bug-reports/bug-report-20260708T055430Z/bug-report-20260708T055430Z.json +1 -0
  28. package/tests/bug-reports/bug-report-20260708T095725Z/__snapshots__/bug-report-20260708T095725Z.snap.svg +1 -15
  29. package/tests/bug-reports/bug-report-20260708T095725Z/bug-report-20260708T095725Z.json +1 -0
  30. package/tests/bug-reports/bug-report-20260716T144856Z/__snapshots__/bug-report-20260716T144856Z.snap.svg +1 -43
  31. package/tests/bug-reports/bug-report-20260716T144856Z/bug-report-20260716T144856Z.json +1 -0
  32. package/tests/bug-reports/bug-report-20260717T022934Z/__snapshots__/bug-report-20260717T022934Z.snap.svg +2 -30
  33. package/tests/bug-reports/bug-report-20260717T022934Z/bug-report-20260717T022934Z.json +1 -0
  34. package/tests/bug-reports/bug-report-20260717T031704Z/__snapshots__/bug-report-20260717T031704Z.snap.svg +1 -8
  35. package/tests/bug-reports/bug-report-20260717T031704Z/bug-report-20260717T031704Z.json +1 -0
  36. package/tests/bug-reports/bug-report-20260721T221026Z/__snapshots__/bug-report-20260721T221026Z.snap.svg +1 -92
  37. package/tests/bug-reports/bug-report-20260721T221026Z/bug-report-20260721T221026Z.json +1 -0
  38. package/tests/bug-reports/bug-report-20260728T144234Z/__snapshots__/bug-report-20260728T144234Z.snap.svg +1 -29
  39. package/tests/bug-reports/bug-report-20260728T144234Z/bug-report-20260728T144234Z.json +1 -0
  40. package/tests/bug-reports/bug-report-20260728T225606Z/__snapshots__/bug-report-20260728T225606Z.snap.svg +1 -22
  41. package/tests/bug-reports/bug-report-20260728T225606Z/bug-report-20260728T225606Z.json +1 -0
  42. package/tests/bug-reports/bug-report-20260730T061837Z/__snapshots__/bug-report-20260730T061837Z.snap.svg +1 -8
  43. package/tests/bug-reports/bug-report-20260730T061837Z/bug-report-20260730T061837Z.json +1 -0
  44. package/tests/bug-reports/bug-report-20260804T095800Z/__snapshots__/bug-report-20260804T095800Z.snap.svg +1 -36
  45. package/tests/bug-reports/bug-report-20260804T095800Z/bug-report-20260804T095800Z.json +1 -0
  46. package/tests/bug-reports/bug-report-20260804T171919Z/__snapshots__/bug-report-20260804T171919Z.snap.svg +2 -121
  47. package/tests/bug-reports/bug-report-20260804T171919Z/bug-report-20260804T171919Z.json +1 -0
  48. package/tests/bug-reports/bug-report-20260804T225912Z/__snapshots__/bug-report-20260804T225912Z.snap.svg +1 -8
  49. package/tests/bug-reports/bug-report-20260804T225912Z/bug-report-20260804T225912Z.json +1 -0
  50. package/tests/bug-reports/bug-report-20260805T061316Z/__snapshots__/bug-report-20260805T061316Z.snap.svg +1 -15
  51. package/tests/bug-reports/bug-report-20260805T061316Z/bug-report-20260805T061316Z.json +1 -0
  52. package/tests/bug-reports/bug-report-20260806T061548Z/__snapshots__/bug-report-20260806T061548Z.snap.svg +1 -15
  53. package/tests/bug-reports/bug-report-20260806T061548Z/bug-report-20260806T061548Z.json +1 -0
  54. package/tests/bug-reports/bug-report-20260806T093501Z/__snapshots__/bug-report-20260806T093501Z.snap.svg +1 -22
  55. package/tests/bug-reports/bug-report-20260806T093501Z/bug-report-20260806T093501Z.json +1 -0
  56. package/tests/bug-reports/bug-report-20260811T075142Z/__snapshots__/bug-report-20260811T075142Z.snap.svg +1 -8
  57. package/tests/bug-reports/bug-report-20260811T075142Z/bug-report-20260811T075142Z.json +1 -0
  58. package/tests/bug-reports/bug-report-20260815T073240Z/__snapshots__/bug-report-20260815T073240Z.snap.svg +1 -22
  59. package/tests/bug-reports/bug-report-20260815T073240Z/bug-report-20260815T073240Z.json +1 -0
  60. package/tests/bug-reports/bug-report-20260819T091818Z/__snapshots__/bug-report-20260819T091818Z.snap.svg +1 -15
  61. package/tests/bug-reports/bug-report-20260819T091818Z/bug-report-20260819T091818Z.json +1 -0
  62. package/tests/bug-reports/bug-report-20260825T103621Z/__snapshots__/bug-report-20260825T103621Z.snap.svg +1 -29
  63. package/tests/bug-reports/bug-report-20260825T103621Z/bug-report-20260825T103621Z.json +1 -0
  64. package/tests/bug-reports/bug-report-20260826T072956Z/__snapshots__/bug-report-20260826T072956Z.snap.svg +31 -95
  65. package/tests/bug-reports/bug-report-20260826T072956Z/bug-report-20260826T072956Z.json +1 -0
  66. package/tests/repros/__snapshots__/board-1273-trace-overlap-cycle.snap.svg +1 -113
  67. package/tests/repros/__snapshots__/board-15984-same-net-junction.snap.svg +1 -29
  68. package/tests/repros/__snapshots__/board1096-usb-label-overlap-iteration.snap.svg +64 -56
  69. package/tests/repros/__snapshots__/bugreport-001-gnd-overlap.snap.svg +1 -15
  70. package/tests/repros/__snapshots__/netlabel-connector-through-rail-label.snap.svg +1 -22
  71. package/tests/repros/__snapshots__/repro-atmega328p-missing-gnd-netlabel.snap.svg +185 -186
  72. package/tests/repros/__snapshots__/repro-board-589-regulator-section.snap.svg +1 -15
  73. package/tests/repros/__snapshots__/repro-board-648-esp12f-section.snap.svg +1 -15
  74. package/tests/repros/__snapshots__/repro-board-8090-power-section.snap.svg +126 -0
  75. package/tests/repros/__snapshots__/repro-bq24074-battery-charger.snap.svg +1 -29
  76. package/tests/repros/__snapshots__/repro-bq25895-cross-net-trace-overlap.snap.svg +1 -8
  77. package/tests/repros/__snapshots__/repro-cc2340r5.snap.svg +1 -15
  78. package/tests/repros/__snapshots__/repro-example35-minimize-trace-crossing.snap.svg +1 -8
  79. package/tests/repros/__snapshots__/repro-hub-usb-sheet.snap.svg +545 -0
  80. package/tests/repros/__snapshots__/repro-ina237-current-monitor.snap.svg +1 -22
  81. package/tests/repros/__snapshots__/repro-isolated-rs485-isow7841.snap.svg +2 -2
  82. package/tests/repros/__snapshots__/repro-mcp73831-charger-traces.snap.svg +131 -0
  83. package/tests/repros/__snapshots__/repro-missing-trace-netlabel.snap.svg +1 -15
  84. package/tests/repros/__snapshots__/repro-mouse-switch-ground-unnecessary-jog.snap.svg +83 -0
  85. package/tests/repros/__snapshots__/repro-mspm0l1306-capacitor-symmetry.snap.svg +1 -29
  86. package/tests/repros/__snapshots__/repro-netlabel-overlap-trace.snap.svg +1 -8
  87. package/tests/repros/__snapshots__/repro-nrf52810-clock-routing.snap.svg +1 -29
  88. package/tests/repros/__snapshots__/repro-pmp11282-isolated-dcdc.snap.svg +2 -2
  89. package/tests/repros/__snapshots__/repro-powerbank-3v-system-power.snap.svg +1 -29
  90. package/tests/repros/__snapshots__/repro-rf1-unnecessary-dogleg.snap.svg +72 -0
  91. package/tests/repros/__snapshots__/repro-rp2040-gamepad-trace-alignment.snap.svg +1 -8
  92. package/tests/repros/__snapshots__/repro-rp2040-usb-cc2-ground-overlap.snap.svg +1 -8
  93. package/tests/repros/__snapshots__/repro-smartwatch-power-sheet.snap.svg +4 -4
  94. package/tests/repros/__snapshots__/repro-tps61222-trace-intersection.snap.svg +1 -8
  95. package/tests/repros/__snapshots__/repro-usb-power-vbus-label-detour.snap.svg +991 -1091
  96. package/tests/repros/__snapshots__/repro130-bq27441-fuel-gauge-trace-through-c1.snap.svg +2 -2
  97. package/tests/repros/__snapshots__/repro161-power-section-autolayout.snap.svg +1 -15
  98. package/tests/repros/__snapshots__/repro48-555-timer-vcc-rail-label.snap.svg +1 -22
  99. package/tests/repros/__snapshots__/repro51-overlap-junction-crossing.snap.svg +1 -15
  100. package/tests/repros/__snapshots__/small-variant-resistor-facing-direction.snap.svg +65 -79
  101. package/tests/repros/__snapshots__/trace-overlap-box-resistor.snap.svg +1 -8
  102. package/tests/repros/assets/board-1273-trace-overlap-cycle.input.json +1 -0
  103. package/tests/repros/assets/board-15984-schematic-trace-input.json +1 -0
  104. package/tests/repros/assets/bugreport-001-gnd-overlap.input.json +1 -0
  105. package/tests/repros/assets/repro-atmega328p-fault-pullup.input.json +1 -0
  106. package/tests/repros/assets/repro-atmega328p-missing-gnd-netlabel.input.json +1 -0
  107. package/tests/repros/assets/repro-board-589-regulator-section.input.json +1 -0
  108. package/tests/repros/assets/repro-board-648-esp12f-section.input.json +1 -0
  109. package/tests/repros/assets/repro-board-8090-power-section.input.json +322 -0
  110. package/tests/repros/assets/repro-bq24074-battery-charger.input.json +1 -0
  111. package/tests/repros/assets/repro-bq25895-cross-net-trace-overlap.input.json +1 -0
  112. package/tests/repros/assets/repro-cc2340r5.input.json +1 -0
  113. package/tests/repros/assets/repro-example35-minimize-trace-crossing.input.json +1 -0
  114. package/tests/repros/assets/repro-hub-usb-sheet.input.json +3967 -0
  115. package/tests/repros/assets/repro-ina237-current-monitor.input.json +1 -0
  116. package/tests/repros/assets/repro-mcp73831-charger-traces.input.json +256 -0
  117. package/tests/repros/assets/repro-missing-trace-netlabel.input.json +1 -0
  118. package/tests/repros/assets/repro-mouse-switch-ground-unnecessary-jog.input.json +158 -0
  119. package/tests/repros/assets/repro-mspm0l1306-capacitor-symmetry.input.json +1 -0
  120. package/tests/repros/assets/repro-netlabel-connector-through-label.input.json +1 -0
  121. package/tests/repros/assets/repro-netlabel-overlap-trace.input.json +1 -0
  122. package/tests/repros/assets/repro-nrf52810-clock-routing.input.json +1 -0
  123. package/tests/repros/assets/repro-powerbank-3v-system-power.input.json +1 -0
  124. package/tests/repros/assets/repro-rf1-unnecessary-dogleg.input.json +90 -0
  125. package/tests/repros/assets/repro-rp2040-gamepad-trace-alignment.input.json +1 -0
  126. package/tests/repros/assets/repro-rp2040-usb-cc2-ground-overlap.input.json +1 -0
  127. package/tests/repros/assets/repro-tps61222-trace-intersection.input.json +1 -0
  128. package/tests/repros/assets/repro-usb-power-vbus-label-detour.input.json +1 -0
  129. package/tests/repros/assets/repro126-trace-overlap-box-resistor.input.json +1 -0
  130. package/tests/repros/assets/repro161-power-section-autolayout.input.json +1 -0
  131. package/tests/repros/assets/repro48-555-timer-vcc-rail-label.input.json +1 -0
  132. package/tests/repros/assets/repro51-overlap-junction-crossing.input.json +1 -0
  133. package/tests/repros/assets/small-variant-resistor-facing-direction.input.json +1 -0
  134. package/tests/repros/board1096-usb-label-overlap-iteration.json +1 -0
  135. package/tests/repros/board1096-usb-label-overlap-iteration.test.ts +1 -1
  136. package/tests/repros/repro-battery-management-bq24073.test.ts +17 -0
  137. package/tests/repros/repro-board-8090-power-section.test.ts +18 -0
  138. package/tests/repros/repro-hub-usb-sheet.test.ts +56 -0
  139. package/tests/repros/repro-mcp73831-charger-traces.test.ts +16 -0
  140. package/tests/repros/repro-mouse-switch-ground-unnecessary-jog.test.ts +15 -0
  141. package/tests/repros/repro-rf1-unnecessary-dogleg.test.ts +15 -0
  142. package/tests/repros/repro-smartwatch-power-sheet.test.ts +31 -5
@@ -5,6 +5,8 @@ import type { FacingDirection } from "lib/utils/dir"
5
5
  import "tests/fixtures/matcher"
6
6
  import inputProblem from "./assets/repro-battery-management-bq24073.input.json"
7
7
 
8
+ const EXPECTED_BOTTOM_GROUND_LABEL_X = 1.1
9
+
8
10
  const getPinPair = (pinIds: string[]): [string, string] => {
9
11
  if (pinIds.length !== 2) {
10
12
  throw new Error(`Expected two pin IDs, received ${pinIds.length}`)
@@ -57,6 +59,21 @@ test("repro BatteryManagement_BQ24073 schematic traces", () => {
57
59
  const solver = new SchematicTracePipelineSolver(solverInput)
58
60
  solver.solve()
59
61
 
62
+ const output = solver.netLabelToTraceSolver!.getOutput()
63
+ const groundNetIds = new Set(
64
+ solverInput.netConnections
65
+ .filter((connection) => connection.isGround)
66
+ .map((connection) => connection.netId),
67
+ )
68
+ const bottomGroundLabel = output.netLabelPlacements
69
+ .filter(
70
+ (label) => label.netId !== undefined && groundNetIds.has(label.netId),
71
+ )
72
+ .sort((first, second) => first.anchorPoint.y - second.anchorPoint.y)[0]!
73
+
60
74
  expect(solver.inlineNetLabelSolver!.stats.pushedAnchoredNetLabelCount).toBe(1)
75
+ expect(bottomGroundLabel.anchorPoint.x).toBeCloseTo(
76
+ EXPECTED_BOTTOM_GROUND_LABEL_X,
77
+ )
61
78
  expect(solver).toMatchSolverSnapshot(import.meta.path)
62
79
  })
@@ -0,0 +1,18 @@
1
+ import { expect, test } from "bun:test"
2
+ import { SchematicTracePipelineSolver } from "lib/solvers/SchematicTracePipelineSolver/SchematicTracePipelineSolver"
3
+ import type { InputProblem } from "lib/types/InputProblem"
4
+ import "tests/fixtures/matcher"
5
+ import inputProblem from "./assets/repro-board-8090-power-section.input.json"
6
+
7
+ // Isolated from board 8090's power section: battery and solar inputs,
8
+ // BAT54S selection, MCP1700 regulation, and the three local support components.
9
+ test("board 8090 power section routing", () => {
10
+ const solver = new SchematicTracePipelineSolver(inputProblem as InputProblem)
11
+
12
+ solver.solve()
13
+
14
+ expect(
15
+ solver.sameNetJunctionAlignmentSolver?.stats.alignedJunctionCount,
16
+ ).toBe(1)
17
+ expect(solver).toMatchSolverSnapshot(import.meta.path)
18
+ })
@@ -0,0 +1,56 @@
1
+ import { expect, test } from "bun:test"
2
+ import { tracePathContainsPoint } from "lib/solvers/RailNetLabelCornerPlacementSolver/geometry"
3
+ import { SchematicTracePipelineSolver } from "lib/solvers/SchematicTracePipelineSolver/SchematicTracePipelineSolver"
4
+ import { isVertical } from "lib/solvers/TraceCleanupSolver/sameNetRailAlignment/geometry"
5
+ import type { InputChip, InputProblem, PinId } from "lib/types/InputProblem"
6
+ import "tests/fixtures/matcher"
7
+ import inputProblemJson from "./assets/repro-hub-usb-sheet.input.json"
8
+
9
+ // Captured from @tsci/mohan-bee.hub 1.0.12 using @tscircuit/core 0.0.1816.
10
+ // Only opaque schematic component IDs were replaced with unique source names.
11
+ test("repro hub USB sheet schematic trace routing", () => {
12
+ const inputProblem: InputProblem = JSON.parse(
13
+ JSON.stringify(inputProblemJson),
14
+ )
15
+ const solver = new SchematicTracePipelineSolver(inputProblem)
16
+
17
+ solver.solve()
18
+
19
+ const output = solver.netLabelToTraceSolver!.getOutput()
20
+ const groundNetIds = new Set(
21
+ inputProblem.netConnections
22
+ .filter((connection) => connection.isGround)
23
+ .map((connection) => connection.netId),
24
+ )
25
+ const pinChipMap = new Map<PinId, InputChip>(
26
+ inputProblem.chips.flatMap((chip) =>
27
+ chip.pins.map((pin) => [pin.pinId, chip] as const),
28
+ ),
29
+ )
30
+ const sameChipGroundLabel = output.netLabelPlacements.find((label) => {
31
+ if (
32
+ label.pinIds.length !== 2 ||
33
+ label.netId === undefined ||
34
+ !groundNetIds.has(label.netId)
35
+ ) {
36
+ return false
37
+ }
38
+ const firstChip = pinChipMap.get(label.pinIds[0]!)
39
+ const secondChip = pinChipMap.get(label.pinIds[1]!)
40
+ return firstChip === secondChip && (firstChip?.pins.length ?? 0) > 2
41
+ })!
42
+ const sameChipGroundHostTrace = output.traces.find((trace) =>
43
+ sameChipGroundLabel.mspConnectionPairIds.includes(trace.mspPairId),
44
+ )!
45
+ const verticalHostPoint = sameChipGroundHostTrace.tracePath.find(
46
+ (point, index, path) => index > 0 && isVertical(path[index - 1]!, point),
47
+ )!
48
+ const tracesAtSameChipGroundLabel = output.traces.filter((trace) =>
49
+ tracePathContainsPoint(trace.tracePath, sameChipGroundLabel.anchorPoint),
50
+ )
51
+
52
+ expect(sameChipGroundLabel.orientation).toBe("y-")
53
+ expect(sameChipGroundLabel.anchorPoint.x).toBeCloseTo(verticalHostPoint.x)
54
+ expect(tracesAtSameChipGroundLabel).toHaveLength(1)
55
+ expect(solver).toMatchSolverSnapshot(import.meta.path)
56
+ })
@@ -0,0 +1,16 @@
1
+ import { expect, test } from "bun:test"
2
+ import { SchematicTracePipelineSolver } from "lib/solvers/SchematicTracePipelineSolver/SchematicTracePipelineSolver"
3
+ import "tests/fixtures/matcher"
4
+ import inputProblem from "./assets/repro-mcp73831-charger-traces.input.json"
5
+
6
+ // Captured from @tscircuit/core 0.0.1829 at commit b761dc8.
7
+ // The source circuit contains only the MCP73831 charger, its programming and
8
+ // LED resistors, VBAT capacitor, and LED. This preserves the long CHG_STAT path
9
+ // needed to reproduce the VBAT label crossing it.
10
+ test("repro VBAT label crossing the MCP73831 CHG_STAT trace", () => {
11
+ const solver = new SchematicTracePipelineSolver(inputProblem as any)
12
+
13
+ solver.solve()
14
+
15
+ expect(solver).toMatchSolverSnapshot(import.meta.path)
16
+ })
@@ -0,0 +1,15 @@
1
+ import { expect, test } from "bun:test"
2
+ import { SchematicTracePipelineSolver } from "lib/solvers/SchematicTracePipelineSolver/SchematicTracePipelineSolver"
3
+ import "tests/fixtures/matcher"
4
+ import inputProblem from "./assets/repro-mouse-switch-ground-unnecessary-jog.input.json"
5
+
6
+ // Captured from @tscircuit/core 0.0.1829 at commit b761dc8.
7
+ // The GND route should use one straight vertical trunk between its terminal
8
+ // stubs instead of adding the unnecessary horizontal step near the midpoint.
9
+ test("repro unnecessary jog in mouse switch ground trunk", () => {
10
+ const solver = new SchematicTracePipelineSolver(inputProblem as any)
11
+
12
+ solver.solve()
13
+
14
+ expect(solver).toMatchSolverSnapshot(import.meta.path)
15
+ })
@@ -0,0 +1,15 @@
1
+ import { expect, test } from "bun:test"
2
+ import { SchematicTracePipelineSolver } from "lib/solvers/SchematicTracePipelineSolver/SchematicTracePipelineSolver"
3
+ import "tests/fixtures/matcher"
4
+ import inputProblem from "./assets/repro-rf1-unnecessary-dogleg.input.json"
5
+
6
+ // Captured from @tscircuit/core 0.0.1829 at commit b761dc8.
7
+ // The nearly level RF1 endpoints should produce an effectively straight trace,
8
+ // rather than a clearance-sized dogleg between the two inductors.
9
+ test("repro RF1 unnecessary dogleg between aligned inductors", () => {
10
+ const solver = new SchematicTracePipelineSolver(inputProblem as any)
11
+
12
+ solver.solve()
13
+
14
+ expect(solver).toMatchSolverSnapshot(import.meta.path)
15
+ })
@@ -1,9 +1,13 @@
1
1
  import { expect, test } from "bun:test"
2
+ import { tracePathContainsPoint } from "lib/solvers/RailNetLabelCornerPlacementSolver/geometry"
2
3
  import { SchematicTracePipelineSolver } from "lib/solvers/SchematicTracePipelineSolver/SchematicTracePipelineSolver"
4
+ import { isVertical } from "lib/solvers/TraceCleanupSolver/sameNetRailAlignment/geometry"
3
5
  import type { InputProblem } from "lib/types/InputProblem"
4
6
  import "tests/fixtures/matcher"
5
7
  import inputProblem from "./assets/repro-smartwatch-power-sheet.input.json"
6
8
 
9
+ const MIN_CONNECTOR_GROUND_RAIL_EXTENSION = 0.2
10
+
7
11
  test("smartwatch power sheet", () => {
8
12
  const solver = new SchematicTracePipelineSolver(
9
13
  inputProblem as unknown as InputProblem,
@@ -17,11 +21,33 @@ test("smartwatch power sheet", () => {
17
21
  "schematic_port_0",
18
22
  "schematic_port_11",
19
23
  ])
20
- const connectorGroundLabels = solver
21
- .netLabelToTraceSolver!.getOutput()
22
- .netLabelPlacements.filter((label) =>
23
- label.pinIds.some((pinId) => connectorGroundPinIds.has(pinId)),
24
- )
24
+ const output = solver.netLabelToTraceSolver!.getOutput()
25
+ const connectorGroundLabels = output.netLabelPlacements.filter((label) =>
26
+ label.pinIds.some((pinId) => connectorGroundPinIds.has(pinId)),
27
+ )
25
28
  expect(connectorGroundLabels).toHaveLength(1)
29
+ const connectorGroundLabel = connectorGroundLabels[0]!
30
+ const connectorGroundPins = inputProblem.chips.flatMap((chip) =>
31
+ chip.pins.filter((pin) => connectorGroundPinIds.has(pin.pinId)),
32
+ )
33
+ const connectorGroundHostTrace = output.traces.find((trace) =>
34
+ connectorGroundLabel.mspConnectionPairIds.includes(trace.mspPairId),
35
+ )!
36
+ const verticalHostPoint = connectorGroundHostTrace.tracePath.find(
37
+ (point, index, path) => index > 0 && isVertical(path[index - 1]!, point),
38
+ )!
39
+ const lowestConnectorGroundPinY = Math.min(
40
+ ...connectorGroundPins.map((pin) => pin.y),
41
+ )
42
+ const tracesAtConnectorGroundLabel = output.traces.filter((trace) =>
43
+ tracePathContainsPoint(trace.tracePath, connectorGroundLabel.anchorPoint),
44
+ )
45
+
46
+ expect(connectorGroundLabel.orientation).toBe("y-")
47
+ expect(connectorGroundLabel.anchorPoint.x).toBeCloseTo(verticalHostPoint.x)
48
+ expect(connectorGroundLabel.anchorPoint.y).toBeCloseTo(
49
+ lowestConnectorGroundPinY - MIN_CONNECTOR_GROUND_RAIL_EXTENSION,
50
+ )
51
+ expect(tracesAtConnectorGroundLabel).toHaveLength(1)
26
52
  expect(solver).toMatchSolverSnapshot(import.meta.path)
27
53
  })