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 partial lowering.** Exact profiles and extrusion/revolution are
39//! implemented vertical slices. Every other assigned declaration is tracked in
40//! the support ledger; attempting an unimplemented lowering returns typed
41//! [`crate::GeometryError::Unsupported`] rather than panicking or substituting
42//! approximate geometry.
43//!
44//! **Neutral DAG output.** Implemented lowerers resolve IFC units, placements,
45//! profiles, and representation relationships into `axiolid-model` nodes. Active
46//! lowering owns no duplicate geometry types and never selects a CPU/GPU
47//! provider.
48//!
49//! **Feature `lowering`** (default on) carries the neutral geometry crates.
50//! Without it this crate is representation selection only -- contexts,
51//! plan/body choice, profiles, curves, surfaces, solids, units and
52//! placements -- and links no geometry code at all.
53
54pub mod authoring;
55#[cfg(feature = "compile")]
56pub mod compile;
57pub mod constraint;
58pub mod curve;
59pub mod error;
60#[cfg(feature = "lowering")]
61pub mod lower;
62pub mod resource;
63pub mod rules;
64pub mod select;
65pub mod slots;
66pub mod solid;
67pub mod surface;
68pub mod transform;
69pub mod units;
70
71// Neutral geometry vocabulary, re-exported so a lowering consumer needs only
72// this crate in scope. Gated with the lowering it exists to serve.
73#[cfg(feature = "lowering")]
74pub use axiolid_model::BooleanOperator as GeometryBooleanOperator;
75#[cfg(feature = "lowering")]
76pub use axiolid_model::{GeometryGraph, GeometryNode, NodeId, SolidOperation};
77#[cfg(feature = "lowering")]
78pub use axiolid_primitive::Primitive as AnalyticPrimitive;
79#[cfg(feature = "lowering")]
80pub use axiolid_profile::Profile as ExactProfile;
81// Placement resolution is the most-reused operation in any IFC consumer
82// and the one most often reimplemented wrongly, so it is reachable from
83// the crate root and does not require the `lowering` feature: a 2D drawing
84// needs world coordinates without compiling a solid kernel.
85pub use constraint::{product_world_transform, products_world_transforms};
86pub use error::{GeometryError, GeometryResult};
87pub use slots::Slots;
88pub use transform::Transform;
89pub use units::UnitScale;
90mod input;
91
92// Representation contexts and selection policy. Public because drawing
93// production is a first-class consumer: choosing the geometry a plan is drawn
94// from is a question about contexts, not about lowering.
95pub use input::context::{
96    all_contexts, context_of, plan_contexts, product_representation_frame, RepresentationContext,
97    TargetView,
98};
99// Geometry-shaping material inputs only. Material identity, quantities, and
100// association policy remain owned by `ifc-material`.
101pub use input::material_usage::{
102    CardinalPoint, DirectionSense, LayerSetDirection, MaterialLayerSetUsageGeometry,
103    MaterialProfileGeometry, MaterialProfileSetUsageGeometry,
104    MaterialProfileSetUsageTaperingGeometry,
105};
106pub use input::representation::{
107    select_plan_representation, select_product_representation, select_shape_representation,
108    ProductShape, Representation, RepresentationPurpose, PLAN_IDENTIFIERS, SOLID_IDENTIFIERS,
109};
110
111// Which entities carry a shape at all. Kernel-free: a slot read, not a lowering
112// question, so a 2D or auditing consumer reaches it without linking a kernel.
113pub use input::product::geometric_products;
114
115// Which openings void a host (`IfcRelVoidsElement`). Kernel-free for the same
116// reason; `lower::lower_product_net` turns the answer into subtractions.
117pub use input::openings::{openings_of, voiding_conflicts, VoidingConflict};
118
119// How a body is modelled -- kind, swept-solid profile parameters, direction
120// and depth -- in SI and world coordinates. Kernel-free: a rule check asking
121// "is this beam an HEA300" must not link a solid kernel for the answer.
122pub use input::body::{
123    body_description, BodyDescription, BodyItem, BodyKind, SweepPath, SweptSolid,
124};
125// Profile families read into SI parameters. The same reader feeds
126// `lower::profile`, so a description and a lowering cannot disagree.
127pub use input::profile::{
128    describe_profile, profile_outline, ProfileDescription, ProfileOperator, ProfileOutline,
129    ProfileParameters, ProfilePosition,
130};