-
Notifications
You must be signed in to change notification settings - Fork 1
Query API
Ifc-Factory provides a fluent, chainable query builder and composable filter predicates for finding entities in an IfcModel.
import { QueryBuilder } from '@ifc-factory/core';
// Get all walls
const walls = new QueryBuilder(model)
.ofType('IfcWall')
.execute();
// Get first door
const door = new QueryBuilder(model)
.ofType('IfcDoor')
.first();
// Count windows
const windowCount = new QueryBuilder(model)
.ofType('IfcWindow')
.count();All filter methods return the QueryBuilder, so they can be chained:
const results = new QueryBuilder(model)
.ofType('IfcWall') // Filter by entity type
.whereProperty('Name', 'Exterior Wall') // Filter by property value
.where(e => e.PredefinedType === 'SOLIDWALL') // Custom predicate
.limit(10) // Max results
.execute(); // Run queryFilter entities by their IFC type name.
.ofType('IfcWall')
.ofType('IfcDoor')
.ofType('IfcRelAggregates')Filter with a custom predicate function. Can be called multiple times — all predicates must match (AND).
// Custom logic
.where(e => e.Name !== null && e.Name !== '')
// Numeric comparison
.where(e => typeof e.OverallHeight === 'number' && e.OverallHeight > 2.0)
// Check for existence
.where(e => 'PredefinedType' in e && e.PredefinedType !== null)Shorthand for filtering by a property's exact value.
.whereProperty('Name', 'Exterior Wall')
.whereProperty('PredefinedType', 'SOLIDWALL')
.whereProperty('IsExternal', true)Equivalent to .where(e => e[name] === value).
Limit the number of results returned.
.limit(10) // Return at most 10 results
.limit(1) // Return at most 1 resultRun the query and return all matching entities as an array.
const results = new QueryBuilder(model)
.ofType('IfcWall')
.execute();
// Returns: IfcGenericEntity[]Run the query and return the first matching entity, or undefined if none match.
const project = new QueryBuilder(model)
.ofType('IfcProject')
.first();
// Returns: IfcGenericEntity | undefinedRun the query and return the count of matching entities.
const wallCount = new QueryBuilder(model)
.ofType('IfcWall')
.count();
// Returns: numberFor more complex queries, use composable filter predicates with boolean combinators.
import { byType, byProperty, byPropertyExists, and, or, not } from '@ifc-factory/core';Match entities by type.
const isWall = byType('IfcWall');
// Matches entities where entity.type === 'IfcWall'Match entities by property value.
const isExternal = byProperty('IsExternal', true);
const namedExterior = byProperty('Name', 'Exterior Wall');Match entities that have a non-null, non-undefined value for the given property.
const hasName = byPropertyExists('Name');
const hasDescription = byPropertyExists('Description');All predicates must match.
const externalWall = and(
byType('IfcWall'),
byProperty('PredefinedType', 'SOLIDWALL')
);At least one predicate must match.
const wallOrDoor = or(
byType('IfcWall'),
byType('IfcDoor')
);Invert a predicate.
const notExternal = not(byProperty('IsExternal', true));import { QueryBuilder, byType, byProperty, byPropertyExists, and, or, not } from '@ifc-factory/core';
// Complex query: exterior walls or doors, with a name, not using USERDEFINED type
const filter = and(
or(
byType('IfcWall'),
byType('IfcDoor')
),
byPropertyExists('Name'),
not(byProperty('PredefinedType', 'USERDEFINED'))
);
const results = new QueryBuilder(model)
.where(filter)
.execute();
console.log(`Found ${results.length} matching elements`);
for (const entity of results) {
console.log(` ${entity.type}: ${entity.Name} [#${entity.expressID}]`);
}Filters are plain predicate functions (entity: IfcGenericEntity) => boolean, so you can use them anywhere:
const isExternalWall = and(byType('IfcWall'), byProperty('IsExternal', true));
// Use with Array.filter
const allEntities = model.getAllOfType('IfcWall');
const externalWalls = allEntities.filter(isExternalWall);
// Use in conditions
const entity = model.get(42);
if (entity && isExternalWall(entity)) {
console.log('Entity #42 is an external wall');
}const loadBearingWalls = new QueryBuilder(model)
.ofType('IfcWall')
.where(e => {
// Check property sets for LoadBearing
const psets = getPropertySets(model, e.expressID);
for (const pset of psets) {
const props = pset.HasProperties as number[];
for (const propId of props) {
const prop = model.get(propId);
if (prop?.Name === 'LoadBearing' && prop?.NominalValue === true) {
return true;
}
}
}
return false;
})
.execute();const groundFloorElements = model.getContainedElements(groundFloorId);
// Further filter to only walls
const groundFloorWalls = groundFloorElements.filter(e => e.type === 'IfcWall');const typeCounts = new Map<string, number>();
const entityTypes = ['IfcWall', 'IfcDoor', 'IfcWindow', 'IfcSlab', 'IfcColumn', 'IfcBeam'];
for (const type of entityTypes) {
const count = new QueryBuilder(model).ofType(type).count();
if (count > 0) {
typeCounts.set(type, count);
}
}
for (const [type, count] of typeCounts) {
console.log(`${type}: ${count}`);
}- core — IfcModel and helpers
- API Reference — Complete reference
- Tutorials — Practical examples
Ifc-Factory
Getting Started
Concepts
Packages
API & Reference
Development