Extracting Geometry from an IFC File
An IFC element keeps its shape and its position apart. The geometry
items sit in a LOCAL coordinate system; the element's place in the world
is carried separately by ObjectPlacement. Extracting usable geometry
means doing two things ALWAYS together: decoding the shape items, and
resolving the placement chain to a world transformation matrix.
Verified against the buildingSMART IFC4.3 specification, with IFC4 ADD2
TC1 and IFC2x3 TC1 deltas noted. See references/methods.md for full
entity signatures, references/examples.md for worked STEP snippets and
matrix computation, and references/anti-patterns.md for the extraction
mistakes that produce wrong or empty geometry.
Quick Reference
The resolution path
IfcProduct.Representation
-> IfcProductDefinitionShape.Representations (a list)
-> IfcShapeRepresentation (pick by RepresentationIdentifier)
-> Items (the geometry primitives)
-> IfcExtrudedAreaSolid / IfcFacetedBrep / IfcTriangulatedFaceSet / ...
In parallel, ALWAYS resolve placement:
IfcProduct.ObjectPlacement
-> IfcLocalPlacement.PlacementRelTo (walk up to the root)
-> compose each RelativePlacement into one world matrix
World geometry = world matrix applied to the local geometry items. NEVER render or measure the raw items without applying the placement.
RepresentationIdentifier: which representation kind
| Identifier | Holds | Use for |
|---|---|---|
Body |
3D solid / surface geometry | rendering, meshing, volume |
Axis |
2D/3D axis line | wall/beam centreline analysis |
FootPrint |
2D ground projection | plan drawings, site layout |
Box |
bounding box solid | fast culling, spatial queries |
Profile |
3D profile outline | section display |
Surface |
analytical surface | structural analysis |
Reference |
non-Body reference geometry | opening reference shapes |
CoG |
centre-of-gravity point | mass properties |
ALWAYS read the Body representation for solid rendering or quantity
work. NEVER take whichever representation appears first: a product can
carry Box, Axis, and Body at once.
RepresentationType: which geometry encoding
| Type | Decode by | Versions |
|---|---|---|
SweptSolid |
sweep a profile (IfcExtrudedAreaSolid, IfcRevolvedAreaSolid) |
all |
Clipping |
Boolean DIFFERENCE (IfcBooleanClippingResult) |
all |
CSG |
Boolean tree (IfcBooleanResult) |
all |
Brep |
read explicit faces/shells (IfcFacetedBrep) |
all |
AdvancedBrep |
B-spline faces (IfcAdvancedBrep) |
IFC4+ |
AdvancedSweptSolid |
sweep along directrix, swept-disk | IFC4+ |
Tessellation |
indexed face set (IfcTriangulatedFaceSet) |
IFC4+ |
MappedRepresentation |
resolve IfcMappedItem + transform |
all |
SurfaceModel |
face/shell surface set | all |
BoundingBox |
simple box | all |
Tessellation, AdvancedBrep, and AdvancedSweptSolid do NOT exist in
IFC2x3. An IFC2x3 file delivers solid shape as SweptSolid, Clipping,
Brep, CSG, or SurfaceModel.
IFC indices are 1-based
Every index list in IFC (CoordIndex, PnIndex, IfcIndexedPolygonalFace)
is 1-based. The first coordinate is index 1, not 0. ALWAYS subtract 1
before indexing a zero-based array.
Decision Trees
Which representation to extract
What is the geometry needed for?
├── Rendering / display
│ Is a Tessellation Body representation present?
│ ├── YES -> use it directly; it is render-ready triangles.
│ └── NO -> decode the Body SweptSolid / Brep / Clipping items.
├── Exact quantity (volume, area, exact dimensions)
│ NEVER use Tessellation: it is a faceted approximation.
│ Use the Body parametric solid (SweptSolid / Brep / CSG).
│ If Body is only Tessellation, report the result as approximate.
├── 2D plan output
│ Use the FootPrint representation; fall back to Body projected.
└── Fast spatial query / culling
Use the Box representation if present; else the Body bounding box.
How to decode one IfcShapeRepresentation
Read RepresentationType of the IfcShapeRepresentation.
├── SweptSolid / AdvancedSweptSolid
│ For each item: sweep SweptArea profile along the swept geometry,
│ then apply the item Position.
├── Clipping / CSG
│ Item is an IfcBooleanResult tree. Recurse into FirstOperand and
│ SecondOperand; apply Operator (DIFFERENCE for Clipping).
│ A geometry kernel is required to evaluate the Boolean.
├── Brep / AdvancedBrep / SurfaceModel
│ Geometry is already explicit: read shells -> faces -> loops ->
│ IfcCartesianPoint. No sweeping needed.
├── Tessellation
│ Read Coordinates pool and CoordIndex; build triangles directly.
└── MappedRepresentation
Each item is an IfcMappedItem. Resolve MappingSource
(IfcRepresentationMap.MappedRepresentation) and recurse, then apply
MappingTarget (an IfcCartesianTransformationOperator).
Patterns
Pattern 1: resolve a product to its Body items
shape = product.Representation # IfcProductDefinitionShape
reps = shape.Representations # list of IfcShapeRepresentation
body = first rep where rep.RepresentationIdentifier == 'Body'
items = body.Items # geometry primitives
If product.Representation is $ the product has no geometry (common
for spatial elements such as IfcBuildingStorey). ALWAYS handle that.
Pattern 2: the placement chain to a world matrix
Each IfcAxis2Placement3D yields a 4x4 matrix: Location is the
translation, Axis is the local Z, RefDirection is the approximate
local X. The Y axis is Z cross X; RefDirection is re-orthogonalised
against Axis.
M = identity
p = product.ObjectPlacement # IfcLocalPlacement
chain = []
while p is not null:
chain.prepend( matrix_of(p.RelativePlacement) )
p = p.PlacementRelTo
for m in chain: # root first, element last
M = M * m
world_point = M * local_point
NEVER skip the chain and NEVER reverse the multiplication order: both put
elements in the wrong place. See references/examples.md for the full
matrix formula.
Pattern 3: SweptSolid
item = IfcExtrudedAreaSolid
profile = item.SweptArea # e.g. IfcRectangleProfileDef
solid = extrude(profile, item.ExtrudedDirection, item.Depth)
solid = apply(item.Position, solid) # item-local placement
IfcRevolvedAreaSolid revolves SweptArea around Axis by Angle
instead of extruding.
Pattern 4: Tessellation
coords = item.Coordinates.CoordList # IfcCartesianPointList3D
for tri in item.CoordIndex: # each row has 3 indices
a = coords[ tri[0] - 1 ] # 1-based -> 0-based
b = coords[ tri[1] - 1 ]
c = coords[ tri[2] - 1 ]
If item.PnIndex is present, a CoordIndex value i resolves as
coords[ PnIndex[i-1] - 1 ]. IfcPolygonalFaceSet is the same idea with
variable-length faces in Faces (IfcIndexedPolygonalFace).
Pattern 5: Brep
brep = IfcFacetedBrep
shell = brep.Outer # IfcClosedShell
for face in shell.CfsFaces: # IfcFace
for bound in face.Bounds: # IfcFaceOuterBound / IfcFaceBound
loop = bound.Bound # IfcPolyLoop
polygon = loop.Polygon # list of IfcCartesianPoint
Brep geometry is already explicit: read it, do not sweep. ALWAYS respect
IfcFaceOuterBound versus IfcFaceBound so holes are not filled in.
Pattern 6: MappedRepresentation
mapped = IfcMappedItem
source = mapped.MappingSource # IfcRepresentationMap
geom = decode( source.MappedRepresentation ) # recurse
geom = apply( source.MappingOrigin, geom )
geom = apply( mapped.MappingTarget, geom ) # per-instance transform
Typed families (doors, furniture) carry geometry once on the type and
reuse it through IfcMappedItem. NEVER skip the resolve step: the
element appears empty otherwise.
Reference Links
references/methods.md: full attribute signatures for the representation, placement, solid, Brep, tessellation, and mapping entities, per version.references/examples.md: worked STEP snippets per RepresentationType and the complete placement-to-matrix formula.references/anti-patterns.md: the extraction mistakes that produce elements at the origin, blocky models, scrambled meshes, or empty geometry.
Related skills
ifc-syntax-geometry-representations: the representation framework syntax,IfcShapeRepresentation, and the identifier/type catalogue.ifc-syntax-geometry-placement: the placement tree syntax and the right-handed axis derivation.ifc-impl-reading-parsing: the two-pass parse and#idreference resolution that geometry extraction depends on.
Official sources
- IFC4.3 specification: https://ifc43-docs.standards.buildingsmart.org/
- IFC4 ADD2 TC1: https://standards.buildingsmart.org/IFC/RELEASE/IFC4/ADD2_TC1/HTML/
- IFC2x3 TC1: https://standards.buildingsmart.org/IFC/RELEASE/IFC2x3/TC1/HTML/