Skip to content

The BIM Layer ​

brepjs-bim turns brepjs geometry into building information. You describe elements as typed parametric specs (a wall is a length, height, thickness, placement, and material, not a mesh); the model assembles them into a building or focused civil spatial structure, layers on property sets, materials, quantities, and classifications, and serializes the result to a valid IFC-SPF file. A matching importer reads IFC back in.

bash
npm install brepjs-bim brepjs web-ifc

Two ways in:

  • Through families (recommended for new models): author a declarative element tree with brepjs-families and project it with familiesToBim. Identity, openings, and containment come from the tree; GlobalIds derive from key paths and survive reorders. Start at IFC Export.
  • Direct BimModel: imperative add* calls when you already know exactly what to build, or when you need elements the families projection does not cover yet.
typescript
import { BimModel, toIfc } from 'brepjs-bim';
import { unwrap } from 'brepjs';

const model = new BimModel();
model.init({ name: 'Example' });

const siteId = unwrap(model.addSite({ name: 'Site' }));
const buildingId = unwrap(model.addBuilding({ name: 'Building' }));
const storeyId = unwrap(model.addStorey({ name: 'Level 1', elevation: 0 }));
const project = model.getProject();
if (project) model.aggregate(project.localId, siteId);
model.aggregate(siteId, buildingId);
model.aggregate(buildingId, storeyId);

const wall = model.addWall({
  length: 4000,
  height: 3000,
  thickness: 200,
  origin: [0, 0, 0],
  axisX: [1, 0, 0],
  axisZ: [0, 0, 1],
  materialName: 'Concrete',
});
if (wall.ok) model.placeIn(wall.value, storeyId);

const ifc = await toIfc(model, { applicationName: 'example-app', applicationVersion: '1' });
// ifc.ok && ifc.value instanceof Uint8Array

Three design decisions carry the package:

  1. Typed specs anchor the model. Every add* call validates its spec (zod schemas; the parse*Spec functions are exported for standalone use) and stores a typed element. Parametric physical specs build analytical solids, with IFC encoding determined by the element type. Civil spatial elements are body-less, while explicitly arbitrary bodies such as Earthworks Fill serialize as tessellation. Families-projected civil walls and railings always retain the evaluated authored items as an AUTHORITATIVE Product Body and export every item as tessellation.
  2. Geometry is unplaced template geometry. Element solids live in local coordinates; origin / axisX / axisZ are applied by the IFC layer via IfcLocalPlacement. placedSolids(element) applies the element frame; when its spatial parent is placed, pass the cumulative parentFrame to obtain world coordinates.
  3. Results, not exceptions. Every operation returns Result<T, BimError> from brepjs. Validation issues travel inside reports; nothing throws across the API boundary.

Dimensions are millimeters everywhere; IFC export emits SI metres. Reading element geometry needs only the brepjs kernel; toIfc / fromIfc additionally load the web-ifc peer dependency.

Focused civil bridge profile ​

For IFC4X3, the public Families path supports Project → Site → Bridge → recursively nested Bridge Part, exact Earthworks Fill bodies, and nearest-part product containment. Civil Product semantics route the infrastructure fixture's existing Beam (beam, cross-girder, girder), Column (pier-stem), Footing (pad), Railing (guardrail), Slab (deck), and Wall (wall) categories to their normal typed BIM elements. Semantic material is used when the element does not separately provide materialName.

Civil-semantic wall and railing routes require bodyEvaluator or the proxyEvaluator fallback to retain their authored Product Bodies. Without an evaluator, projection returns FAMILIES_PRODUCT_BODY_EVALUATOR_REQUIRED. Conventional archetype walls and railings retain their existing recipe authoring behavior and do not need an evaluator. The adapter registers wall openings before installing the authored Body and copies every borrowed evaluator item into Product-local coordinates. It retains AUTHORITATIVE authority even when the geometry coincides with the nominal recipe. These products keep their typed Wall or Railing classification and export every Body item as tessellation. The evaluator's source handles remain borrowed. Other typed civil routes continue to use the reference Families' semantic envelope dimensions.

Member and Sign are explicitly outside this profile. They remain hard unsupported-type errors unless proxyEvaluator is deliberately enabled, in which case projected.proxied reports them. This profile does not claim complete IFC infrastructure coverage or unchanged full scratch-example parity.

Continue with the element catalog, IFC export & import, validation, and interop.

IfcOpenShell 0.8.5 currently reports a tessellation Normals schema error for the existing IFC4X3 writer, including single Proxy and retained Families Body items. The verified fixtures still produce the expected shapes and world placement. IFC4X3 schema conformance is not established by those geometry checks.

Released under the Apache 2.0 License.