IFC Relationships
IFC does not connect objects with plain pointer attributes. Every
connection between objects is a separate, identifiable entity: an
IfcRelationship. This is the objectified relationship pattern. This
skill covers why IFC objectifies relationships, the six relationship
families, the Relating versus Related direction convention, the
concrete IfcRel* entities, and how to traverse them.
Verified against the IFC 4.3.2 specification (ISO 16739-1:2024) with IFC4 and IFC2x3 deltas noted inline. Applies to IFC2x3, IFC4, IFC4.3.
Quick Reference
The objectified relationship pattern
IfcRelationship is a direct subtype of IfcRoot, so every relationship
instance carries its own GlobalId, OwnerHistory, Name, and
Description. A relationship is a node in the model, not an attribute on
the connected objects.
Consequences that drive every rule in this skill:
- A relationship can carry its own data: connection geometry, priorities, boundary type. That data lives ON the relationship, not on the objects.
- A relationship is added or removed WITHOUT editing the connected objects. ALWAYS edit the relationship instance, NEVER the participants.
- A relationship is itself identifiable and versionable through its
GlobalId. - The cost is indirection: to reach a wall's property sets you follow the
wall's
IsDefinedByINVERSE toIfcRelDefinesByPropertiesinstances, then readRelatingPropertyDefinition. NEVER expect a direct attribute.
The six relationship families
IfcRelationship is abstract with exactly six direct subtypes (verified).
NEVER instantiate IfcRelationship or any abstract family supertype.
| Family | Purpose | Concrete entities used most |
|---|---|---|
IfcRelAssigns |
Cross-domain assignment of objects to a group, process, resource, control, actor, or product | IfcRelAssignsToGroup |
IfcRelAssociates |
Associate external information with objects | IfcRelAssociatesMaterial, IfcRelAssociatesClassification |
IfcRelConnects |
Connectivity, containment, fills, space boundaries | IfcRelContainedInSpatialStructure, IfcRelConnectsElements, IfcRelFillsElement |
IfcRelDeclares |
Declare objects or types into an IfcContext (project or library) |
IfcRelDeclares |
IfcRelDecomposes |
Whole and part decomposition, plus feature subtraction | IfcRelAggregates, IfcRelNests, IfcRelVoidsElement |
IfcRelDefines |
Assign a type or a property set to objects | IfcRelDefinesByType, IfcRelDefinesByProperties |
The Relating versus Related convention
Every relationship has one Relating... role and one Related... role.
The direction is part of the semantics. A backwards relationship is a
structurally valid but meaningless model.
- The
Relating...side is the single anchor: the whole, the type, the spatial container, the property set, the opening. - The
Related...side is the dependent participant. In one-to-many relationships it is an aggregate (SETorLIST, cardinality1..n).
ALWAYS read the entity attribute documentation to know which object goes on which side. NEVER guess the direction.
Key IfcRel* reference table
All entities and attribute types below are verified against the IFC4.3
specification. Full positional signatures are in references/methods.md.
| Entity | Supertype | Relating side | Related side |
|---|---|---|---|
IfcRelAggregates |
IfcRelDecomposes |
RelatingObject: IfcObjectDefinition (the whole) |
RelatedObjects: SET [1:?] OF IfcObjectDefinition (the parts) |
IfcRelNests |
IfcRelDecomposes |
RelatingObject: IfcObjectDefinition (the whole) |
RelatedObjects: LIST [1:?] OF IfcObjectDefinition (ordered parts) |
IfcRelContainedInSpatialStructure |
IfcRelConnects |
RelatingStructure: IfcSpatialElement |
RelatedElements: SET [1:?] OF IfcProduct |
IfcRelReferencedInSpatialStructure |
IfcRelConnects |
RelatingStructure: IfcSpatialElement |
RelatedElements: SET [1:?] OF IfcSpatialReferenceSelect |
IfcRelDefinesByProperties |
IfcRelDefines |
RelatingPropertyDefinition: IfcPropertySetDefinitionSelect |
RelatedObjects: SET [1:?] OF IfcObjectDefinition |
IfcRelDefinesByType |
IfcRelDefines |
RelatingType: IfcTypeObject |
RelatedObjects: SET [1:?] OF IfcObject |
IfcRelAssociatesMaterial |
IfcRelAssociates |
RelatingMaterial: IfcMaterialSelect |
RelatedObjects: SET [1:?] OF IfcDefinitionSelect |
IfcRelAssociatesClassification |
IfcRelAssociates |
RelatingClassification: IfcClassificationSelect |
RelatedObjects: SET [1:?] OF IfcDefinitionSelect |
IfcRelConnectsElements |
IfcRelConnects |
RelatingElement: IfcElement |
RelatedElement: IfcElement |
IfcRelConnectsPathElements |
IfcRelConnectsElements |
inherits RelatingElement |
inherits RelatedElement |
IfcRelVoidsElement |
IfcRelDecomposes |
RelatingBuildingElement: IfcElement |
RelatedOpeningElement: IfcFeatureElementSubtraction |
IfcRelFillsElement |
IfcRelConnects |
RelatingOpeningElement: IfcOpeningElement |
RelatedBuildingElement: IfcElement |
IfcRelSpaceBoundary |
IfcRelConnects |
RelatingSpace: IfcSpaceBoundarySelect |
RelatedBuildingElement: IfcElement |
Note the reversed anchor between IfcRelVoidsElement and
IfcRelFillsElement: see the door-in-wall pattern below.
Decision Trees
Which relationship do I use?
What am I trying to express?
|
+- A whole made of parts, order does NOT matter
| -> IfcRelAggregates (spatial tree, element assemblies)
|
+- A whole made of parts, order DOES matter
| -> IfcRelNests (ordered ports, ordered cost items, ordered tasks)
|
+- Place a physical element into a spatial level (storey, space)
| -> IfcRelContainedInSpatialStructure
|
+- Reference an element from a second spatial structure
| -> IfcRelReferencedInSpatialStructure
|
+- Attach a property set or quantity set to objects
| -> IfcRelDefinesByProperties
|
+- Link occurrences to their shared type object
| -> IfcRelDefinesByType
|
+- Assign a material to elements or element types
| -> IfcRelAssociatesMaterial
|
+- Assign a classification reference (Uniclass, OmniClass)
| -> IfcRelAssociatesClassification
|
+- Connect two elements physically or logically
| -> IfcRelConnectsElements (or IfcRelConnectsPathElements for wall joins)
|
+- Cut an opening into an element
| -> IfcRelVoidsElement
|
+- Fill an opening with a door or window
| -> IfcRelFillsElement
|
+- Define the surfaces that bound a space
| -> IfcRelSpaceBoundary (or its 1stLevel / 2ndLevel subtypes)
|
+- Group objects across domains (a system, a zone, a schedule)
-> IfcRelAssignsToGroup
Aggregate or nest?
Does the order of the parts carry meaning?
|
+- No -> IfcRelAggregates : RelatedObjects is a SET, order is irrelevant.
| The spatial tree (Project, Site, Building, Storey) ALWAYS uses
| IfcRelAggregates.
|
+- Yes -> IfcRelNests : RelatedObjects is a LIST, position is meaningful.
Use for ordered distribution ports, ordered cost items, ordered
subtasks.
NEVER use IfcRelNests for the spatial tree. NEVER use IfcRelAggregates
when the consumer depends on part order.
Containment or aggregation for the spatial tree?
What are the two objects?
|
+- Both are spatial elements (Site inside Project, Storey inside Building)
| -> IfcRelAggregates : spatial element decomposes spatial element.
|
+- A physical element placed into a spatial element (a wall in a storey)
| -> IfcRelContainedInSpatialStructure : NEVER IfcRelAggregates.
|
+- A physical element that also belongs to a second structure
-> add IfcRelReferencedInSpatialStructure for the secondary link.
The single primary containment stays IfcRelContainedInSpatialStructure.
A physical element ALWAYS sits in exactly ONE
IfcRelContainedInSpatialStructure (the WR31 rule on that entity enforces
at-most-once). Extra spatial links ALWAYS go through
IfcRelReferencedInSpatialStructure. See ifc-core-spatial-structure.
Patterns
Every snippet uses STEP physical file syntax. $ marks an unset optional
attribute. Attribute order is the EXPRESS declared order. Full verified
signatures are in references/methods.md; runnable instances are in
references/examples.md.
Pattern: aggregate parts into a whole
IfcRelAggregates has 6 positional attributes: the 4 from IfcRoot, then
RelatingObject (the whole), then RelatedObjects (the SET of parts).
#30=IFCRELAGGREGATES(
'1Hkj5pQ9X8x9bq0d6FZ7yA', /* GlobalId */
#5, /* OwnerHistory */
$, /* Name */
$, /* Description */
#10, /* RelatingObject : IfcBuilding (the whole) */
(#11,#12) /* RelatedObjects : the IfcBuildingStorey parts */
);
ALWAYS put the whole on RelatingObject and the parts on RelatedObjects.
A reversed instance describes a storey aggregating a building.
Pattern: contain elements in a spatial structure
IfcRelContainedInSpatialStructure places physical elements into one
spatial level. RelatedElements comes BEFORE RelatingStructure in the
declared order.
#40=IFCRELCONTAINEDINSPATIALSTRUCTURE(
'2k7sB$Qe9X8x9bq0d6FZ7y', /* GlobalId */
#5, /* OwnerHistory */
'Storey contents', /* Name */
$, /* Description */
(#21,#22), /* RelatedElements : the IfcWall occurrences */
#11 /* RelatingStructure : the IfcBuildingStorey */
);
Each physical element appears in RelatedElements of exactly one such
relationship. NEVER list the same element in two
IfcRelContainedInSpatialStructure instances.
Pattern: attach a property set
IfcRelDefinesByProperties links an IfcPropertySet or IfcElementQuantity
to objects. RelatedObjects precedes RelatingPropertyDefinition.
#50=IFCRELDEFINESBYPROPERTIES(
'3mNp7rTf0Y9y0cr1e7GA8z', /* GlobalId */
#5, /* OwnerHistory */
$, /* Name */
$, /* Description */
(#21,#22), /* RelatedObjects : the elements */
#48 /* RelatingPropertyDefinition : the IfcPropertySet */
);
One relationship can serve many objects (N-to-N). See
ifc-syntax-property-sets for building the IfcPropertySet itself.
Pattern: link occurrences to a type
IfcRelDefinesByType is 1-to-N: one type, many occurrences.
#52=IFCRELDEFINESBYTYPE(
'4pQr9sUg1Z0z1ds2f8HB9$', /* GlobalId */
#5, /* OwnerHistory */
$, $, /* Name, Description */
(#21,#22), /* RelatedObjects : IfcWall occurrences */
#20 /* RelatingType : the IfcWallType */
);
NEVER place a type object in RelatedObjects: that slot accepts IfcObject
occurrences only. See ifc-core-entity-hierarchy for the type model.
Pattern: associate a material
IfcRelAssociatesMaterial inherits RelatedObjects from IfcRelAssociates
and adds RelatingMaterial as the last attribute.
#54=IFCRELASSOCIATESMATERIAL(
'5qRs0tVh2$1$2et3g9IC0_', /* GlobalId */
#5, /* OwnerHistory */
$, $, /* Name, Description */
(#21,#22), /* RelatedObjects : the elements */
#53 /* RelatingMaterial : IfcMaterial or IfcMaterialLayerSet... */
);
RelatingMaterial accepts the IfcMaterialSelect choices: IfcMaterial,
IfcMaterialLayerSet, IfcMaterialLayerSetUsage, IfcMaterialProfileSet,
IfcMaterialProfileSetUsage, IfcMaterialConstituentSet, IfcMaterialList.
See ifc-syntax-materials.
Pattern: the door-in-wall void then fill
The canonical opening pattern uses two relationships, in this order:
IfcRelVoidsElementsubtracts anIfcOpeningElementfrom the wall.IfcRelFillsElementplaces theIfcDoorinto that opening.
/* step 1 : the wall voids the opening */
#60=IFCRELVOIDSELEMENT(
'6rSt1uWi3_2_3fu4h0JD1A', /* GlobalId */
#5, $, $, /* OwnerHistory, Name, Description */
#21, /* RelatingBuildingElement : the IfcWall */
#58 /* RelatedOpeningElement : the IfcOpeningElement */
);
/* step 2 : the opening is filled by the door */
#62=IFCRELFILLSELEMENT(
'7sTu2vXj4A3A4gv5i1KE2B', /* GlobalId */
#5, $, $, /* OwnerHistory, Name, Description */
#58, /* RelatingOpeningElement : the IfcOpeningElement */
#59 /* RelatedBuildingElement : the IfcDoor */
);
The anchor reverses between the two relationships. The wall is the
Relating side of IfcRelVoidsElement; the SAME opening (#58) is the
Relating side of IfcRelFillsElement. ALWAYS create the void first, then
the fill. NEVER point IfcRelFillsElement straight from wall to door:
the door fills the opening, not the wall.
Version note: IfcRelVoidsElement is a subtype of IfcRelDecomposes in
IFC4 and IFC4.3. In IFC2x3 it sat under the connectivity branch. The
attribute names and order are stable across all three versions.
Pattern: traverse through INVERSE attributes
Objects do not store relationships as forward attributes. They expose INVERSE attributes that the parser populates by scanning relationship instances. To find what defines an object, follow its inverses:
| From object | INVERSE attribute | Reaches |
|---|---|---|
IfcObject |
IsDefinedBy |
IfcRelDefinesByProperties, IfcRelDefinesByType |
IfcObjectDefinition |
IsDecomposedBy |
IfcRelAggregates where this is the whole |
IfcObjectDefinition |
Decomposes |
IfcRelAggregates where this is a part |
IfcObjectDefinition |
HasAssociations |
IfcRelAssociatesMaterial, IfcRelAssociatesClassification |
IfcElement |
ContainedInStructure |
IfcRelContainedInSpatialStructure |
IfcElement |
HasOpenings |
IfcRelVoidsElement |
IfcOpeningElement |
HasFillings |
IfcRelFillsElement |
To read a wall's property sets: take wall.IsDefinedBy, keep the
IfcRelDefinesByProperties instances, then read each
RelatingPropertyDefinition. NEVER look for a direct PropertySets
attribute on the wall: it does not exist.
Anti-Patterns
Full detail with the failure mechanism is in references/anti-patterns.md.
The five that matter most:
- Reversing
RelatingandRelated. The model parses but states the wrong fact (a storey aggregating a building, a part owning the whole). - Using
IfcRelAggregatesto place a physical element into a storey. Containment of physical elements ALWAYS usesIfcRelContainedInSpatialStructure. - Listing one element in two
IfcRelContainedInSpatialStructureinstances. Violates WR31; the element belongs to the spatial tree once only. - Pointing
IfcRelFillsElementfrom the wall to the door directly, skipping theIfcOpeningElement. The door has nothing to fill. - Treating a relationship as a pointer and editing the participants to
"connect" them. Connections ALWAYS exist only as
IfcRel*instances.
Reference Links
This skill
references/methods.md: full positional attribute signatures for everyIfcRel*entity in this skill, with supertypes and version notes.references/examples.md: verified STEP physical file instances.references/anti-patterns.md: failure modes and their root causes.
Related skills
ifc-core-entity-hierarchy:IfcRootand the object inheritance tree that relationships connect.ifc-core-spatial-structure:IfcProject, the spatial tree, the containment versus reference rule.ifc-syntax-property-sets: building theIfcPropertySetattached viaIfcRelDefinesByProperties.ifc-syntax-building-elements: the concrete elements that participate asRelatingandRelatedobjects.
Official sources
- IfcRelationship: https://ifc43-docs.standards.buildingsmart.org/IFC/RELEASE/IFC4x3/HTML/lexical/IfcRelationship.htm
- IfcRelAggregates: https://ifc43-docs.standards.buildingsmart.org/IFC/RELEASE/IFC4x3/HTML/lexical/IfcRelAggregates.htm
- IfcRelContainedInSpatialStructure: https://ifc43-docs.standards.buildingsmart.org/IFC/RELEASE/IFC4x3/HTML/lexical/IfcRelContainedInSpatialStructure.htm
- IfcRelDefinesByProperties: https://ifc43-docs.standards.buildingsmart.org/IFC/RELEASE/IFC4x3/HTML/lexical/IfcRelDefinesByProperties.htm
- IfcRelVoidsElement: https://ifc43-docs.standards.buildingsmart.org/IFC/RELEASE/IFC4x3/HTML/lexical/IfcRelVoidsElement.htm
- IfcRelFillsElement: https://ifc43-docs.standards.buildingsmart.org/IFC/RELEASE/IFC4x3/HTML/lexical/IfcRelFillsElement.htm