Hole-aware sketch profiles: multi-loop extrude + no-crossing boolean fast path#396
Hole-aware sketch profiles: multi-loop extrude + no-crossing boolean fast path#396ecto wants to merge 7 commits into
Conversation
… booleans Sketch2D gains interior hole loops (IR: optional holes field, serde/ts back-compat via default); vcad-kernel-sketch extrude_with_holes builds the multi-loop BRep directly (outer + hole laterals, holed caps) so a polygon-with-holes extrudes in one operation with no boolean pipeline. vcad-kernel-booleans grows a no_crossing fast path: when two solids' boundaries provably do not cross (AABB + no face-pair intersection), union/difference/intersection resolve by containment ray tests instead of the full SSI pipeline. Consumers wired per the IR checklist: eval (extrude/revolve reject holes where unsupported with a typed error), vcode syntax + docs, to_loon, app materializer/document_api/migrate, kernel-wasm, engine evaluate.ts, ir:gen regenerated. vcad-gdsii bridge emits holed islands as single multi-loop extrudes (the Difference path is gone); vcad-process prisms use native holes too. New holed_islands example + tests across sketch (volume, watertightness), booleans (containment), gdsii (picture-frame ring now = 1 extrude, 0 Differences), eval. Unblocks: fast rendering of merged GDS die layers (power grids with hundreds of holes previously built giant 3D Difference trees). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Choji review — Looks good This PR adds hole-aware sketch profiles (multi-loop extrude) and a no-crossing boolean fast path to eliminate the expensive Difference-tree pipeline for chip-layer geometry. The implementation is thorough: IR, kernel, tessellator, eval, WASM, vcode, gdsii, and process bridges are all updated consistently. Both open findings from the prior review have been addressed by the owner with regression tests and explanations. The remaining code is well-structured and the correctness-critical paths (earcut fallback on failure, winding normalization, vcode H-marker guard) are handled correctly. Live verification in progress — Choji is booting your app and running checks to confirm these changes. This comment updates with the result shortly. Correctness
Was this review useful? Rate the findings → — your thumbs up or down trains Choji on what's worth flagging. Reviewed |
…p on slotmap keys, vcode empty-outer error - Winding normalization now sums signed area over ALL earcut output triangles instead of probing the first non-degenerate one — immune to per-triangle degeneracy and to assumptions about ring order. - EARCUT_VERTEX_THRESHOLD 64 -> 256 with the quality/speed trade-off documented: ordinary curved caps stay on the Steiner path, chip-scale polygons take earcut. - no_crossing test helper keys its half-edge pairing map on VertexId tuples directly (slotmap keys are Hash+Eq) instead of hashing Debug strings. - planar_regions_touch doc now states why outer-region separation is sufficient (holes lie strictly inside their outer region), not merely conservative. - vcode: targeted parse error for a sketch whose hole loops (H) precede any outer-loop segment. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Dismissing prior approval to re-evaluate 14952ea.
…ode H-first error placement - bbox: regression test proving sweep_candidate_face_pairs equals the quadratic reference as an exact multiset even when A and B faces share min.x — each event scans only the opposite active list before pushing itself, so a pair is emitted exactly once, by whichever face enters second. - tessellate: regression test on a symmetric square frame proving earcut output triangles share one winding and their signed areas sum to the frame area — the region between outer and holes is what gets triangulated, so cancellation to zero cannot occur; the total-area probe is well-defined. - vcode: empty-outer guard moved into the H arm — errors at the H line itself and cannot be bypassed by early loop exits. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Dismissing prior approval to re-evaluate 4c95ae7.
planar_regions_touch was O(na·nb) twice over — every vertex of each polygon ray-cast against the other, then every edge pair tested. The gate runs for every coplanar candidate face pair in a union tree, and chip-layer islands carry thousands of vertices: profiling the 88k-poly die showed the contact gate itself dominating evaluation (>20 min). Now: edge contact is swept over tolerance-padded x-intervals (same pattern as the face broadphase), and when no edges touch the regions are provably either disjoint or nested, so one boundary-inclusive containment probe per side replaces the all-vertex scan. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Dismissing prior approval to re-evaluate 8233bc8.
earcut_polygon_with_holes returned an empty mesh on earcutr::Err, silently dropping the cap face and leaving the tessellation non-watertight. It now returns Option; both call sites fall through to the bridge/ear-clip path on None, so a failed triangulation costs speed, never a hole in the solid. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Dismissing prior approval to re-evaluate 33a433c.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…rance Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Render benchmark (88k-polygon sky130 die, merged per-layer solids with holes, top view 2000px):
So: the merged-solid path goes from impossible to correct but slow. Profiling shows the remaining cost is the coplanar-contact gate on full-die power rails: their edges span the whole die in x, so the x-interval sweep (8233bc8) prunes nothing for exactly those faces and the gate degenerates toward quadratic for rail-vs-rail pairs. Follow-up candidates, in rough order of leverage:
None of these block this PR: correctness is proven, the flat path is untouched, and every merged-solid workload that previously hung now terminates. 🤖 Generated with Claude Code |
What
Sketch2Dgains optional interiorholesloops (serde + ts-rs back-compat;ir:genregenerated,ir:checkclean).extrude_with_holesbuilds multi-loop BReps directly — outer + hole lateral faces and holed caps, no boolean pipeline. Volume/watertightness tests included.no_crossingfast path — when boundaries provably don't cross, union/difference/intersection resolve by containment ray tests instead of full SSI.evaluate.ts— the full New-IR-operation checklist.Differencepath is deleted (picture-frame test: was 2 extrudes + 1 Difference → now 1 extrude, 0 Differences).Why
Merged GDS die layers (power grids: hundreds of interior holes per island) previously built giant 3D Difference trees that the boolean pipeline chewed on for tens of minutes. With profiles that carry their holes, the geometry is exact and the boolean pipeline never runs for them.
Gates
cargo test: all affected crates green (sketch 37, booleans 103, eval 33, gdsii 44, process 36, ir 27 + workspace suite)-D warnings: stable and nightly both clean (workspace, CI-matching)npm run ir:check: generated TS up to dateRender benchmark of the 88k-polygon sky130 die through the new path is running; number to follow as a comment.
🤖 Generated with Claude Code