# Ifc Impl Spatial Decomposition

> Use when authoring an IFC file and you must build the spatial breakdown tree and place every physical element into it, or when a wall, slab, or door does not show up in a viewer because it has no storey. Prevents orphan elements, double containment, placing elements with IfcRelAggregates instead of IfcRelContainedInSpatialStructure, and reversing the Relating and Related roles. Covers the top-down build order, IfcRelAggregates wiring, single-container placement, IfcRelReferencedInSpatialStructure for multi-storey elements, the IFC4.3 IfcFacility and IfcFacilityPart tree, and the orphan-check verification step. Keywords: IfcRelAggregates, IfcRelContainedInSpatialStructure, IfcRelReferencedInSpatialStructure, IfcProject, IfcSite, IfcBuilding, IfcBuildingStorey, IfcSpace, IfcFacility, IfcFacilityPart, spatial decomposition, spatial breakdown, build the spatial tree, place element in storey, orphan element, element not in viewer, wall has no storey, element missing from model, how do I add a wall to a storey, mul

- Skill: `impertio-studio/ifc-impl-spatial-decomposition` (Agent Skill, multi-file: 4 files)
- Install (CLI): `npx skillmds@latest add impertio-studio/ifc-impl-spatial-decomposition`
- Raw SKILL.md: https://api.skillmd.com/api/skills/impertio-studio/ifc-impl-spatial-decomposition/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: AI & ML
- License: MIT
- Author: Impertio-Studio (https://skillmd.com/u/impertio-studio)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/impertio-studio/ifc-impl-spatial-decomposition

---


# ifc-impl-spatial-decomposition

This skill is the write-side workflow for the IFC spatial structure. It teaches
the exact order of operations to build the spatial breakdown tree, place every
physical element into it, and verify that no element is left orphaned.

For the structure itself (what the tree is, the entity hierarchy, WHERE rules)
see `ifc-core-spatial-structure`. For failure recovery see
`ifc-errors-spatial-structure`. For the overall file-authoring sequence see
`ifc-impl-authoring-file`.

ALWAYS build the spatial tree before placing any element. An element placed
into a node that does not yet exist cannot be wired, and an element with no
container is an orphan that the buildingSMART validation service and most
viewers reject.

## Quick Reference

### The decomposition workflow (7 steps, in order)

```
1. Create IfcProject                  the context root, NOT a spatial node
2. Create the spatial nodes top-down  Site, Building/Facility, Storey, Space
3. Wire the tree with IfcRelAggregates one relationship per parent node
4. Create the physical elements        IfcWall, IfcSlab, IfcDoor, ...
5. Place each element                  IfcRelContainedInSpatialStructure,
                                        exactly one container per element
6. Reference spanning elements          IfcRelReferencedInSpatialStructure,
                                        for elements reaching extra nodes
7. Verify                               every element has exactly one
                                        container; every node reaches the
                                        project; no orphans
```

### The two wiring relationships : NEVER confuse them

| Relationship | Wires | Relating role | Related role |
|--------------|-------|---------------|--------------|
| `IfcRelAggregates` | spatial node to spatial node (the tree) | `RelatingObject` : the parent node (1) | `RelatedObjects` : `SET [1:?]` of child nodes |
| `IfcRelContainedInSpatialStructure` | physical element into one spatial node | `RelatingStructure` : the containing node | `RelatedElements` : `SET [1:?]` of `IfcProduct` |
| `IfcRelReferencedInSpatialStructure` | physical element to extra nodes (non-tree) | `RelatingStructure` : the referencing node | `RelatedElements` : `SET [1:?]` of `IfcSpatialReferenceSelect` |

### Hard rules

- ALWAYS create a node before any relationship that points at it. STEP entity
  order in the file does not matter, but the node instance must exist.
- ALWAYS wire each spatial node to its parent with `IfcRelAggregates`. This is
  rule WR41 on `IfcSpatialStructureElement`, verbatim : "All spatial structure
  elements shall be associated (using the IfcRelAggregates relationship) with
  another spatial structure element, or with IfcProject."
- ALWAYS place each physical element into exactly one node with
  `IfcRelContainedInSpatialStructure`. `IfcElement.ContainedInStructure` is
  `SET [0:1]` : the schema permits zero or one container, never two.
- NEVER use `IfcRelAggregates` to place a physical element into a storey. It
  builds the tree of spatial nodes only. Placing a wall this way makes the
  wall a child node of the tree, not contained content.
- NEVER use `IfcRelContainedInSpatialStructure` to nest a spatial node inside
  another. Rule WR31 forbids it, verbatim : "The relationship object shall not
  be used to include other spatial structure elements into a spatial structure
  element. The hierarchy of the spatial structure is defined using
  IfcRelAggregates."
- NEVER reverse `Relating` and `Related`. Putting the storey in
  `RelatedElements` and the wall in `RelatingStructure` produces a
  schema-valid but meaningless model.
- NEVER aggregate anything above `IfcProject`. `IfcProject.NoDecomposition`
  requires `IfcProject.Decomposes` to be empty : the project is the apex.

## Decision Trees

### Which spatial node contains this element?

```
What kind of physical element?
|
+-- Terrain, landscaping, fencing, site utility   --> contain in IfcSite
+-- Element belonging to the whole building       --> contain in IfcBuilding
|   (foundation slab spanning the footprint,
|    a site-wide vertical shaft)
+-- Normal wall, slab, beam, column, door, window --> contain in IfcBuildingStorey
+-- Furniture, equipment, sanitary item in a room --> contain in IfcSpace
|
+-- Element spans several storeys (tall column,
    multi-storey curtain wall, a stair)
    --> contain in ONE storey, reference the rest
        with IfcRelReferencedInSpatialStructure
```

Default rule : when in doubt, contain a physical element in the
`IfcBuildingStorey`. Storey-level containment is what viewers, schedules, and
quantity take-off tools expect.

### Contain or reference?

```
Does the element belong to exactly one spatial node?
|
+-- Yes  --> one IfcRelContainedInSpatialStructure. Done.
|
+-- No, it physically reaches several nodes
    --> pick the PRIMARY node (where the element starts, or its base level)
        1. one IfcRelContainedInSpatialStructure into the primary node
        2. one IfcRelReferencedInSpatialStructure per additional node
    NEVER add a second IfcRelContainedInSpatialStructure : containment is
    single by schema (SET [0:1]).
```

### Which version's tree am I building?

```
Target IFC version?
|
+-- IFC2x3  --> IfcProject > IfcSite > IfcBuilding > IfcBuildingStorey > IfcSpace
|              CompositionType is MANDATORY on every node.
|              OwnerHistory is MANDATORY on every rooted instance.
|
+-- IFC4    --> same five-level tree as IFC2x3.
|              CompositionType and OwnerHistory became OPTIONAL.
|
+-- IFC4.3  --> IfcProject > IfcSite > IfcFacility-subtype
               > storey-slot > IfcSpace.
               For buildings : IfcBuilding (a subtype of IfcFacility) and
               IfcBuildingStorey (still a direct subtype of
               IfcSpatialStructureElement).
               For infrastructure : IfcBridge / IfcRoad / IfcRailway /
               IfcMarineFacility and an IfcFacilityPart subtype
               (IfcBridgePart / IfcRoadPart / IfcRailwayPart /
               IfcMarinePart / IfcFacilityPartCommon).
```

## Patterns

### Pattern : build the tree top-down

ALWAYS create the tree in this order so every relationship target exists:

1. Create `IfcProject`. Give it `Name`, `UnitsInContext`, and
   `RepresentationContexts`. It is the context root, not a spatial node.
2. Create `IfcSite`, then `IfcBuilding`, then each `IfcBuildingStorey`, then
   each `IfcSpace`. Set `CompositionType` to `.ELEMENT.` on each ordinary node.
3. Wire the levels with one `IfcRelAggregates` per parent :
   - `IfcProject` --aggregates--> `IfcSite`
   - `IfcSite` --aggregates--> `IfcBuilding`
   - `IfcBuilding` --aggregates--> all its `IfcBuildingStorey` nodes
   - each `IfcBuildingStorey` --aggregates--> its `IfcSpace` nodes (if any)
4. In each `IfcRelAggregates`, the parent is the single `RelatingObject` and
   the children fill the `RelatedObjects` set. One relationship instance can
   carry many children, so all storeys of one building share one
   `IfcRelAggregates`.

See `references/examples.md` for a complete verified STEP fragment.

### Pattern : place a physical element

After the tree exists, place each physical element with one
`IfcRelContainedInSpatialStructure` :

- `RelatingStructure` = the chosen spatial node (usually the storey).
- `RelatedElements` = the set of products to place there.

One relationship instance can place many elements at once, so all walls of one
storey share a single `IfcRelContainedInSpatialStructure`. Prefer one
containment relationship per spatial node, not one per element : it is fewer
instances and the same semantics.

### Pattern : multi-storey element

A stair, a tall column, or a multi-storey curtain wall physically belongs to
more than one storey. Model it once, reference it elsewhere:

1. Choose the PRIMARY storey (the base level the element starts on).
2. One `IfcRelContainedInSpatialStructure` puts the element in that storey.
3. One `IfcRelReferencedInSpatialStructure` per additional storey the element
   reaches. Its `RelatingStructure` is the extra storey, its `RelatedElements`
   set holds the element.

`IfcRelReferencedInSpatialStructure` is non-hierarchical : an element may be
referenced by several nodes while it is contained by exactly one. NEVER model
the spanning element with two containments.

### Pattern : IFC4.3 facility tree

In IFC4.3 the building-only chain generalises to facilities. `IfcBuilding` is a
subtype of the abstract `IfcFacility`. An infrastructure project uses
`IfcBridge`, `IfcRoad`, `IfcRailway`, or `IfcMarineFacility` in the same tree
slot as `IfcBuilding`. The storey slot is filled by `IfcBuildingStorey` for
buildings, or by an `IfcFacilityPart` subtype for infrastructure
(`IfcBridgePart`, `IfcRoadPart`, `IfcRailwayPart`, `IfcMarinePart`,
`IfcFacilityPartCommon`). `IfcFacilityPart` carries `UsageType`
(`IfcFacilityUsageEnum`) to declare how the facility is subdivided.

The wiring is unchanged : every node still attaches to its parent with
`IfcRelAggregates` and obeys WR41, and physical elements are still placed with
`IfcRelContainedInSpatialStructure`.

### Pattern : verify no orphan elements

Run this check after step 5 of the workflow, before writing the file out:

```
For every IfcElement occurrence in the model:
    count its IfcRelContainedInSpatialStructure links
    (the inverse attribute IfcElement.ContainedInStructure)
    |
    +-- count == 1  --> OK
    +-- count == 0  --> ORPHAN. Add an IfcRelContainedInSpatialStructure.
    +-- count >  1  --> schema-invalid (ContainedInStructure is SET [0:1]).
                        Remove the extra containment relationships.

For every spatial node:
    walk Decomposes upward via IfcRelAggregates
    |
    +-- reaches IfcProject  --> OK
    +-- does not reach it   --> DETACHED node. Add the missing
                                IfcRelAggregates to its parent.
```

A node detached from the project and an element with no container are the two
failures the buildingSMART validation service reports most for this area. See
`ifc-errors-spatial-structure` for the full error catalogue.

## Version Matrix

| Aspect | IFC2x3 | IFC4 | IFC4.3 |
|--------|--------|------|--------|
| Tree levels | Project, Site, Building, Storey, Space | same | Project, Site, Facility-subtype, storey-slot, Space |
| `CompositionType` | mandatory on every node | optional | optional |
| `IfcRoot.OwnerHistory` | mandatory | optional | optional |
| Building entity | `IfcBuilding` under `IfcSpatialStructureElement` | same | `IfcBuilding` is a subtype of `IfcFacility` |
| Infrastructure facilities | not available | not available | `IfcBridge`, `IfcRoad`, `IfcRailway`, `IfcMarineFacility` |
| `IfcRelReferencedInSpatialStructure` `RelatedElements` type | `SET OF IfcProduct` | `SET OF IfcProduct` | `SET OF IfcSpatialReferenceSelect` |
| Tree wiring relationship | `IfcRelAggregates` | `IfcRelAggregates` | `IfcRelAggregates` |
| Element placement relationship | `IfcRelContainedInSpatialStructure` | same | same |

## Reference Links

- `references/methods.md` : entity and attribute signatures for the three
  decomposition relationships and the spatial nodes, WHERE rules WR31 / WR41 /
  NoSelfReference, per-version notes, source URLs.
- `references/examples.md` : verified STEP fragments for the full tree, element
  placement, multi-storey reference, the IFC4.3 facility tree, and the
  orphan-check procedure.
- `references/anti-patterns.md` : the spatial-decomposition mistakes that break
  files, and why each one fails.

Related skills : `ifc-core-spatial-structure`, `ifc-core-relationships`,
`ifc-errors-spatial-structure`, `ifc-impl-authoring-file`,
`ifc-syntax-building-elements`.

Authoritative sources (see `SOURCES.md`) :
- IFC 4.3.2 specification : https://ifc43-docs.standards.buildingsmart.org/
- IFC 4 ADD2 TC1 specification :
  https://standards.buildingsmart.org/IFC/RELEASE/IFC4/ADD2_TC1/HTML/
- IFC 2x3 TC1 specification :
  https://standards.buildingsmart.org/IFC/RELEASE/IFC2x3/TC1/HTML/

