@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.
@@ -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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tscircuit/rectdiff",
3
- "version": "0.0.17",
3
+ "version": "0.0.18",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "scripts": {
@@ -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="-3" data-y="0" x="86.66666666666666" y="40" width="66.66666666666666" height="400" fill="#dbeafe" stroke="black" stroke-width="0.015"/></g><g><rect data-type="rect" data-label="node" data-x="3" data-y="0" x="486.6666666666667" y="40" width="66.66666666666669" height="400" fill="#dbeafe" stroke="black" stroke-width="0.015"/></g><g><rect data-type="rect" data-label="node" data-x="0" data-y="0" x="253.33333333333331" y="206.66666666666666" width="133.33333333333337" height="66.66666666666666" fill="#dbeafe" stroke="black" stroke-width="0.015"/></g><g><rect data-type="rect" data-label="node" data-x="-1.75" data-y="0" x="153.33333333333331" y="40" width="100" height="400" fill="#dbeafe" stroke="black" stroke-width="0.015"/></g><g><rect data-type="rect" data-label="node" data-x="1.75" data-y="0" x="386.6666666666667" y="40" width="100" height="400" fill="#dbeafe" stroke="black" stroke-width="0.015"/></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[
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":66.66666666666667,"c":0,"e":320,"b":0,"d":-66.66666666666667,"f":240};
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 { GapFillSolverPipeline } from "lib/solvers/GapFillSolver/GapFillSolverPipeline"
5
- import type { CapacityMeshNode } from "lib/types/capacity-mesh-types"
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("should expand capacityMeshNode to fill the gap", async () => {
9
- const solver = new GapFillSolverPipeline({
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 { outputNodes } = solver.getOutput()
12
+ const { meshNodes } = solver.getOutput()
13
+ expect(meshNodes.length).toBeGreaterThanOrEqual(2)
16
14
 
17
- expect(outputNodes.length).toBeGreaterThanOrEqual(
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
- }