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