@tscircuit/rectdiff 0.0.27 → 0.0.29
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/.github/workflows/bun-pver-release.yml +24 -45
- package/dist/index.d.ts +0 -46
- package/dist/index.js +220 -774
- package/lib/RectDiffPipeline.ts +0 -46
- package/lib/types/srj-types.ts +0 -1
- package/package.json +1 -2
- package/pages/repro/merge-single-layer-node.page.tsx +17 -0
- package/tests/__snapshots__/board-outline.snap.svg +2 -2
- package/tests/solver/__snapshots__/rectDiffGridSolverPipeline.snap.svg +1 -1
- package/tests/solver/both-points-equivalent/__snapshots__/both-points-equivalent.snap.svg +1 -1
- package/tests/solver/bugreport01-be84eb/__snapshots__/bugreport01-be84eb.snap.svg +1 -1
- package/tests/solver/bugreport02-bc4361/__snapshots__/bugreport02-bc4361.snap.svg +1 -1
- package/tests/solver/bugreport03-fe4a17/__snapshots__/bugreport03-fe4a17.snap.svg +1 -1
- package/tests/solver/bugreport07-d3f3be/__snapshots__/bugreport07-d3f3be.snap.svg +1 -1
- package/tests/solver/bugreport08-e3ec95/__snapshots__/bugreport08-e3ec95.snap.svg +1 -1
- package/tests/solver/bugreport09-618e09/__snapshots__/bugreport09-618e09.snap.svg +1 -1
- package/tests/solver/bugreport10-71239a/__snapshots__/bugreport10-71239a.snap.svg +1 -1
- package/tests/solver/bugreport11-b2de3c/__snapshots__/bugreport11-b2de3c.snap.svg +1 -1
- package/tests/solver/bugreport12-35ce1c/__snapshots__/bugreport12-35ce1c.snap.svg +1 -1
- package/tests/solver/bugreport13-b9a758/__snapshots__/bugreport13-b9a758.snap.svg +1 -1
- package/tests/solver/bugreport16-d95f38/__snapshots__/bugreport16-d95f38.snap.svg +1 -1
- package/tests/solver/bugreport19/__snapshots__/bugreport19.snap.svg +1 -1
- package/tests/solver/bugreport20-obstacle-clipping/__snapshots__/bugreport20-obstacle-clipping.snap.svg +1 -1
- package/tests/solver/bugreport21-board-outline/__snapshots__/bugreport21-board-outline.snap.svg +2 -2
- package/tests/solver/bugreport22-2a75ce/__snapshots__/bugreport22-2a75ce.snap.svg +1 -1
- package/tests/solver/bugreport23-LGA15x4/__snapshots__/bugreport23-LGA15x4.snap.svg +1 -1
- package/tests/solver/bugreport24-05597c/__snapshots__/bugreport24-05597c.snap.svg +1 -1
- package/tests/solver/bugreport25-4b1d55/__snapshots__/bugreport25-4b1d55.snap.svg +1 -1
- package/tests/solver/bugreport36-bf8303/__snapshots__/bugreport36-bf8303.snap.svg +1 -1
- package/tests/solver/interaction/__snapshots__/interaction.snap.svg +1 -1
- package/tests/solver/multi-point/__snapshots__/multi-point.snap.svg +1 -1
- package/tests/solver/no-better-path/__snapshots__/no-better-path.snap.svg +1 -1
- package/tests/solver/repros/merge-single-layer-node/merge-single-layer-node.json +861 -0
- package/tests/solver/{bugreport50-multi-support-layer-merge/bugreport50-multi-support-layer-merge.test.ts → repros/merge-single-layer-node/merge-single-layer-node.test.ts} +7 -42
- package/tests/solver/transitivity/__snapshots__/transitivity.snap.svg +2 -2
- package/tsconfig.json +5 -1
- package/vite.config.ts +4 -0
- package/lib/solvers/AdjacentLayerContainmentMergeSolver/AdjacentLayerContainmentMergeSolver.ts +0 -456
- package/lib/solvers/OuterLayerContainmentMergeSolver/OuterLayerContainmentMergeSolver.ts +0 -311
- package/pages/bugreports/bugreport50-multi-support-layer-merge.page.tsx +0 -19
- package/pages/pour.page.tsx +0 -18
- package/test-assets/bugreport49-634662.json +0 -412
- package/tests/solver/bugreport49-634662/__snapshots__/bugreport49-634662.snap.svg +0 -44
- package/tests/solver/bugreport49-634662/bugreport49-634662.test.ts +0 -134
- package/tests/solver/bugreport50-multi-support-layer-merge/__snapshots__/bugreport50-multi-support-layer-merge.snap.svg +0 -44
- package/tests/solver/bugreport50-multi-support-layer-merge/bugreport50-multi-support-layer-merge.json +0 -972
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { expect, test } from "bun:test"
|
|
2
|
-
import
|
|
2
|
+
import inputProblems from "./merge-single-layer-node.json"
|
|
3
3
|
import {
|
|
4
4
|
getBounds,
|
|
5
5
|
getSvgFromGraphicsObject,
|
|
@@ -12,46 +12,10 @@ import { RectDiffPipeline } from "lib/RectDiffPipeline"
|
|
|
12
12
|
import { makeCapacityMeshNodeWithLayerInfo } from "tests/fixtures/makeCapacityMeshNodeWithLayerInfo"
|
|
13
13
|
import { makeSimpleRouteOutlineGraphics } from "tests/fixtures/makeSimpleRouteOutlineGraphics"
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
const
|
|
19
|
-
meshNodes: ReturnType<RectDiffPipeline["getOutput"]>["meshNodes"],
|
|
20
|
-
) => {
|
|
21
|
-
const counts = new Map<string, number>()
|
|
22
|
-
|
|
23
|
-
for (const node of meshNodes) {
|
|
24
|
-
if (node._containsObstacle || node._containsTarget) continue
|
|
25
|
-
|
|
26
|
-
const key = node.availableZ.join(",")
|
|
27
|
-
counts.set(key, (counts.get(key) ?? 0) + 1)
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
return counts
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
test("bugreport50-multi-support-layer-merge promotes adjacent-layer nodes supported by multiple peers", () => {
|
|
34
|
-
const solver = new RectDiffPipeline({
|
|
35
|
-
simpleRouteJson: srj,
|
|
36
|
-
})
|
|
37
|
-
|
|
38
|
-
solver.solve()
|
|
39
|
-
|
|
40
|
-
const counts = getFreeNodeCounts(solver.getOutput().meshNodes)
|
|
41
|
-
const z0 = counts.get("0") ?? 0
|
|
42
|
-
const z01 = counts.get("0,1") ?? 0
|
|
43
|
-
|
|
44
|
-
expect(z01).toBeGreaterThan(40)
|
|
45
|
-
expect(z01).toBeGreaterThan(z0)
|
|
46
|
-
expect(z0).toBeLessThan(10)
|
|
47
|
-
})
|
|
48
|
-
|
|
49
|
-
test("bugreport50-multi-support-layer-merge", async () => {
|
|
50
|
-
const solver = new RectDiffPipeline({
|
|
51
|
-
simpleRouteJson: srj,
|
|
52
|
-
})
|
|
53
|
-
|
|
54
|
-
const outline = makeSimpleRouteOutlineGraphics(srj)
|
|
15
|
+
test("node-solver input repro snapshot", async () => {
|
|
16
|
+
const problem = inputProblems[0]!
|
|
17
|
+
const solver = new RectDiffPipeline(problem)
|
|
18
|
+
const outline = makeSimpleRouteOutlineGraphics(problem.simpleRouteJson)
|
|
55
19
|
|
|
56
20
|
solver.solve()
|
|
57
21
|
|
|
@@ -59,7 +23,7 @@ test("bugreport50-multi-support-layer-merge", async () => {
|
|
|
59
23
|
const rectsByCombo = makeCapacityMeshNodeWithLayerInfo(meshNodes)
|
|
60
24
|
const allGraphicsObjects: GraphicsObject[] = []
|
|
61
25
|
|
|
62
|
-
for (
|
|
26
|
+
for (let z = 0; z < problem.simpleRouteJson.layerCount; z++) {
|
|
63
27
|
const layerRects: Rect[] = []
|
|
64
28
|
|
|
65
29
|
for (const [key, rects] of rectsByCombo) {
|
|
@@ -121,5 +85,6 @@ test("bugreport50-multi-support-layer-merge", async () => {
|
|
|
121
85
|
svgWidth,
|
|
122
86
|
svgHeight,
|
|
123
87
|
})
|
|
88
|
+
|
|
124
89
|
await expect(svg).toMatchSvgSnapshot(import.meta.path)
|
|
125
90
|
})
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<svg width="640" height="1652" viewBox="0 0 640 1652" xmlns="http://www.w3.org/2000/svg"><rect width="100%" height="100%" fill="white"/><g><polyline data-points="-5,-5 25,-5 25,25 -5,25 -5,-5" data-type="line" data-label="bounds" points="39.99999999999997,745.6944444444446 600,745.6944444444446 600,185.6944444444445 39.99999999999997,185.6944444444445 39.99999999999997,745.6944444444446" fill="none" stroke="#111827" stroke-width="1.866666666666667"/></g><g><polyline data-points="-5,-48.02083333333333 25,-48.02083333333333 25,-18.02083333333333 -5,-18.02083333333333 -5,-48.02083333333333" data-type="line" data-label="bounds" points="39.99999999999997,1548.75 600,1548.75 600,988.75 39.99999999999997,988.75 39.99999999999997,1548.75" fill="none" stroke="#111827" stroke-width="1.866666666666667"/></g><g><rect data-type="rect" data-label="node" data-x="2.25" data-y="13.25" x="39.99999999999997" y="185.6944444444445" width="270.66666666666663" height="438.6666666666667" fill="#dbeafe" stroke="black" stroke-width="0.05357142857142857"/></g><g><rect data-type="rect" data-label="node" data-x="17.25" data-y="2.25" x="310.66666666666663" y="475.0277777777778" width="289.33333333333337" height="270.66666666666674" fill="#dbeafe" stroke="black" stroke-width="0.05357142857142857"/></g><g><rect data-type="rect" data-label="node" data-x="14.5" data-y="17.75" x="310.66666666666663" y="185.6944444444445" width="186.66666666666669" height="270.6666666666667" fill="#dbeafe" stroke="black" stroke-width="0.05357142857142857"/></g><g><rect data-type="rect" data-label="node" data-x="14.924999999999997" data-y="10" x="376.9333333333333" y="456.3611111111112" width="70" height="18.66666666666663" fill="#dbeafe" stroke="black" stroke-width="0.05357142857142857"/></g><g><rect data-type="rect" data-label="node" data-x="18.5375" data-y="10" x="446.9333333333334" y="456.3611111111112" width="64.86666666666656" height="18.66666666666663" fill="#dbeafe" stroke="black" stroke-width="0.05357142857142857"/></g><g><rect data-type="rect" data-label="node" data-x="2.75" data-y="-2.75" x="58.66666666666664" y="661.6944444444446" width="252" height="84" fill="#dbeafe" stroke="black" stroke-width="0.05357142857142857"/></g><g><rect data-type="rect" data-label="node" data-x="22.75" data-y="18.0375" x="516" y="185.6944444444445" width="84" height="259.93333333333334" fill="#dbeafe" stroke="black" stroke-width="0.05357142857142857"/></g><g><rect data-type="rect" data-label="node" data-x="-2.75" data-y="0.5" x="39.99999999999997" y="624.3611111111112" width="84.00000000000001" height="37.33333333333337" fill="#dbeafe" stroke="black" stroke-width="0.05357142857142857"/></g><g><rect data-type="rect" data-label="node" data-x="5.275" data-y="0.5" x="175.79999999999998" y="624.3611111111112" width="112.00000000000003" height="37.33333333333337" fill="#dbeafe" stroke="black" stroke-width="0.05357142857142857"/></g><g><rect data-type="rect" data-label="node" data-x="11.775" data-y="10" x="329.3333333333333" y="456.3611111111112" width="47.60000000000002" height="18.66666666666663" fill="#dbeafe" stroke="black" stroke-width="0.05357142857142857"/></g><g><rect data-type="rect" data-label="node" data-x="22.6375" data-y="10.2875" x="511.79999999999995" y="445.62777777777785" width="88.20000000000005" height="29.399999999999977" fill="#dbeafe" stroke="black" stroke-width="0.05357142857142857"/></g><g><rect data-type="rect" data-label="node" data-x="8.8875" data-y="0.5" x="287.79999999999995" y="624.3611111111112" width="22.866666666666674" height="37.33333333333337" fill="#dbeafe" stroke="black" stroke-width="0.05357142857142857"/></g><g><rect data-type="rect" data-label="node" data-x="0" data-y="1" x="123.99999999999999" y="624.3611111111112" width="18.66666666666667" height="18.66666666666663" fill="#dbeafe" stroke="black" stroke-width="0.05357142857142857"/></g><g><rect data-type="rect" data-label="node" data-x="1.3875" data-y="0" x="142.66666666666666" y="643.0277777777778" width="33.133333333333326" height="18.666666666666742" fill="#dbeafe" stroke="black" stroke-width="0.05357142857142857"/></g><g><rect data-type="rect" data-label="node" data-x="20" data-y="15.2875" x="497.3333333333333" y="288.3611111111112" width="18.666666666666686" height="157.26666666666665" fill="#dbeafe" stroke="black" stroke-width="0.05357142857142857"/></g><g><rect data-type="rect" data-label="node" data-x="20" data-y="22.75" x="497.3333333333333" y="185.6944444444445" width="18.666666666666686" height="84" fill="#dbeafe" stroke="black" stroke-width="0.05357142857142857"/></g><g><rect data-type="rect" data-label="node" data-x="-4.5" data-y="-2.68125" x="39.99999999999997" y="661.6944444444446" width="18.66666666666667" height="81.43333333333328" fill="#dbeafe" stroke="black" stroke-width="0.05357142857142857"/></g><g><rect data-type="rect" data-label="node" data-x="1.8875" data-y="1" x="161.33333333333331" y="624.3611111111112" width="14.466666666666669" height="18.66666666666663" fill="#dbeafe" stroke="black" stroke-width="0.05357142857142857"/></g><g><rect data-type="rect" data-label="node" data-x="19.8875" data-y="10.7875" x="497.3333333333333" y="445.62777777777785" width="14.46666666666664" height="10.733333333333348" fill="#dbeafe" stroke="black" stroke-width="0.05357142857142857"/></g><g><rect data-type="rect" data-label="node" data-x="0" data-y="0" x="123.99999999999999" y="643.0277777777778" width="18.66666666666667" height="18.666666666666742" fill="red" stroke="black" stroke-width="0.05357142857142857"/></g><g><rect data-type="rect" data-label="node" data-x="10" data-y="10" x="310.66666666666663" y="456.3611111111112" width="18.666666666666686" height="18.66666666666663" fill="red" stroke="black" stroke-width="0.05357142857142857"/></g><g><rect data-type="rect" data-label="node" data-x="20" data-y="20" x="497.3333333333333" y="269.6944444444445" width="18.666666666666686" height="18.666666666666686" fill="red" stroke="black" stroke-width="0.05357142857142857"/></g><g><rect data-type="rect" data-label="node" data-x="1" data-y="1" x="142.66666666666666" y="624.3611111111112" width="18.666666666666657" height="18.66666666666663" fill="red" stroke="black" stroke-width="0.05357142857142857"/></g><g><rect data-type="rect" data-label="node" data-x="2.25" data-y="-29.77083333333333" x="39.99999999999997" y="988.75" width="270.66666666666663" height="438.66666666666674" fill="#dbeafe" stroke="black" stroke-width="0.05357142857142857"/></g><g><rect data-type="rect" data-label="node" data-x="17.25" data-y="-40.77083333333333" x="310.66666666666663" y="1278.0833333333335" width="289.33333333333337" height="270.6666666666665" fill="#dbeafe" stroke="black" stroke-width="0.05357142857142857"/></g><g><rect data-type="rect" data-label="node" data-x="14.5" data-y="-25.27083333333333" x="310.66666666666663" y="988.75" width="186.66666666666669" height="270.66666666666674" fill="#dbeafe" stroke="black" stroke-width="0.05357142857142857"/></g><g><rect data-type="rect" data-label="node" data-x="14.924999999999997" data-y="-33.02083333333333" x="376.9333333333333" y="1259.4166666666667" width="70" height="18.666666666666742" fill="#dbeafe" stroke="black" stroke-width="0.05357142857142857"/></g><g><rect data-type="rect" data-label="node" data-x="18.5375" data-y="-33.02083333333333" x="446.9333333333334" y="1259.4166666666667" width="64.86666666666656" height="18.666666666666742" fill="#dbeafe" stroke="black" stroke-width="0.05357142857142857"/></g><g><rect data-type="rect" data-label="node" data-x="2.75" data-y="-45.77083333333333" x="58.66666666666664" y="1464.75" width="252" height="84" fill="#dbeafe" stroke="black" stroke-width="0.05357142857142857"/></g><g><rect data-type="rect" data-label="node" data-x="22.75" data-y="-24.983333333333327" x="516" y="988.75" width="84" height="259.9333333333334" fill="#dbeafe" stroke="black" stroke-width="0.05357142857142857"/></g><g><rect data-type="rect" data-label="node" data-x="-2.75" data-y="-42.52083333333333" x="39.99999999999997" y="1427.4166666666667" width="84.00000000000001" height="37.33333333333326" fill="#dbeafe" stroke="black" stroke-width="0.05357142857142857"/></g><g><rect data-type="rect" data-label="node" data-x="5.275" data-y="-42.52083333333333" x="175.79999999999998" y="1427.4166666666667" width="112.00000000000003" height="37.33333333333326" fill="#dbeafe" stroke="black" stroke-width="0.05357142857142857"/></g><g><rect data-type="rect" data-label="node" data-x="11.775" data-y="-33.02083333333333" x="329.3333333333333" y="1259.4166666666667" width="47.60000000000002" height="18.666666666666742" fill="#dbeafe" stroke="black" stroke-width="0.05357142857142857"/></g><g><rect data-type="rect" data-label="node" data-x="22.6375" data-y="-32.73333333333333" x="511.79999999999995" y="1248.6833333333334" width="88.20000000000005" height="29.40000000000009" fill="#dbeafe" stroke="black" stroke-width="0.05357142857142857"/></g><g><rect data-type="rect" data-label="node" data-x="8.8875" data-y="-42.52083333333333" x="287.79999999999995" y="1427.4166666666667" width="22.866666666666674" height="37.33333333333326" fill="#dbeafe" stroke="black" stroke-width="0.05357142857142857"/></g><g><rect data-type="rect" data-label="node" data-x="0" data-y="-42.02083333333333" x="123.99999999999999" y="1427.4166666666667" width="18.66666666666667" height="18.666666666666742" fill="#dbeafe" stroke="black" stroke-width="0.05357142857142857"/></g><g><rect data-type="rect" data-label="node" data-x="1.3875" data-y="-43.02083333333333" x="142.66666666666666" y="1446.0833333333335" width="33.133333333333326" height="18.666666666666515" fill="#dbeafe" stroke="black" stroke-width="0.05357142857142857"/></g><g><rect data-type="rect" data-label="node" data-x="20" data-y="-27.733333333333327" x="497.3333333333333" y="1091.4166666666667" width="18.666666666666686" height="157.26666666666665" fill="#dbeafe" stroke="black" stroke-width="0.05357142857142857"/></g><g><rect data-type="rect" data-label="node" data-x="20" data-y="-20.27083333333333" x="497.3333333333333" y="988.75" width="18.666666666666686" height="84" fill="#dbeafe" stroke="black" stroke-width="0.05357142857142857"/></g><g><rect data-type="rect" data-label="node" data-x="-4.5" data-y="-45.70208333333333" x="39.99999999999997" y="1464.75" width="18.66666666666667" height="81.4333333333334" fill="#dbeafe" stroke="black" stroke-width="0.05357142857142857"/></g><g><rect data-type="rect" data-label="node" data-x="1.8875" data-y="-42.02083333333333" x="161.33333333333331" y="1427.4166666666667" width="14.466666666666669" height="18.666666666666742" fill="#dbeafe" stroke="black" stroke-width="0.05357142857142857"/></g><g><rect data-type="rect" data-label="node" data-x="19.8875" data-y="-32.23333333333333" x="497.3333333333333" y="1248.6833333333334" width="14.46666666666664" height="10.733333333333348" fill="#dbeafe" stroke="black" stroke-width="0.05357142857142857"/></g><g><rect data-type="rect" data-label="node" data-x="10" data-y="-33.02083333333333" x="310.66666666666663" y="1259.4166666666667" width="18.666666666666686" height="18.666666666666742" fill="#fef3c7" stroke="black" stroke-width="0.05357142857142857"/></g><g><rect data-type="rect" data-label="node" data-x="0" data-y="-43.02083333333333" x="123.99999999999999" y="1446.0833333333335" width="18.66666666666667" height="18.666666666666515" fill="#fef3c7" stroke="black" stroke-width="0.05357142857142857"/></g><g><rect data-type="rect" data-label="node" data-x="1" data-y="-42.02083333333333" x="142.66666666666666" y="1427.4166666666667" width="18.666666666666657" height="18.666666666666742" fill="#fef3c7" stroke="black" stroke-width="0.05357142857142857"/></g><g><rect data-type="rect" data-label="node" data-x="20" data-y="-23.02083333333333" x="497.3333333333333" y="1072.75" width="18.666666666666686" height="18.666666666666742" fill="#fef3c7" stroke="black" stroke-width="0.05357142857142857"/></g><text data-type="text" data-label="Layer z=0" data-x="0" data-y="28.916666666666664" x="133.33333333333331" y="112.58333333333348" fill="black" font-size="9.333333333333334" font-family="sans-serif" text-anchor="end" dominant-baseline="text-before-edge">Layer z=0</text><text data-type="text" data-label="Layer z=1" data-x="0" data-y="-14.104166666666664" x="133.33333333333331" y="915.6388888888889" fill="black" font-size="9.333333333333334" font-family="sans-serif" text-anchor="end" dominant-baseline="text-before-edge">Layer z=1</text><g id="crosshair" style="display: none"><line id="crosshair-h" y1="0" y2="1652" 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="1652" viewBox="0 0 640 1652" xmlns="http://www.w3.org/2000/svg"><rect width="100%" height="100%" fill="white"/><g><polyline data-points="-5,-5 25,-5 25,25 -5,25 -5,-5" data-type="line" data-label="bounds" points="40,745.6944444444446 600,745.6944444444446 600,185.69444444444457 40,185.69444444444457 40,745.6944444444446" fill="none" stroke="#111827" stroke-width="1.8666666666666665"/></g><g><polyline data-points="-5,-48.02083333333333 25,-48.02083333333333 25,-18.02083333333333 -5,-18.02083333333333 -5,-48.02083333333333" data-type="line" data-label="bounds" points="40,1548.75 600,1548.75 600,988.75 40,988.75 40,1548.75" fill="none" stroke="#111827" stroke-width="1.8666666666666665"/></g><g><rect data-type="rect" data-label="node" data-x="2.25" data-y="13.25" x="40" y="185.69444444444457" width="270.66666666666663" height="438.66666666666663" fill="#dbeafe" stroke="black" stroke-width="0.053571428571428575"/></g><g><rect data-type="rect" data-label="node" data-x="17.25" data-y="2.25" x="310.66666666666663" y="475.0277777777779" width="289.33333333333337" height="270.6666666666667" fill="#dbeafe" stroke="black" stroke-width="0.053571428571428575"/></g><g><rect data-type="rect" data-label="node" data-x="14.5" data-y="17.75" x="310.66666666666663" y="185.69444444444457" width="186.66666666666663" height="270.66666666666663" fill="#dbeafe" stroke="black" stroke-width="0.053571428571428575"/></g><g><rect data-type="rect" data-label="node" data-x="14.925" data-y="10" x="376.9333333333333" y="456.3611111111112" width="70" height="18.666666666666686" fill="#dbeafe" stroke="black" stroke-width="0.053571428571428575"/></g><g><rect data-type="rect" data-label="node" data-x="18.5375" data-y="10" x="446.9333333333333" y="456.3611111111112" width="64.86666666666667" height="18.666666666666686" fill="#dbeafe" stroke="black" stroke-width="0.053571428571428575"/></g><g><rect data-type="rect" data-label="node" data-x="2.7500000000000004" data-y="-2.75" x="58.66666666666667" y="661.6944444444446" width="251.99999999999994" height="84" fill="#dbeafe" stroke="black" stroke-width="0.053571428571428575"/></g><g><rect data-type="rect" data-label="node" data-x="22.75" data-y="18.0375" x="516" y="185.69444444444457" width="84" height="259.9333333333333" fill="#dbeafe" stroke="black" stroke-width="0.053571428571428575"/></g><g><rect data-type="rect" data-label="node" data-x="-2.75" data-y="0.5" x="40" y="624.3611111111112" width="83.99999999999999" height="37.33333333333337" fill="#dbeafe" stroke="black" stroke-width="0.053571428571428575"/></g><g><rect data-type="rect" data-label="node" data-x="5.275" data-y="0.5" x="175.79999999999998" y="624.3611111111112" width="111.99999999999997" height="37.33333333333337" fill="#dbeafe" stroke="black" stroke-width="0.053571428571428575"/></g><g><rect data-type="rect" data-label="node" data-x="11.774999999999999" data-y="10" x="329.33333333333326" y="456.3611111111112" width="47.599999999999966" height="18.666666666666686" fill="#dbeafe" stroke="black" stroke-width="0.053571428571428575"/></g><g><rect data-type="rect" data-label="node" data-x="22.637500000000003" data-y="10.2875" x="511.79999999999995" y="445.6277777777779" width="88.20000000000005" height="29.399999999999977" fill="#dbeafe" stroke="black" stroke-width="0.053571428571428575"/></g><g><rect data-type="rect" data-label="node" data-x="8.8875" data-y="0.5" x="287.79999999999995" y="624.3611111111112" width="22.866666666666674" height="37.33333333333337" fill="#dbeafe" stroke="black" stroke-width="0.053571428571428575"/></g><g><rect data-type="rect" data-label="node" data-x="0" data-y="1" x="123.99999999999999" y="624.3611111111112" width="18.66666666666667" height="18.66666666666663" fill="#dbeafe" stroke="black" stroke-width="0.053571428571428575"/></g><g><rect data-type="rect" data-label="node" data-x="1.3875000000000002" data-y="0" x="142.66666666666666" y="643.0277777777778" width="33.133333333333326" height="18.666666666666742" fill="#dbeafe" stroke="black" stroke-width="0.053571428571428575"/></g><g><rect data-type="rect" data-label="node" data-x="20" data-y="15.2875" x="497.33333333333326" y="288.36111111111126" width="18.666666666666742" height="157.26666666666665" fill="#dbeafe" stroke="black" stroke-width="0.053571428571428575"/></g><g><rect data-type="rect" data-label="node" data-x="20" data-y="22.75" x="497.33333333333326" y="185.69444444444457" width="18.666666666666742" height="84" fill="#dbeafe" stroke="black" stroke-width="0.053571428571428575"/></g><g><rect data-type="rect" data-label="node" data-x="-4.5" data-y="-2.68125" x="40" y="661.6944444444446" width="18.66666666666667" height="81.43333333333328" fill="#dbeafe" stroke="black" stroke-width="0.053571428571428575"/></g><g><rect data-type="rect" data-label="node" data-x="1.8875000000000002" data-y="1" x="161.33333333333331" y="624.3611111111112" width="14.466666666666669" height="18.66666666666663" fill="#dbeafe" stroke="black" stroke-width="0.053571428571428575"/></g><g><rect data-type="rect" data-label="node" data-x="19.887500000000003" data-y="10.7875" x="497.33333333333326" y="445.6277777777779" width="14.466666666666754" height="10.733333333333292" fill="#dbeafe" stroke="black" stroke-width="0.053571428571428575"/></g><g><rect data-type="rect" data-label="node" data-x="0" data-y="0" x="123.99999999999999" y="643.0277777777778" width="18.66666666666667" height="18.666666666666742" fill="red" stroke="black" stroke-width="0.053571428571428575"/></g><g><rect data-type="rect" data-label="node" data-x="10" data-y="10" x="310.66666666666663" y="456.3611111111112" width="18.66666666666663" height="18.666666666666686" fill="red" stroke="black" stroke-width="0.053571428571428575"/></g><g><rect data-type="rect" data-label="node" data-x="20" data-y="20" x="497.33333333333326" y="269.69444444444457" width="18.666666666666742" height="18.666666666666686" fill="red" stroke="black" stroke-width="0.053571428571428575"/></g><g><rect data-type="rect" data-label="node" data-x="1" data-y="1" x="142.66666666666666" y="624.3611111111112" width="18.666666666666657" height="18.66666666666663" fill="red" stroke="black" stroke-width="0.053571428571428575"/></g><g><rect data-type="rect" data-label="node" data-x="2.25" data-y="-29.77083333333333" x="40" y="988.75" width="270.66666666666663" height="438.6666666666665" fill="#dbeafe" stroke="black" stroke-width="0.053571428571428575"/></g><g><rect data-type="rect" data-label="node" data-x="17.25" data-y="-40.77083333333333" x="310.66666666666663" y="1278.0833333333333" width="289.33333333333337" height="270.66666666666674" fill="#dbeafe" stroke="black" stroke-width="0.053571428571428575"/></g><g><rect data-type="rect" data-label="node" data-x="14.5" data-y="-25.27083333333333" x="310.66666666666663" y="988.75" width="186.66666666666663" height="270.6666666666665" fill="#dbeafe" stroke="black" stroke-width="0.053571428571428575"/></g><g><rect data-type="rect" data-label="node" data-x="14.925" data-y="-33.02083333333333" x="376.9333333333333" y="1259.4166666666665" width="70" height="18.666666666666742" fill="#dbeafe" stroke="black" stroke-width="0.053571428571428575"/></g><g><rect data-type="rect" data-label="node" data-x="18.5375" data-y="-33.02083333333333" x="446.9333333333333" y="1259.4166666666665" width="64.86666666666667" height="18.666666666666742" fill="#dbeafe" stroke="black" stroke-width="0.053571428571428575"/></g><g><rect data-type="rect" data-label="node" data-x="2.7500000000000004" data-y="-45.77083333333333" x="58.66666666666667" y="1464.75" width="251.99999999999994" height="84" fill="#dbeafe" stroke="black" stroke-width="0.053571428571428575"/></g><g><rect data-type="rect" data-label="node" data-x="22.75" data-y="-24.983333333333327" x="516" y="988.75" width="84" height="259.93333333333317" fill="#dbeafe" stroke="black" stroke-width="0.053571428571428575"/></g><g><rect data-type="rect" data-label="node" data-x="-2.75" data-y="-42.52083333333333" x="40" y="1427.4166666666665" width="83.99999999999999" height="37.333333333333485" fill="#dbeafe" stroke="black" stroke-width="0.053571428571428575"/></g><g><rect data-type="rect" data-label="node" data-x="5.275" data-y="-42.52083333333333" x="175.79999999999998" y="1427.4166666666665" width="111.99999999999997" height="37.333333333333485" fill="#dbeafe" stroke="black" stroke-width="0.053571428571428575"/></g><g><rect data-type="rect" data-label="node" data-x="11.774999999999999" data-y="-33.02083333333333" x="329.33333333333326" y="1259.4166666666665" width="47.599999999999966" height="18.666666666666742" fill="#dbeafe" stroke="black" stroke-width="0.053571428571428575"/></g><g><rect data-type="rect" data-label="node" data-x="22.637500000000003" data-y="-32.73333333333333" x="511.79999999999995" y="1248.6833333333332" width="88.20000000000005" height="29.40000000000009" fill="#dbeafe" stroke="black" stroke-width="0.053571428571428575"/></g><g><rect data-type="rect" data-label="node" data-x="8.8875" data-y="-42.52083333333333" x="287.79999999999995" y="1427.4166666666665" width="22.866666666666674" height="37.333333333333485" fill="#dbeafe" stroke="black" stroke-width="0.053571428571428575"/></g><g><rect data-type="rect" data-label="node" data-x="0" data-y="-42.02083333333333" x="123.99999999999999" y="1427.4166666666665" width="18.66666666666667" height="18.666666666666742" fill="#dbeafe" stroke="black" stroke-width="0.053571428571428575"/></g><g><rect data-type="rect" data-label="node" data-x="1.3875000000000002" data-y="-43.02083333333333" x="142.66666666666666" y="1446.0833333333333" width="33.133333333333326" height="18.666666666666742" fill="#dbeafe" stroke="black" stroke-width="0.053571428571428575"/></g><g><rect data-type="rect" data-label="node" data-x="20" data-y="-27.733333333333327" x="497.33333333333326" y="1091.4166666666665" width="18.666666666666742" height="157.26666666666665" fill="#dbeafe" stroke="black" stroke-width="0.053571428571428575"/></g><g><rect data-type="rect" data-label="node" data-x="20" data-y="-20.27083333333333" x="497.33333333333326" y="988.75" width="18.666666666666742" height="84" fill="#dbeafe" stroke="black" stroke-width="0.053571428571428575"/></g><g><rect data-type="rect" data-label="node" data-x="-4.5" data-y="-45.70208333333333" x="40" y="1464.75" width="18.66666666666667" height="81.43333333333317" fill="#dbeafe" stroke="black" stroke-width="0.053571428571428575"/></g><g><rect data-type="rect" data-label="node" data-x="10" data-y="-33.02083333333333" x="310.66666666666663" y="1259.4166666666665" width="18.66666666666663" height="18.666666666666742" fill="#fef3c7" stroke="black" stroke-width="0.053571428571428575"/></g><g><rect data-type="rect" data-label="node" data-x="0" data-y="-43.02083333333333" x="123.99999999999999" y="1446.0833333333333" width="18.66666666666667" height="18.666666666666742" fill="#fef3c7" stroke="black" stroke-width="0.053571428571428575"/></g><g><rect data-type="rect" data-label="node" data-x="1.3875000000000002" data-y="-42.02083333333333" x="142.66666666666666" y="1427.4166666666665" width="33.133333333333326" height="18.666666666666742" fill="#fef3c7" stroke="black" stroke-width="0.053571428571428575"/></g><g><rect data-type="rect" data-label="node" data-x="19.887500000000003" data-y="-32.23333333333333" x="497.33333333333326" y="1248.6833333333332" width="14.466666666666754" height="10.733333333333348" fill="#fef3c7" stroke="black" stroke-width="0.053571428571428575"/></g><g><rect data-type="rect" data-label="node" data-x="20" data-y="-23.02083333333333" x="497.33333333333326" y="1072.75" width="18.666666666666742" height="18.666666666666515" fill="#fef3c7" stroke="black" stroke-width="0.053571428571428575"/></g><text data-type="text" data-label="Layer z=0" data-x="0" data-y="28.916666666666664" x="133.33333333333331" y="112.58333333333348" fill="black" font-size="9.333333333333332" font-family="sans-serif" text-anchor="end" dominant-baseline="text-before-edge">Layer z=0</text><text data-type="text" data-label="Layer z=1" data-x="0" data-y="-14.104166666666664" x="133.33333333333331" y="915.6388888888889" fill="black" font-size="9.333333333333332" font-family="sans-serif" text-anchor="end" dominant-baseline="text-before-edge">Layer z=1</text><g id="crosshair" style="display: none"><line id="crosshair-h" y1="0" y2="1652" 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', '1652');
|
|
21
21
|
|
|
22
22
|
// Calculate real coordinates using inverse transformation
|
|
23
|
-
const matrix = {"a":18.
|
|
23
|
+
const matrix = {"a":18.666666666666664,"c":0,"e":133.33333333333331,"b":0,"d":-18.666666666666664,"f":652.3611111111112};
|
|
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
|
package/tsconfig.json
CHANGED
|
@@ -8,7 +8,11 @@
|
|
|
8
8
|
"jsx": "react-jsx",
|
|
9
9
|
"allowJs": true,
|
|
10
10
|
"paths": {
|
|
11
|
-
"lib/*": ["./lib/*"]
|
|
11
|
+
"lib/*": ["./lib/*"],
|
|
12
|
+
"components/*": ["./components/*"],
|
|
13
|
+
"tests/*": ["./tests/*"],
|
|
14
|
+
"pages/*": ["./pages/*"],
|
|
15
|
+
"utils/*": ["./utils/*"]
|
|
12
16
|
},
|
|
13
17
|
"baseUrl": ".",
|
|
14
18
|
|
package/vite.config.ts
CHANGED
|
@@ -8,6 +8,10 @@ export default defineConfig({
|
|
|
8
8
|
resolve: {
|
|
9
9
|
alias: {
|
|
10
10
|
lib: path.resolve(__dirname, "lib"),
|
|
11
|
+
components: path.resolve(__dirname, "components"),
|
|
12
|
+
tests: path.resolve(__dirname, "tests"),
|
|
13
|
+
pages: path.resolve(__dirname, "pages"),
|
|
14
|
+
utils: path.resolve(__dirname, "utils"),
|
|
11
15
|
},
|
|
12
16
|
},
|
|
13
17
|
})
|
package/lib/solvers/AdjacentLayerContainmentMergeSolver/AdjacentLayerContainmentMergeSolver.ts
DELETED
|
@@ -1,456 +0,0 @@
|
|
|
1
|
-
import { BaseSolver } from "@tscircuit/solver-utils"
|
|
2
|
-
import type { GraphicsObject } from "graphics-debug"
|
|
3
|
-
import type { XYRect } from "lib/rectdiff-types"
|
|
4
|
-
import type { CapacityMeshNode } from "lib/types/capacity-mesh-types"
|
|
5
|
-
import type { SimpleRouteJson } from "lib/types/srj-types"
|
|
6
|
-
import { getColorForZLayer } from "lib/utils/getColorForZLayer"
|
|
7
|
-
import { EPS, overlaps, subtractRect2D } from "lib/utils/rectdiff-geometry"
|
|
8
|
-
|
|
9
|
-
type AdjacentLayerContainmentMergeSolverInput = {
|
|
10
|
-
meshNodes: CapacityMeshNode[]
|
|
11
|
-
simpleRouteJson: SimpleRouteJson
|
|
12
|
-
minFragmentArea?: number
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
const DEFAULT_MIN_FRAGMENT_AREA = 0.2 ** 2
|
|
16
|
-
|
|
17
|
-
const nodeToRect = (node: CapacityMeshNode): XYRect => ({
|
|
18
|
-
x: node.center.x - node.width / 2,
|
|
19
|
-
y: node.center.y - node.height / 2,
|
|
20
|
-
width: node.width,
|
|
21
|
-
height: node.height,
|
|
22
|
-
})
|
|
23
|
-
|
|
24
|
-
const rectArea = (rect: XYRect) => rect.width * rect.height
|
|
25
|
-
|
|
26
|
-
const cloneNode = (node: CapacityMeshNode): CapacityMeshNode => ({
|
|
27
|
-
...node,
|
|
28
|
-
center: { ...node.center },
|
|
29
|
-
availableZ: [...node.availableZ],
|
|
30
|
-
})
|
|
31
|
-
|
|
32
|
-
const cloneNodeWithRect = (
|
|
33
|
-
node: CapacityMeshNode,
|
|
34
|
-
rect: XYRect,
|
|
35
|
-
capacityMeshNodeId: string,
|
|
36
|
-
): CapacityMeshNode => ({
|
|
37
|
-
...node,
|
|
38
|
-
capacityMeshNodeId,
|
|
39
|
-
center: {
|
|
40
|
-
x: rect.x + rect.width / 2,
|
|
41
|
-
y: rect.y + rect.height / 2,
|
|
42
|
-
},
|
|
43
|
-
width: rect.width,
|
|
44
|
-
height: rect.height,
|
|
45
|
-
availableZ: [...node.availableZ],
|
|
46
|
-
layer: `z${node.availableZ.join(",")}`,
|
|
47
|
-
})
|
|
48
|
-
|
|
49
|
-
const clonePromotedNodeWithRect = (
|
|
50
|
-
node: CapacityMeshNode,
|
|
51
|
-
rect: XYRect,
|
|
52
|
-
capacityMeshNodeId: string,
|
|
53
|
-
availableZ: number[],
|
|
54
|
-
): CapacityMeshNode => ({
|
|
55
|
-
...node,
|
|
56
|
-
capacityMeshNodeId,
|
|
57
|
-
center: {
|
|
58
|
-
x: rect.x + rect.width / 2,
|
|
59
|
-
y: rect.y + rect.height / 2,
|
|
60
|
-
},
|
|
61
|
-
width: rect.width,
|
|
62
|
-
height: rect.height,
|
|
63
|
-
availableZ: [...availableZ],
|
|
64
|
-
layer: `z${availableZ.join(",")}`,
|
|
65
|
-
})
|
|
66
|
-
|
|
67
|
-
const isFreeNode = (node: CapacityMeshNode) =>
|
|
68
|
-
!node._containsObstacle && !node._containsTarget
|
|
69
|
-
|
|
70
|
-
const isSingletonNodeOnLayer = (node: CapacityMeshNode, z: number) =>
|
|
71
|
-
node.availableZ.length === 1 && node.availableZ[0] === z
|
|
72
|
-
|
|
73
|
-
const sameRect = (a: XYRect, b: XYRect) =>
|
|
74
|
-
Math.abs(a.x - b.x) <= EPS &&
|
|
75
|
-
Math.abs(a.y - b.y) <= EPS &&
|
|
76
|
-
Math.abs(a.width - b.width) <= EPS &&
|
|
77
|
-
Math.abs(a.height - b.height) <= EPS
|
|
78
|
-
|
|
79
|
-
const subtractRects = (target: XYRect, cutters: XYRect[]) => {
|
|
80
|
-
let remaining: XYRect[] = [target]
|
|
81
|
-
|
|
82
|
-
for (const cutter of cutters) {
|
|
83
|
-
if (remaining.length === 0) return remaining
|
|
84
|
-
|
|
85
|
-
const nextRemaining: XYRect[] = []
|
|
86
|
-
for (const piece of remaining) {
|
|
87
|
-
nextRemaining.push(...subtractRect2D(piece, cutter))
|
|
88
|
-
}
|
|
89
|
-
remaining = nextRemaining
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
return remaining
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
const isFullyCoveredByRects = (target: XYRect, coveringRects: XYRect[]) => {
|
|
96
|
-
return subtractRects(target, coveringRects).length === 0
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
const sortAndDedupeCuts = (values: number[]) => {
|
|
100
|
-
const sorted = [...values].sort((a, b) => a - b)
|
|
101
|
-
const out: number[] = []
|
|
102
|
-
|
|
103
|
-
for (const value of sorted) {
|
|
104
|
-
const last = out[out.length - 1]
|
|
105
|
-
if (last == null || Math.abs(last - value) > EPS) {
|
|
106
|
-
out.push(value)
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
return out
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
const partitionRectByRects = (target: XYRect, supportRects: XYRect[]) => {
|
|
114
|
-
const xCuts = [target.x, target.x + target.width]
|
|
115
|
-
const yCuts = [target.y, target.y + target.height]
|
|
116
|
-
const targetMaxX = target.x + target.width
|
|
117
|
-
const targetMaxY = target.y + target.height
|
|
118
|
-
|
|
119
|
-
for (const rect of supportRects) {
|
|
120
|
-
const x0 = Math.max(target.x, rect.x)
|
|
121
|
-
const x1 = Math.min(targetMaxX, rect.x + rect.width)
|
|
122
|
-
const y0 = Math.max(target.y, rect.y)
|
|
123
|
-
const y1 = Math.min(targetMaxY, rect.y + rect.height)
|
|
124
|
-
|
|
125
|
-
if (x1 <= x0 + EPS || y1 <= y0 + EPS) continue
|
|
126
|
-
|
|
127
|
-
xCuts.push(x0, x1)
|
|
128
|
-
yCuts.push(y0, y1)
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
const xs = sortAndDedupeCuts(xCuts)
|
|
132
|
-
const ys = sortAndDedupeCuts(yCuts)
|
|
133
|
-
const cells: XYRect[] = []
|
|
134
|
-
|
|
135
|
-
for (let xi = 0; xi < xs.length - 1; xi++) {
|
|
136
|
-
const x0 = xs[xi]!
|
|
137
|
-
const x1 = xs[xi + 1]!
|
|
138
|
-
|
|
139
|
-
if (x1 <= x0 + EPS) continue
|
|
140
|
-
|
|
141
|
-
for (let yi = 0; yi < ys.length - 1; yi++) {
|
|
142
|
-
const y0 = ys[yi]!
|
|
143
|
-
const y1 = ys[yi + 1]!
|
|
144
|
-
|
|
145
|
-
if (y1 <= y0 + EPS) continue
|
|
146
|
-
|
|
147
|
-
cells.push({
|
|
148
|
-
x: x0,
|
|
149
|
-
y: y0,
|
|
150
|
-
width: x1 - x0,
|
|
151
|
-
height: y1 - y0,
|
|
152
|
-
})
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
return cells
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
const canMergeHorizontally = (a: XYRect, b: XYRect) =>
|
|
160
|
-
Math.abs(a.y - b.y) <= EPS &&
|
|
161
|
-
Math.abs(a.height - b.height) <= EPS &&
|
|
162
|
-
Math.abs(a.x + a.width - b.x) <= EPS
|
|
163
|
-
|
|
164
|
-
const canMergeVertically = (a: XYRect, b: XYRect) =>
|
|
165
|
-
Math.abs(a.x - b.x) <= EPS &&
|
|
166
|
-
Math.abs(a.width - b.width) <= EPS &&
|
|
167
|
-
Math.abs(a.y + a.height - b.y) <= EPS
|
|
168
|
-
|
|
169
|
-
const mergeTouchingRects = (rects: XYRect[]) => {
|
|
170
|
-
const out = rects.map((rect) => ({ ...rect }))
|
|
171
|
-
let changed = true
|
|
172
|
-
|
|
173
|
-
while (changed) {
|
|
174
|
-
changed = false
|
|
175
|
-
|
|
176
|
-
outer: for (let i = 0; i < out.length; i++) {
|
|
177
|
-
for (let j = i + 1; j < out.length; j++) {
|
|
178
|
-
const a = out[i]!
|
|
179
|
-
const b = out[j]!
|
|
180
|
-
|
|
181
|
-
if (canMergeHorizontally(a, b) || canMergeHorizontally(b, a)) {
|
|
182
|
-
const merged: XYRect = {
|
|
183
|
-
x: Math.min(a.x, b.x),
|
|
184
|
-
y: a.y,
|
|
185
|
-
width: a.width + b.width,
|
|
186
|
-
height: a.height,
|
|
187
|
-
}
|
|
188
|
-
out.splice(j, 1)
|
|
189
|
-
out.splice(i, 1, merged)
|
|
190
|
-
changed = true
|
|
191
|
-
break outer
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
if (canMergeVertically(a, b) || canMergeVertically(b, a)) {
|
|
195
|
-
const merged: XYRect = {
|
|
196
|
-
x: a.x,
|
|
197
|
-
y: Math.min(a.y, b.y),
|
|
198
|
-
width: a.width,
|
|
199
|
-
height: a.height + b.height,
|
|
200
|
-
}
|
|
201
|
-
out.splice(j, 1)
|
|
202
|
-
out.splice(i, 1, merged)
|
|
203
|
-
changed = true
|
|
204
|
-
break outer
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
return out
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
const isPromotableRect = (params: {
|
|
214
|
-
rect: XYRect
|
|
215
|
-
viaMinSize: number
|
|
216
|
-
minFragmentArea: number
|
|
217
|
-
}) => {
|
|
218
|
-
const { rect, viaMinSize, minFragmentArea } = params
|
|
219
|
-
|
|
220
|
-
return (
|
|
221
|
-
rect.width > EPS &&
|
|
222
|
-
rect.height > EPS &&
|
|
223
|
-
rectArea(rect) + EPS >= minFragmentArea &&
|
|
224
|
-
rect.width + EPS >= viaMinSize &&
|
|
225
|
-
rect.height + EPS >= viaMinSize
|
|
226
|
-
)
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
const isResidualRect = (rect: XYRect, minFragmentArea: number) =>
|
|
230
|
-
rect.width > EPS &&
|
|
231
|
-
rect.height > EPS &&
|
|
232
|
-
rectArea(rect) + EPS >= minFragmentArea
|
|
233
|
-
|
|
234
|
-
const computePromotablePieces = (params: {
|
|
235
|
-
target: XYRect
|
|
236
|
-
supportRects: XYRect[]
|
|
237
|
-
viaMinSize: number
|
|
238
|
-
minFragmentArea: number
|
|
239
|
-
}) => {
|
|
240
|
-
const { target, supportRects, viaMinSize, minFragmentArea } = params
|
|
241
|
-
const overlappingSupports = supportRects.filter((rect) =>
|
|
242
|
-
overlaps(rect, target),
|
|
243
|
-
)
|
|
244
|
-
|
|
245
|
-
if (overlappingSupports.length === 0) return []
|
|
246
|
-
|
|
247
|
-
if (
|
|
248
|
-
isFullyCoveredByRects(target, overlappingSupports) &&
|
|
249
|
-
isPromotableRect({ rect: target, viaMinSize, minFragmentArea })
|
|
250
|
-
) {
|
|
251
|
-
return [target]
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
const partitioned = partitionRectByRects(target, overlappingSupports)
|
|
255
|
-
const coveredPieces = partitioned.filter((piece) =>
|
|
256
|
-
isFullyCoveredByRects(piece, overlappingSupports),
|
|
257
|
-
)
|
|
258
|
-
|
|
259
|
-
if (coveredPieces.length === 0) return []
|
|
260
|
-
|
|
261
|
-
const mergedCoveredPieces = mergeTouchingRects(coveredPieces)
|
|
262
|
-
|
|
263
|
-
return mergedCoveredPieces.filter(
|
|
264
|
-
(piece) =>
|
|
265
|
-
isFullyCoveredByRects(piece, overlappingSupports) &&
|
|
266
|
-
isPromotableRect({ rect: piece, viaMinSize, minFragmentArea }),
|
|
267
|
-
)
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
export class AdjacentLayerContainmentMergeSolver extends BaseSolver {
|
|
271
|
-
private outputNodes: CapacityMeshNode[] = []
|
|
272
|
-
private promotedNodeIds = new Set<string>()
|
|
273
|
-
private residualNodeIds = new Set<string>()
|
|
274
|
-
|
|
275
|
-
constructor(private input: AdjacentLayerContainmentMergeSolverInput) {
|
|
276
|
-
super()
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
override _setup() {
|
|
280
|
-
this.outputNodes = this.input.meshNodes.map(cloneNode)
|
|
281
|
-
this.promotedNodeIds.clear()
|
|
282
|
-
this.residualNodeIds.clear()
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
override _step() {
|
|
286
|
-
this.outputNodes = this.processAdjacentLayerContainmentMerges()
|
|
287
|
-
this.solved = true
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
private processAdjacentLayerContainmentMerges(): CapacityMeshNode[] {
|
|
291
|
-
const srj = this.input.simpleRouteJson
|
|
292
|
-
const layerCount = Math.max(1, srj.layerCount || 1)
|
|
293
|
-
|
|
294
|
-
if (layerCount < 2) {
|
|
295
|
-
return this.input.meshNodes.map(cloneNode)
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
const viaMinSize = Math.max(srj.minViaDiameter ?? 0, srj.minTraceWidth || 0)
|
|
299
|
-
const minFragmentArea = Math.max(
|
|
300
|
-
EPS,
|
|
301
|
-
this.input.minFragmentArea ?? DEFAULT_MIN_FRAGMENT_AREA,
|
|
302
|
-
)
|
|
303
|
-
|
|
304
|
-
let workingNodes = this.input.meshNodes.map(cloneNode)
|
|
305
|
-
let nextResidualId = 0
|
|
306
|
-
let nextPromotedId = 0
|
|
307
|
-
|
|
308
|
-
for (let lowerZ = 0; lowerZ < layerCount - 1; lowerZ++) {
|
|
309
|
-
const upperZ = lowerZ + 1
|
|
310
|
-
const mutableNodes = workingNodes.filter(
|
|
311
|
-
(node) =>
|
|
312
|
-
isFreeNode(node) &&
|
|
313
|
-
(isSingletonNodeOnLayer(node, lowerZ) ||
|
|
314
|
-
isSingletonNodeOnLayer(node, upperZ)),
|
|
315
|
-
)
|
|
316
|
-
|
|
317
|
-
if (mutableNodes.length === 0) continue
|
|
318
|
-
|
|
319
|
-
const immutableNodes = workingNodes.filter(
|
|
320
|
-
(node) => !mutableNodes.includes(node),
|
|
321
|
-
)
|
|
322
|
-
const supportRectsByLayer = new Map<number, XYRect[]>()
|
|
323
|
-
|
|
324
|
-
supportRectsByLayer.set(
|
|
325
|
-
lowerZ,
|
|
326
|
-
mutableNodes
|
|
327
|
-
.filter((node) => isSingletonNodeOnLayer(node, lowerZ))
|
|
328
|
-
.map(nodeToRect),
|
|
329
|
-
)
|
|
330
|
-
supportRectsByLayer.set(
|
|
331
|
-
upperZ,
|
|
332
|
-
mutableNodes
|
|
333
|
-
.filter((node) => isSingletonNodeOnLayer(node, upperZ))
|
|
334
|
-
.map(nodeToRect),
|
|
335
|
-
)
|
|
336
|
-
|
|
337
|
-
const promotedRects: XYRect[] = []
|
|
338
|
-
const promotedNodes: CapacityMeshNode[] = []
|
|
339
|
-
const candidateNodes = mutableNodes
|
|
340
|
-
.filter((node) =>
|
|
341
|
-
isPromotableRect({
|
|
342
|
-
rect: nodeToRect(node),
|
|
343
|
-
viaMinSize,
|
|
344
|
-
minFragmentArea,
|
|
345
|
-
}),
|
|
346
|
-
)
|
|
347
|
-
.sort((a, b) => rectArea(nodeToRect(b)) - rectArea(nodeToRect(a)))
|
|
348
|
-
|
|
349
|
-
for (const candidate of candidateNodes) {
|
|
350
|
-
const candidateRect = nodeToRect(candidate)
|
|
351
|
-
const candidatePieces = subtractRects(
|
|
352
|
-
candidateRect,
|
|
353
|
-
promotedRects,
|
|
354
|
-
).filter((piece) => isResidualRect(piece, minFragmentArea))
|
|
355
|
-
const candidateZ = candidate.availableZ[0]!
|
|
356
|
-
const oppositeZ = candidateZ === lowerZ ? upperZ : lowerZ
|
|
357
|
-
const supportRects = supportRectsByLayer.get(oppositeZ) ?? []
|
|
358
|
-
|
|
359
|
-
for (const piece of candidatePieces) {
|
|
360
|
-
const promotablePieces = computePromotablePieces({
|
|
361
|
-
target: piece,
|
|
362
|
-
supportRects,
|
|
363
|
-
viaMinSize,
|
|
364
|
-
minFragmentArea,
|
|
365
|
-
})
|
|
366
|
-
|
|
367
|
-
for (const promotablePiece of promotablePieces) {
|
|
368
|
-
promotedRects.push(promotablePiece)
|
|
369
|
-
|
|
370
|
-
const promotedNode = clonePromotedNodeWithRect(
|
|
371
|
-
candidate,
|
|
372
|
-
promotablePiece,
|
|
373
|
-
`${candidate.capacityMeshNodeId}-adjacent-merge-${nextPromotedId++}`,
|
|
374
|
-
[lowerZ, upperZ],
|
|
375
|
-
)
|
|
376
|
-
promotedNodes.push(promotedNode)
|
|
377
|
-
this.promotedNodeIds.add(promotedNode.capacityMeshNodeId)
|
|
378
|
-
}
|
|
379
|
-
}
|
|
380
|
-
}
|
|
381
|
-
|
|
382
|
-
const residualNodes: CapacityMeshNode[] = []
|
|
383
|
-
|
|
384
|
-
for (const node of mutableNodes) {
|
|
385
|
-
const nodeRect = nodeToRect(node)
|
|
386
|
-
const remainingPieces = subtractRects(nodeRect, promotedRects).filter(
|
|
387
|
-
(piece) => isResidualRect(piece, minFragmentArea),
|
|
388
|
-
)
|
|
389
|
-
|
|
390
|
-
if (
|
|
391
|
-
remainingPieces.length === 1 &&
|
|
392
|
-
sameRect(remainingPieces[0]!, nodeRect)
|
|
393
|
-
) {
|
|
394
|
-
residualNodes.push(node)
|
|
395
|
-
continue
|
|
396
|
-
}
|
|
397
|
-
|
|
398
|
-
for (const piece of remainingPieces) {
|
|
399
|
-
const residualNode = cloneNodeWithRect(
|
|
400
|
-
node,
|
|
401
|
-
piece,
|
|
402
|
-
`${node.capacityMeshNodeId}-adjacent-residual-${nextResidualId++}`,
|
|
403
|
-
)
|
|
404
|
-
residualNodes.push(residualNode)
|
|
405
|
-
this.residualNodeIds.add(residualNode.capacityMeshNodeId)
|
|
406
|
-
}
|
|
407
|
-
}
|
|
408
|
-
|
|
409
|
-
workingNodes = [...immutableNodes, ...promotedNodes, ...residualNodes]
|
|
410
|
-
}
|
|
411
|
-
|
|
412
|
-
return workingNodes
|
|
413
|
-
}
|
|
414
|
-
|
|
415
|
-
override getOutput(): { outputNodes: CapacityMeshNode[] } {
|
|
416
|
-
return { outputNodes: this.outputNodes }
|
|
417
|
-
}
|
|
418
|
-
|
|
419
|
-
override visualize(): GraphicsObject {
|
|
420
|
-
return {
|
|
421
|
-
title: "AdjacentLayerContainmentMergeSolver",
|
|
422
|
-
coordinateSystem: "cartesian",
|
|
423
|
-
rects: this.outputNodes.map((node) => {
|
|
424
|
-
const colors = getColorForZLayer(node.availableZ)
|
|
425
|
-
const isPromoted = this.promotedNodeIds.has(node.capacityMeshNodeId)
|
|
426
|
-
const isResidual = this.residualNodeIds.has(node.capacityMeshNodeId)
|
|
427
|
-
|
|
428
|
-
return {
|
|
429
|
-
center: node.center,
|
|
430
|
-
width: node.width,
|
|
431
|
-
height: node.height,
|
|
432
|
-
stroke: isPromoted
|
|
433
|
-
? "rgba(245, 158, 11, 0.95)"
|
|
434
|
-
: isResidual
|
|
435
|
-
? "rgba(37, 99, 235, 0.95)"
|
|
436
|
-
: colors.stroke,
|
|
437
|
-
fill: node._containsObstacle
|
|
438
|
-
? "rgba(239, 68, 68, 0.35)"
|
|
439
|
-
: isPromoted
|
|
440
|
-
? "rgba(251, 191, 36, 0.28)"
|
|
441
|
-
: isResidual
|
|
442
|
-
? "rgba(59, 130, 246, 0.18)"
|
|
443
|
-
: colors.fill,
|
|
444
|
-
layer: `z${node.availableZ.join(",")}`,
|
|
445
|
-
label: [
|
|
446
|
-
`node ${node.capacityMeshNodeId}`,
|
|
447
|
-
`z:${node.availableZ.join(",")}`,
|
|
448
|
-
].join("\n"),
|
|
449
|
-
}
|
|
450
|
-
}),
|
|
451
|
-
points: [],
|
|
452
|
-
lines: [],
|
|
453
|
-
texts: [],
|
|
454
|
-
}
|
|
455
|
-
}
|
|
456
|
-
}
|