8.7 KiB
8.7 KiB
Void Geometry Graph Plan (Surfaces + Boundaries)
Progress Checkpoint (2026-02-13)
- Completed:
GeometryStoreis persisted in document state and populated from solids runtime snapshots.- Selection pipeline was split to
interact/selection_resolver.jsand now emits typed candidates (profile/solid-face/solid-edge) with canonical entity descriptors. - Extrude targets carry
region_id; chamfer edge refs carryboundary_segment_id+ entity metadata. - New canonical mapping bridge is active in solids selection:
- face key -> canonical
surfaceid - edge key -> canonical
boundary-segmentid - loop edge key -> canonical
boundaryid - Resolver now consumes these mappings (
resolveCanonicalFaceEntity,resolveCanonicalEdgeEntity) as primary IDs.
Resume Pointers
- Canonical mapping source:
src/void/api/solids.js:buildGeometryStoreSnapshot()map populationresolveCanonicalFaceEntity()resolveCanonicalEdgeEntity()- Canonical mapping consumer:
src/void/interact/selection_resolver.jsresolvePrimarySurfaceHit()entity assignment for face/edge candidates.- Canonical hard cutover completed:
- Extrude profile refs resolve via
region_idonly. - Chamfer refs resolve via canonical
segment:*/boundary:*ids only. input.solidscompatibility branches removed from solid-op edit paths.- Boundary-hover correction applied:
- Face-edge resolution now prioritizes hovered-face boundary lookup before global solid edge intersections.
- Boundary extraction uses the same crease threshold as rendered edges (
SOLID_CREASE_ANGLE_DEG) to reduce partial/extra loop mismatches. getFaceEdgeHit()now prefers closed-loop boundaries over open seam chains when both are near cursor.- Follow-up TODO:
- During sketch editing,
Use (u)should derive from other visible sketch entities (not only solids).
Target Architecture
- Adopt a single geometric graph centered on
surfacesandboundaries, with solids as derived artifacts only. - Treat every selectable thing as one of:
SurfaceRegion(planar/non-planar bounded patch).Boundary(closed loop on a surface).BoundarySegment(line/arc/spline edge piece inside a boundary).BoundaryPoint(segment endpoint, midpoint, center, intersection, projected point).
Core Data Model
- Add
GeometryStore(document-persisted, versioned): surface_id,type(planar|curved),frame(for planar),sourceprovenance.boundary_id,surface_id, orderedsegment_ids, orientation, closure, area sign, nesting depth.segment_id,kind(line|arc|circle|polyline|nurbs), param data,owner_boundary_id.point_id, world/local coords, role (endpoint|midpoint|center|derived|intersection), references.region_id,surface_id, boundary rings (outer + holes), selectable extrusion/chamfer profile token.- Add stable identity layer:
- Every entity gets deterministic
geom_sig+ persistentid. - Derived entities keep
origin_refand dependency chain for rebind/rebuild. - Add
TopologyIndex(runtime cache): - Maps solid mesh triangles/edges to source
surface_idandboundary_segment_id. - Supports nearest-hit resolution with tolerance and tie-break rules.
Selection and Hover System
- Replace mode-specific picking with one
SelectionResolverpipeline. - Input: ray hits + current mode + intent mask.
- Output: ranked candidates of
point/segment/boundary/surface/region. - Ranking rules:
- Point proximity always wins near threshold.
- Segment wins next when distance-to-curve below threshold.
- Boundary/region wins when inside region and not near point/segment.
- Surface wins otherwise.
- Add per-mode intent masks:
- Sketch mode:
point,segment,boundary,surface(region projection). - Extrude mode:
regiononly. - Chamfer mode:
segmentonly (plus face-to-edge expansion helper). - Boolean mode:
surface/bodyselection groups. - Add consistent multi-select semantics:
- Plain click toggles in active picker.
space/escclear picker-local selection.- No cross-picker stealing while dialog active.
Geometry Build Pipeline
- Introduce staged rebuild in worker:
- Stage A: Feature evaluation -> sketch geometry on target surfaces.
- Stage B: Boundary graph build per surface (loop extraction, splitting, nesting).
- Stage C: Region synthesis (
outer/holes) with fill-rule consistency. - Stage D: Solid operations (extrude/boolean/chamfer) from region/surface references.
- Stage E: Topology annotation back into
GeometryStorefor interaction. - Cache keys:
feature_sig,surface_sig,boundary_sig,region_sig.- Recompute only invalidated downstream stages.
Sketch Integration
- Sketches bind to
surface_id+ local frame, not transient face index. Use (u)createsderived segment/pointreferencing sourcesegment_id/point_id.- Derived geometry stores transform relation to host surface frame.
- Midpoints become first-class
point_idwith constraint targetability. - Closed-area detection uses
boundary/regiongraph directly (no separate ad-hoc fill path).
Extrude Integration
- Extrude input stores selected
region_ids, not ad-hoc loops. - Region hover/selection always from boundary graph.
- Live preview reads from current region snapshots.
- Targets/tools in add/subtract reference resulting body ids, but source remains region-driven.
Chamfer Integration
- Chamfer input stores
boundary_segment_ids (or section ids for partial edges). - Face click expands to boundary segments by adjacency policy.
- No selection against regenerated transient mesh during edit.
- Preview and final solve read same boundary refs to avoid drift.
Projection / Derive Reliability
- Stop pre-projecting everything.
- Resolve hovered source entity first.
- Project only selected/hovered entity into current sketch frame.
- Keep source and projected visuals separate but linked by shared entity id.
Planar/Non-Planar Classification
- Surface classification at creation:
- Planar stores orthonormal frame and scalar offset.
- Curved stores param evaluator and principal directions where available.
- Boundary segments on curved surfaces can still be selected/extruded/chamfered as references.
- Sketch-on-face initially allowed only on planar surfaces; curved support can be staged later.
Document Persistence
- Persist
GeometryStoreplus feature list and timeline. - Persist only canonical geometry entities, not transient mesh selections.
- Add schema version bump and hard reset path (allowed in this project stage).
- Undo/redo stores deltas against
GeometryStoreentities for atomic operations.
Migration Strategy
- Phase 0: Add new store in parallel, keep existing runtime behavior.
- Phase 1: Route hover/selection to
SelectionResolverwhile existing builders stay. - Phase 2: Route sketch profiles/areas to
boundary/region. - Phase 3: Route extrude inputs to
region_id. - Phase 4: Route chamfer inputs to
segment_id. - Phase 5: Remove legacy face/edge ad-hoc paths.
- Forward-only: remove rollout toggles and legacy branching once parity is reached.
Performance and Worker Plan
- Keep all heavy geometry graph and topology steps in worker.
- Main thread receives compact immutable snapshots and draw buffers.
- Use incremental invalidation by dependency DAG from edited feature forward.
- Add rebuild budget logging per stage to catch regressions early.
Testing Plan
- Unit tests:
- Boundary extraction and nesting.
- Region fill-rule behavior (self-intersecting + nested bulls-eye cases).
- Selection ranking with tolerance.
- Projection correctness for points/segments/surfaces.
- Integration tests:
- Sketch-on-face propagation after upstream edits.
- Extrude profile row hover maps to produced solids.
- Chamfer edit stability with multi-select.
- Undo/redo atomicity in dialogs.
- Fuzz tests:
- Random sketch mutations + constraints + rebuild consistency checks.
- Determinism check: same doc state yields same entity ids/topology signatures.
Deliverables Sequence
GeometryStore+ ids + schema.SelectionResolver+ mode masks.BoundaryGraphBuilder+RegionBuilder.- Extrude refactor to
region_id. - Chamfer refactor to
segment_id. - Projection/use refactor to source-first selection.
- Legacy path removal and cleanup docs.
Acceptance Criteria
- Hover/select behavior is identical and predictable across sketch/solid/chamfer modes.
- Derived sketches follow upstream changes without requiring manual edit-open.
- Extrude/chamfer operate on stable references, not transient mesh hits.
- Nested/self-intersecting regions behave correctly for selection and extrusion.
- No mode where selection silently switches entity class unexpectedly.