Skip to main content

ifclite-geom

Native ifc-lite geometry tessellation for Python. It turns an IFC file into per-entity triangle meshes with no Node, no WASM, and no subprocess: the Rust geometry kernel runs directly inside the Python process.

Meshes come back welded, IFC Z-up, in absolute world metres, keyed by IFC STEP id (occurrences only). This is the analysis-ready export, distinct from the render-oriented GLB the viewer uses.

Install

pip install ifclite-geom

Prebuilt wheels ship for CPython 3.9+ on Linux (x86_64, aarch64), macOS (Apple silicon and Intel), and Windows (x64). No Rust toolchain needed.

Quick start

The module is ifclite_geom and exposes three functions, all taking the raw IFC file as bytes. geometry_data_buffers and geometry_data_json return the same geometry and differ only in output format; entity_data reads attributes and property sets instead, without tessellating.

import ifclite_geom
import numpy as np

with open("model.ifc", "rb") as f:
    ifc_bytes = f.read()

data = ifclite_geom.geometry_data_buffers(ifc_bytes)

print(data["element_count"], "elements")
print("up axis:", data["up_axis"], "| units:", data["units"])
print("rtc offset:", data["rtc_offset"])

for step_id, el in data["elements"].items():
    verts = np.frombuffer(el["vertices"], dtype=np.float64).reshape(-1, 3)
    faces = np.frombuffer(el["faces"],    dtype=np.uint32 ).reshape(-1, 3)
    print(step_id, el["ifc_type"], el["global_id"], verts.shape, faces.shape)

Prefer no numpy dependency? Use the JSON variant, which returns the same data as arrays of numbers:

import ifclite_geom, json

doc = json.loads(ifclite_geom.geometry_data_json(ifc_bytes))
first = next(iter(doc["elements"].values()))
print(first["ifc_type"], first["vertices"][0])  # [x, y, z] in metres

API

geometry_data_buffers(ifc_bytes: bytes, quality: str | None = None) -> dict

The fast path. Vertices and faces come back as raw little-endian byte buffers so you can hand them straight to numpy.frombuffer with zero parsing.

{
  "up_axis": "Z",            # always Z (IFC native)
  "units": "m",              # always metres
  "rtc_offset": [x, y, z],   # geo-reference offset already folded into vertices
  "element_count": 1234,
  "elements": {
    <step_id:int>: {
      "ifc_type":  "IfcWall",
      "global_id": "3vB2...",   # may be None
      "name":      "Basic Wall:...",  # may be None
      "color":     [r, g, b, a],      # 0..1
      "vertices":  <bytes>,           # f64 little-endian, xyz triplets
      "faces":     <bytes>,           # u32 little-endian, triangle indices
    },
    ...
  }
}

Decode the buffers with:

verts = np.frombuffer(el["vertices"], dtype=np.float64).reshape(-1, 3)  # (V, 3)
faces = np.frombuffer(el["faces"],    dtype=np.uint32 ).reshape(-1, 3)  # (F, 3)

geometry_data_json(ifc_bytes: bytes, quality: str | None = None) -> str

The same geometry as a readable ifc-lite-geometry-data JSON document (a string; call json.loads on it). Vertices are [x, y, z] arrays and faces are [a, b, c] index arrays, so no numpy is required. Each element also carries global_id and name when the source entity has them.

Tessellation quality

Both geometry functions take an optional quality label:

label density
"lowest" quarter
"low" half
"medium" engine default, used when quality is omitted
"high" double
"highest" quadruple

It scales the segment count on every curved primitive: swept-disk tubes, cylinders, revolutions, arcs, circular profiles. On curve-heavy elements the effect is large. A single IfcReinforcingBar authored as an IfcSweptDiskSolid over a composite arc tessellates to 1056 triangles at "medium" and 96 at "lowest".

data = ifclite_geom.geometry_data_buffers(ifc_bytes, "lowest")

An unrecognised label raises ValueError rather than silently falling back, so a typo cannot cost you a 10x triangle budget without saying so. This is the same knob the browser build exposes as setTessellationQuality and the server as ?tessellation_quality=; the level is model-wide, not per IFC type.

entity_data(ifc_bytes: bytes, placements: bool = False) -> dict

Attributes, property sets and quantity sets. No tessellation runs, so this is cheap compared with the geometry functions.

{
  "length_unit_scale": 0.001,      # file length unit -> metres
  "plane_angle_to_radians": 0.0174,
  "project_id": 42,                # may be None
  "entity_count": 1234,
  "entities": {
    <step_id:int>: {
      "ifc_type":      "IfcWall",
      "global_id":     "3vB2...",       # may be None
      "name":          "WALL 1",        # may be None
      "description":   None,
      "object_type":   None,
      "has_geometry":  True,
      "placement":     None,            # see below
      "property_sets": [
        {"name": "Pset_WallCommon",
         "properties": [{"name": "IsExternal", "value": "True",
                         "value_type": "IFCBOOLEAN"}]},
      ],
      "quantity_sets": [
        {"name": "Qto_WallBaseQuantities",
         "quantities": [{"name": "Length", "value": 3000.0, "kind": "Length"}]},
      ],
    },
    ...
  }
}

entities is keyed by IFC STEP id in file order, the same key geometry_data_buffers uses, so the two join directly. The join is one-way total: every meshed element has a row, but not every row has an element, so drive the loop from elements (or use .get()) rather than the other way round. Besides products with no geometry, an orphan IfcTypeProduct carries has_geometry: True and still never appears in elements, because the geometry functions emit occurrences only.

geom = ifclite_geom.geometry_data_buffers(ifc_bytes)
ents = ifclite_geom.entity_data(ifc_bytes)

for step_id, el in geom["elements"].items():
    row = ents["entities"].get(step_id)
    if row:
        print(el["ifc_type"], row["name"], row["property_sets"])

Pass placements=True to also resolve each product's ObjectPlacement into a list of 16 floats: a column-major 4x4, translation in metres at indices 12/13/14. It is off by default because it costs an extra decode per product.

The matrix is in the same absolute IFC world frame as geometry_data_buffers vertices, so the two line up directly. Do not fold rtc_offset into either: the geometry export already adds it back into every vertex, and the placement is never RTC-rebased. On a georeferenced model both are large absolute coordinates, and a product's placement origin lands inside its own mesh bounds.

Units, and two current limits

  • Property and quantity values are in the file's own units, unlike geometry, which is always metres. A millimetre model reports a wall length of 3000. Property values are always strings; quantity values are floats.

    Converting is per dimension, not one blanket factor:

    quantity kind to SI
    Length value * length_unit_scale
    Area value * length_unit_scale ** 2
    Volume value * length_unit_scale ** 3
    Count unchanged (dimensionless)
    angles (properties) value * plane_angle_to_radians

    Only the length and plane-angle scales are resolved, so a model that declares an area or volume unit inconsistent with its length unit cannot be reconciled from what is returned here.

  • Only IfcPropertySingleValue properties are decoded. Enumerated, list, bounded, table and reference properties are skipped; the pset still appears, with those entries missing.

  • Type-level properties surface only for types that carry orphan geometry. A type attaches its sets through IfcTypeObject.HasPropertySets, and a type gets a row here only if it also has RepresentationMaps that no occurrence instantiates; such a row does carry its psets, but has no matching entry in elements. A plain IfcWallType holding Pset_WallCommon has no representation, so it produces no row at all, and its properties are not merged down into the occurrences that inherit them via IfcRelDefinesByType. That is the common case, and authoring tools put a lot on types, so treat a missing property as "not asked for yet" rather than "absent from the file".

Notes

  • One mesh per element. Per-material submeshes of an element are merged into a single indexed triangle soup, keyed by its IFC STEP id.
  • Coordinates are absolute world metres. The per-element local frame and the model RTC offset are folded back into every vertex. For geo-referenced models rtc_offset is non-zero; subtract it if you want f32-friendly local coordinates.
  • Welded and indexed. Coincident corners are merged (1 micron grid), so closed-mesh consumers (volume, watertightness checks) work directly.
  • Occurrences only. Type-product / RepresentationMap geometry is not emitted, matching what occurrence-based tessellators produce.
  • Errors surface as RuntimeError (pipeline failure) or ValueError (an unrecognised quality label, or JSON serialization failure).

Examples

Runnable scripts live in examples/:

  • quickstart_numpy.py - load a file and inspect meshes via numpy.
  • dump_json.py - write the JSON document to disk.
  • export_obj.py - write every element to a single Wavefront .obj (numpy only, no extra deps).
  • schedule_csv.py - join entity_data against geometry_data_buffers and write a quantity schedule to CSV (stdlib only).

License

MPL-2.0. Part of the ifc-lite project.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

ifclite_geom-4.3.0-cp39-abi3-win_amd64.whl (2.1 MB view details)

Uploaded CPython 3.9+Windows x86-64

ifclite_geom-4.3.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (2.4 MB view details)

Uploaded CPython 3.9+manylinux: glibc 2.17+ x86-64

ifclite_geom-4.3.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (2.3 MB view details)

Uploaded CPython 3.9+manylinux: glibc 2.17+ ARM64

ifclite_geom-4.3.0-cp39-abi3-macosx_11_0_arm64.whl (2.1 MB view details)

Uploaded CPython 3.9+macOS 11.0+ ARM64

ifclite_geom-4.3.0-cp39-abi3-macosx_10_12_x86_64.whl (2.2 MB view details)

Uploaded CPython 3.9+macOS 10.12+ x86-64

File details

Details for the file ifclite_geom-4.3.0-cp39-abi3-win_amd64.whl.

File metadata

  • Download URL: ifclite_geom-4.3.0-cp39-abi3-win_amd64.whl
  • Upload date:
  • Size: 2.1 MB
  • Tags: CPython 3.9+, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for ifclite_geom-4.3.0-cp39-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 2522bdf27f930f6050e80aa64cd8763459c6272214cb3f847610b9a073b72ed7
MD5 be969dbc37f0d860ecf3efa15287c8b0
BLAKE2b-256 5b52847eb7f125ef9b3fed5be96dc1303b0cd9bbacf01f039334a0fd8af61dbb

See more details on using hashes here.

Provenance

The following attestation bundles were made for ifclite_geom-4.3.0-cp39-abi3-win_amd64.whl:

Publisher: python-wheels.yml on LTplus-AG/ifc-lite

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file ifclite_geom-4.3.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for ifclite_geom-4.3.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 d7249a3c647eac339ce22eb71f2a104210ca887fb9f42f128fe5069769ccce74
MD5 54264adabd73cc8fdb77e75baae5754c
BLAKE2b-256 b0953d243e577b87296e303c090fa14c60885f6210cff80caf41e36580ceb3a4

See more details on using hashes here.

Provenance

The following attestation bundles were made for ifclite_geom-4.3.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: python-wheels.yml on LTplus-AG/ifc-lite

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file ifclite_geom-4.3.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for ifclite_geom-4.3.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 18e803c9a89de1c7aaa8acba9163cbd8159c5d0f5043c68e87ac37bc354f5c24
MD5 7f9c329bf99c7a143e7fca58c3416398
BLAKE2b-256 d0f8c6c7eb251b70ee93fd750fa7dd924ede945d46e342a7198b5c1639d84ef2

See more details on using hashes here.

Provenance

The following attestation bundles were made for ifclite_geom-4.3.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl:

Publisher: python-wheels.yml on LTplus-AG/ifc-lite

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file ifclite_geom-4.3.0-cp39-abi3-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for ifclite_geom-4.3.0-cp39-abi3-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 11ad83ee6e9d92548fd252499eacae5114fb8e60dc6a43bba7fedcbbe65e5bcf
MD5 cb02932d5405119b98b2c317c7bd6596
BLAKE2b-256 2e2342faba8e85fada5146fcd5ce8ad9c8c5be1bc9c5cab6a49cecc248a15cef

See more details on using hashes here.

Provenance

The following attestation bundles were made for ifclite_geom-4.3.0-cp39-abi3-macosx_11_0_arm64.whl:

Publisher: python-wheels.yml on LTplus-AG/ifc-lite

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file ifclite_geom-4.3.0-cp39-abi3-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for ifclite_geom-4.3.0-cp39-abi3-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 643bdd48754d53707239c01e2b29b919630fce6f63d1be4cfb66553ce60663ae
MD5 6f79873eddb04a05ca369fc2e3fd2361
BLAKE2b-256 75bc8a369e9bc3766ee95d2181796c123ef1db7385442e33e504effe026fc055

See more details on using hashes here.

Provenance

The following attestation bundles were made for ifclite_geom-4.3.0-cp39-abi3-macosx_10_12_x86_64.whl:

Publisher: python-wheels.yml on LTplus-AG/ifc-lite

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

4.4.0

5 files

This release

4.3.0 This release

5 files

4.2.1

5 files

4.2.0

5 files

4.1.0

5 files

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page