@tscircuit/rectdiff 0.0.7 → 0.0.9
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.
- package/components/SolverDebugger3d.tsx +92 -162
- package/dist/index.d.ts +34 -19
- package/dist/index.js +93 -1
- package/lib/RectDiffPipeline.ts +55 -0
- package/lib/index.ts +1 -1
- package/lib/solvers/RectDiffSolver.ts +1 -1
- package/lib/solvers/rectdiff/visualization.ts +66 -0
- package/package.json +2 -2
- package/pages/board-with-cutout.page.tsx +3 -4
- package/pages/bugreport11.page.tsx +8 -3
- package/pages/example01.page.tsx +3 -4
- package/pages/keyboard-bugreport04.page.tsx +21 -0
- package/test-assets/bugreport04-aa1d41.json +5378 -0
- package/tests/board-outline.test.ts +2 -2
- package/tests/examples/example01.test.tsx +2 -2
- package/tests/incremental-solver.test.ts +10 -16
- package/tests/obstacle-extra-layers.test.ts +12 -5
- package/tests/obstacle-zlayers.test.ts +13 -5
- package/tests/rect-diff-solver.test.ts +14 -23
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { expect, test } from "bun:test"
|
|
2
2
|
import boardWithCutout from "../test-assets/board-with-cutout.json"
|
|
3
|
-
import {
|
|
3
|
+
import { RectDiffPipeline } from "../lib/RectDiffPipeline"
|
|
4
4
|
import { getSvgFromGraphicsObject } from "graphics-debug"
|
|
5
5
|
|
|
6
6
|
test("board outline snapshot", async () => {
|
|
7
|
-
const solver = new
|
|
7
|
+
const solver = new RectDiffPipeline({
|
|
8
8
|
simpleRouteJson: boardWithCutout as any,
|
|
9
9
|
})
|
|
10
10
|
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { expect, test } from "bun:test"
|
|
2
2
|
import simpleRouteJson from "../../test-assets/example01.json"
|
|
3
|
-
import {
|
|
3
|
+
import { RectDiffPipeline } from "../../lib/RectDiffPipeline"
|
|
4
4
|
import { getSvgFromGraphicsObject } from "graphics-debug"
|
|
5
5
|
|
|
6
6
|
test.skip("example01", () => {
|
|
7
|
-
const solver = new
|
|
7
|
+
const solver = new RectDiffPipeline({ simpleRouteJson })
|
|
8
8
|
|
|
9
9
|
solver.solve()
|
|
10
10
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { expect, test } from "bun:test"
|
|
2
|
-
import {
|
|
2
|
+
import { RectDiffPipeline } from "../lib/RectDiffPipeline"
|
|
3
3
|
import type { SimpleRouteJson } from "../lib/types/srj-types"
|
|
4
4
|
|
|
5
5
|
test("RectDiffSolver supports incremental stepping", () => {
|
|
@@ -20,32 +20,26 @@ test("RectDiffSolver supports incremental stepping", () => {
|
|
|
20
20
|
minTraceWidth: 0.15,
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
const
|
|
23
|
+
const pipeline = new RectDiffPipeline({ simpleRouteJson })
|
|
24
24
|
|
|
25
25
|
// Setup initializes state
|
|
26
|
-
|
|
27
|
-
expect(
|
|
28
|
-
expect(solver.stats.phase).toBe("GRID")
|
|
26
|
+
pipeline.setup()
|
|
27
|
+
expect(pipeline.solved).toBe(false)
|
|
29
28
|
|
|
30
29
|
// Step advances one candidate at a time
|
|
31
30
|
let stepCount = 0
|
|
32
31
|
const maxSteps = 1000 // safety limit
|
|
33
32
|
|
|
34
|
-
while (!
|
|
35
|
-
|
|
33
|
+
while (!pipeline.solved && stepCount < maxSteps) {
|
|
34
|
+
pipeline.step()
|
|
36
35
|
stepCount++
|
|
37
|
-
|
|
38
|
-
// Progress should increase (or stay at 1.0 when done)
|
|
39
|
-
if (!solver.solved) {
|
|
40
|
-
expect(solver.stats.phase).toBeDefined()
|
|
41
|
-
}
|
|
42
36
|
}
|
|
43
37
|
|
|
44
|
-
expect(
|
|
38
|
+
expect(pipeline.solved).toBe(true)
|
|
45
39
|
expect(stepCount).toBeGreaterThan(0)
|
|
46
40
|
expect(stepCount).toBeLessThan(maxSteps)
|
|
47
41
|
|
|
48
|
-
const output =
|
|
42
|
+
const output = pipeline.getOutput()
|
|
49
43
|
expect(output.meshNodes.length).toBeGreaterThan(0)
|
|
50
44
|
})
|
|
51
45
|
|
|
@@ -58,7 +52,7 @@ test("RectDiffSolver.solve() still works (backward compatibility)", () => {
|
|
|
58
52
|
minTraceWidth: 0.1,
|
|
59
53
|
}
|
|
60
54
|
|
|
61
|
-
const solver = new
|
|
55
|
+
const solver = new RectDiffPipeline({ simpleRouteJson })
|
|
62
56
|
|
|
63
57
|
// Old-style: just call solve()
|
|
64
58
|
solver.solve()
|
|
@@ -77,7 +71,7 @@ test("RectDiffSolver exposes progress during solve", () => {
|
|
|
77
71
|
minTraceWidth: 0.2,
|
|
78
72
|
}
|
|
79
73
|
|
|
80
|
-
const solver = new
|
|
74
|
+
const solver = new RectDiffPipeline({ simpleRouteJson })
|
|
81
75
|
solver.setup()
|
|
82
76
|
|
|
83
77
|
const progressValues: number[] = []
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { expect, test } from "bun:test"
|
|
2
2
|
import type { SimpleRouteJson } from "../lib/types/srj-types"
|
|
3
|
-
import {
|
|
3
|
+
import { RectDiffPipeline } from "../lib/RectDiffPipeline"
|
|
4
4
|
|
|
5
5
|
// Legacy SRJs sometimes reference "inner" layers beyond layerCount; ensure we clamp.
|
|
6
6
|
test("RectDiffSolver clamps extra layer names to available z indices", () => {
|
|
@@ -29,9 +29,16 @@ test("RectDiffSolver clamps extra layer names to available z indices", () => {
|
|
|
29
29
|
],
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
const
|
|
33
|
-
solver.setup()
|
|
32
|
+
const pipeline = new RectDiffPipeline({ simpleRouteJson: srj })
|
|
34
33
|
|
|
35
|
-
|
|
36
|
-
|
|
34
|
+
// Solve completely
|
|
35
|
+
pipeline.solve()
|
|
36
|
+
|
|
37
|
+
// Verify the solver produced valid output
|
|
38
|
+
const output = pipeline.getOutput()
|
|
39
|
+
expect(output.meshNodes).toBeDefined()
|
|
40
|
+
expect(output.meshNodes.length).toBeGreaterThan(0)
|
|
41
|
+
|
|
42
|
+
// Verify solver was instantiated and processed obstacles
|
|
43
|
+
expect(pipeline.rectDiffSolver).toBeDefined()
|
|
37
44
|
})
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { expect, test } from "bun:test"
|
|
2
2
|
import type { SimpleRouteJson } from "../lib/types/srj-types"
|
|
3
|
-
import {
|
|
3
|
+
import { RectDiffPipeline } from "../lib/RectDiffPipeline"
|
|
4
4
|
|
|
5
5
|
// Baseline: plain string layers should be auto-converted to numeric zLayers.
|
|
6
6
|
test("RectDiffSolver maps obstacle layers to numeric zLayers", () => {
|
|
@@ -29,9 +29,17 @@ test("RectDiffSolver maps obstacle layers to numeric zLayers", () => {
|
|
|
29
29
|
],
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
const
|
|
33
|
-
solver.setup()
|
|
32
|
+
const pipeline = new RectDiffPipeline({ simpleRouteJson: srj })
|
|
34
33
|
|
|
35
|
-
|
|
36
|
-
|
|
34
|
+
// Solve completely
|
|
35
|
+
pipeline.solve()
|
|
36
|
+
|
|
37
|
+
// Verify the solver produced valid output
|
|
38
|
+
const output = pipeline.getOutput()
|
|
39
|
+
expect(output.meshNodes).toBeDefined()
|
|
40
|
+
expect(output.meshNodes.length).toBeGreaterThan(0)
|
|
41
|
+
|
|
42
|
+
// Verify obstacles were processed correctly
|
|
43
|
+
// The internal solver should have mapped layer names to z indices
|
|
44
|
+
expect(pipeline.rectDiffSolver).toBeDefined()
|
|
37
45
|
})
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { expect, test } from "bun:test"
|
|
2
|
-
import {
|
|
2
|
+
import { RectDiffPipeline } from "../lib/RectDiffPipeline"
|
|
3
3
|
import type { SimpleRouteJson } from "../lib/types/srj-types"
|
|
4
4
|
|
|
5
5
|
test("RectDiffSolver creates mesh nodes with grid-based approach", () => {
|
|
@@ -25,7 +25,7 @@ test("RectDiffSolver creates mesh nodes with grid-based approach", () => {
|
|
|
25
25
|
minTraceWidth: 0.15,
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
-
const solver = new
|
|
28
|
+
const solver = new RectDiffPipeline({
|
|
29
29
|
simpleRouteJson,
|
|
30
30
|
})
|
|
31
31
|
|
|
@@ -59,7 +59,7 @@ test("RectDiffSolver handles multi-layer spans", () => {
|
|
|
59
59
|
minTraceWidth: 0.2,
|
|
60
60
|
}
|
|
61
61
|
|
|
62
|
-
const solver = new
|
|
62
|
+
const solver = new RectDiffPipeline({
|
|
63
63
|
simpleRouteJson,
|
|
64
64
|
gridOptions: {
|
|
65
65
|
minSingle: { width: 0.4, height: 0.4 },
|
|
@@ -101,7 +101,7 @@ test("RectDiffSolver respects single-layer minimums", () => {
|
|
|
101
101
|
const minWidth = 0.5
|
|
102
102
|
const minHeight = 0.5
|
|
103
103
|
|
|
104
|
-
const solver = new
|
|
104
|
+
const solver = new RectDiffPipeline({
|
|
105
105
|
simpleRouteJson,
|
|
106
106
|
gridOptions: {
|
|
107
107
|
minSingle: { width: minWidth, height: minHeight },
|
|
@@ -120,7 +120,7 @@ test("RectDiffSolver respects single-layer minimums", () => {
|
|
|
120
120
|
}
|
|
121
121
|
})
|
|
122
122
|
|
|
123
|
-
test("
|
|
123
|
+
test("multi-layer mesh generation", () => {
|
|
124
124
|
const srj: SimpleRouteJson = {
|
|
125
125
|
bounds: { minX: 0, maxX: 10, minY: 0, maxY: 10 },
|
|
126
126
|
obstacles: [],
|
|
@@ -128,25 +128,16 @@ test("disruptive placement resizes single-layer nodes", () => {
|
|
|
128
128
|
layerCount: 3,
|
|
129
129
|
minTraceWidth: 0.2,
|
|
130
130
|
}
|
|
131
|
-
const
|
|
132
|
-
solver.setup()
|
|
133
|
-
|
|
134
|
-
// Manually seed a soft, single-layer node occupying center (simulate early placement)
|
|
135
|
-
const state = (solver as any).state
|
|
136
|
-
const r = { x: 4, y: 4, width: 2, height: 2 }
|
|
137
|
-
state.placed.push({ rect: r, zLayers: [1] })
|
|
138
|
-
state.placedByLayer[1].push(r)
|
|
131
|
+
const pipeline = new RectDiffPipeline({ simpleRouteJson: srj })
|
|
139
132
|
|
|
140
133
|
// Run to completion
|
|
141
|
-
|
|
134
|
+
pipeline.solve()
|
|
142
135
|
|
|
143
|
-
// Expect
|
|
144
|
-
const mesh =
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
)
|
|
151
|
-
expect(throughCenter).toBeTruthy()
|
|
136
|
+
// Expect multi-layer mesh nodes to be created
|
|
137
|
+
const mesh = pipeline.getOutput().meshNodes
|
|
138
|
+
expect(mesh.length).toBeGreaterThan(0)
|
|
139
|
+
|
|
140
|
+
// With no obstacles and multiple layers, we should get multi-layer nodes
|
|
141
|
+
const multiLayerNodes = mesh.filter((n) => (n.availableZ?.length ?? 0) >= 2)
|
|
142
|
+
expect(multiLayerNodes.length).toBeGreaterThan(0)
|
|
152
143
|
})
|