@tscircuit/schematic-trace-solver 0.0.187 → 0.0.189

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 (60) hide show
  1. package/dist/index.d.ts +42 -23
  2. package/dist/index.js +1053 -316
  3. package/lib/solvers/InlineNetLabelSolver/InlineNetLabelSolver.ts +612 -230
  4. package/lib/solvers/InlineNetLabelSolver/alignPortOnlyInlineNetLabelStubs.ts +2 -6
  5. package/lib/solvers/InlineNetLabelSolver/getAnchoredNetLabelRenderedBounds.ts +13 -0
  6. package/lib/solvers/InlineNetLabelSolver/getInlineLabelObstacles.ts +64 -0
  7. package/lib/solvers/InlineNetLabelSolver/getLocalTraceLabelShifts.ts +407 -0
  8. package/lib/solvers/InlineNetLabelSolver/getOutputLabelCollisions.ts +145 -0
  9. package/lib/solvers/InlineNetLabelSolver/isLabelRepresentedInline.ts +15 -0
  10. package/lib/solvers/InlineNetLabelSolver/pushAnchoredNetLabelsAwayFromInlineLabels.ts +61 -31
  11. package/lib/solvers/NetLabelNetLabelCollisionSolver/NetLabelNetLabelCollisionSolver.ts +94 -16
  12. package/lib/solvers/NetLabelToTraceSolver/NetLabelToTraceSolver.ts +4 -3
  13. package/lib/solvers/SameNetJunctionAlignmentSolver/alignSameNetJunctions.ts +7 -7
  14. package/lib/solvers/SchematicTracePipelineSolver/SchematicTracePipelineSolver.ts +3 -0
  15. package/lib/solvers/TraceCleanupSolver/sub-solver/generateLShapeRerouteCandidates.ts +5 -1
  16. package/lib/types/InputProblem.ts +2 -2
  17. package/package.json +1 -1
  18. package/site/SchematicTracePipelineSolver/repro-robot-controller-imu-tof.page.tsx +7 -0
  19. package/site/bug-reports/bug-report-20260907T110144Z.page.tsx +4 -0
  20. package/site/bug-reports/bug-report-20260907T145640Z.page.tsx +4 -0
  21. package/tests/bug-reports/bug-report-20260730T061837Z/__snapshots__/bug-report-20260730T061837Z.snap.svg +2 -2
  22. package/tests/bug-reports/bug-report-20260806T093501Z/__snapshots__/bug-report-20260806T093501Z.snap.svg +2 -2
  23. package/tests/bug-reports/bug-report-20260811T075142Z/__snapshots__/bug-report-20260811T075142Z.snap.svg +18 -18
  24. package/tests/bug-reports/bug-report-20260819T091818Z/__snapshots__/bug-report-20260819T091818Z.snap.svg +2 -2
  25. package/tests/bug-reports/bug-report-20260819T091818Z/bug-report-20260819T091818Z.test.ts +21 -0
  26. package/tests/bug-reports/bug-report-20260825T103621Z/__snapshots__/bug-report-20260825T103621Z.snap.svg +5 -38
  27. package/tests/bug-reports/bug-report-20260826T072956Z/__snapshots__/bug-report-20260826T072956Z.snap.svg +3 -9
  28. package/tests/bug-reports/bug-report-20260901T055358Z/__snapshots__/bug-report-20260901T055358Z.snap.svg +18 -30
  29. package/tests/bug-reports/bug-report-20260901T055358Z/bug-report-20260901T055358Z.test.ts +33 -0
  30. package/tests/bug-reports/bug-report-20260907T110144Z/__snapshots__/bug-report-20260907T110144Z.snap.svg +282 -0
  31. package/tests/bug-reports/bug-report-20260907T110144Z/bug-report-20260907T110144Z.json +1073 -0
  32. package/tests/bug-reports/bug-report-20260907T110144Z/bug-report-20260907T110144Z.test.ts +12 -0
  33. package/tests/bug-reports/bug-report-20260907T145640Z/__snapshots__/bug-report-20260907T145640Z.snap.svg +1107 -0
  34. package/tests/bug-reports/bug-report-20260907T145640Z/bug-report-20260907T145640Z.json +3563 -0
  35. package/tests/bug-reports/bug-report-20260907T145640Z/bug-report-20260907T145640Z.test.ts +117 -0
  36. package/tests/repros/__snapshots__/repro-battery-management-bq24073.snap.svg +4 -4
  37. package/tests/repros/__snapshots__/repro-board-648-esp12f-section.snap.svg +2 -2
  38. package/tests/repros/__snapshots__/repro-core-tb67s579ftg-inline-label-routing.snap.svg +20 -20
  39. package/tests/repros/__snapshots__/repro-esp12f-section.snap.svg +37 -55
  40. package/tests/repros/__snapshots__/repro-hub-usb-sheet.snap.svg +44 -68
  41. package/tests/repros/__snapshots__/repro-mspm0l1306-capacitor-symmetry.snap.svg +3 -9
  42. package/tests/repros/__snapshots__/repro-robot-controller-imu-tof.snap.svg +199 -0
  43. package/tests/repros/__snapshots__/repro-robot-controller-imu-tof.source.svg +33 -0
  44. package/tests/repros/__snapshots__/repro-usb-power-vbus-label-detour.snap.svg +50 -74
  45. package/tests/repros/__snapshots__/repro48-555-timer-vcc-rail-label.snap.svg +2 -2
  46. package/tests/repros/__snapshots__/rp2040-robot-controller-disconnected-gnd.snap.svg +103 -0
  47. package/tests/repros/assets/repro-robot-controller-imu-tof.input.json +540 -0
  48. package/tests/repros/assets/rp2040-robot-controller.input.json +349 -0
  49. package/tests/repros/repro-battery-management-bq24073.test.ts +13 -1
  50. package/tests/repros/repro-hub-usb-sheet.test.ts +25 -0
  51. package/tests/repros/repro-robot-controller-imu-tof.test.ts +83 -0
  52. package/tests/repros/repro-usb-power-vbus-label-detour.test.ts +59 -13
  53. package/tests/repros/rp2040-robot-controller-disconnected-gnd.test.ts +59 -0
  54. package/tests/solvers/InlineNetLabelSolver/get-anchored-net-label-rendered-bounds.test.ts +24 -0
  55. package/tests/solvers/InlineNetLabelSolver/local-trace-label-shifts.test.ts +296 -0
  56. package/tests/solvers/InlineNetLabelSolver/multi-pin-connected-components.test.ts +7 -4
  57. package/tests/solvers/InlineNetLabelSolver/push-anchored-net-labels-away.test.ts +2 -1
  58. package/tests/solvers/InlineNetLabelSolver/shared-direct-and-named-connection.test.ts +62 -0
  59. package/tests/solvers/InlineNetLabelSolver/two-pin-terminal-stubs-atomic.test.ts +9 -3
  60. package/tests/solvers/TraceCleanupSolver/perpendicular-detours-preserve-endpoints.test.ts +60 -0
@@ -0,0 +1,117 @@
1
+ import { getOutputLabelCollisions } from "lib/solvers/InlineNetLabelSolver/getOutputLabelCollisions"
2
+ import { doSegmentsIntersect } from "@tscircuit/math-utils/line-intersections"
3
+ import { expect, test } from "bun:test"
4
+ import { getAnchoredNetLabelRenderedBounds } from "lib/solvers/InlineNetLabelSolver/getAnchoredNetLabelRenderedBounds"
5
+ import { SchematicTracePipelineSolver } from "lib/solvers/SchematicTracePipelineSolver/SchematicTracePipelineSolver"
6
+ import { simplifyPath } from "lib/solvers/TraceCleanupSolver/simplifyPath"
7
+ import { segmentIntersectsRect } from "lib/solvers/SchematicTraceLinesSolver/SchematicTraceSingleLineSolver2/collisions"
8
+ import inputProblem from "./bug-report-20260907T145640Z.json"
9
+ import "tests/fixtures/matcher"
10
+
11
+ test("bug-report-20260907T145640Z", async () => {
12
+ const original = structuredClone(inputProblem)
13
+ const solver = new SchematicTracePipelineSolver(inputProblem as any, {
14
+ hideRatsNet: true,
15
+ })
16
+ solver.solve()
17
+ expect(solver.solved).toBe(true)
18
+ expect(solver.failed).toBe(false)
19
+ // This is the output consumed by core, before NetLabelToTraceSolver renders
20
+ // diagnostic terminal wires.
21
+ const output = solver.inlineNetLabelSolver!.getOutput()
22
+ // Audit the entire report, including U3, rather than selected screenshots.
23
+ expect([...getOutputLabelCollisions(output)]).toEqual([])
24
+ for (const connection of inputProblem.netConnections.filter(
25
+ (connection) => connection.allowInlineNetLabel,
26
+ )) {
27
+ expect(
28
+ output.netLabelPlacements.filter(
29
+ (label) => label.netId === connection.netId,
30
+ ),
31
+ ).toEqual([])
32
+ for (const pinId of connection.pinIds)
33
+ expect(
34
+ output.inlineNetLabelPlacements.filter(
35
+ (label) =>
36
+ label.netId === connection.netId && label.pinIds.includes(pinId),
37
+ ),
38
+ ).toHaveLength(1)
39
+ }
40
+ // Remote routes must clear entire terminal wires, including their tails
41
+ // beyond the text and terminals on the same net (the U3 SCL regression).
42
+ const terminalWireCrossings = output.inlineNetLabelPlacements.flatMap(
43
+ (label) => {
44
+ if (!label.stubTracePath) return []
45
+ const [start, end] = label.stubTracePath
46
+ return output.traces
47
+ .filter(
48
+ (trace) =>
49
+ !trace.pinIds.some((pinId) => label.pinIds.includes(pinId)) &&
50
+ trace.tracePath
51
+ .slice(1)
52
+ .some((point, index) =>
53
+ doSegmentsIntersect(
54
+ start!,
55
+ end!,
56
+ trace.tracePath[index]!,
57
+ point,
58
+ ),
59
+ ),
60
+ )
61
+ .map((trace) => ({ terminal: label.pinIds, trace: trace.mspPairId }))
62
+ },
63
+ )
64
+ expect(terminalWireCrossings).toEqual([])
65
+ // U2 pin 17 must remain connected and clear of the final signal labels.
66
+ const traceId = "schematic_port_57-schematic_port_86"
67
+ const clearedTrace = solver
68
+ .traceLabelOverlapAvoidanceSolver!.getOutput()
69
+ .traces.find((trace) => trace.mspPairId === traceId)!
70
+ const finalTrace = output.traces.find((trace) => trace.mspPairId === traceId)!
71
+ expect(finalTrace).toBeDefined()
72
+ expect(finalTrace.tracePath).toHaveLength(4)
73
+ const beforeInline = new Map(
74
+ solver
75
+ .inlineNetLabelSolver!.getConstructorParams()[0]
76
+ .traces.map((trace) => [trace.mspPairId, trace]),
77
+ )
78
+ for (const trace of output.traces) {
79
+ const before = beforeInline.get(trace.mspPairId)
80
+ if (before)
81
+ expect(simplifyPath(trace.tracePath).length).toBeLessThanOrEqual(
82
+ simplifyPath(before.tracePath).length,
83
+ )
84
+ }
85
+ expect(finalTrace.tracePath[0]).toEqual(clearedTrace.tracePath[0])
86
+ expect(finalTrace.tracePath.at(-1)).toEqual(clearedTrace.tracePath.at(-1))
87
+ for (const label of output.netLabelPlacements) {
88
+ if (label.globalConnNetId === finalTrace.globalConnNetId) continue
89
+ const bounds = getAnchoredNetLabelRenderedBounds(label)
90
+ expect(
91
+ finalTrace.tracePath
92
+ .slice(1)
93
+ .some((end, index) =>
94
+ segmentIntersectsRect(finalTrace.tracePath[index]!, end, bounds),
95
+ ),
96
+ ).toBe(false)
97
+ }
98
+ // Power labels in the supplied input are not opted in. Preserve them rather
99
+ // than overriding the caller's policy to make every label appear inline.
100
+ for (const netId of [
101
+ "PMID",
102
+ "OLED_3V",
103
+ "V3",
104
+ "PACK_P",
105
+ "GAUGE_VDD",
106
+ "BAT_SYS",
107
+ ]) {
108
+ expect(
109
+ output.netLabelPlacements.some((label) => label.netId === netId),
110
+ ).toBe(true)
111
+ expect(
112
+ output.inlineNetLabelPlacements.some((label) => label.netId === netId),
113
+ ).toBe(false)
114
+ }
115
+ expect(inputProblem).toEqual(original)
116
+ await expect(solver).toMatchSolverSnapshot(import.meta.path)
117
+ })