| name | thatopen-core-web-ifc |
| description | Use when working with web-ifc directly for IFC parsing, querying IFC entities, extracting geometry, or understanding the WASM engine beneath ThatOpen components. Prevents WASM initialization failures and memory leaks from unclosed models. Covers IfcAPI, SetWasmPath, Init, OpenModel, GetLine, GetFlatMesh, StreamAllMeshes, properties helper, LoaderSettings, schema detection. Keywords: web-ifc, wasm, ifc, parser, ifcapi, geometry, properties, spatial structure, express id, flatmesh, parse IFC in browser, read IFC JavaScript, IFC web.
|
| license | MIT |
| compatibility | Designed for Claude Code. Requires web-ifc 0.0.77+. |
| metadata | {"author":"OpenAEC-Foundation","version":"1.0"} |
web-ifc Engine: Direct WASM IFC Parser
Overview
web-ifc is the WASM-powered IFC parsing engine beneath the ThatOpen component stack. It reads and writes IFC files at native speed in browser and Node.js environments. The central class is IfcAPI.
When using ThatOpen components (@thatopen/components), you rarely call web-ifc directly — the IfcLoader component wraps it. Use this skill when you need low-level IFC access, custom geometry extraction, or bulk property queries outside the component framework.
Critical Warnings
- ALWAYS call
Init() before any other method (except SetWasmPath). Every method silently fails or throws without WASM initialization.
- ALWAYS call
CloseModel(modelID) when done — each open model holds significant WASM heap memory. Forgetting this causes memory leaks that crash browser tabs.
- ALWAYS use
.size() and .get(i) for Vector<T> access — NEVER use array indexing ([]). WASM vectors are not JavaScript arrays.
- ALWAYS call
Dispose() when the IfcAPI instance is no longer needed — this releases the entire WASM module.
- NEVER create multiple
IfcAPI instances — one instance handles multiple models. Extra instances waste memory by loading duplicate WASM modules.
- Vertex format is 6 floats per vertex:
[x, y, z, nx, ny, nz] — position followed by normal. ALWAYS account for this interleaved layout when extracting geometry.
- All 4x4 matrices are column-major (16 floats) — directly compatible with
THREE.Matrix4.fromArray().
Quick Start
import * as WebIFC from "web-ifc";
const ifcApi = new WebIFC.IfcAPI();
ifcApi.SetWasmPath("/wasm/");
await ifcApi.Init();
const data = new Uint8Array(buffer);
const modelID = ifcApi.OpenModel(data);
const wallIDs = ifcApi.GetLineIDsWithType(modelID, WebIFC.IFCWALL);
for (let i = 0; i < wallIDs.size(); i++) {
const wall = ifcApi.GetLine(modelID, wallIDs.get(i));
console.log(wall.Name?.value);
}
const mesh = ifcApi.GetFlatMesh(modelID, wallIDs.get(0));
const matrix = ifcApi.GetCoordinationMatrix(modelID);
ifcApi.CloseModel(modelID);
Initialization
SetWasmPath(path: string, absolute?: boolean): void
Sets the directory containing WASM files. MUST be called before Init(). The directory MUST contain web-ifc.wasm (and web-ifc-mt.wasm for multi-threaded mode).
ifcApi.SetWasmPath("/static/wasm/");
ifcApi.SetWasmPath("https://cdn.example.com/wasm/", true);
NEVER hardcode a version in the WASM path — ALWAYS match the installed web-ifc npm version.
Init(customLocateFileHandler?, forceSingleThread?): Promise<void>
Initializes the WASM module. MUST be awaited before calling any other API method.
await ifcApi.Init();
await ifcApi.Init(undefined, true);
await ifcApi.Init((path, prefix) => "/custom/" + path);
Dispose(): void
Releases the entire WASM module and all resources. Call when the IfcAPI instance is no longer needed.
Model Lifecycle
| Method | Signature | Purpose |
|---|
OpenModel | (data: Uint8Array, settings?: LoaderSettings) => number | Load IFC from buffer, returns modelID |
OpenModels | (dataSets: Uint8Array[], settings?) => number[] | Load multiple IFC files at once |
OpenModelFromCallback | (callback: ModelLoadCallback, settings?) => number | Stream-load without full buffer in memory |
CreateModel | (model: NewIfcModel, settings?) => number | Create empty IFC model |
SaveModel | (modelID: number) => Uint8Array | Serialize model to IFC bytes |
CloseModel | (modelID: number) => void | Free all WASM memory for this model |
IsModelOpen | (modelID: number) => boolean | Check if model is open |
LoaderSettings
interface LoaderSettings {
COORDINATE_TO_ORIGIN?: boolean;
USE_FAST_BOOLS?: boolean;
CIRCLE_SEGMENTS_LOW?: number;
CIRCLE_SEGMENTS_MEDIUM?: number;
CIRCLE_SEGMENTS_HIGH?: number;
BOOL_ABORT_THRESHOLD?: number;
MEMORY_LIMIT?: number;
}
ALWAYS use COORDINATE_TO_ORIGIN: true for models with large world coordinates — prevents floating-point precision issues in rendering.
Data Queries
Core Query Methods
| Method | Returns | Purpose |
|---|
GetAllLines(modelID) | Vector<number> | All expressIDs in the model |
GetLineIDsWithType(modelID, type, includeInherited?) | Vector<number> | ExpressIDs by IFC type |
GetLine(modelID, expressID, flatten?, inverse?, inversePropKey?) | any | Single entity by expressID |
GetLines(modelID, expressIDs, flatten?, inverse?, inversePropKey?) | any[] | Batch entity retrieval |
GetRawLineData(modelID, expressID) | RawLineData | Raw unparsed data (faster) |
GetLineType(modelID, expressID) | number | IFC type code only |
GetMaxExpressID(modelID) | number | Highest expressID |
GetNextExpressID(modelID, expressID) | number | Next valid expressID |
GetLine Parameters
| Parameter | Type | Default | Description |
|---|
flatten | boolean | false | Recursively resolve all references inline |
inverse | boolean | false | Include inverse relationships |
inversePropKey | string? | null | Filter inverse props to specific key |
NEVER use flatten: true on large models without limiting scope — it recursively resolves every reference and causes severe performance degradation.
Schema & Type Information
| Method | Returns | Purpose |
|---|
GetModelSchema(modelID) | string | Schema version ("IFC2X3", "IFC4", "IFC4X3") |
GetAllTypesOfModel(modelID) | IfcType[] | All IFC types present in model |
GetHeaderLine(modelID, headerType) | any | IFC header info |
Geometry Extraction
Single-Element Geometry
const flatMesh = ifcApi.GetFlatMesh(modelID, expressID);
for (let i = 0; i < flatMesh.geometries.size(); i++) {
const pg = flatMesh.geometries.get(i);
const geom = ifcApi.GetGeometry(modelID, pg.geometryExpressID);
const verts = ifcApi.GetVertexArray(geom.GetVertexData(), geom.GetVertexDataSize());
const indices = ifcApi.GetIndexArray(geom.GetIndexData(), geom.GetIndexDataSize());
}
Geometry Streaming (Memory-Efficient)
ALWAYS prefer streaming over LoadAllGeometry for models with more than a few hundred elements.
| Method | Purpose |
|---|
StreamAllMeshes(modelID, callback) | Stream ALL meshable entities |
StreamAllMeshesWithTypes(modelID, types[], callback) | Stream filtered by IFC types |
StreamMeshes(modelID, expressIDs[], callback) | Stream specific elements |
LoadAllGeometry(modelID) | Load all at once (AVOID for large models) |
Callback signature: (mesh: FlatMesh, index: number, total: number) => void
Coordination & Transforms
| Method | Purpose |
|---|
GetCoordinationMatrix(modelID) | 4x4 matrix for multi-model alignment |
SetGeometryTransformation(modelID, matrix) | Apply global transform to all geometry output |
GetWorldTransformMatrix(modelID, placementExpressId) | Transform for specific placement |
Properties Helper
The ifcApi.properties object provides high-level async methods for property queries.
| Method | Returns | Purpose |
|---|
getItemProperties(modelID, id, recursive?, inverse?) | Promise<any> | All properties for an element |
getPropertySets(modelID, elementID?, recursive?) | Promise<any[]> | Property sets (Psets) |
getTypeProperties(modelID, elementID?, recursive?) | Promise<any[]> | Type object properties |
getMaterialsProperties(modelID, elementID?, recursive?) | Promise<any[]> | Material definitions |
getSpatialStructure(modelID, includeProperties?) | Promise<Node> | Full spatial hierarchy tree |
The spatial structure returns a tree: { expressID, type, children: [...] }.
GUID Utilities
| Method | Purpose |
|---|
GetExpressIdFromGuid(modelID, guid) | Convert IFC GUID string to expressID |
GetGuidFromExpressId(modelID, expressID) | Convert expressID to IFC GUID string |
CreateIfcGuidToExpressIdMapping(modelID) | Pre-build mapping for faster lookups |
ALWAYS call CreateIfcGuidToExpressIdMapping first if performing many GUID lookups — it builds an index that makes subsequent calls faster.
Writing Data
| Method | Purpose |
|---|
WriteLine(modelID, lineObject) | Write or update a single entity |
WriteLines(modelID, lineObjects[]) | Batch write |
DeleteLine(modelID, expressID) | Remove entity from model |
CreateIfcEntity(modelID, type, ...args) | Create new IFC entity |
After modifications, use SaveModel(modelID) to serialize back to IFC format.
Logging
import { LogLevel } from "web-ifc";
ifcApi.SetLogLevel(LogLevel.LOG_LEVEL_OFF);
ifcApi.SetLogLevel(LogLevel.LOG_LEVEL_ERROR);
ifcApi.SetLogLevel(LogLevel.LOG_LEVEL_DEBUG);
Key Types
See references/methods.md for complete type definitions.
| Type | Description |
|---|
FlatMesh | Triangulated geometry result: { expressID, geometries: Vector<PlacedGeometry> } |
PlacedGeometry | Single geometry piece: color (RGBA), transform (4x4), geometryExpressID |
IfcGeometry | Raw WASM geometry: GetVertexData/Size(), GetIndexData/Size() |
Vector<T> | WASM vector: access via .size() and .get(i) ONLY |
RawLineData | Unparsed entity: { ID, type, arguments } |
LoaderSettings | Model loading configuration |
IfcType | Type descriptor: { typeID, typeName } |
Common IFC Type Constants
import {
IFCWALL, IFCWALLSTANDARDCASE, IFCSLAB, IFCBEAM, IFCCOLUMN,
IFCDOOR, IFCWINDOW, IFCOPENINGELEMENT,
IFCROOF, IFCSTAIR, IFCFURNISHINGELEMENT,
IFCPROJECT, IFCSITE, IFCBUILDING, IFCBUILDINGSTOREY, IFCSPACE,
IFCPROPERTYSET, IFCPROPERTYSINGLEVALUE,
IFCRELDEFINESBYPROPERTIES, IFCRELCONTAINEDINSPATIALSTRUCTURE,
IFCRELAGGREGATES, IFCRELVOIDSELEMENT,
} from "web-ifc";
References
references/methods.md — Complete IfcAPI method signatures and type definitions
references/examples.md — Full working examples: init, load, query, geometry, properties
references/anti-patterns.md — Common failures: WASM init, memory leaks, Vector access
Sources