Module space_dcel

Module space_dcel 

Source
Expand description

§Persistent, editable space topology (DCEL)

This is the Rust core of the Room tool’s interactive room layout. It does what the one-shot TS auto-space-detect pipeline does — turn a set of 2D wall-axis segments into the enclosed room faces of a floor plate — but instead of building a half-edge graph, walking it once, and throwing it away (returning bare Vec<[f64;2]> outlines), it keeps the SpacePlate alive as the authoritative topology and exposes local, O(degree) edit operations on it:

  • SpacePlate::drag_vertex — move a vertex; every incident face follows in the same call because a shared wall is one edge whose endpoints are shared vertices. This is the whole “pull one room, the neighbour follows” trick, and it falls out of the structure for free.
  • SpacePlate::split_face — insert a partition between two vertices of a face (subdivide a room). O(1) surgery; both children valid immediately.
  • SpacePlate::merge_faces — remove a shared edge, unioning the two rooms it separated. O(1) surgery.

Every edit returns the FaceIds it touched (with recomputed outline

  • area) so the TS mirror can re-render only what changed.

§What this adds over the TS detector

  1. Persistence. The DCEL survives across edits; ids are stable (tombstoned, never reused) so a TS-side hit-test mirror can reference a face/edge across frames.
  2. Source-element provenance. Each input segment carries the IFC element id it came from; that id is propagated through snapping, T-junction resolution and intersection-splitting onto every bounding half-edge. This is what makes IfcRelSpaceBoundary emission and the leak-repair affordance possible at bake — the TS detector drops it.
  3. prev pointers + the outer face as a real face, so split/merge are pure pointer surgery with no re-walk of the whole plate.

§Conventions

  • Interior (room) faces wind CCW (signed area > 0). The unbounded exterior winds CW and is flagged [Face::is_outer]. A plate with several disconnected wall clusters has one outer face per component.
  • A half-edge’s [HalfEdge::face] is the face on its left.
  • Holes / nested faces (a room enclosing a courtyard) are out of scope for this prototype: every CW cycle is treated as exterior, matching the TS detector. See the module TODO at the bottom.

Structs§

BuildOptions
Tuning for the arrangement pass. Distances are in the same units as the input segments (the caller is expected to pre-scale to metres, exactly as extract-walls does on the TS side).
FaceId
Stable handle to a face (a room, or the unbounded exterior).
FacePatch
A face touched by an edit, with enough geometry for the caller to re-render it without re-querying the whole plate.
HalfEdgeId
Stable handle to a directed half-edge.
InputSegment
An input wall-axis segment tagged with the IFC element it came from.
SpacePlate
The persistent floor-plate topology. See the module docs.
VertexId
Stable handle to a vertex. Survives edits; never reused after tombstoning.

Enums§

EditError
Errors an edit op can reject with. Build never fails — a malformed input just yields fewer (or zero) interior faces, matching the TS detector.