Skip to content

Commit 17a5602

Browse files
authored
Merge pull request #1 from tscircuit/rect-expansion
Rect Expansion
2 parents 79f7b64 + 305189c commit 17a5602

File tree

13 files changed

+1707
-993
lines changed

13 files changed

+1707
-993
lines changed

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,4 +34,5 @@ report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json
3434
.DS_Store
3535

3636
.vscode
37-
repomix-output.xml
37+
repomix-output.xml
38+
*.diff.png

components/SolverDebugger3d.tsx

Lines changed: 56 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -80,9 +80,9 @@ function buildPrismsFromNodes(
8080
const xyKey = (n: CapacityMeshNode) =>
8181
`${n.center.x.toFixed(8)}|${n.center.y.toFixed(8)}|${n.width.toFixed(8)}|${n.height.toFixed(8)}`
8282
const azKey = (n: CapacityMeshNode) => {
83-
const zs = (n.availableZ && n.availableZ.length ? [...new Set(n.availableZ)] : [0]).sort(
84-
(a, b) => a - b,
85-
)
83+
const zs = (
84+
n.availableZ && n.availableZ.length ? [...new Set(n.availableZ)] : [0]
85+
).sort((a, b) => a - b)
8686
return `zset:${zs.join(",")}`
8787
}
8888
const key = (n: CapacityMeshNode) => `${xyKey(n)}|${azKey(n)}`
@@ -226,8 +226,13 @@ const ThreeBoardView: React.FC<{
226226
const w = el.clientWidth || 800
227227
const h = el.clientHeight || height
228228

229-
const renderer = new THREE.WebGLRenderer({ antialias: true })
230-
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2))
229+
const renderer = new THREE.WebGLRenderer({
230+
antialias: true,
231+
alpha: true,
232+
premultipliedAlpha: false,
233+
})
234+
// Increase pixel ratio for better alphaHash quality
235+
renderer.setPixelRatio(window.devicePixelRatio)
231236
renderer.setSize(w, h)
232237
el.innerHTML = ""
233238
el.appendChild(renderer.domElement)
@@ -300,7 +305,7 @@ const ThreeBoardView: React.FC<{
300305
const dx = b.maxX - b.minX
301306
const dz = b.maxY - b.minY // map board Y -> three Z
302307
const dy = (b.z1 - b.z0) * layerThickness
303-
const cx = (b.minX + b.maxX) / 2
308+
const cx = -((b.minX + b.maxX) / 2) // negate X to match expected orientation
304309
const cz = (b.minY + b.maxY) / 2
305310
// Negate Y so z=0 is at top, higher z goes down
306311
const cy = -((b.z0 + b.z1) / 2) * layerThickness
@@ -321,6 +326,7 @@ const ThreeBoardView: React.FC<{
321326
opacity: clampedOpacity,
322327
transparent: clampedOpacity < 1,
323328
alphaHash: clampedOpacity < 1,
329+
alphaToCoverage: true,
324330
})
325331

326332
const mesh = new THREE.Mesh(geom, mat)
@@ -472,15 +478,15 @@ const ThreeBoardView: React.FC<{
472478
const dist = size * 2.0
473479
// Camera looks from above-right-front, with negative Y being "up" (z=0 at top)
474480
camera.position.set(
475-
fitBox.maxX + dist * 0.6,
481+
-(fitBox.maxX + dist * 0.6), // negate X to account for flipped axis
476482
-dy / 2 + dist, // negative Y is up, so position above the center
477483
fitBox.maxY + dist * 0.6,
478484
)
479485
camera.near = Math.max(0.1, size / 100)
480486
camera.far = dist * 10 + size * 10
481487
camera.updateProjectionMatrix()
482488
controls.target.set(
483-
(fitBox.minX + fitBox.maxX) / 2,
489+
-((fitBox.minX + fitBox.maxX) / 2), // negate X to account for flipped axis
484490
-dy / 2, // center of the inverted Y range
485491
(fitBox.minY + fitBox.maxY) / 2,
486492
)
@@ -553,7 +559,7 @@ export const SolverDebugger3d: React.FC<SolverDebugger3dProps> = ({
553559
solver,
554560
simpleRouteJson,
555561
layerThickness = 1,
556-
height = 460,
562+
height = 600,
557563
defaultShowRoot = true,
558564
defaultShowObstacles = false, // don't show obstacles by default
559565
defaultShowOutput = true,
@@ -568,31 +574,58 @@ export const SolverDebugger3d: React.FC<SolverDebugger3dProps> = ({
568574
const [showOutput, setShowOutput] = useState(defaultShowOutput)
569575
const [wireframeOutput, setWireframeOutput] = useState(defaultWireframeOutput)
570576

571-
const [meshOpacity, setMeshOpacity] = useState(1) // fully opaque by default
572-
const [shrinkBoxes, setShrinkBoxes] = useState(false)
577+
const [meshOpacity, setMeshOpacity] = useState(0.6)
578+
const [shrinkBoxes, setShrinkBoxes] = useState(true)
573579
const [boxShrinkAmount, setBoxShrinkAmount] = useState(0.1)
574-
const [showBorders, setShowBorders] = useState(false)
580+
const [showBorders, setShowBorders] = useState(true)
575581

576-
// Keep mesh nodes in sync with solver
577-
const meshNodes = useMemo(() => {
582+
// Mesh nodes state - updated when solver completes or during stepping
583+
const [meshNodes, setMeshNodes] = useState<CapacityMeshNode[]>([])
584+
585+
// Update mesh nodes from solver output
586+
const updateMeshNodes = useCallback(() => {
578587
try {
579-
if (
580-
(solver as any).solved !== true &&
581-
typeof solver.solve === "function"
582-
) {
583-
solver.solve()
584-
}
585-
} catch {}
586-
return solver.getOutput().meshNodes ?? []
588+
const output = solver.getOutput()
589+
const nodes = output.meshNodes ?? []
590+
setMeshNodes(nodes)
591+
} catch {
592+
setMeshNodes([])
593+
}
587594
}, [solver])
588595

596+
// Initialize mesh nodes on mount (in case solver is already solved)
597+
useEffect(() => {
598+
updateMeshNodes()
599+
// eslint-disable-next-line react-hooks/exhaustive-deps
600+
}, [])
601+
602+
// Handle solver completion
603+
const handleSolverCompleted = useCallback(() => {
604+
updateMeshNodes()
605+
}, [updateMeshNodes])
606+
607+
// Poll for updates during stepping (GenericSolverDebugger doesn't have onStep)
608+
useEffect(() => {
609+
const interval = setInterval(() => {
610+
// Only update if solver has output available
611+
if ((solver as any).solved || (solver as any).stats?.placed > 0) {
612+
updateMeshNodes()
613+
}
614+
}, 100) // Poll every 100ms during active solving
615+
616+
return () => clearInterval(interval)
617+
}, [updateMeshNodes, solver])
618+
589619
const toggle3d = useCallback(() => setShow3d((s) => !s), [])
590620
const rebuild = useCallback(() => setRebuildKey((k) => k + 1), [])
591621

592622
return (
593623
<>
594624
<div style={{ display: "grid", gap: 12, ...style }}>
595-
<GenericSolverDebugger solver={solver as any} />
625+
<GenericSolverDebugger
626+
solver={solver as any}
627+
onSolverCompleted={handleSolverCompleted}
628+
/>
596629

597630
<div
598631
style={{

0 commit comments

Comments
 (0)