@tscircuit/schematic-trace-solver 0.0.175 → 0.0.177

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 (46) hide show
  1. package/dist/index.d.ts +3 -0
  2. package/dist/index.js +570 -17
  3. package/lib/solvers/AvailableNetOrientationSolver/AvailableNetOrientationSolver.ts +5 -1
  4. package/lib/solvers/MspConnectionPairSolver/getGroundConnectionPolicy.ts +13 -0
  5. package/lib/solvers/SameNetJunctionAlignmentSolver/SameNetJunctionAlignmentSolver.ts +2 -0
  6. package/lib/solvers/SameNetJunctionAlignmentSolver/alignSameNetJunctions.ts +748 -15
  7. package/lib/solvers/SameNetJunctionAlignmentSolver/findNearestSharedPinExitRail.ts +140 -0
  8. package/lib/solvers/SchematicTracePipelineSolver/SchematicTracePipelineSolver.ts +3 -5
  9. package/package.json +1 -1
  10. package/tests/bug-reports/bug-report-20260707T134549Z/__snapshots__/bug-report-20260707T134549Z.snap.svg +2 -2
  11. package/tests/bug-reports/bug-report-20260707T134549Z/bug-report-20260707T134549Z.test.ts +9 -0
  12. package/tests/bug-reports/bug-report-20260707T230831Z/__snapshots__/bug-report-20260707T230831Z.snap.svg +2 -2
  13. package/tests/bug-reports/bug-report-20260717T042845Z/__snapshots__/bug-report-20260717T042845Z.snap.svg +2 -2
  14. package/tests/bug-reports/bug-report-20260721T221026Z/__snapshots__/bug-report-20260721T221026Z.snap.svg +2 -2
  15. package/tests/bug-reports/bug-report-20260730T061837Z/__snapshots__/bug-report-20260730T061837Z.snap.svg +2 -2
  16. package/tests/bug-reports/bug-report-20260730T061837Z/bug-report-20260730T061837Z.test.ts +8 -4
  17. package/tests/bug-reports/bug-report-20260804T171919Z/__snapshots__/bug-report-20260804T171919Z.snap.svg +2 -2
  18. package/tests/bug-reports/bug-report-20260805T061316Z/__snapshots__/bug-report-20260805T061316Z.snap.svg +2 -2
  19. package/tests/bug-reports/bug-report-20260806T061548Z/__snapshots__/bug-report-20260806T061548Z.snap.svg +2 -2
  20. package/tests/bug-reports/bug-report-20260825T045913Z/__snapshots__/bug-report-20260825T045913Z.snap.svg +2 -2
  21. package/tests/bug-reports/bug-report-20260826T072956Z/__snapshots__/bug-report-20260826T072956Z.snap.svg +6 -6
  22. package/tests/bug-reports/bug-report-20260901T134241Z/__snapshots__/bug-report-20260901T134241Z.snap.svg +7 -7
  23. package/tests/bug-reports/bug-report-20260901T134241Z/bug-report-20260901T134241Z.test.ts +48 -0
  24. package/tests/examples/__snapshots__/example51.snap.svg +2 -2
  25. package/tests/repros/__snapshots__/board-1273-trace-overlap-cycle.snap.svg +10 -10
  26. package/tests/repros/__snapshots__/board1096-usb-label-overlap-iteration.snap.svg +2 -2
  27. package/tests/repros/__snapshots__/repro-bq25895-cross-net-trace-overlap.snap.svg +2 -2
  28. package/tests/repros/__snapshots__/repro-core-ground-inline-label-fallback.snap.svg +10 -10
  29. package/tests/repros/__snapshots__/repro-example35-minimize-trace-crossing.snap.svg +2 -2
  30. package/tests/repros/__snapshots__/repro-isolated-rs485-isow7841.snap.svg +18 -18
  31. package/tests/repros/__snapshots__/repro-pga300-redundant-ground-traces.snap.svg +18 -18
  32. package/tests/repros/__snapshots__/repro-pmp11282-isolated-dcdc.snap.svg +10 -10
  33. package/tests/repros/__snapshots__/repro-powerbank-3v-system-power.snap.svg +2 -2
  34. package/tests/repros/__snapshots__/repro-smartwatch-power-sheet.snap.svg +451 -0
  35. package/tests/repros/__snapshots__/repro-ti-power-output-section.snap.svg +2 -2
  36. package/tests/repros/__snapshots__/repro-tida-01389-hbridge.snap.svg +2 -2
  37. package/tests/repros/__snapshots__/repro-tida010076-page02.snap.svg +2 -2
  38. package/tests/repros/__snapshots__/repro161-power-section-autolayout.snap.svg +2 -2
  39. package/tests/repros/__snapshots__/repro48-555-timer-vcc-rail-label.snap.svg +2 -2
  40. package/tests/repros/assets/repro-smartwatch-power-sheet.input.json +1112 -0
  41. package/tests/repros/repro-isolated-rs485-isow7841.test.ts +4 -1
  42. package/tests/repros/repro-powerbank-3v-system-power.test.ts +24 -0
  43. package/tests/repros/repro-smartwatch-power-sheet.test.ts +27 -0
  44. package/tests/repros/repro-tida-01389-hbridge.test.ts +24 -0
  45. package/tests/solvers/MspConnectionPairSolver/ground-direct-connection-groups.test.ts +11 -0
  46. package/tests/solvers/SameNetJunctionAlignmentSolver/parallel-load-rails.test.ts +1 -0
@@ -0,0 +1,140 @@
1
+ import type { Point } from "@tscircuit/math-utils"
2
+ import { tracePathContainsPoint } from "lib/solvers/RailNetLabelCornerPlacementSolver/geometry"
3
+ import {
4
+ isHorizontal,
5
+ isVertical,
6
+ } from "lib/solvers/TraceCleanupSolver/sameNetRailAlignment/geometry"
7
+ import type { InputPin } from "lib/types/InputProblem"
8
+ import { dir } from "lib/utils/dir"
9
+
10
+ export type Axis = "x" | "y"
11
+
12
+ export interface AxisAlignedSegment {
13
+ start: Point
14
+ end: Point
15
+ axis: Axis
16
+ coordinate: number
17
+ }
18
+
19
+ export interface SharedPinExitRail {
20
+ segment: AxisAlignedSegment
21
+ sharedPinExit: Point
22
+ }
23
+
24
+ export const getPinFacingAxis = (pin: InputPin): Axis | null => {
25
+ if (!pin._facingDirection) return null
26
+ return dir(pin._facingDirection).x === 0 ? "y" : "x"
27
+ }
28
+
29
+ export const isCoordinateOnPinFacingSide = ({
30
+ coordinate,
31
+ axis,
32
+ pin,
33
+ }: {
34
+ coordinate: number
35
+ axis: Axis
36
+ pin: InputPin
37
+ }) => {
38
+ if (!pin._facingDirection) return false
39
+ const facingVector = dir(pin._facingDirection)
40
+ return (coordinate - pin[axis]) * facingVector[axis] > 0
41
+ }
42
+
43
+ const getSegmentAxis = (start: Point, end: Point): Axis | null => {
44
+ if (isHorizontal(start, end)) return "x"
45
+ if (isVertical(start, end)) return "y"
46
+ return null
47
+ }
48
+
49
+ const getAxisAlignedSegments = (path: Point[]): AxisAlignedSegment[] => {
50
+ const segments: AxisAlignedSegment[] = []
51
+ for (let index = 0; index < path.length - 1; index++) {
52
+ const start = path[index]!
53
+ const end = path[index + 1]!
54
+ const axis = getSegmentAxis(start, end)
55
+ if (!axis) continue
56
+ const coordinateAxis = axis === "x" ? "y" : "x"
57
+ segments.push({ start, end, axis, coordinate: start[coordinateAxis] })
58
+ }
59
+ return segments
60
+ }
61
+
62
+ const getPinExitPoint = ({
63
+ pin,
64
+ departureAxis,
65
+ railCoordinate,
66
+ }: {
67
+ pin: InputPin
68
+ departureAxis: Axis
69
+ railCoordinate: number
70
+ }): Point =>
71
+ departureAxis === "x"
72
+ ? { x: railCoordinate, y: pin.y }
73
+ : { x: pin.x, y: railCoordinate }
74
+
75
+ /**
76
+ * Finds the nearest existing donor rail that joins two same-side pin exits
77
+ * and is already reached by the branch leaving the shared pin.
78
+ */
79
+ export const findNearestSharedPinExitRail = ({
80
+ donorPath,
81
+ branchDepartureSegment,
82
+ sharedPin,
83
+ adjacentPin,
84
+ }: {
85
+ donorPath: Point[]
86
+ branchDepartureSegment: [Point, Point]
87
+ sharedPin: InputPin
88
+ adjacentPin: InputPin
89
+ }): SharedPinExitRail | null => {
90
+ const departureAxis = getPinFacingAxis(sharedPin)
91
+ if (!departureAxis) return null
92
+ const railAxis = departureAxis === "x" ? "y" : "x"
93
+
94
+ const branchDeparture = getAxisAlignedSegments(branchDepartureSegment)[0]
95
+ if (!branchDeparture || branchDeparture.axis !== departureAxis) return null
96
+
97
+ let nearestRail: SharedPinExitRail | null = null
98
+ let nearestDistance = Number.POSITIVE_INFINITY
99
+
100
+ for (const segment of getAxisAlignedSegments(donorPath)) {
101
+ if (segment.axis !== railAxis) continue
102
+ if (
103
+ !isCoordinateOnPinFacingSide({
104
+ coordinate: segment.coordinate,
105
+ axis: departureAxis,
106
+ pin: sharedPin,
107
+ })
108
+ ) {
109
+ continue
110
+ }
111
+
112
+ const sharedPinExit = getPinExitPoint({
113
+ pin: sharedPin,
114
+ departureAxis,
115
+ railCoordinate: segment.coordinate,
116
+ })
117
+ const adjacentPinExit = getPinExitPoint({
118
+ pin: adjacentPin,
119
+ departureAxis,
120
+ railCoordinate: segment.coordinate,
121
+ })
122
+ if (
123
+ !tracePathContainsPoint([segment.start, segment.end], sharedPinExit) ||
124
+ !tracePathContainsPoint([segment.start, segment.end], adjacentPinExit) ||
125
+ !tracePathContainsPoint(
126
+ [branchDeparture.start, branchDeparture.end],
127
+ sharedPinExit,
128
+ )
129
+ ) {
130
+ continue
131
+ }
132
+
133
+ const distance = Math.abs(segment.coordinate - sharedPin[departureAxis])
134
+ if (distance >= nearestDistance) continue
135
+ nearestRail = { segment, sharedPinExit }
136
+ nearestDistance = distance
137
+ }
138
+
139
+ return nearestRail
140
+ }
@@ -385,11 +385,7 @@ export class SchematicTracePipelineSolver extends BaseSolver {
385
385
  inputTracePaths: instance.availableNetOrientationSolver!.traces,
386
386
  globalConnMap: instance.mspConnectionPairSolver!.globalConnMap,
387
387
  traceIdsToShift: new Set(
388
- instance
389
- .availableNetOrientationSolver!.traces.filter((trace) =>
390
- trace.mspPairId.startsWith("available-net-orientation-"),
391
- )
392
- .map((trace) => trace.mspPairId),
388
+ instance.availableNetOrientationSolver!.netLabelConnectorTraceIds,
393
389
  ),
394
390
  },
395
391
  ],
@@ -571,6 +567,8 @@ export class SchematicTracePipelineSolver extends BaseSolver {
571
567
  inputProblem: instance.inputProblem,
572
568
  traces: instance.netLabelNetLabelCollisionSolver!.traces,
573
569
  netLabelPlacements: collisionOutput.netLabelPlacements,
570
+ netLabelConnectorTraceIds:
571
+ instance.availableNetOrientationSolver!.netLabelConnectorTraceIds,
574
572
  },
575
573
  ]
576
574
  },
package/package.json CHANGED
@@ -5,7 +5,7 @@
5
5
  "url": "https://github.com/tscircuit/schematic-trace-solver.git"
6
6
  },
7
7
  "main": "dist/index.js",
8
- "version": "0.0.175",
8
+ "version": "0.0.177",
9
9
  "type": "module",
10
10
  "scripts": {
11
11
  "start": "cosmos",