@tscircuit/schematic-trace-solver 0.0.183 → 0.0.185

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 (109) hide show
  1. package/dist/index.js +242 -24
  2. package/lib/solvers/SameNetJunctionAlignmentSolver/alignSameNetJunctions.ts +30 -12
  3. package/lib/solvers/SameNetJunctionAlignmentSolver/collapseRedundantSharedEndpointStubs.ts +267 -0
  4. package/lib/solvers/SameNetJunctionAlignmentSolver/collapseSameNetCycles.ts +1 -1
  5. package/lib/solvers/SameNetJunctionAlignmentSolver/getSharedPin.ts +13 -0
  6. package/lib/solvers/UnroutedTraceRecoverySolver/UnroutedTraceRecoverySolver.ts +12 -4
  7. package/package.json +1 -1
  8. package/site/bug-reports/bug-report-20260905T041712Z.page.tsx +4 -0
  9. package/tests/bug-reports/bug-report-20260706T213649Z/__snapshots__/bug-report-20260706T213649Z.snap.svg +2 -2
  10. package/tests/bug-reports/bug-report-20260706T220324Z/__snapshots__/bug-report-20260706T220324Z.snap.svg +2 -2
  11. package/tests/bug-reports/bug-report-20260707T020342Z/__snapshots__/bug-report-20260707T020342Z.snap.svg +2 -2
  12. package/tests/bug-reports/bug-report-20260707T020342Z/bug-report-20260707T020342Z.test.ts +10 -0
  13. package/tests/bug-reports/bug-report-20260707T092615Z/__snapshots__/bug-report-20260707T092615Z.snap.svg +524 -533
  14. package/tests/bug-reports/bug-report-20260707T134549Z/__snapshots__/bug-report-20260707T134549Z.snap.svg +2 -2
  15. package/tests/bug-reports/bug-report-20260707T140410Z/__snapshots__/bug-report-20260707T140410Z.snap.svg +2 -2
  16. package/tests/bug-reports/bug-report-20260707T141025Z/__snapshots__/bug-report-20260707T141025Z.snap.svg +2 -2
  17. package/tests/bug-reports/bug-report-20260707T141421Z/__snapshots__/bug-report-20260707T141421Z.snap.svg +2 -2
  18. package/tests/bug-reports/bug-report-20260707T230831Z/__snapshots__/bug-report-20260707T230831Z.snap.svg +2 -2
  19. package/tests/bug-reports/bug-report-20260708T095725Z/__snapshots__/bug-report-20260708T095725Z.snap.svg +2 -2
  20. package/tests/bug-reports/bug-report-20260716T144856Z/__snapshots__/bug-report-20260716T144856Z.snap.svg +2 -2
  21. package/tests/bug-reports/bug-report-20260717T022934Z/__snapshots__/bug-report-20260717T022934Z.snap.svg +2 -2
  22. package/tests/bug-reports/bug-report-20260717T042845Z/__snapshots__/bug-report-20260717T042845Z.snap.svg +2 -2
  23. package/tests/bug-reports/bug-report-20260721T221026Z/__snapshots__/bug-report-20260721T221026Z.snap.svg +2 -2
  24. package/tests/bug-reports/bug-report-20260724T175257Z/__snapshots__/bug-report-20260724T175257Z.snap.svg +2 -2
  25. package/tests/bug-reports/bug-report-20260728T144234Z/__snapshots__/bug-report-20260728T144234Z.snap.svg +2 -2
  26. package/tests/bug-reports/bug-report-20260728T144234Z/bug-report-20260728T144234Z.test.ts +2 -0
  27. package/tests/bug-reports/bug-report-20260730T061837Z/__snapshots__/bug-report-20260730T061837Z.snap.svg +2 -2
  28. package/tests/bug-reports/bug-report-20260730T061837Z/bug-report-20260730T061837Z.test.ts +1 -1
  29. package/tests/bug-reports/bug-report-20260731T052229Z/__snapshots__/bug-report-20260731T052229Z.snap.svg +2 -2
  30. package/tests/bug-reports/bug-report-20260804T171919Z/__snapshots__/bug-report-20260804T171919Z.snap.svg +2 -2
  31. package/tests/bug-reports/bug-report-20260804T225912Z/__snapshots__/bug-report-20260804T225912Z.snap.svg +2 -2
  32. package/tests/bug-reports/bug-report-20260805T061316Z/__snapshots__/bug-report-20260805T061316Z.snap.svg +2 -2
  33. package/tests/bug-reports/bug-report-20260806T061548Z/__snapshots__/bug-report-20260806T061548Z.snap.svg +2 -2
  34. package/tests/bug-reports/bug-report-20260815T073240Z/__snapshots__/bug-report-20260815T073240Z.snap.svg +2 -2
  35. package/tests/bug-reports/bug-report-20260819T091818Z/__snapshots__/bug-report-20260819T091818Z.snap.svg +2 -2
  36. package/tests/bug-reports/bug-report-20260825T045913Z/__snapshots__/bug-report-20260825T045913Z.snap.svg +2 -2
  37. package/tests/bug-reports/bug-report-20260825T103621Z/__snapshots__/bug-report-20260825T103621Z.snap.svg +2 -2
  38. package/tests/bug-reports/bug-report-20260826T072956Z/__snapshots__/bug-report-20260826T072956Z.snap.svg +2 -2
  39. package/tests/bug-reports/bug-report-20260901T055358Z/__snapshots__/bug-report-20260901T055358Z.snap.svg +2 -2
  40. package/tests/bug-reports/bug-report-20260901T064117Z/__snapshots__/bug-report-20260901T064117Z.snap.svg +2 -2
  41. package/tests/bug-reports/bug-report-20260901T134241Z/__snapshots__/bug-report-20260901T134241Z.snap.svg +2 -2
  42. package/tests/bug-reports/bug-report-20260902T092425Z/__snapshots__/bug-report-20260902T092425Z.snap.svg +2 -2
  43. package/tests/bug-reports/bug-report-20260905T041712Z/__snapshots__/bug-report-20260905T041712Z.snap.svg +546 -0
  44. package/tests/bug-reports/bug-report-20260905T041712Z/bug-report-20260905T041712Z.json +2023 -0
  45. package/tests/bug-reports/bug-report-20260905T041712Z/bug-report-20260905T041712Z.test.ts +33 -0
  46. package/tests/examples/__snapshots__/example02.snap.svg +2 -2
  47. package/tests/examples/__snapshots__/example13.snap.svg +2 -2
  48. package/tests/examples/__snapshots__/example14.snap.svg +2 -2
  49. package/tests/examples/__snapshots__/example15.snap.svg +2 -2
  50. package/tests/examples/__snapshots__/example18.snap.svg +2 -2
  51. package/tests/examples/__snapshots__/example19.snap.svg +2 -2
  52. package/tests/examples/__snapshots__/example21.snap.svg +2 -2
  53. package/tests/examples/__snapshots__/example27.snap.svg +2 -2
  54. package/tests/examples/__snapshots__/example29.snap.svg +2 -2
  55. package/tests/examples/__snapshots__/example42.snap.svg +2 -2
  56. package/tests/examples/__snapshots__/example45.snap.svg +2 -2
  57. package/tests/examples/__snapshots__/example46.snap.svg +2 -2
  58. package/tests/examples/__snapshots__/example47.snap.svg +2 -2
  59. package/tests/examples/__snapshots__/example51.snap.svg +2 -2
  60. package/tests/repros/__snapshots__/board-1273-trace-overlap-cycle.snap.svg +2 -2
  61. package/tests/repros/__snapshots__/board-15984-same-net-junction.snap.svg +2 -2
  62. package/tests/repros/__snapshots__/board1096-usb-label-overlap-iteration.snap.svg +2 -2
  63. package/tests/repros/__snapshots__/bugreport-001-gnd-overlap.snap.svg +2 -2
  64. package/tests/repros/__snapshots__/netlabel-connector-through-rail-label.snap.svg +2 -2
  65. package/tests/repros/__snapshots__/repro-battery-management-bq24073.snap.svg +2 -2
  66. package/tests/repros/__snapshots__/repro-bc107a-common-emitter-routing.snap.svg +2 -2
  67. package/tests/repros/__snapshots__/repro-bluetooth-controller-ground-decoupling-groups.snap.svg +2 -2
  68. package/tests/repros/__snapshots__/repro-board-589-regulator-section.snap.svg +2 -2
  69. package/tests/repros/__snapshots__/repro-board-648-esp12f-section.snap.svg +2 -2
  70. package/tests/repros/__snapshots__/repro-board-8090-power-section.snap.svg +2 -2
  71. package/tests/repros/__snapshots__/repro-bq24074-battery-charger.snap.svg +2 -2
  72. package/tests/repros/__snapshots__/repro-bq25895-cross-net-trace-overlap.snap.svg +2 -2
  73. package/tests/repros/__snapshots__/repro-bq40z60-current-sense.snap.svg +2 -2
  74. package/tests/repros/__snapshots__/repro-cc2340r5.snap.svg +2 -2
  75. package/tests/repros/__snapshots__/repro-core-ground-inline-label-fallback.snap.svg +2 -2
  76. package/tests/repros/__snapshots__/repro-esp12f-section.snap.svg +508 -0
  77. package/tests/repros/__snapshots__/repro-example35-minimize-trace-crossing.snap.svg +2 -2
  78. package/tests/repros/__snapshots__/repro-hdc2080-ground-label-alignment.snap.svg +2 -2
  79. package/tests/repros/__snapshots__/repro-hdc3020-ground-label-alignment.snap.svg +2 -2
  80. package/tests/repros/__snapshots__/repro-hub-usb-sheet.snap.svg +2 -2
  81. package/tests/repros/__snapshots__/repro-ina237-current-monitor.snap.svg +2 -2
  82. package/tests/repros/__snapshots__/repro-isolated-rs485-isow7841.snap.svg +2 -2
  83. package/tests/repros/__snapshots__/repro-mspm0l1306-capacitor-symmetry.snap.svg +2 -2
  84. package/tests/repros/__snapshots__/repro-pga300-c6-trace-alignment.snap.svg +2 -2
  85. package/tests/repros/__snapshots__/repro-pga300-redundant-ground-traces.snap.svg +2 -2
  86. package/tests/repros/__snapshots__/repro-pmp11282-isolated-dcdc.snap.svg +18 -18
  87. package/tests/repros/__snapshots__/repro-power-group-rail-labels.snap.svg +2 -2
  88. package/tests/repros/__snapshots__/repro-powerbank-3v-system-power.snap.svg +2 -2
  89. package/tests/repros/__snapshots__/repro-rectifier-trace-overlap.snap.svg +2 -2
  90. package/tests/repros/__snapshots__/repro-rp2040-gamepad-trace-alignment.snap.svg +2 -2
  91. package/tests/repros/__snapshots__/repro-rp2040-usb-cc2-ground-overlap.snap.svg +2 -2
  92. package/tests/repros/__snapshots__/repro-smartwatch-power-sheet.snap.svg +2 -2
  93. package/tests/repros/__snapshots__/repro-ti-power-output-section.snap.svg +2 -2
  94. package/tests/repros/__snapshots__/repro-tida-01389-hbridge.snap.svg +2 -2
  95. package/tests/repros/__snapshots__/repro-tida00553-j4-cell-divider.snap.svg +2 -2
  96. package/tests/repros/__snapshots__/repro-tida010076-j4-ground-bus.snap.svg +2 -2
  97. package/tests/repros/__snapshots__/repro-tida010076-page02.snap.svg +2 -2
  98. package/tests/repros/__snapshots__/repro-tmp1075-ground-label-overlap.snap.svg +2 -2
  99. package/tests/repros/__snapshots__/repro-tps61222-trace-intersection.snap.svg +2 -2
  100. package/tests/repros/__snapshots__/repro-trellis-core-gnd-net-label-overlap.snap.svg +2 -2
  101. package/tests/repros/__snapshots__/repro-type-c-vbus-led-ground-label.snap.svg +2 -2
  102. package/tests/repros/__snapshots__/repro-usb-power-vbus-label-detour.snap.svg +2 -2
  103. package/tests/repros/__snapshots__/repro130-bq27441-fuel-gauge-trace-through-c1.snap.svg +2 -2
  104. package/tests/repros/__snapshots__/repro161-power-section-autolayout.snap.svg +2 -2
  105. package/tests/repros/__snapshots__/repro48-555-timer-vcc-rail-label.snap.svg +2 -2
  106. package/tests/repros/assets/repro-esp12f-status-section.input.json +1394 -0
  107. package/tests/repros/repro-esp12f-section.test.ts +12 -0
  108. package/tests/solvers/SameNetJunctionAlignmentSolver/collapse-redundant-shared-endpoint-stubs.test.ts +101 -0
  109. package/tests/solvers/UnroutedTraceRecoverySolver/local-elbow-obstacles.test.ts +74 -0
@@ -0,0 +1,12 @@
1
+ import { expect, test } from "bun:test"
2
+ import { SchematicTracePipelineSolver } from "lib/solvers/SchematicTracePipelineSolver/SchematicTracePipelineSolver"
3
+ import inputProblem from "./assets/repro-esp12f-status-section.input.json"
4
+ import "tests/fixtures/matcher"
5
+
6
+ test("reproduces ESP-12F schematic section routing", () => {
7
+ const solver = new SchematicTracePipelineSolver(inputProblem as any)
8
+
9
+ solver.solve()
10
+
11
+ expect(solver).toMatchSolverSnapshot(import.meta.path)
12
+ })
@@ -0,0 +1,101 @@
1
+ import { expect, test } from "bun:test"
2
+ import type { Point } from "@tscircuit/math-utils"
3
+ import type { MspConnectionPairId } from "lib/solvers/MspConnectionPairSolver/MspConnectionPairSolver"
4
+ import { collapseRedundantSharedEndpointStubs } from "lib/solvers/SameNetJunctionAlignmentSolver/collapseRedundantSharedEndpointStubs"
5
+ import type { SolvedTracePath } from "lib/solvers/SchematicTraceLinesSolver/SchematicTraceLinesSolver"
6
+ import type { PinId } from "lib/types/InputProblem"
7
+
8
+ const createTrace = ({
9
+ mspPairId,
10
+ pinIds,
11
+ tracePath,
12
+ }: {
13
+ mspPairId: MspConnectionPairId
14
+ pinIds: [PinId, PinId]
15
+ tracePath: Point[]
16
+ }): SolvedTracePath => ({
17
+ mspPairId,
18
+ dcConnNetId: "gnd",
19
+ globalConnNetId: "gnd",
20
+ pins: [
21
+ { pinId: pinIds[0], chipId: "first-chip", ...tracePath[0]! },
22
+ { pinId: pinIds[1], chipId: "second-chip", ...tracePath.at(-1)! },
23
+ ],
24
+ tracePath,
25
+ mspConnectionPairIds: [mspPairId],
26
+ pinIds,
27
+ })
28
+
29
+ test("collapses one duplicate stub at a shared same-net endpoint", () => {
30
+ const traces = [
31
+ createTrace({
32
+ mspPairId: "upper-shared",
33
+ pinIds: ["upper", "shared"],
34
+ tracePath: [
35
+ { x: 0, y: 0 },
36
+ { x: 2, y: 0 },
37
+ { x: 2, y: 2 },
38
+ { x: 1, y: 2 },
39
+ ],
40
+ }),
41
+ createTrace({
42
+ mspPairId: "lower-shared",
43
+ pinIds: ["lower", "shared"],
44
+ tracePath: [
45
+ { x: 0, y: 5 },
46
+ { x: 0, y: 4 },
47
+ { x: 2, y: 4 },
48
+ { x: 2, y: 2 },
49
+ { x: 1, y: 2 },
50
+ ],
51
+ }),
52
+ ]
53
+
54
+ const result = collapseRedundantSharedEndpointStubs({
55
+ traces,
56
+ netLabelPlacements: [],
57
+ netLabelConnectorTraceIds: new Set<MspConnectionPairId>(),
58
+ multiPinNetPinIds: new Set(["shared"]),
59
+ })
60
+
61
+ expect(result.map((trace) => trace.tracePath.length)).toEqual([4, 4])
62
+ expect(result[1]?.tracePath.at(-1)).toEqual({ x: 2, y: 2 })
63
+ })
64
+
65
+ test("collapses a shared stub and partial rail overlap", () => {
66
+ const traces = [
67
+ createTrace({
68
+ mspPairId: "shared-trunk",
69
+ pinIds: ["shared", "trunk"],
70
+ tracePath: [
71
+ { x: 0, y: 0 },
72
+ { x: 0, y: -1 },
73
+ { x: -4, y: -1 },
74
+ { x: -4, y: 0 },
75
+ ],
76
+ }),
77
+ createTrace({
78
+ mspPairId: "feed-shared",
79
+ pinIds: ["feed", "shared"],
80
+ tracePath: [
81
+ { x: -1, y: 3 },
82
+ { x: -1, y: -1 },
83
+ { x: 0, y: -1 },
84
+ { x: 0, y: 0 },
85
+ ],
86
+ }),
87
+ ]
88
+
89
+ const result = collapseRedundantSharedEndpointStubs({
90
+ traces,
91
+ netLabelPlacements: [],
92
+ netLabelConnectorTraceIds: new Set<MspConnectionPairId>(),
93
+ multiPinNetPinIds: new Set(["shared"]),
94
+ })
95
+
96
+ expect(result[0]?.tracePath).toEqual(traces[0]?.tracePath)
97
+ expect(result[1]?.tracePath).toEqual([
98
+ { x: -1, y: 3 },
99
+ { x: -1, y: -1 },
100
+ ])
101
+ })
@@ -0,0 +1,74 @@
1
+ import { expect, test } from "bun:test"
2
+ import {
3
+ countPathIntersections,
4
+ getPathLength,
5
+ } from "lib/solvers/Example28Solver/geometry"
6
+ import { SchematicTracePipelineSolver } from "lib/solvers/SchematicTracePipelineSolver/SchematicTracePipelineSolver"
7
+ import { findFirstCollision } from "lib/solvers/SchematicTraceLinesSolver/SchematicTraceSingleLineSolver2/collisions"
8
+ import { UnroutedTraceRecoverySolver } from "lib/solvers/UnroutedTraceRecoverySolver/UnroutedTraceRecoverySolver"
9
+ import type { InputProblem } from "lib/types/InputProblem"
10
+ import inputProblem from "tests/bug-reports/bug-report-20260905T041712Z/bug-report-20260905T041712Z.json"
11
+
12
+ test.each(["chip", "text", "trace"] as const)(
13
+ "rejects a local recovery elbow blocked by a %s",
14
+ (obstacleKind) => {
15
+ const pipeline = new SchematicTracePipelineSolver(
16
+ structuredClone(inputProblem) as InputProblem,
17
+ )
18
+ pipeline.solveUntilPhase("unroutedTraceRecoverySolver")
19
+
20
+ const connectionPair =
21
+ pipeline.schematicTraceLinesSolver!.failedConnectionPairs.find(
22
+ (pair) => pair.mspPairId === "schematic_port_101-schematic_port_125",
23
+ )!
24
+ const problem = pipeline.inputProblem
25
+ const existingTraces = [
26
+ ...pipeline.longDistancePairSolver!.getOutput().allTracesMerged,
27
+ ]
28
+ const blockingBounds = { minX: 3.6, maxX: 3.7, minY: -8.96, maxY: -8.94 }
29
+ const blockingPath = [
30
+ { x: 3.6, y: -8.95 },
31
+ { x: 3.7, y: -8.95 },
32
+ ]
33
+
34
+ if (obstacleKind === "chip") {
35
+ problem.chips.push({
36
+ chipId: "blocking-chip",
37
+ center: { x: 3.65, y: -8.95 },
38
+ width: 0.1,
39
+ height: 0.02,
40
+ pins: [],
41
+ })
42
+ }
43
+ if (obstacleKind === "text") {
44
+ problem.textBoxes!.push({
45
+ center: { x: 3.65, y: -8.95 },
46
+ width: 0.1,
47
+ height: 0.02,
48
+ })
49
+ }
50
+ if (obstacleKind === "trace") {
51
+ const otherNetTrace = existingTraces.find(
52
+ (trace) => trace.globalConnNetId !== connectionPair.globalConnNetId,
53
+ )!
54
+ existingTraces.splice(existingTraces.indexOf(otherNetTrace), 1, {
55
+ ...otherNetTrace,
56
+ tracePath: blockingPath,
57
+ })
58
+ }
59
+
60
+ const recovery = new UnroutedTraceRecoverySolver({
61
+ inputProblem: problem,
62
+ failedConnectionPairs: [connectionPair],
63
+ alreadySolvedTraces: existingTraces,
64
+ })
65
+ recovery.solve()
66
+
67
+ expect(recovery.solved).toBe(true)
68
+ expect(recovery.solvedUnroutedTraces).toHaveLength(1)
69
+ const recoveredPath = recovery.solvedUnroutedTraces[0]!.tracePath
70
+ expect(getPathLength(recoveredPath)).toBeGreaterThan(0.8)
71
+ expect(findFirstCollision(recoveredPath, [blockingBounds])).toBeNull()
72
+ expect(countPathIntersections(recoveredPath, blockingPath)).toBe(0)
73
+ },
74
+ )