Skip to content

Getting Started

Maarten Vroegindeweij edited this page Feb 18, 2026 · 1 revision

Getting Started

Installation

Using pnpm (recommended)

pnpm add @ifc-factory/core @ifc-factory/schema

Using npm

npm install @ifc-factory/core @ifc-factory/schema

Using yarn

yarn add @ifc-factory/core @ifc-factory/schema

Optional packages

# Model validation, diffing, and batch operations
pnpm add @ifc-factory/ifc-utils

# Low-level STEP file I/O (for custom parsers)
pnpm add @ifc-factory/step-serializer

# EXPRESS schema parser (for custom code generation)
pnpm add @ifc-factory/express-parser

Requirements

  • Node.js >= 20 (uses crypto.randomUUID())
  • Module system: ESM or CJS (dual-format builds provided)
  • TypeScript >= 5.0 (for full type support)
  • No native dependencies — pure TypeScript, no WASM, no C++ bindings

Quick Examples

1. Parse an IFC File

The most common starting point: read an existing .ifc file and inspect its contents.

import { IfcModel } from '@ifc-factory/core';
import { readFileSync } from 'node:fs';

// Read the raw STEP file
const source = readFileSync('model.ifc', 'utf-8');

// Parse into an IfcModel
const model = IfcModel.fromStep(source);

// Basic model information
console.log(`Schema version: ${model.schema}`);    // e.g. 'IFC4X3'
console.log(`Total entities: ${model.size}`);       // e.g. 4523
console.log(`Project name: ${model.project?.Name}`); // e.g. 'My Building'

// Access a specific entity by its express ID (#123 in the STEP file)
const entity = model.get(123);
if (entity) {
  console.log(`Entity type: ${entity.type}`);        // e.g. 'IfcWall'
  console.log(`Entity name: ${entity.Name}`);        // e.g. 'Wall-001'
  console.log(`Global ID: ${entity.GlobalId}`);      // e.g. '2TGt$H0E5Cexq0Fmv1x7tP'
}

2. Query Entities

Find entities by type, name, or custom predicates.

// Get all walls
const walls = model.getAllOfType('IfcWall');
console.log(`Found ${walls.length} walls`);

// Get all doors
const doors = model.getAllOfType('IfcDoor');
console.log(`Found ${doors.length} doors`);

// List all entity types in the model
const types = new Set<string>();
for (let id = 1; id <= model.size * 2; id++) {
  const e = model.get(id);
  if (e) types.add(e.type);
}
console.log('Entity types:', [...types].sort().join(', '));

Using the Fluent Query Builder

import { QueryBuilder } from '@ifc-factory/core';

// Find walls named "Exterior Wall"
const exteriorWalls = new QueryBuilder(model)
  .ofType('IfcWall')
  .whereProperty('Name', 'Exterior Wall')
  .execute();

// Find the first IfcProject
const project = new QueryBuilder(model)
  .ofType('IfcProject')
  .first();

// Count windows
const windowCount = new QueryBuilder(model)
  .ofType('IfcWindow')
  .count();

// Custom predicate: walls with GlobalId starting with '2T'
const filtered = new QueryBuilder(model)
  .ofType('IfcWall')
  .where(entity => typeof entity.GlobalId === 'string' && entity.GlobalId.startsWith('2T'))
  .execute();

Using Composable Filters

import { QueryBuilder, byType, byProperty, and, or, not } from '@ifc-factory/core';

// Combine filters with boolean logic
const filter = and(
  byType('IfcWall'),
  or(
    byProperty('Name', 'Exterior Wall'),
    byProperty('Name', 'Interior Wall')
  )
);

const results = new QueryBuilder(model)
  .where(filter)
  .execute();

3. Create a New Model from Scratch

Build a complete IFC model programmatically.

import {
  IfcModel,
  createSpatialStructure,
  createPropertySet,
  assignPropertySet,
  generateIfcGuid,
} from '@ifc-factory/core';

// Create empty model
const model = new IfcModel();

// Build the spatial hierarchy: Project → Site → Building → Storeys
const { project, site, building, storeys } = createSpatialStructure(model, {
  projectName: 'Residential Tower',
  siteName: 'Amsterdam Noord',
  buildingName: 'Tower A',
  storeyNames: ['Basement', 'Ground Floor', 'Floor 1', 'Floor 2', 'Floor 3'],
});

console.log(`Project ID: #${project.expressID}`);
console.log(`Building ID: #${building.expressID}`);
console.log(`Storeys: ${storeys.map(s => s.Name).join(', ')}`);

// Create a wall entity
const wall = model.create('IfcWall', {
  GlobalId: generateIfcGuid(),
  Name: 'Exterior Wall East',
  Description: 'Load-bearing exterior wall',
  PredefinedType: 'SOLIDWALL',
});

// Place the wall in the ground floor
model.containInSpatialStructure(storeys[1].expressID, wall.expressID);

// Add properties to the wall
const pset = createPropertySet(model, 'Pset_WallCommon', [
  { name: 'IsExternal', value: true },
  { name: 'LoadBearing', value: true },
  { name: 'FireRating', value: 'REI90' },
  { name: 'ThermalTransmittance', value: 0.18, type: 'IFCREAL' },
  { name: 'AcousticRating', value: '52 dB' },
]);
assignPropertySet(model, pset.expressID, [wall.expressID]);

// Export to STEP file
const stepOutput = model.toStep();
console.log(stepOutput.substring(0, 500)); // Preview

4. Traverse the Spatial Structure

Navigate the project hierarchy.

import { flattenSpatialTree } from '@ifc-factory/core';

const tree = model.getSpatialTree();

// Recursive tree print
function printTree(node: any, indent = 0) {
  const prefix = '  '.repeat(indent);
  const name = node.entity.Name ?? '(unnamed)';
  console.log(`${prefix}${node.entity.type}: ${name} [#${node.entity.expressID}]`);
  for (const child of node.children) {
    printTree(child, indent + 1);
  }
}

printTree(tree);
// Output:
// IfcProject: Residential Tower [#1]
//   IfcSite: Amsterdam Noord [#2]
//     IfcBuilding: Tower A [#3]
//       IfcBuildingStorey: Basement [#4]
//       IfcBuildingStorey: Ground Floor [#5]
//       IfcBuildingStorey: Floor 1 [#6]
//       ...

// Flatten to array for iteration
const allNodes = flattenSpatialTree(tree);
for (const node of allNodes) {
  const elements = model.getContainedElements(node.entity.expressID);
  console.log(`${node.entity.Name}: ${elements.length} elements`);
}

5. Round-Trip: Parse → Modify → Write

Read an IFC file, modify it, and save.

import { IfcModel, createPropertySet, assignPropertySet } from '@ifc-factory/core';
import { readFileSync, writeFileSync } from 'node:fs';

// Parse
const source = readFileSync('input.ifc', 'utf-8');
const model = IfcModel.fromStep(source);

// Modify: add a property set to all walls
const walls = model.getAllOfType('IfcWall');
const pset = createPropertySet(model, 'Pset_Custom', [
  { name: 'LastModifiedBy', value: 'Ifc-Factory Script' },
  { name: 'ModificationDate', value: new Date().toISOString() },
]);
assignPropertySet(model, pset.expressID, walls.map(w => w.expressID));

// Write
const output = model.toStep();
writeFileSync('output.ifc', output);
console.log(`Wrote ${model.size} entities to output.ifc`);

6. Validate a Model

import { IfcModel } from '@ifc-factory/core';
import { validateModel, detectSchemaVersion } from '@ifc-factory/ifc-utils';
import { readFileSync } from 'node:fs';

const source = readFileSync('model.ifc', 'utf-8');

// Check schema version before parsing
const version = detectSchemaVersion(source);
console.log(`Schema: ${version}`); // 'IFC4X3', 'IFC4', 'IFC2X3', etc.

// Parse and validate
const model = IfcModel.fromStep(source);
const issues = validateModel(model);

const errors = issues.filter(i => i.severity === 'error');
const warnings = issues.filter(i => i.severity === 'warning');

console.log(`Errors: ${errors.length}, Warnings: ${warnings.length}`);
for (const issue of issues) {
  console.log(`[${issue.severity.toUpperCase()}] ${issue.message}`);
}

Next Steps

Clone this wiki locally