2026-03-19 16:58:08 +01:00
2026-03-13 21:42:44 +01:00
2026-03-19 16:58:08 +01:00
2026-03-13 21:42:44 +01:00
2026-03-19 16:58:08 +01:00
2026-03-19 16:58:08 +01:00
2026-03-13 21:42:44 +01:00
2026-03-13 21:42:44 +01:00
2026-03-13 21:42:44 +01:00
2026-03-13 21:42:44 +01:00
2026-03-19 16:58:08 +01:00
2026-03-13 21:42:44 +01:00
2026-03-19 16:58:08 +01:00
2026-03-19 16:58:08 +01:00

Speckle-Grasshopper to IFC 4.3 Exporter

A Speckle Automate function that converts Speckle models into IFC 4.3 files using ifcopenshell. Built for Grasshopper + Rhino workflows, but compatible with any application that produces Speckle objects matching the expected property structure.

What It Does

The exporter receives a Speckle model version, walks its nested collection tree, and produces a standards-compliant IFC 4.3 file. Each Speckle object becomes an IFC element with:

  • Correct IFC entity classification read from _properties.Attributes.type
  • Tessellated geometry (IfcPolygonalFaceSet)
  • Material colours from Speckle render materials
  • All property sets cloned from _properties.Property Sets
  • All quantity sets cloned from _properties.Quantities
  • IFC type objects created from _properties.Element Type Attributes
  • Building storeys derived from _properties.Building Storey
  • Spatial structure (IfcProject > IfcSite > IfcBuilding > IfcBuildingStorey)

Object Structure

The exporter expects Speckle objects with the following _properties layout:

_properties
├── Attributes                  → IFC element attributes (type, GlobalId, Name, Tag, etc.)
├── Property Sets               → dict of {pset_name: {prop_name: value}}
├── Quantities                  → dict of {qto_name: {qty_name: {name, units, value}}}
├── Building Storey             → string, used for storey assignment
├── Element Type Attributes     → type class, Name, GlobalId (creates IfcTypeObject)
└── Element Type Property Sets  → property sets written on the IfcTypeObject

The nested collection tree is expected as: Root Collection > Collection > ... > Object

Pipeline Overview

Speckle Model
    │
    ▼
1. Receive version (specklepy)
    │
    ▼
2. Build definition map (for instance geometry reuse)
    │
    ▼
3. Create IFC scaffold (Project → Site → Building)
    │
    ▼
4. Traverse collection tree
    │   For each leaf element:
    │   ├── Classify → IFC entity class (from _properties.Attributes.type)
    │   ├── Convert geometry → IfcPolygonalFaceSet
    │   ├── Create IFC element + placement
    │   ├── Clone all properties & quantities
    │   ├── Assign to Building Storey (from _properties.Building Storey)
    │   └── Assign IFC type object (from Element Type Attributes)
    │
    ▼
5. Flush spatial containment & type relationships
    │
    ▼
6. Write .ifc file

Module Structure

File Purpose
main.py Entry point, orchestrates the full pipeline
utils/traversal.py Walks the Speckle collection tree (Root > Collection* > Object)
utils/mapper.py Reads IFC entity class from _properties.Attributes.type
utils/geometry.py Converts Speckle meshes to IfcPolygonalFaceSet geometry
utils/instances.py Handles InstanceProxy objects with shared geometry (IfcMappedItem)
utils/properties.py Clones all properties, quantities, and attributes into IFC entities
utils/type_manager.py Creates and caches IfcTypeObjects from Element Type Attributes
utils/materials.py Maps Speckle render materials to IfcSurfaceStyle colours
utils/writer.py Creates the IFC file scaffold and manages storey creation
utils/receiver.py Standalone Speckle model receiver utility

Classification

IFC entity classification is read directly from _properties.Attributes.type on each object. For example, an object with Attributes.type = "IfcWall" becomes an IfcWall element. If the field is missing, the object falls back to IfcBuildingElementProxy.

For instance proxy objects without their own type, the exporter looks up the definition object's Attributes.type.

Property Handling

All properties are cloned generically — no source-application-specific logic:

Source IFC Target
_properties.Attributes Element attributes: GlobalId, Name, Tag, ObjectType, Description, PredefinedType
_properties.Property Sets.* IfcPropertySet per sub-dict (e.g. Pset_WallCommon → IfcPropertySet with IfcPropertySingleValue entries)
_properties.Quantities.* IfcElementQuantity per sub-dict, with automatic unit detection (mm → IfcQuantityLength, m² → IfcQuantityArea, m³ → IfcQuantityVolume)
_properties.Element Type Attributes Shared IfcTypeObject (e.g. IfcWallType), cached by GlobalId
_properties.Element Type Property Sets Property sets on the IfcTypeObject

Property values are auto-typed: bool → IfcBoolean, int → IfcInteger, float → IfcReal, str → IfcLabel, list → comma-joined IfcLabel.

Geometry Handling

Direct Meshes (Path B1)

Objects with displayValue containing Mesh objects are converted directly:

  1. Extract vertices and faces from each mesh in displayValue
  2. Scale vertices to millimetres based on the mesh's unit declaration
  3. Deduplicate vertices via snap grid (0.01mm tolerance) to avoid IFC GEM111 errors
  4. Build IfcPolygonalFaceSet with IfcCartesianPointList3D + IfcIndexedPolygonalFace
  5. Compute bounding box origin for IfcLocalPlacement, offset vertices relative to it

Instance Objects (Path A / B2)

Speckle InstanceProxy objects reference shared definition geometry via definitionId. Geometry is built once as an IfcRepresentationMap, then each instance references it via IfcMappedItem + IfcCartesianTransformationOperator3DnonUniform. This avoids duplicating vertex data across hundreds of identical elements.

Function Inputs

Input Description
file_name Output IFC filename (timestamp is appended automatically)
IFC_PROJECT_NAME Name for the IfcProject entity
IFC_SITE_NAME Name for the IfcSite entity
IFC_BUILDING_NAME Name for the IfcBuilding entity

Resources

S
Description
No description provided
Readme 130 KiB
Languages
Python 99.4%
Dockerfile 0.6%