Skip to main content

ifc_geometry/
lib.rs

1//! `ifc-geometry` — the IFC side of geometry.
2//!
3//! # What this crate is
4//!
5//! It answers *"what does this IFC entity mean geometrically"* and lowers
6//! implemented slices into the format-neutral `axiolid-model` DAG. It does not
7//! triangulate, evaluate NURBS, or perform booleans itself.
8//!
9//! The opt-in `compile` feature is the one narrow exception: it hands the
10//! lowered DAG to an Axiolid provider and returns triangles. It is off by
11//! default because selecting a provider and a memory budget is application
12//! policy, not something the IFC file determines. See the `compile` module
13//! and ADR 0004.
14//!
15//! ```text
16//!   ifc-model            this crate                    geometry package
17//!   (untyped graph) -->  typed/family views  -->  GeometryGraph
18//!                        + IFC resolution       (implemented elsewhere)
19//! ```
20//!
21//! # Scope
22//!
23//! The three IFC geometry resource schemas, counted from IFC4 ADD2 TC1:
24//!
25//! | Schema | Entities | Types | Functions |
26//! | --- | ---: | ---: | ---: |
27//! | `IfcGeometryResource` | 59 | 14 | 25 |
28//! | `IfcGeometricModelResource` | 42 | 4 | 2 |
29//! | `IfcGeometricConstraintResource` | 11 | 5 | 1 |
30//!
31//! # Design
32//!
33//! **Views and explicit inventory.** The 89 concrete entities are represented by
34//! dedicated or shared subtype-aware borrowed views. The 23 abstract entities
35//! are inheritance/inventory entries, not falsely presented as constructible
36//! views. All 23 schema types are modeled.
37//!
38//! **Honest lowering.** The dispatcher's `IMPLEMENTED` list (in
39//! `lower::dispatch`) names every representation-item type it lowers: swept,
40//! CSG, boolean and half-space solids, faceted and advanced B-reps,
41//! tessellated face sets, surfaces, curves, surface models, collections and
42//! mapped items. Every other concrete IFC4 representation item has a
43//! recorded disposition in `data/ifc4-representation-item-dispositions.tsv`
44//! (nested input, non-shape, or typed refusal). IFC4X3 ADD2 adds 17
45//! representation items: `IfcCurveSegment`, `IfcGradientCurve`,
46//! `IfcDirectrixDerivedReferenceSweptAreaSolid` and
47//! `IfcTriangulatedIrregularNetwork` lower (each with named refused forms in
48//! `PARTIAL`), and the rest are in `PLANNED` with a named reason. Input that
49//! cannot be lowered
50//! exactly returns a typed [`crate::GeometryError`], such as
51//! [`crate::GeometryError::Unsupported`], rather than panicking or
52//! substituting approximate geometry.
53//!
54//! **Neutral DAG output.** Implemented lowerers resolve IFC units, placements,
55//! profiles, and representation relationships into `axiolid-model` nodes. Active
56//! lowering owns no duplicate geometry types and never selects a CPU/GPU
57//! provider.
58//!
59//! **Feature `lowering`** (default on) carries the neutral geometry crates.
60//! Without it this crate is representation selection only -- contexts,
61//! plan/body choice, profiles, curves, surfaces, solids, units and
62//! placements -- and links no geometry code at all.
63
64pub mod authoring;
65#[cfg(feature = "compile")]
66pub mod compile;
67pub mod constraint;
68pub mod curve;
69pub mod error;
70#[cfg(feature = "lowering")]
71pub mod lower;
72pub mod resource;
73pub mod rules;
74pub mod select;
75pub mod slots;
76pub mod solid;
77pub mod surface;
78pub mod transform;
79pub mod units;
80
81// Neutral geometry vocabulary, re-exported so a lowering consumer needs only
82// this crate in scope. Gated with the lowering it exists to serve.
83#[cfg(feature = "lowering")]
84pub use axiolid_model::BooleanOperator as GeometryBooleanOperator;
85#[cfg(feature = "lowering")]
86pub use axiolid_model::{GeometryGraph, GeometryNode, NodeId, SolidOperation};
87#[cfg(feature = "lowering")]
88pub use axiolid_primitive::Primitive as AnalyticPrimitive;
89#[cfg(feature = "lowering")]
90pub use axiolid_profile::Profile as ExactProfile;
91// Placement resolution is the most-reused operation in any IFC consumer
92// and the one most often reimplemented wrongly, so it is reachable from
93// the crate root and does not require the `lowering` feature: a 2D drawing
94// needs world coordinates without compiling a solid kernel.
95pub use constraint::{product_world_transform, products_world_transforms};
96pub use error::{GeometryError, GeometryResult};
97pub use slots::Slots;
98pub use transform::Transform;
99pub use units::UnitScale;
100mod input;
101
102// Representation contexts and selection policy. Public because drawing
103// production is a first-class consumer: choosing the geometry a plan is drawn
104// from is a question about contexts, not about lowering.
105pub use input::context::{
106    all_contexts, context_of, plan_contexts, product_representation_frame, RepresentationContext,
107    TargetView,
108};
109// Geometry-shaping material inputs only. Material identity, quantities, and
110// association policy remain owned by `ifc-material`.
111pub use input::material_usage::{
112    CardinalPoint, DirectionSense, LayerSetDirection, MaterialLayerSetUsageGeometry,
113    MaterialProfileGeometry, MaterialProfileSetUsageGeometry,
114    MaterialProfileSetUsageTaperingGeometry,
115};
116pub use input::representation::{
117    select_plan_representation, select_product_representation, select_shape_representation,
118    ProductShape, Representation, RepresentationPurpose, PLAN_IDENTIFIERS, SOLID_IDENTIFIERS,
119};
120
121// Which entities carry a shape at all. Kernel-free: a slot read, not a lowering
122// question, so a 2D or auditing consumer reaches it without linking a kernel.
123pub use input::product::geometric_products;
124
125// Which openings void a host (`IfcRelVoidsElement`). Kernel-free for the same
126// reason; `lower::lower_product_net` turns the answer into subtractions.
127pub use input::openings::{openings_of, voiding_conflicts, VoidingConflict};
128
129// How a body is modelled -- kind, swept-solid profile parameters, direction
130// and depth -- in SI and world coordinates. Kernel-free: a rule check asking
131// "is this beam an HEA300" must not link a solid kernel for the answer.
132pub use input::body::{
133    body_description, BodyDescription, BodyItem, BodyKind, SweepPath, SweptSolid,
134};
135// Profile families read into SI parameters. The same reader feeds
136// `lower::profile`, so a description and a lowering cannot disagree.
137pub use input::profile::{
138    describe_profile, profile_outline, ProfileDescription, ProfileOperator, ProfileOutline,
139    ProfileParameters, ProfilePosition,
140};