@tscircuit/schematic-trace-solver 0.0.31 → 0.0.33

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 (32) hide show
  1. package/CLAUDE.md +8 -0
  2. package/dist/index.d.ts +24 -53
  3. package/dist/index.js +494 -807
  4. package/lib/index.ts +1 -0
  5. package/lib/solvers/MspConnectionPairSolver/MspConnectionPairSolver.ts +54 -3
  6. package/lib/solvers/MspConnectionPairSolver/doesPairCrossRestrictedCenterLines.ts +62 -0
  7. package/lib/solvers/MspConnectionPairSolver/getMspConnectionPairsFromPins.ts +7 -2
  8. package/lib/solvers/SchematicTraceLinesSolver/SchematicTraceLinesSolver.ts +5 -11
  9. package/lib/solvers/SchematicTraceLinesSolver/SchematicTraceSingleLineSolver/SchematicTraceSingleLineSolver.ts +37 -7
  10. package/lib/solvers/SchematicTraceLinesSolver/SchematicTraceSingleLineSolver/generateElbowVariants.ts +7 -0
  11. package/lib/solvers/SchematicTraceLinesSolver/SchematicTraceSingleLineSolver2/SchematicTraceSingleLineSolver2.ts +239 -0
  12. package/lib/solvers/SchematicTraceLinesSolver/SchematicTraceSingleLineSolver2/collisions.ts +57 -0
  13. package/lib/solvers/SchematicTraceLinesSolver/SchematicTraceSingleLineSolver2/mid.ts +97 -0
  14. package/lib/solvers/SchematicTraceLinesSolver/SchematicTraceSingleLineSolver2/pathOps.ts +65 -0
  15. package/lib/solvers/SchematicTraceLinesSolver/SchematicTraceSingleLineSolver2/rect.ts +19 -0
  16. package/lib/solvers/SchematicTracePipelineSolver/SchematicTracePipelineSolver.ts +14 -14
  17. package/package.json +1 -1
  18. package/site/SchematicTracePipelineSolver/SchematicTracePipelineSolver03.page.tsx +486 -0
  19. package/site/examples/example09.page.tsx +1 -1
  20. package/tests/examples/__snapshots__/example01.snap.svg +29 -29
  21. package/tests/examples/__snapshots__/example02.snap.svg +13 -10
  22. package/tests/examples/__snapshots__/example04.snap.svg +12 -12
  23. package/tests/examples/__snapshots__/example05.snap.svg +38 -38
  24. package/tests/examples/__snapshots__/example06.snap.svg +14 -14
  25. package/tests/examples/__snapshots__/example08.snap.svg +29 -23
  26. package/tests/examples/__snapshots__/example09.snap.svg +119 -149
  27. package/tests/examples/__snapshots__/example11.snap.svg +39 -33
  28. package/tests/examples/__snapshots__/example12.snap.svg +32 -29
  29. package/tests/examples/__snapshots__/example13.snap.svg +87 -84
  30. package/tests/examples/__snapshots__/example15.snap.svg +57 -57
  31. package/tests/examples/__snapshots__/example16.snap.svg +3 -3
  32. package/tests/solvers/SchematicTracePipelineSolver/SchematicTracePipelineSolver_repro03.test.ts +491 -0
@@ -0,0 +1,97 @@
1
+ import type { Point } from "@tscircuit/math-utils"
2
+ import type { ChipWithBounds } from "./rect"
3
+
4
+ const EPS = 1e-9
5
+
6
+ export type Axis = "x" | "y"
7
+
8
+ export const aabbFromPoints = (a: Point, b: Point) => ({
9
+ minX: Math.min(a.x, b.x),
10
+ maxX: Math.max(a.x, b.x),
11
+ minY: Math.min(a.y, b.y),
12
+ maxY: Math.max(a.y, b.y),
13
+ })
14
+
15
+ export const midBetweenPointAndRect = (
16
+ axis: Axis,
17
+ p: Point,
18
+ r: ChipWithBounds,
19
+ eps = EPS,
20
+ ): number[] => {
21
+ if (axis === "x") {
22
+ if (p.x < r.minX - eps) {
23
+ return [(p.x + r.minX) / 2]
24
+ }
25
+ if (p.x > r.maxX + eps) {
26
+ return [(p.x + r.maxX) / 2]
27
+ }
28
+ // Point is within rect bounds on this axis - generate candidates on both sides
29
+ return [r.minX - 0.2, r.maxX + 0.2]
30
+ } else {
31
+ if (p.y < r.minY - eps) {
32
+ return [(p.y + r.minY) / 2]
33
+ }
34
+ if (p.y > r.maxY + eps) {
35
+ return [(p.y + r.maxY) / 2]
36
+ }
37
+ // Point is within rect bounds on this axis - generate candidates on both sides
38
+ return [r.minY - 0.2, r.maxY + 0.2]
39
+ }
40
+ }
41
+
42
+ export const candidateMidsFromSet = (
43
+ axis: Axis,
44
+ colliding: ChipWithBounds,
45
+ rectsById: Map<string, ChipWithBounds>,
46
+ collisionRectIds: Set<string>,
47
+ aabb: { minX: number; maxX: number; minY: number; maxY: number },
48
+ eps = EPS,
49
+ ): number[] => {
50
+ const setRects = [...collisionRectIds]
51
+ .map((id) => rectsById.get(id))
52
+ .filter((r): r is ChipWithBounds => !!r)
53
+
54
+ if (axis === "x") {
55
+ const leftBoundaries = [aabb.minX, ...setRects.map((r) => r.maxX)].filter(
56
+ (v) => v < colliding.minX - eps,
57
+ )
58
+ const rightBoundaries = [aabb.maxX, ...setRects.map((r) => r.minX)].filter(
59
+ (v) => v > colliding.maxX + eps,
60
+ )
61
+
62
+ const leftNeighbor =
63
+ leftBoundaries.length > 0 ? Math.max(...leftBoundaries) : undefined
64
+ const rightNeighbor =
65
+ rightBoundaries.length > 0 ? Math.min(...rightBoundaries) : undefined
66
+
67
+ const out: number[] = []
68
+ if (leftNeighbor !== undefined) {
69
+ out.push((leftNeighbor + colliding.minX) / 2)
70
+ }
71
+ if (rightNeighbor !== undefined) {
72
+ out.push((colliding.maxX + rightNeighbor) / 2)
73
+ }
74
+ return out
75
+ } else {
76
+ const bottomBoundaries = [aabb.minY, ...setRects.map((r) => r.maxY)].filter(
77
+ (v) => v < colliding.minY - eps,
78
+ )
79
+ const topBoundaries = [aabb.maxY, ...setRects.map((r) => r.minY)].filter(
80
+ (v) => v > colliding.maxY + eps,
81
+ )
82
+
83
+ const bottomNeighbor =
84
+ bottomBoundaries.length > 0 ? Math.max(...bottomBoundaries) : undefined
85
+ const topNeighbor =
86
+ topBoundaries.length > 0 ? Math.min(...topBoundaries) : undefined
87
+
88
+ const out: number[] = []
89
+ if (bottomNeighbor !== undefined) {
90
+ out.push((bottomNeighbor + colliding.minY) / 2)
91
+ }
92
+ if (topNeighbor !== undefined) {
93
+ out.push((colliding.maxY + topNeighbor) / 2)
94
+ }
95
+ return out
96
+ }
97
+ }
@@ -0,0 +1,65 @@
1
+ import type { Point } from "@tscircuit/math-utils"
2
+ import { isHorizontal, isVertical } from "./collisions"
3
+
4
+ const EPS = 1e-9
5
+
6
+ export type Axis = "x" | "y"
7
+
8
+ export const shiftSegmentOrth = (
9
+ pts: Point[],
10
+ segIndex: number,
11
+ axis: Axis,
12
+ newCoord: number,
13
+ eps = EPS,
14
+ ): Point[] | null => {
15
+ if (segIndex < 0 || segIndex >= pts.length - 1) return null
16
+ const a = pts[segIndex]!
17
+ const b = pts[segIndex + 1]!
18
+ const vert = isVertical(a, b, eps)
19
+ const horz = isHorizontal(a, b, eps)
20
+ if (!vert && !horz) return null
21
+
22
+ // Ensure axis matches orthogonal shift
23
+ if (vert && axis !== "x") return null
24
+ if (horz && axis !== "y") return null
25
+
26
+ const out = pts.map((p) => ({ ...p }))
27
+
28
+ if (axis === "x") {
29
+ if (Math.abs(a.x - newCoord) < eps && Math.abs(b.x - newCoord) < eps)
30
+ return null
31
+ out[segIndex] = { ...out[segIndex], x: newCoord }
32
+ out[segIndex + 1] = { ...out[segIndex + 1], x: newCoord }
33
+ } else {
34
+ if (Math.abs(a.y - newCoord) < eps && Math.abs(b.y - newCoord) < eps)
35
+ return null
36
+ out[segIndex] = { ...out[segIndex], y: newCoord }
37
+ out[segIndex + 1] = { ...out[segIndex + 1], y: newCoord }
38
+ }
39
+
40
+ // Prevent collapsing adjacent segments
41
+ if (segIndex - 1 >= 0) {
42
+ const p = out[segIndex - 1]!
43
+ const q = out[segIndex]!
44
+ const manhattan = Math.abs(p.x - q.x) + Math.abs(p.y - q.y)
45
+ if (manhattan < eps) return null
46
+ }
47
+ if (segIndex + 2 <= out.length - 1) {
48
+ const p = out[segIndex + 1]!
49
+ const q = out[segIndex + 2]!
50
+ const manhattan = Math.abs(p.x - q.x) + Math.abs(p.y - q.y)
51
+ if (manhattan < eps) return null
52
+ }
53
+
54
+ // Sanity: still orthogonal
55
+ for (let i = 0; i < out.length - 1; i++) {
56
+ const u = out[i]!
57
+ const v = out[i + 1]!
58
+ if (!isHorizontal(u, v, eps) && !isVertical(u, v, eps)) return null
59
+ }
60
+
61
+ return out
62
+ }
63
+
64
+ export const pathKey = (pts: Point[], decimals = 6) =>
65
+ pts.map((p) => `${p.x.toFixed(decimals)},${p.y.toFixed(decimals)}`).join("|")
@@ -0,0 +1,19 @@
1
+ import type { InputChip, InputProblem } from "lib/types/InputProblem"
2
+ import { getInputChipBounds } from "lib/solvers/GuidelinesSolver/getInputChipBounds"
3
+
4
+ export type ChipWithBounds = {
5
+ chipId: string
6
+ minX: number
7
+ minY: number
8
+ maxX: number
9
+ maxY: number
10
+ }
11
+
12
+ export const chipToRect = (chip: InputChip): ChipWithBounds => {
13
+ const b = getInputChipBounds(chip)
14
+ return { chipId: chip.chipId, ...b }
15
+ }
16
+
17
+ export const getObstacleRects = (problem: InputProblem): ChipWithBounds[] => {
18
+ return problem.chips.map(chipToRect)
19
+ }
@@ -48,7 +48,7 @@ function definePipelineStep<
48
48
 
49
49
  export class SchematicTracePipelineSolver extends BaseSolver {
50
50
  mspConnectionPairSolver?: MspConnectionPairSolver
51
- guidelinesSolver?: GuidelinesSolver
51
+ // guidelinesSolver?: GuidelinesSolver
52
52
  schematicTraceLinesSolver?: SchematicTraceLinesSolver
53
53
  traceOverlapShiftSolver?: TraceOverlapShiftSolver
54
54
  netLabelPlacementSolver?: NetLabelPlacementSolver
@@ -69,18 +69,18 @@ export class SchematicTracePipelineSolver extends BaseSolver {
69
69
  onSolved: (mspSolver) => {},
70
70
  },
71
71
  ),
72
- definePipelineStep(
73
- "guidelinesSolver",
74
- GuidelinesSolver,
75
- () => [
76
- {
77
- inputProblem: this.inputProblem,
78
- },
79
- ],
80
- {
81
- onSolved: (guidelinesSolver) => {},
82
- },
83
- ),
72
+ // definePipelineStep(
73
+ // "guidelinesSolver",
74
+ // GuidelinesSolver,
75
+ // () => [
76
+ // {
77
+ // inputProblem: this.inputProblem,
78
+ // },
79
+ // ],
80
+ // {
81
+ // onSolved: (guidelinesSolver) => {},
82
+ // },
83
+ // ),
84
84
  definePipelineStep(
85
85
  "schematicTraceLinesSolver",
86
86
  SchematicTraceLinesSolver,
@@ -90,7 +90,7 @@ export class SchematicTracePipelineSolver extends BaseSolver {
90
90
  dcConnMap: this.mspConnectionPairSolver!.dcConnMap,
91
91
  globalConnMap: this.mspConnectionPairSolver!.globalConnMap,
92
92
  inputProblem: this.inputProblem,
93
- guidelines: this.guidelinesSolver!.guidelines,
93
+ // guidelines: this.guidelinesSolver!.guidelines,
94
94
  chipMap: this.mspConnectionPairSolver!.chipMap,
95
95
  },
96
96
  ],
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@tscircuit/schematic-trace-solver",
3
3
  "main": "dist/index.js",
4
- "version": "0.0.31",
4
+ "version": "0.0.33",
5
5
  "type": "module",
6
6
  "scripts": {
7
7
  "start": "cosmos",