6.1 KiB
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:
- Extract vertices and faces from each mesh in
displayValue - Scale vertices to millimetres based on the mesh's unit declaration
- Deduplicate vertices via snap grid (0.01mm tolerance) to avoid IFC GEM111 errors
- Build
IfcPolygonalFaceSetwithIfcCartesianPointList3D+IfcIndexedPolygonalFace - 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 |