@tscircuit/rectdiff 0.0.17 → 0.0.18
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/lib/fixtures/twoNodeExpansionFixture.ts +66 -0
- package/package.json +1 -1
- package/pages/features/should-expand-node.page.tsx +13 -0
- package/tests/__snapshots__/should-expand-node.snap.svg +2 -2
- package/tests/should-expand-node.test.ts +7 -16
- package/pages/gap-fill-h-shape-should-expand-node.page.tsx +0 -23
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import RBush from "rbush"
|
|
2
|
+
import type {
|
|
3
|
+
RectDiffExpansionSolverInput,
|
|
4
|
+
RectDiffExpansionSolverSnapshot,
|
|
5
|
+
} from "../solvers/RectDiffExpansionSolver/RectDiffExpansionSolver"
|
|
6
|
+
import type { SimpleRouteJson } from "../types/srj-types"
|
|
7
|
+
import type { XYRect } from "../rectdiff-types"
|
|
8
|
+
import type { RTreeRect } from "lib/types/capacity-mesh-types"
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Builds a minimal RectDiffExpansionSolver snapshot with exactly two nodes
|
|
12
|
+
* separated by empty space. This keeps the data close to the solver’s real
|
|
13
|
+
* input shape so we can reuse it for demos/tests that reproduce the gap issue.
|
|
14
|
+
*/
|
|
15
|
+
export const createTwoNodeExpansionInput = (): RectDiffExpansionSolverInput => {
|
|
16
|
+
const srj: SimpleRouteJson = {
|
|
17
|
+
bounds: { minX: 0, maxX: 12, minY: 0, maxY: 4 },
|
|
18
|
+
layerCount: 1,
|
|
19
|
+
minTraceWidth: 0.2,
|
|
20
|
+
obstacles: [],
|
|
21
|
+
connections: [],
|
|
22
|
+
}
|
|
23
|
+
const layerCount = srj.layerCount ?? 1
|
|
24
|
+
const bounds: XYRect = {
|
|
25
|
+
x: srj.bounds.minX,
|
|
26
|
+
y: srj.bounds.minY,
|
|
27
|
+
width: srj.bounds.maxX - srj.bounds.minX,
|
|
28
|
+
height: srj.bounds.maxY - srj.bounds.minY,
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const obstacleIndexByLayer = Array.from(
|
|
32
|
+
{ length: layerCount },
|
|
33
|
+
() => new RBush<RTreeRect>(),
|
|
34
|
+
)
|
|
35
|
+
// Start with all-empty obstacle indexes for a "clean" scenario
|
|
36
|
+
|
|
37
|
+
const initialSnapshot: RectDiffExpansionSolverSnapshot = {
|
|
38
|
+
srj,
|
|
39
|
+
layerNames: ["top"],
|
|
40
|
+
layerCount,
|
|
41
|
+
bounds,
|
|
42
|
+
options: { gridSizes: [1] },
|
|
43
|
+
boardVoidRects: [],
|
|
44
|
+
gridIndex: 0,
|
|
45
|
+
candidates: [],
|
|
46
|
+
placed: [
|
|
47
|
+
{
|
|
48
|
+
rect: { x: 0.5, y: 0.5, width: 2, height: 3 },
|
|
49
|
+
zLayers: [0],
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
rect: { x: 9.5, y: 0.5, width: 2, height: 3 },
|
|
53
|
+
zLayers: [0],
|
|
54
|
+
},
|
|
55
|
+
],
|
|
56
|
+
expansionIndex: 0,
|
|
57
|
+
edgeAnalysisDone: true,
|
|
58
|
+
totalSeedsThisGrid: 0,
|
|
59
|
+
consumedSeedsThisGrid: 0,
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return {
|
|
63
|
+
initialSnapshot,
|
|
64
|
+
obstacleIndexByLayer,
|
|
65
|
+
}
|
|
66
|
+
}
|
package/package.json
CHANGED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { useMemo } from "react"
|
|
2
|
+
import { RectDiffExpansionSolver } from "lib/solvers/RectDiffExpansionSolver/RectDiffExpansionSolver"
|
|
3
|
+
import { createTwoNodeExpansionInput } from "lib/fixtures/twoNodeExpansionFixture"
|
|
4
|
+
import { SolverDebugger3d } from "../../components/SolverDebugger3d"
|
|
5
|
+
|
|
6
|
+
export default () => {
|
|
7
|
+
const solver = useMemo(
|
|
8
|
+
() => new RectDiffExpansionSolver(createTwoNodeExpansionInput()),
|
|
9
|
+
[],
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
return <SolverDebugger3d solver={solver} />
|
|
13
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<svg width="640" height="480" viewBox="0 0 640 480" xmlns="http://www.w3.org/2000/svg"><rect width="100%" height="100%" fill="white"/><g><rect data-type="rect" data-label="node" data-x="
|
|
1
|
+
<svg width="640" height="480" viewBox="0 0 640 480" xmlns="http://www.w3.org/2000/svg"><rect width="100%" height="100%" fill="white"/><g><rect data-type="rect" data-label="node" data-x="1.5" data-y="2" x="40.000000000000014" y="163.63636363636363" width="101.8181818181818" height="152.72727272727275" fill="#dbeafe" stroke="black" stroke-width="0.019642857142857142"/></g><g><rect data-type="rect" data-label="node" data-x="10.5" data-y="2" x="498.1818181818182" y="163.63636363636363" width="101.81818181818181" height="152.72727272727275" fill="#dbeafe" stroke="black" stroke-width="0.019642857142857142"/></g><g id="crosshair" style="display: none"><line id="crosshair-h" y1="0" y2="480" stroke="#666" stroke-width="0.5"/><line id="crosshair-v" x1="0" x2="640" stroke="#666" stroke-width="0.5"/><text id="coordinates" font-family="monospace" font-size="12" fill="#666"></text></g><script><![CDATA[
|
|
2
2
|
document.currentScript.parentElement.addEventListener('mousemove', (e) => {
|
|
3
3
|
const svg = e.currentTarget;
|
|
4
4
|
const rect = svg.getBoundingClientRect();
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
v.setAttribute('y2', '480');
|
|
21
21
|
|
|
22
22
|
// Calculate real coordinates using inverse transformation
|
|
23
|
-
const matrix = {"a":
|
|
23
|
+
const matrix = {"a":50.90909090909091,"c":0,"e":14.545454545454561,"b":0,"d":-50.90909090909091,"f":341.8181818181818};
|
|
24
24
|
// Manually invert and apply the affine transform
|
|
25
25
|
// Since we only use translate and scale, we can directly compute:
|
|
26
26
|
// x' = (x - tx) / sx
|
|
@@ -1,24 +1,18 @@
|
|
|
1
1
|
import { expect, test } from "bun:test"
|
|
2
|
-
import middleGapFixture from "test-assets/gap-fill-h-shape-should-expand-node.json"
|
|
3
2
|
import { getSvgFromGraphicsObject } from "graphics-debug"
|
|
4
|
-
import {
|
|
5
|
-
import
|
|
3
|
+
import { RectDiffExpansionSolver } from "lib/solvers/RectDiffExpansionSolver/RectDiffExpansionSolver"
|
|
4
|
+
import { createTwoNodeExpansionInput } from "lib/fixtures/twoNodeExpansionFixture"
|
|
6
5
|
import { makeCapacityMeshNodeWithLayerInfo } from "./fixtures/makeCapacityMeshNodeWithLayerInfo"
|
|
7
6
|
|
|
8
|
-
test("
|
|
9
|
-
const solver = new
|
|
10
|
-
meshNodes: middleGapFixture.meshNodes as CapacityMeshNode[],
|
|
11
|
-
})
|
|
7
|
+
test("RectDiff expansion reproduces the two-node gap fixture", async () => {
|
|
8
|
+
const solver = new RectDiffExpansionSolver(createTwoNodeExpansionInput())
|
|
12
9
|
|
|
13
10
|
solver.solve()
|
|
14
11
|
|
|
15
|
-
const {
|
|
12
|
+
const { meshNodes } = solver.getOutput()
|
|
13
|
+
expect(meshNodes.length).toBeGreaterThanOrEqual(2)
|
|
16
14
|
|
|
17
|
-
|
|
18
|
-
middleGapFixture.meshNodes.length,
|
|
19
|
-
)
|
|
20
|
-
|
|
21
|
-
const finalGraphics = makeCapacityMeshNodeWithLayerInfo(outputNodes)
|
|
15
|
+
const finalGraphics = makeCapacityMeshNodeWithLayerInfo(meshNodes)
|
|
22
16
|
const svg = getSvgFromGraphicsObject(
|
|
23
17
|
{ rects: finalGraphics.values().toArray().flat() },
|
|
24
18
|
{
|
|
@@ -27,8 +21,5 @@ test("should expand capacityMeshNode to fill the gap", async () => {
|
|
|
27
21
|
},
|
|
28
22
|
)
|
|
29
23
|
|
|
30
|
-
// More means we have added new nodes to fill the gap
|
|
31
|
-
// expect(outputNodes.length).toEqual(3)
|
|
32
|
-
|
|
33
24
|
await expect(svg).toMatchSvgSnapshot(import.meta.path)
|
|
34
25
|
})
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import fixture from "../test-assets/gap-fill-h-shape-should-expand-node.json"
|
|
2
|
-
import { GapFillSolverPipeline } from "../lib/solvers/GapFillSolver/GapFillSolverPipeline"
|
|
3
|
-
import type { CapacityMeshNode } from "../lib/types/capacity-mesh-types"
|
|
4
|
-
import { useMemo } from "react"
|
|
5
|
-
import { SolverDebugger3d } from "../components/SolverDebugger3d"
|
|
6
|
-
|
|
7
|
-
export default () => {
|
|
8
|
-
const solver = useMemo(
|
|
9
|
-
() =>
|
|
10
|
-
new GapFillSolverPipeline({
|
|
11
|
-
meshNodes: fixture.meshNodes as CapacityMeshNode[],
|
|
12
|
-
}),
|
|
13
|
-
[],
|
|
14
|
-
)
|
|
15
|
-
|
|
16
|
-
return (
|
|
17
|
-
<SolverDebugger3d
|
|
18
|
-
solver={solver}
|
|
19
|
-
defaultShowOutput={true}
|
|
20
|
-
defaultShowRoot={true}
|
|
21
|
-
/>
|
|
22
|
-
)
|
|
23
|
-
}
|