Expand description
§IFC-Lite Geometry Processing
Efficient geometry processing for IFC models using earcutr triangulation and nalgebra for transformations.
§Overview
This crate transforms IFC geometry representations into GPU-ready triangle meshes:
- Profile Handling: Extract and process 2D profiles (rectangle, circle, arbitrary)
- Extrusion: Generate 3D meshes from extruded profiles
- Triangulation: Polygon triangulation with hole support via earcutr
- CSG Operations: Full boolean operations (difference, union, intersection)
- Mesh Processing: Normal calculation and coordinate transformations
§Supported Geometry Types
| Type | Status | Description |
|---|---|---|
IfcExtrudedAreaSolid | Full | Most common - extruded profiles |
IfcExtrudedAreaSolidTapered | Full | Lofted extrusion between two profiles |
IfcFacetedBrep | Full | Boundary representation meshes |
IfcTriangulatedFaceSet | Full | Pre-triangulated (IFC4) |
IfcBooleanClippingResult | Full | CSG operations (difference, union, intersection) |
IfcMappedItem | Full | Instanced geometry |
IfcSweptDiskSolid | Full | Pipe/tube geometry |
§Quick Start
ⓘ
use ifc_lite_geometry::{
Profile2D, extrude_profile, triangulate_polygon,
Point2, Point3, Vector3
};
// Create a rectangular profile
let profile = Profile2D::rectangle(2.0, 1.0);
// Extrude to 3D
let direction = Vector3::new(0.0, 0.0, 1.0);
let mesh = extrude_profile(&profile, direction, 3.0)?;
println!("Generated {} triangles", mesh.triangle_count());§Geometry Router
Use the GeometryRouter to automatically dispatch entities to appropriate processors:
ⓘ
use ifc_lite_geometry::{GeometryRouter, GeometryProcessor};
let router = GeometryRouter::new();
// Process entity
if let Some(mesh) = router.process(&decoder, &entity)? {
renderer.add_mesh(mesh);
}§Performance
- Simple extrusions: ~2000 entities/sec
- Complex Breps: ~200 entities/sec
- Boolean operations: ~20 entities/sec
Re-exports§
pub use rect_fast::RectFastStats;pub use csg::calculate_normals;pub use csg::ClippingProcessor;pub use csg::Plane;pub use csg::Triangle;pub use material_layer_index::LayerAxis;pub use material_layer_index::LayerBuildup;pub use material_layer_index::LayerInfo;pub use material_layer_index::MaterialLayerFlat;pub use material_layer_index::MaterialLayerIndex;pub use mesh::InstanceMeta;pub use mesh::Mesh;pub use mesh::SubMesh;pub use mesh::SubMeshCollection;pub use simplify::simplify_mesh;pub use simplify::SimplifyOptions;pub use simplify::SimplifyStats;
Modules§
- csg
- CSG (Constructive Solid Geometry) Operations
- kernel
- Pure-Rust exact mesh-arrangement CSG kernel — the only CSG kernel, on every target (see docs/architecture/geometry-pipeline.md). Pure-Rust exact mesh-arrangement CSG kernel — predicate foundation.
- material_
layer_ index - Material Layer Index
- mesh
- Mesh data structures
- mesh_
weld - Intra-mesh vertex weld + index dedup applied at the per-element mesh source
(
build_mesh_data), collapsing the faceted-brep per-face vertex duplication while keeping creases (distinct normals) split. Intra-mesh vertex weld + index dedup, applied at the mesh SOURCE. - projection_
outline - Winding-independent 2D footprint outline of a mesh, for construction projection on 2D floor plans (issue #979).
- rect_
fast - Analytic fast path for axis-aligned rectangular openings cut through an axis-aligned box host (the dominant case: rectangular windows/doors in a straight wall). This sidesteps the exact mesh-arrangement CSG kernel — which is at its single-threaded, memory-bandwidth-bound floor — for openings that need no exact arithmetic at all.
- simplify
- Per-element mesh simplification for the demesher (cavity removal, grid vertex-clustering decimation, bounding-box collapse). Per-element mesh simplification (“demesher”).
- space_
dcel - Persistent, editable space topology (DCEL)
Structs§
- Advanced
Brep Processor - AdvancedBrep processor Handles IfcAdvancedBrep and IfcAdvancedBrepWithVoids - NURBS/B-spline surfaces Supports planar faces and B-spline surface tessellation
- Alignment
Curve - Parsed alignment curve. Holds horizontal and vertical segments in authored order with cumulative-start stations precomputed.
- Alignment
Frame - Cross-section placement frame at a station.
- Bool
Failure - Single boolean / CSG failure record.
- Boolean
Clipping Processor - BooleanResult processor Handles IfcBooleanResult and IfcBooleanClippingResult - CSG operations
- Classification
Stats - Counts of opening classification outcomes during the most recent
geometry pass. Useful for confirming whether the host-aware
floor-opening classifier guard (commit
1e033f8) is taking effect on a given model. - Classification
Summary - Opening-classifier outcome counts (rectangular / diagonal / non-rectangular).
- Collated
- Result of collation: instanced templates + the meshes left to render flat.
- Decoded
Instance - One occurrence of a decoded template.
- Decoded
Instanced - A decoded instanced shard.
- Decoded
Template - A unique geometry decoded from an instanced shard.
- Extracted
Profile - A profile extracted from a single IFC building element.
- Extruded
Area Solid Processor - ExtrudedAreaSolid processor (P0) Handles IfcExtrudedAreaSolid - extrusion of 2D profiles
- Extruded
Area Solid Tapered Processor - Face
Based Surface Model Processor - FaceBasedSurfaceModel processor Handles IfcFaceBasedSurfaceModel - surface model made of connected face sets
- Faceted
Brep Processor - FacetedBrep processor Handles IfcFacetedBrep - explicit mesh with faces Supports faces with inner bounds (holes) Uses parallel triangulation for large BREPs
- Geometry
Diagnostics - Aggregate CSG / opening diagnostics for one geometry pass — the public
diagnostics contract. Built by
aggregate_diagnosticsfrom drained router data and serialized to the @ifc-lite/geometrycompleteevent, and reused verbatim by the nativeProcessingStatspath (rust/processing/src/processor/mod.rspopulatesgeometry_diagnostics). wasm-free (serde only). - Geometry
Hasher - Accumulates a single entity’s geometry signature across one or more mesh segments. Segments are combined commutatively, so the order in which the kernel emits an entity’s pieces does not affect the result.
- Geometry
Router - Geometry router - routes entities to processors
- Host
Opening Diagnostic - Per-host opening diagnostic captured during void processing.
- Image
Texture Ref - An unresolved
IfcImageTexturereference (#1781). - Instance
Mesh Ref - A borrowed view of a mesh for collation/encoding — lets callers feed geometry
from any owner (geometry’s
Mesh, processing’sMeshData) WITHOUT cloning the vertex data (cloning 219k meshes’ geometry risks the build-container OOM). - Instance
Occurrence - One occurrence of a template geometry.
- Instance
Template - A unique geometry shared by two or more occurrences.
- Mesh
Texture - A decoded RGBA8 image ready for GPU upload.
- Opening
Diagnostic - One opening’s worth of diagnostic data — what
classify_openingsobserved about it. - Polygonal
Face SetProcessor - Handles IfcPolygonalFaceSet - explicit polygon meshes that need triangulation Unlike IfcTriangulatedFaceSet, faces can be arbitrary polygons (not just triangles)
- Profile2D
- 2D Profile with optional holes
- Profile2D
With Voids - Profile with void tracking for depth-aware extrusion
- Profile
Processor - Profile processor - processes IFC profiles into 2D contours
- Reason
Count - One CSG failure reason and its occurrence count this pass.
reasonis one of the stablecrate::diagnostics::BoolFailureReason::labelstrings. - Rect
Fast Summary - rect_fast fast-path engagement counters (perf observability).
- Rect
Param - EXACT parametric oriented box of a rectangular extrusion, in WORLD space.
rcolumns are the orthonormal world axes (profile-X’, profile-Y’, extrude);halfare the half-extents along those axes (XDim/2, YDim/2, Depth/2). Produced byGeometryRouter::parametric_rect_probe. - Resolved
Texture Map - A fully resolved
IfcIndexedTriangleTextureMapfor one face set. - Revolved
Area Solid Processor - RevolvedAreaSolid processor Handles IfcRevolvedAreaSolid - rotates a 2D profile around an axis
- Surface
OfLinear Extrusion Processor - SurfaceOfLinearExtrusion processor Handles IfcSurfaceOfLinearExtrusion - surface created by sweeping a curve along a direction
- Swept
Disk Solid Processor - SweptDiskSolid processor Handles IfcSweptDiskSolid - sweeps a circular profile along a curve
- Texture
Attachment - A surface texture attached to an output mesh: the stable dedup key plus the
pixel source.
texture_idis theIfcSurfaceTextureexpress id — every mesh sampling the same image carries the same id, so consumers create one GPU texture per id instead of one per mesh. - Triangulated
Face SetProcessor - TriangulatedFaceSet processor (P0) Handles IfcTriangulatedFaceSet - explicit triangle meshes
- Void
Index - Index mapping host elements to their voids
- Void
Info - Void metadata for depth-aware extrusion
- Worst
Host - One of the worst-failing host elements (bounded top-N, opt-in detail).
Enums§
- Bool
Failure Reason - Why a boolean operation failed or was skipped.
- BoolOp
- Which boolean operation produced the failure.
- Error
- Errors that can occur during geometry processing
- Opening
Kind Diag - Discriminator for
OpeningDiagnostic::kind. MirrorsOpeningTypewithout dragging the geometry data along. - Profile
Type - Common profile types
- Tessellation
Quality - Detail level for geometry tessellation, selectable by consumers.
- Texture
Source - Where a resolved surface texture’s pixels come from.
Constants§
- DEFAULT_
GEOM_ HASH_ TOLERANCE - Default quantization grid in metres (1 mm). Chosen as a starting point near
the
f32precision floor of RTC-local coordinates; tune empirically with thetolerance_sweeptest against real revision pairs. - GEOMETRY_
DIAGNOSTICS_ SCHEMA_ VERSION - Compatibility handshake for the
GeometryDiagnosticscontract, serialized asschemaVersion. DISTINCT from the viewer cacheFORMAT_VERSION(an invalidation token): this is a promise consumers can gate on. - INSTANCED_
MAGIC "IFNS"little-endian — the instanced-shard magic the TS decoder validates.- INSTANCED_
VERSION - Instanced format version. Bump in lockstep with the TS decoder.
- LARGE_
COORD_ THRESHOLD_ METERS - The streaming / needs-shift large-coordinate threshold (metres): a world
coordinate whose magnitude exceeds this needs RTC re-basing before it is
cast to f32, or the model renders with vertex jitter. Shared by the router’s
own coordinate sampling (
router::rtc_offset) and the streaming pre-pass meta resolver (ifc_lite_processing::stream_meta) so those two make the same decision. (Other 10 km checks carry their own local constant of the same value.)
Traits§
- Geometry
Processor - Geometry processor trait Each processor handles one type of IFC representation
Functions§
- aggregate_
diagnostics - Build a
GeometryDiagnosticsfrom drained router data. wasm-free so both the wasm/viewer path and a future native path can produce the same contract. The caller owns draining: the router accessors are destructive (mem::take), so drain once and pass the results here — do not double-take. - bake_
source_ at_ world - Bake a SOURCE-coords
Meshat a PRE-RTC row-major world transform into absolute POST-RTC world geometry(positions, normals, indices)— the #1623 Phase 2 finalize fallback for a don’t-bake instance whose template occurrence never materialized (an orphan; effectively unreachable for the eligible single-solid type-instanced set, but kept so geometry is NEVER silently lost). The affine part transforms positions; the inverse-transpose of the linear part transforms normals (renormalized). Geometrically equal to the baked flat occurrence (same triangles); the registry source is pre-weld, so vertices are unwelded — that changes only the vertex count, not the rendered surface. - build_
aggregate_ children_ index - Scan
contentforIfcRelAggregatesand build the full (unfiltered) parent → children map used bypropagate_voids_via_aggregates. - build_
texture_ index - Scan the model for
IfcIndexedTriangleTextureMapentities and build an index keyed by the face set id each one maps to (issue #961). Cheap substring bail-out keeps untextured files (the overwhelming majority) off the scan. - collate_
and_ encode - One-shot producer: collate the mesh views into templates + instances and
encode them as an instanced shard. The caller (e.g. the native helper) builds
InstanceMeshRefs borrowing its own mesh storage — no geometry is cloned. - collate_
instances collate_refsover geometryMeshvalues (thin wrapper, no geometry clone).- collate_
refs - Group instanceable meshes by representation identity into templates +
per-instance transforms.
min_groupis the smallest occurrence count worth instancing (groups below it are emitted flat); use 2 to instance any repeat. - compose_
instance_ world_ row_ major - Compose an occurrence’s full PRE-RTC world transform
transform·local·canonicalas a row-major[f64; 16]. Public so the processing crate’s don’t-bake finalize (#1623 Phase 2) can record the SAME world placementcollate_refscomputes for a baked occurrence — without materializing the occurrence’s vertices. - compute_
parts_ to_ skip - Compute the set of aggregated
IfcBuildingElementPartids to skip when the “merge multilayer wall as a single solid” toggle is on (issue #540): a part is skipped when its parent’s layered build-up is sliceable, so the parent’s merged-layer geometry is drawn instead of the individual parts. - compute_
signed_ area - Compute the signed area of a 2D contour Positive = counter-clockwise, Negative = clockwise
- decode_
instanced - Decode an instanced shard. Returns None on a bad magic/version or truncation.
- encode_
instanced encode_refsover geometryMeshvalues, with id/colour accessor closures (thin wrapper, no geometry clone).- encode_
refs - Encode a
Collatedresult + its source mesh views into an instanced shard. Per-occurrence entity id + colour come from eachInstanceMeshRef. - ensure_
ccw - Ensure contour has counter-clockwise winding (positive area)
- ensure_
cw - Ensure contour has clockwise winding (for holes)
- extract_
profiles - Extract profiles for every building element in
content. - extrude_
profile - Extrude a 2D profile along the Z axis
- extrude_
profile_ lofted - Extrude with a different cross section at the top (lofted/tapered extrusion).
- extrude_
profile_ with_ voids - Extrude a 2D profile with void awareness
- hash_
mesh_ world - Convenience: hash a single-segment entity in one call.
- instance_
rel_ row_ major_ f32 - Template-relative instance transform
rel = post_rtc(M_k) · post_rtc(M_ref)⁻¹as a row-major[f32; 16], orNonewhenM_refis singular.m_k/m_refare PRE-RTC row-major world transforms (seecompose_instance_world_row_major);rtcis the model offset. This is EXACTLYcollate_refs’ per-occurrencerel, exposed for the don’t-bake finalize where the occurrence carries no geometry to group — the template’s baked world geometry placed byrelreproduces the occurrence’s world geometry (bounded byverify_recomposition). #1623 Phase 2. - is_
valid_ contour - Check if a contour is valid (has area, not degenerate)
- local_
frame_ set_ enabled_ override - Test/harness-only: force [
local_frame_enabled] on/off, orNonefor the target default. Mirrorsrect_fast::param_set_enabled_override. The mesh-output determinism manifest uses it to run native and wasm with the SAME flag state (wasm defaults ON, native defaults OFF below), so the two targets’ outputs are comparable byte-for-byte. - orient_
mesh_ outward - Orient every connected component of
meshconsistently and outward, in place. Returnstrueiff any triangle’s winding was flipped (the caller must then recompute normals — the existing ones were baked with the old winding). - parse_
axis2_ placement_ 3d - Parse IfcAxis2Placement3D into transformation matrix
- parse_
axis2_ placement_ 3d_ from_ id - Parse IfcAxis2Placement3D from entity ID (fast-path variant)
- parse_
cartesian_ point - Parse IfcCartesianPoint from an entity attribute
- parse_
cartesian_ point_ from_ id - Parse IfcCartesianPoint from entity ID (fast-path variant)
- parse_
direction - Parse IfcDirection entity
- parse_
direction_ from_ id - Parse IfcDirection from entity ID.
- point_
in_ contour - Check if a point is inside a contour using ray casting
- propagate_
voids_ to_ parts - Propagate void (opening) relationships from aggregate parents to their children
and return a child-part → parent-element map covering every emitted aggregate
IfcWall→IfcBuildingElementPartpair. - propagate_
voids_ via_ aggregates - Propagate openings from hosts that aggregate parts to every aggregated descendant — recursive and type-agnostic (IfcWallElementedCase panels, IfcRoof → IfcSlab skylights, nested assemblies, …).
- rotation_
angle_ about_ z - The building/site rotation about the world vertical (Z) axis, derived from a
resolved column-major 4×4 placement matrix (as returned by
crate::GeometryRouter::resolve_scaled_placement). The local X-axis (the placement’s RefDirection, composed through the full parent chain and normalized) is column 0 — elements[0],[1],[2]— so its angle in the world XY plane isatan2(m[1], m[0]). - scale_
segments - Scale a tessellator’s segment count by the selected quality level.
- subtract_
2d - Perform 2D boolean difference: profile - void_contour
- subtract_
multiple_ 2d - Perform 2D boolean difference with multiple voids at once
- subtract_
multiple_ 2d_ counted - Like
subtract_multiple_2d, but also reports how many DISCONNECTED output shapes the difference produced (each with non-degenerate area). The returnedProfile2Dis the largest shape (assubtract_multiple_2d); a caller that must not silently drop geometry — the 2D opening-subtraction re-extrude — checksshapes == 1and otherwise defers to the exact kernel (a void that splits the profile into pieces can’t be re-extruded from a single profile). - take_
bool2d_ stats - Read + reset the 2D-path telemetry: (hosts cut via the 2D path, opening footprints subtracted in those hosts). Process-global; used by the perf harness to report the fast-path hit-rate. Relaxed atomics — a stale read under concurrency only mis-reports a diagnostic count, never geometry.
- take_
prism_ defers - Telemetry disabled in the default build; the perf harness must enable an observability feature to read real counts.
- take_
prism_ stats - triangulate_
polygon - Triangulate a simple polygon (no holes) Returns triangle indices into the input points
- verify_
recomposition - Maximum per-vertex world-space error (in mesh units) when each occurrence is
reconstructed by applying its instance transform to the template’s baked
world geometry, versus the occurrence’s own baked world geometry. The
template-relative transform operates on world coords, so each mesh’s
originis folded in. Used by tests + as a runtime diagnostic.
Type Aliases§
- Item
Dedup Cache - Shared content-dedup cache: maps a 128-bit structural item hash to the
LOCAL (pre-placement, void-free, colour-free) item mesh PLUS its precomputed
instancing
rep_identity(Somewhen instancing tagged it, elseNone). Storing the rep beside the mesh lets a cache hit stamp it without re-running the O(verts)compute_mesh_hash_fullper occurrence. Build ONE per loaded model withGeometryRouter::new_dedup_cacheand inject it into every per-element / per-batch router viaGeometryRouter::enable_content_dedup_sharedso byte-identical geometry is meshed once regardless of how the work is partitioned across threads/batches. - Mapped
Instance Plan - #1623 Phase 2 “don’t-bake” instancing plan:
IfcRepresentationMapexpress id ⇒(occurrence_count, template_item_id), wheretemplate_item_idis the SMALLESTIfcMappedItemexpress id referencing that source (a deterministic, race-free choice of which occurrence materializes its geometry as the shared template). Only sources withoccurrence_count >= 2appear. Built ONCE from the file scan and injected into every per-element / per-batch router viaGeometryRouter::enable_output_instancing. When a mapped item’s source is in this plan AND the occurrence is a single-solid ordinary product, the NON-template occurrences skip the per-occurrence vertex bake and emit an instance-only placeholder (empty geometry carryingcrate::mesh::InstanceMeta) instead of a full materialized mesh — the ~29s / 43M-vertex materialize this phase kills.None⇒ every occurrence materializes (historical flat output, byte-identical); exporters and the determinism harness never arm it. - Point2
- A statically sized 2-dimensional column point.
- Point3
- A statically sized 3-dimensional column point.
- Result
- Result type for geometry operations
- Shared
Mapped Item Cache - Shared
IfcMappedItemsource cache: maps anIfcRepresentationMapexpress id to its SOURCE-coordinate (pre-MappingTarget, pre-placement, colour-free) item mesh. Build ONE per loaded model withGeometryRouter::new_mapped_item_cacheand inject it into every per-element / per-batch router viaGeometryRouter::enable_shared_mapped_item_cache, so a source shared by many owning elements is meshed ONCE model-wide instead of once per element (a fresh router is built per element, so the per-router RefCellmapped_item_cacheonly dedups WITHIN one element — #1623). The value is the same source-coords mesh the RefCell would store; the per-occurrenceMappingTargettransform +instance_metaare applied by the caller AFTER the lookup, so a cross-router cache hit is byte-identical to a fresh build. - Vector2
- A stack-allocated, 2-dimensional column vector.
- Vector3
- A stack-allocated, 3-dimensional column vector.