Skip to content

Exporting Data

Guide to exporting IFC data in various formats.

Quick Start: CDN Export (No Build Required)

Export IFC to GLB directly in the browser with zero setup:

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>IFC to GLB Export</title>
</head>
<body>
    <input type="file" id="file" accept=".ifc">
    <div id="status"></div>

    <script type="module">
        import { GeometryProcessor } from "https://cdn.jsdelivr.net/npm/@ifc-lite/geometry@1.2.1/+esm";
        import { GLTFExporter } from "https://cdn.jsdelivr.net/npm/@ifc-lite/export@1.2.1/+esm";
        import initWasm from "https://cdn.jsdelivr.net/npm/@ifc-lite/wasm@1.2.1/+esm";

        // Initialize WASM with explicit path for CDN
        const wasmUrl = "https://cdn.jsdelivr.net/npm/@ifc-lite/wasm@1.2.1/pkg/ifc-lite_bg.wasm";
        await initWasm({ module_or_path: wasmUrl });

        document.getElementById("file").addEventListener("change", async (e) => {
            const file = e.target.files[0];
            if (!file) return;

            try {
                const processor = new GeometryProcessor();
                await processor.init();

                const buffer = new Uint8Array(await file.arrayBuffer());
                const result = await processor.process(buffer);

                const exporter = new GLTFExporter(result);
                const glb = exporter.exportGLB();

                // Download the GLB file
                const blob = new Blob([glb], { type: "model/gltf-binary" });
                const url = URL.createObjectURL(blob);
                const a = document.createElement("a");
                a.href = url;
                a.download = file.name.replace(/\.ifc$/i, ".glb");
                a.click();
                URL.revokeObjectURL(url);

                document.getElementById("status").textContent = "Done!";
                processor.dispose();
            } catch (error) {
                document.getElementById("status").textContent = "Error: " + error.message;
            }
        });
    </script>
</body>
</html>

HTTP Server Required

This file must be served from an HTTP server (not file://). Use npx serve . or python -m http.server 8000.

Overview

IFClite supports multiple export formats, as well as GLB import for loading existing 3D assets:

flowchart LR subgraph Input["Input"] IFC["ParseResult"] GLBIn["GLB Import"] end subgraph Formats["Export Formats"] glTF["glTF/GLB"] IFCOut["IFC (roundtrip)"] Parquet["Apache Parquet"] Arrow["Apache Arrow"] JSON["JSON-LD"] CSV["CSV"] end subgraph Uses["Use Cases"] Viewer["3D Viewers"] Roundtrip["IFC Roundtrip"] Analytics["Data Analytics"] Linked["Linked Data"] Spreadsheet["Spreadsheets"] end GLBIn --> Viewer IFC --> glTF --> Viewer IFC --> IFCOut --> Roundtrip IFC --> Parquet --> Analytics IFC --> Arrow --> Analytics IFC --> JSON --> Linked IFC --> CSV --> Spreadsheet

glTF Export

Export geometry for use in standard 3D viewers:

import { GltfExporter } from '@ifc-lite/export';

const exporter = new GltfExporter();

// Export to glTF (JSON + binary)
const gltf = await exporter.export(parseResult, {
  format: 'gltf',
  embedImages: true,
  includeProperties: true
});

// Save files
await saveFile('model.gltf', gltf.json);
await saveFile('model.bin', gltf.binary);

// Export to GLB (single binary file)
const glb = await exporter.export(parseResult, {
  format: 'glb'
});
await saveFile('model.glb', glb);

glTF Options

interface GltfExportOptions {
  // Output format
  format: 'gltf' | 'glb';

  // Include IFC properties as extras
  includeProperties?: boolean;

  // Embed textures/images
  embedImages?: boolean;

  // Draco compression
  useDraco?: boolean;
  dracoOptions?: {
    quantization?: number;
    compressionLevel?: number;
  };

  // Filter entities
  entityFilter?: (entity: Entity) => boolean;

  // Coordinate system
  yUp?: boolean; // Convert from Z-up to Y-up
}

glTF with Properties

const gltf = await exporter.export(parseResult, {
  format: 'glb',
  includeProperties: true
});

// Properties are stored in node extras:
// {
//   "nodes": [{
//     "name": "Wall-001",
//     "extras": {
//       "expressId": 123,
//       "globalId": "2O2Fr$...",
//       "type": "IFCWALL",
//       "properties": {
//         "Pset_WallCommon": {
//           "IsExternal": true,
//           "FireRating": 60
//         }
//       }
//     }
//   }]
// }

Parquet Export

Export to Apache Parquet for analytics with tools like DuckDB, Pandas, or Polars:

import { ParquetExporter } from '@ifc-lite/export';

const exporter = new ParquetExporter();

// Export entities
const entitiesParquet = await exporter.exportEntities(parseResult);
await saveFile('entities.parquet', entitiesParquet);

// Export properties
const propsParquet = await exporter.exportProperties(parseResult);
await saveFile('properties.parquet', propsParquet);

// Export quantities
const quantsParquet = await exporter.exportQuantities(parseResult);
await saveFile('quantities.parquet', quantsParquet);

// Export all tables
const bundle = await exporter.exportAll(parseResult);
await saveFile('entities.parquet', bundle.entities);
await saveFile('properties.parquet', bundle.properties);
await saveFile('quantities.parquet', bundle.quantities);
await saveFile('relationships.parquet', bundle.relationships);

Parquet Schema

erDiagram ENTITIES { int64 express_id PK string type string global_id string name string description boolean has_geometry } PROPERTIES { int64 entity_id FK string pset_name string prop_name string value string value_type } QUANTITIES { int64 entity_id FK string name float64 value string unit } RELATIONSHIPS { int64 from_id FK int64 to_id FK string rel_type } ENTITIES ||--o{ PROPERTIES : has ENTITIES ||--o{ QUANTITIES : has ENTITIES ||--o{ RELATIONSHIPS : from ENTITIES ||--o{ RELATIONSHIPS : to

Using Parquet with Python

import polars as pl

# Load exported data
entities = pl.read_parquet('entities.parquet')
properties = pl.read_parquet('properties.parquet')
quantities = pl.read_parquet('quantities.parquet')

# Analyze wall areas
wall_areas = (
    entities
    .filter(pl.col('type').str.contains('IFCWALL'))
    .join(quantities, left_on='express_id', right_on='entity_id')
    .filter(pl.col('name') == 'NetArea')
    .group_by('type')
    .agg([
        pl.count('express_id').alias('count'),
        pl.sum('value').alias('total_area'),
        pl.mean('value').alias('avg_area')
    ])
)
print(wall_areas)

JSON-LD Export

Export as linked data for semantic web applications:

import { JsonLdExporter } from '@ifc-lite/export';

const exporter = new JsonLdExporter();

const jsonld = await exporter.export(parseResult, {
  // Base URI for identifiers
  baseUri: 'https://example.com/project/',

  // Include geometry as GeoJSON
  includeGeometry: false,

  // IFC ontology namespace
  ontology: 'https://standards.buildingsmart.org/IFC/DEV/IFC4/ADD2/OWL'
});

await saveFile('model.jsonld', JSON.stringify(jsonld, null, 2));

JSON-LD Structure

{
  "@context": {
    "ifc": "https://standards.buildingsmart.org/IFC/DEV/IFC4/ADD2/OWL#",
    "schema": "https://schema.org/",
    "geo": "http://www.opengis.net/ont/geosparql#"
  },
  "@graph": [
    {
      "@id": "https://example.com/project/wall-123",
      "@type": "ifc:IfcWall",
      "ifc:globalId": "2O2Fr$t4X7Zf8NOew3FL9r",
      "ifc:name": "Wall-001",
      "ifc:hasPropertySet": [
        {
          "@type": "ifc:IfcPropertySet",
          "ifc:name": "Pset_WallCommon",
          "ifc:hasProperty": [
            {
              "@type": "ifc:IfcPropertySingleValue",
              "ifc:name": "IsExternal",
              "ifc:value": true
            }
          ]
        }
      ]
    }
  ]
}

CSV Export

Export tabular data for spreadsheet applications:

import { CsvExporter } from '@ifc-lite/export';

const exporter = new CsvExporter();

// Export entity list
const entitiesCsv = await exporter.exportEntities(parseResult, {
  columns: ['expressId', 'type', 'globalId', 'name']
});
await saveFile('entities.csv', entitiesCsv);

// Export properties (pivoted)
const propsCsv = await exporter.exportPropertiesPivot(parseResult, {
  psetName: 'Pset_WallCommon',
  entityTypes: ['IFCWALL', 'IFCWALLSTANDARDCASE']
});
await saveFile('wall_properties.csv', propsCsv);

// Export quantities
const quantsCsv = await exporter.exportQuantities(parseResult);
await saveFile('quantities.csv', quantsCsv);

CSV Output Example

expressId,type,globalId,name,IsExternal,FireRating,LoadBearing
123,IFCWALL,2O2Fr$t4X7Zf8NOew3FL9r,Wall-001,true,60,true
456,IFCWALLSTANDARDCASE,3P3Gs$u5Y8Ag9PQfx4GM0s,Wall-002,false,30,false

IFC Export

Export back to IFC format for roundtrip workflows and interoperability with other BIM tools:

import { StepExporter } from '@ifc-lite/export';

const exporter = new StepExporter(dataStore, sourceBuffer);

// Full export
const result = exporter.export();
await saveFile('model.ifc', result.content);

// Visible-only export (exclude hidden entities)
const visibleResult = exporter.export({
  visibleOnly: true,
  hiddenEntityIds: hiddenSet,       // Set<number> of local expressIds
  isolatedEntityIds: isolatedSet,   // Set<number> | null
});
await saveFile('visible_only.ifc', visibleResult.content);

Visible-Only Export

When visibleOnly is enabled, the exporter:

  1. Always includes infrastructure (units, owner history) and spatial structure
  2. Checks each product entity against hiddenEntityIds / isolatedEntityIds
  3. Walks #ID references transitively to include all dependent geometry, properties, and materials
  4. Collects IfcStyledItem entities via reverse reference pass (preserves colors/materials)
  5. Propagates visibility to openings via IfcRelVoidsElement (hidden slab = hidden openings)

Supports all 202 IfcProduct subtypes from IFC4 and IFC4X3 schemas, including infrastructure types (bridges, roads, railways, marine facilities).

Multi-Model Merged Export

Merge multiple IFC models into a single file:

import { MergedExporter } from '@ifc-lite/export';

const exporter = new MergedExporter();
const result = await exporter.export([
  { dataStore: store1, source: buffer1, name: 'Architecture' },
  { dataStore: store2, source: buffer2, name: 'Structure' },
], {
  visibleOnly: true,
  hiddenEntityIds: hiddenSet,
  isolatedEntityIds: isolatedSet,
});
await saveFile('merged.ifc', result.content);

GLB Import

Load existing GLB files for viewing alongside IFC models:

import { GlbImporter } from '@ifc-lite/import';

const importer = new GlbImporter();
const glbBuffer = await fetch('model.glb').then(r => r.arrayBuffer());
const meshes = await importer.import(new Uint8Array(glbBuffer));

// Add imported meshes to the renderer
renderer.addMeshes(meshes);

Arrow Export

Export to Apache Arrow for in-memory analytics and streaming pipelines:

import { ArrowExporter } from '@ifc-lite/export';

const exporter = new ArrowExporter();
const arrowBuffer = await exporter.exportEntities(parseResult);

// Use with Arrow-compatible tools (DuckDB, DataFusion, etc.)
await saveFile('entities.arrow', arrowBuffer);

Custom Export

Create custom export formats:

import { ExportPipeline } from '@ifc-lite/export';

import { extractPropertiesOnDemand, extractQuantitiesOnDemand } from '@ifc-lite/parser';

// Define custom exporter
class CustomExporter {
  export(store: IfcDataStore, buffer: Uint8Array): CustomFormat {
    const output: CustomFormat = {
      metadata: {
        schema: store.schemaVersion,
        timestamp: new Date().toISOString()
      },
      elements: []
    };

    // Get all wall expressIds
    const wallIds = store.entityIndex.byType.get('IFCWALL') ?? [];

    for (const expressId of wallIds) {
      const entityRef = store.entityIndex.byId.get(expressId);
      if (entityRef) {
        output.elements.push({
          id: expressId,
          name: entityRef.name,
          properties: extractPropertiesOnDemand(store, expressId, buffer),
          quantities: extractQuantitiesOnDemand(store, expressId, buffer)
        });
      }
    }

    return output;
  }
}

// Use custom exporter
const exporter = new CustomExporter();
const custom = exporter.export(store, buffer);

Filtered Export

Export only specific entities:

import { GltfExporter } from '@ifc-lite/export';
import { IfcQuery } from '@ifc-lite/query';

// Filter entities with query
const query = new IfcQuery(parseResult);
const externalWalls = query
  .walls()
  .whereProperty('Pset_WallCommon', 'IsExternal', '=', true)
  .toArray();

// Export filtered set
const exporter = new GltfExporter();
const glb = await exporter.export(parseResult, {
  format: 'glb',
  entityFilter: (entity) =>
    externalWalls.some(w => w.expressId === entity.expressId)
});

Export Pipeline

Chain multiple exports:

flowchart LR Parse["Parse IFC"] Filter["Filter Entities"] Transform["Transform Data"] subgraph Exports["Parallel Exports"] E1["glTF"] E2["Parquet"] E3["CSV"] end Parse --> Filter --> Transform --> Exports
import { ExportPipeline } from '@ifc-lite/export';

const pipeline = new ExportPipeline(parseResult);

// Run multiple exports in parallel
const results = await pipeline.export([
  { format: 'glb', options: { useDraco: true } },
  { format: 'parquet', tables: ['entities', 'properties'] },
  { format: 'csv', columns: ['expressId', 'type', 'name'] }
]);

// Save all results
await saveFile('model.glb', results.glb);
await saveFile('entities.parquet', results.parquet.entities);
await saveFile('entities.csv', results.csv);

Next Steps