Architecture
COMPAS IFC is organised as a three-layer front-end / back-end structure that separates what users interact with from how IFC data is read, written, and kept consistent. The architecture is described in detail in chapter 4 of the underlying thesis (Data Model for Humans); this page summarises it.
Top layer — front-end API
The user-facing API consists of four components:
BuildingInformationModelThe orchestrator. Opens, queries, modifies, and saves IFC files. Holds project-level metadata (name, schema version, units) and exposes the spatial tree, the interaction graph, the element factory, the validation engine, and visualisation helpers.
GenericElementA single element class that represents every IFC product subclass —
IfcWall,IfcSlab,IfcSpace,IfcSite,IfcBuildingStorey, and the rest. Distinguished by anifc_typestring that maps back to the appropriate IFC class on export. Custom strings without a matching IFC class fall back toIfcBuildingElementProxywhile preserving the original type asObjectType.- Spatial tree (
model.tree) An explicit tree built on COMPAS’
Treedata structure. Each node has directparent/childrenpointers and a placement matrix relative to its parent. Spatial-containment relationships in the IFC schema (IfcRelContainedInSpatialStructure,IfcRelAggregates) are normalised into this tree on import; placement chains that don’t align with the spatial parent are rectified automatically.- Interaction graph (
model.graph) A bidirectional graph that captures the non-hierarchical relationships that don’t fit the tree structure — structural connections, MEP system flows, material associations, geometric dependencies (openings, fills, space boundaries). Edges are labelled by category and group, so users can query
model.connections,model.space_boundaries, ormodel.get_interactions_by_group("structural").
Bidirectional mapping layer
The middle layer keeps the front-end abstractions and the underlying IFC file in sync. It is implementation detail — users do not need to interact with it directly — but understanding it helps when reading the source code:
Relationship resolution. Spatial-containment and decomposition relationships are converted to tree edges; structural, MEP, and geometric relationships are converted to graph edges. Round-tripping reverses the process: graph and tree edges are rewritten back into the appropriate
IfcRel...instances on save.Placement-chain rectification. During import, each element’s
IfcLocalPlacement.PlacementRelTois checked against its spatial parent. Misalignments — for instance an opening element placed relative to the storey instead of its host wall — are corrected so that the global position is preserved while the relative transform conforms to the hierarchy.Representation conversion. Each IFC geometric representation type is routed to the appropriate computational kernel: simple primitives and meshes use the COMPAS core library, while swept solids and freeform B-Reps go through OpenCascade (via
compas_occ). Boolean operations are currently evaluated through OpenCascade and the COMPAS core/Shapely path; routing to CGAL (compas_cgal) is planned. The mapping is bidirectional: parametric definitions are preserved on round-trip rather than collapsing to tessellated meshes.Type normalisation.
model.create_element(ifc_type=...)accepts"IfcWall","Wall","wall", or any custom string; the value is resolved against the active schema and either mapped to its canonical class name or stored asObjectTypeon anIfcBuildingElementProxy.Property serialisation. Pset definitions and IFC schema attributes are unified into
element.propertiesfor reading, and split back into the appropriate sinks (Pset_*instances vs. direct entity attributes) on write.
Bottom layer — IFC schema interface
At the bottom, compas_ifc.file.IFCFile adapts
IfcOpenShell to the rest of the toolkit. It
handles low-level parsing and writing, schema dispatch (IFC2X3 / IFC4 /
IFC4X3), entity creation, and instance lookup. The
compas_ifc.entities package provides Python wrappers that add convenience
methods (geometry, frame, children, property_sets) to raw
ifcopenshell entities; these wrappers are an internal implementation
detail of the mapping layer.
Geometry kernels
Three computational kernels combine to cover the full IFC geometry spectrum without degradation:
IFC representation |
COMPAS class |
Kernel |
|---|---|---|
|
|
COMPAS core |
|
|
|
|
|
OpenCascade |
|
||
|
|
CGAL / OpenCascade |
|
||
|
|
COMPAS core / CGAL |
|
|
OpenCascade |
|
|
COMPAS core |
|
||
|
|
OpenCascade |
|
|
Note
CGAL routing (via compas_cgal) is part of the intended architecture
but is not yet wired in: the CGAL cells above are currently served by
OpenCascade and the COMPAS core mesh path. CGAL integration is planned.
The user-facing API is uniform across kernels: element.volume,
element.surface_area, and element.aabb work identically regardless
of the underlying representation type.
Validation engine
Custom property requirements are expressed as
Pydantic schemas. A
Specification ties a schema to the IFC types
it applies to. Specifications can be:
attached to
model.specificationsfor enforcement — validation runs insideadd_element/create_elementand rejects non-conforming insertions immediately; orpassed to
model.validate(specs)for advisory checking, which returns per-elementValidationResultrecords without modifying the model.
Pydantic schemas are substantially more concise than the equivalent
IDS (Information Delivery Specification) XML, and they export to JSON
Schema for consumption by external tools.
Further reading
The thesis chapter 4 (Data Model for Humans) describes the design principles, the cognitive-complexity target (≤ 100 user-facing API members), and the evaluation results in detail.
The reproducible evaluation scripts are in
thesis/appendix/A/of the source repository.