-
Notifications
You must be signed in to change notification settings - Fork 1
step parser
Layer 2 — Depends on step-serializer and schema. Schema-aware STEP parser that combines raw STEP parsing with IFC type resolution.
pnpm add @ifc-factory/step-parserimport { parseStepToEntities } from '@ifc-factory/step-parser';
import { readFileSync } from 'node:fs';
const source = readFileSync('model.ifc', 'utf-8');
const result = parseStepToEntities(source);
console.log(`Schema: ${result.schema}`);
console.log(`Entities: ${result.entities.size}`);
// All entities are now typed with named attributes
for (const [id, entity] of result.entities) {
console.log(`#${id}: ${entity.type}`);
if (entity.type === 'IfcWall') {
console.log(` Name: ${entity.Name}`);
console.log(` GlobalId: ${entity.GlobalId}`);
console.log(` PredefinedType: ${entity.PredefinedType}`);
}
}import { writeEntitiesToStep } from '@ifc-factory/step-parser';
const stepOutput = writeEntitiesToStep(result.entities, 'IFC4X3');
writeFileSync('output.ifc', stepOutput);import { parseStepToEntities, writeEntitiesToStep } from '@ifc-factory/step-parser';
const source = readFileSync('input.ifc', 'utf-8');
const result = parseStepToEntities(source);
// Modify an entity
const wall = result.entities.get(42);
if (wall) {
wall.Name = 'Updated Wall Name';
}
// Write back
const output = writeEntitiesToStep(result.entities, result.schema);
writeFileSync('output.ifc', output);The step-parser implements a two-pass architecture. See Architecture for the full picture.
Delegates to @ifc-factory/step-serializer:
STEP source → Tokenizer → Reader → StepFile
├── header: StepHeader
└── entities: Map<number, StepEntityInstance>
{ id: 1, typeName: "IFCWALL", attributes: [...] }
Uses @ifc-factory/schema metadata:
StepEntityInstance → Instance Builder → IfcGenericEntity
For each raw instance:
1. Look up ENTITY_REGISTRY["IFCWALL"] → "IfcWall"
2. Look up SCHEMA_METADATA["IfcWall"] → { allAttributes: [...] }
3. Map positional attributes to named properties
4. Convert StepEntityRef → number (expressID)
5. Convert StepEnum → string
6. Convert StepTypedValue → unwrapped value
7. Convert null ($) → null
8. Convert StepDerived (*) → undefined
| STEP Value | TypeScript Value |
|---|---|
42 (integer) |
42 (number) |
3.14 (real) |
3.14 (number) |
'text' (string) |
'text' (string) |
.T. (boolean) |
true (boolean) |
.F. (boolean) |
false (boolean) |
$ (omitted) |
null |
* (derived) |
undefined |
#123 (entity ref) |
123 (number) |
.SOLIDWALL. (enum) |
'SOLIDWALL' (string) |
IFCLABEL('text') (typed) |
'text' (unwrapped) |
(1, 2, 3) (list) |
[1, 2, 3] (array) |
(#10, #20) (ref list) |
[10, 20] (number array) |
If a STEP entity type is not found in ENTITY_REGISTRY (e.g., from a newer or different schema), the parser creates an IfcGenericEntity with:
-
typeset to the raw type name - All attributes stored as an indexed object (
attr_0,attr_1, etc.)
This provides graceful degradation — the model can still be loaded and round-tripped even with unrecognized types.
Full two-pass parse from STEP string to typed entities.
Parameters:
-
source— Complete STEP file content
Returns:
interface ParseResult {
schema: string; // e.g., 'IFC4X3'
entities: Map<number, IfcGenericEntity>; // All typed entities
header: StepHeader; // Parsed header info
}Serialize typed entities back to a STEP file string.
Parameters:
-
entities— Map of expressID → entity -
schema— Schema identifier (default:'IFC4X3')
Returns: Valid ISO 10303-21 string
Behavior:
- Uses
SCHEMA_METADATAto determine attribute order - Converts named properties back to positional attributes
- Entity references (numbers) become
#N - Enum strings become
.VALUE. - Entities sorted by ID for deterministic output
Maps raw StepEntityInstance to IfcGenericEntity:
function buildTypedEntity(
instance: StepEntityInstance,
metadata: EntityMetadata
): IfcGenericEntity {
const entity: IfcGenericEntity = {
expressID: instance.id,
type: ENTITY_REGISTRY[instance.typeName.toUpperCase()],
};
for (let i = 0; i < metadata.allAttributes.length; i++) {
const attrMeta = metadata.allAttributes[i];
const rawValue = instance.attributes[i];
entity[attrMeta.name] = convertValue(rawValue);
}
return entity;
}Converts StepValue to JavaScript values:
function convertValue(value: StepValue): unknown {
if (value === null) return null; // $
if (typeof value === 'number') return value; // integer/real
if (typeof value === 'string') return value; // string
if (typeof value === 'boolean') return value; // .T./.F.
if ('ref' in value) return value.ref; // #N → number
if ('enum' in value) return value.enum; // .ENUM. → string
if ('typeName' in value) return convertValue(value.value); // unwrap
if ('derived' in value) return undefined; // *
if (Array.isArray(value)) return value.map(convertValue); // list
return value;
}Entity references are kept as plain numbers (expressIDs). No object-level resolution is performed — this is by design. See Architecture for the rationale.
- step-serializer — Pass 1: raw STEP parsing
- schema — Provides metadata for Pass 2
- core — High-level API that wraps step-parser
- Architecture — Two-pass design explanation
Ifc-Factory
Getting Started
Concepts
Packages
API & Reference
Development