Skip to content

Design Query

Read-only enumeration and inspection of scene-committed BIM entities. No query mutates the scene. Accessed via snaptrude.design.query.

Every list* method returns a snapshot ComponentHandle[] ([], never null) filtered by the shared PluginEntityFilter; per-entity reads take a ComponentHandle and return primitive records / child handles, or null when the entity is gone. Resolve details of a returned handle with getProperties / measure / design.query.geometry.*.

Entity Queries

Discovery and inspection of BIM entities by kind, plus identity, hierarchy, property, and metric reads. Accessed via snaptrude.design.query.

Types

PluginEntityType

The kind of a BIM entity — the discovery/filter vocabulary for the whole design.query.* surface. Values are clean lowerCamel tokens; the host maps each to the engine's internal type (whose raw strings are case-inconsistent — never surfaced here).

ValueEntity
"wall"Wall
"space"Space (a room mass)
"mass"Generic mass (non-room)
"door"Door
"window"Window
"floor"Floor
"slab"Slab
"roof"Roof
"column"Column
"beam"Beam
"ceiling"Ceiling
"staircase"Staircase
"furniture"Furniture
"referenceLine"Reference line
"curtainWall"Parametric curtain wall
"mullion"Curtain-wall mullion
"panel"Curtain-wall panel

PluginEntityFilter

The single filter shared by every design.query.list* method, so filtering is identical across all BIM object types. Every field is optional and AND-combined: a component must satisfy all provided fields. Plural fields are arrays (match any of); singular fields are scalars. A field that names a type-specific dimension (massTypes/spaceTypes/departmentId) excludes components that lack that dimension.

FieldTypeKeeps components where
typesPluginEntityType[]entity kind ∈ types (ignored by per-type list* — the method fixes the kind)
storeysnumber[]storey/floor level ∈ storeys (negative = basement)
buildingIdsstring[]building ∈ buildingIds
structureIdsstring[]structure ∈ structureIds
labelstringlabel (room_type ?? mesh label) === label
massTypesPluginMassType[]mass-type ∈ (masses only)
spaceTypesPluginSpaceType[]space-type ∈ (spaces only)
departmentIdPluginDepartmentIddepartment ===
isSelectedbooleancurrent selection state ===
isLockedbooleanlock flag ===
isHiddenbooleanuser-hidden flag ===
withinBBoxComponentsthe entity's bounding box intersects the region
overlapsComponentHandlethe entity's plan footprint overlaps the given space's bottom-face footprint — non-zero intersection area, so fully-inside, boundary-nested, and partially-overhanging entities all match; edge-touching with zero interior overlap does not. Exact polygon intersection (holes respected). Tested in plan — storey height is ignored; compose with storeys to scope a floor. Hidden entities are excluded by default — pass isHidden explicitly to override. The reference space itself is never returned. Throws on an unknown id. Entities without a brep footprint use their bounding-box plan rectangle.
idsComponentHandle[]id ∈ ids (restrict to a known set)

PluginEntityProperties

The common property record returned by getProperties — a partial object (a field is present only when it applies to the entity). Type-specific and geometry reads live on measure and design.query.geometry.*, keeping this record generic across every type.

PropertyTypeDescription
idstringThe entity id
typePluginEntityTypeEntity kind
labelstringroom_type ?? mesh label ?? ""
storeynumberStorey/floor level
buildingIdstringOwning building
structureIdstringOwning structure
massTypestringMass-type (masses only)
spaceTypePluginSpaceTypeSpace-type (spaces only)
areaClassPluginAreaClassArea classification (spaces only)
departmentIdstringDepartment (masses only)
buildingTypestringAssigned building type NAME (walls / slabs / floors / roofs / ceilings only) — the Object Properties panel's Wall/Slab/Floor/Roof/Ceiling Type dropdown value, matching the names from design.types.list(kind)
isLockedbooleanLock flag
isHiddenbooleanUser-hidden flag
isSelectedbooleanCurrent selection state
boundingBoxBBoxComponentsWorld-space AABB
adjacency{ spaceId: string, value: number }[]Adjacency relationships (spaces/masses only). value: 2 Direct (required), 1 Indirect or physical contact, -1 Restricted; 0 entries are filtered out. [] when adjacency has never been computed — see Adjacency.

PluginEntityMeasurements

The multi-metric bundle returned by measure. boundingBox is always present; the numeric metrics appear only when the entity's type computes them (area: floors/masses/slabs/roofs/beams/columns; volume: all; length: walls/beams). Values are in Snaptrude units — convert with snaptrude.core.units.convert(value, from, to).

thickness and height are the Object Properties panel's dimension reads — the same getMeshDimensions engine seam the panel and the design.update.wall / .slab / .floor / .roof / .ceiling write side use, in engine units. thickness is present for walls (the plan thickness — straight orthogonal walls only, exactly when the panel shows it) and for the slab family (the vertical extent the panel calls Thickness); height for walls only.

PropertyTypeDescription
areanumber (optional)Bottom-face area
volumenumber (optional)Solid volume
lengthnumber (optional)Running length (linear elements)
thicknessnumber (optional)Panel Thickness — walls (straight orthogonal only) and slabs/floors/roofs/ceilings
heightnumber (optional)Panel Height — walls only
boundingBoxBBoxComponentsWorld-space AABB (always present)

PluginStaircaseParams

The parametric fields of a staircase, returned by getStaircaseParams. Dimensions are in Snaptrude (engine) units — the same units the design.update.staircase write side takes. The three type-specific fields (wellSize / landingWidth / flightStartDistAfterTurn) are omitted when the preset doesn't use them.

PropertyTypeDescription
staircaseTypestringType token (straight, dogLegged, lShaped, …)
staircasePresetstringPreset token
staircaseHeightnumberTotal rise
stepsnumberStep count
risernumberRiser height
treadnumberTread depth
widthnumberFlight width
depthnumberFlight depth
baseOffsetnumberBase offset from the storey
isStoreyHeightUnlockedbooleanWhether height is decoupled from the storey
isStaircaseHeightUnlockedbooleanWhether height is decoupled from steps × riser
storeynumberStorey/floor level
wellSizenumber?Well size (well-based presets only)
landingWidthnumber?Landing width (landing-based presets only)
flightStartDistAfterTurnnumber?Flight start distance after a turn (turn presets only)

Functions

listEntities(filter?)

List all BIM entities in the project matching the filter.

  • Parameters:
  • Returns: ComponentHandle[] — Matching entities ([] if none)
ts
const doorsAndWindows = await snaptrude.design.query.listEntities({
  types: ["door", "window"],
  storeys: [0]
});

listByType(type, filter?)

List entities of a single PluginEntityType, plus filter.

  • Parameters:
    • type: PluginEntityType — The entity kind to list
    • filter: PluginEntityFilter (optional) — The shared entity filter
  • Returns: ComponentHandle[] — Matching entities
ts
const lockedSlabs = await snaptrude.design.query.listByType("slab", { isLocked: true });

listWalls(filter?)

List all walls, filtered. The types field of the filter is ignored (this method fixes the kind).

  • Parameters:
  • Returns: ComponentHandle[] — Wall handles
ts
const groundFloorWalls = await snaptrude.design.query.listWalls({ storeys: [0] });

listSpaces(filter?)

List all spaces (room masses), filtered. See listWalls.

ts
// Which spaces sit on a bigger floor-plate space? Exact plan intersection —
// fully-inside, boundary-nested, and partially-overhanging spaces all match;
// outside and merely edge-touching spaces don't, and the plate itself is excluded.
const [plate] = await snaptrude.design.query.listSpaces({ label: "Bigger floorplate" });
const onPlate = await snaptrude.design.query.listSpaces({ overlaps: plate });

listMasses(filter?)

List all generic masses (non-room masses), filtered.


listDoors(filter?)

List all doors, filtered.


listWindows(filter?)

List all windows, filtered.


listFloors(filter?)

List all floors, filtered.


listSlabs(filter?)

List all slabs, filtered.


listRoofs(filter?)

List all roofs, filtered.


listColumns(filter?)

List all columns, filtered.


listBeams(filter?)

List all beams, filtered.


listCeilings(filter?)

List all ceilings, filtered.


listStaircases(filter?)

List all staircases, filtered.


listFurniture(filter?)

List all furniture, filtered.


listReferenceLines(filter?)

List all reference lines, filtered.


listMullions(filter?)

List all curtain-wall mullions, filtered.


getById(id)

Look an entity up by id — returns the same handle if it still resolves live, else null. A cheap validity probe (distinct from exists).

  • Parameters:
    • id: ComponentHandle — The entity id to look up
  • Returns: ComponentHandle | null — The handle, or null if it no longer resolves

exists(id)

Test whether an entity id resolves to a live scene entity.

  • Parameters:
    • id: ComponentHandle — The entity id to test
  • Returns: booleantrue if it exists, otherwise false

getEntityType(component)

Get an entity's PluginEntityType.

  • Parameters:
    • component: ComponentHandle — The entity to read
  • Returns: PluginEntityType | null — The kind, or null if the entity is gone / its type is unknown

getLabel(component)

Get an entity's human label (room_type for spaces/masses, else the mesh label; "" when unlabelled). The write side is design.update (setLabel).

  • Parameters:
    • component: ComponentHandle — The entity to read
  • Returns: string — The label

getEntityRef(component)

Get a serializable, persistable reference to an entity. Under the all-handle model a ComponentHandle already IS the ref (raw Component.id), so this is the identity passthrough — provided for API completeness.

  • Parameters:
    • component: ComponentHandle — The entity
  • Returns: ComponentHandle — The entity's handle

listChildren(component)

List an entity's direct child entities.

  • Parameters:
    • component: ComponentHandle — The parent entity
  • Returns: ComponentHandle[] — Child handles ([] if none)

getHost(component)

Get an entity's host/parent entity (e.g. the wall a door is cut into).

  • Parameters:
    • component: ComponentHandle — The entity
  • Returns: ComponentHandle | null — The host, or null if top-level

getProperties(component)

Read an entity's common properties as a PluginEntityProperties record (only applicable fields are present). For spaces/masses this includes adjacency — the per-entity adjacency read (bulk form: program.adjacency.getMatrix). For walls and the slab family (slab/floor/roof/ceiling) this includes buildingType — the assigned building type NAME the panel's type dropdown shows, matching the names from design.types.list(kind).

  • Parameters:
    • component: ComponentHandle — The entity to read
  • Returns: PluginEntityProperties — The property record
ts
const [wall] = await snaptrude.design.query.listWalls();
const props = await snaptrude.design.query.getProperties(wall);
console.log(props.type, props.storey, props.buildingType);

measure(component)

Measure an entity — the multi-metric bundle (area/volume/length + bbox). For walls this also carries the panel's thickness (straight orthogonal walls only) and height; for the slab family (slab/floor/roof/ceiling) the panel's thickness — the read side of design.update.wall / .slab / .floor / .roof / .ceiling, in engine units.

  • Parameters:
    • component: ComponentHandle — The entity to measure
  • Returns: PluginEntityMeasurements | null — The metrics, or null if the entity is gone
ts
const [space] = await snaptrude.design.query.listSpaces();
const m = await snaptrude.design.query.measure(space);
console.log(m?.area, m?.volume);

const [wall] = await snaptrude.design.query.listWalls();
const wm = await snaptrude.design.query.measure(wall);
console.log(wm?.thickness, wm?.height); // the panel's Thickness / Height

getBoundingBox(components)

Get the union axis-aligned bounding box enclosing a set of entities.

  • Parameters:
    • components: ComponentHandle[] — The entities to enclose
  • Returns: BBoxComponents | null — The union box, or null if the set is empty / none resolve
ts
const walls = await snaptrude.design.query.listWalls();
const box = await snaptrude.design.query.getBoundingBox(walls);

getStaircaseParams(staircase)

Read the parametric fields of a staircase. The write counterpart is design.update.staircase; a read → write round-trips exactly.

  • Parameters:
    • staircase: ComponentHandle — The staircase to read
  • Returns: PluginStaircaseParams | nullnull when the handle is gone or is not a staircase
ts
const [stair] = await snaptrude.design.query.listStaircases();
const params = stair ? await snaptrude.design.query.getStaircaseParams(stair) : null;
console.log(params?.steps, params?.riser);

Geometry

Read the geometry of scene BIM entities. Accessed via snaptrude.design.query.geometry.

This is the bridge from the BIM/scene layer (design.*, keyed by ComponentHandle) into the geometry kernel (core.geom.query.*, keyed by value/topology handles). getBrep mints a BrepHandle for a component's boundary-representation mesh; getBottomContour mints a ContourHandle for its footprint outline; getCenterline mints a CurveHandle for a wall's core curve.

Returned handles are session-ephemeral and go stale on undo/redo/re-topologize — re-fetch a fresh one after edits.

Functions

getBrep(component)

Get the boundary-representation (BREP) mesh of a scene component.

  • Parameters:
    • component: ComponentHandle — The scene component to read
  • Returns: BrepHandle | null — The brep, or null if the component has no brep geometry
ts
const brep = await snaptrude.design.query.geometry.getBrep(component);
if (brep) {
  const faces = await snaptrude.core.geom.query.brep.listFaces(brep);
}

getBottomContour(component)

Get the bottom-face contour of a component — the footprint outline (outer profile + holes) of its lowest horizontal face, as a reusable ContourHandle.

Extracted from the component's B-rep; robust to inverted face normals. Read its geometry via snaptrude.core.geom.query.contour.*, or feed it back into design.create.* / core.geom.*.

  • Parameters:
    • component: ComponentHandle — The scene component to read
  • Returns: ContourHandle | null — The footprint contour, or null if the component has no extractable bottom face (e.g. it carries no B-rep)
ts
const [wall] = await snaptrude.design.query.listWalls();
const contour = await snaptrude.design.query.geometry.getBottomContour(wall);
if (contour) {
  const area = await snaptrude.core.geom.query.contour.getArea(contour);
}

getCenterline(component)

Get the centerline (core curve) of a wall — the single curve running down the middle of the wall, as a reusable CurveHandle (a Line for a straight wall, an Arc for a curved wall).

For a parametric wall this is its stored core curve; otherwise it is derived from the wall's B-rep bottom face. Read its geometry via snaptrude.core.geom.query.curve.*, or feed it into design.create.*.

Only walls have a centerline. As with all get* reads it never throws: a non-wall component, or a wall with no derivable centerline, yields null.

  • Parameters:
    • component: ComponentHandle — The scene component to read (only walls yield a centerline)
  • Returns: CurveHandle | null — The centerline curve, or null if the component is not a wall or the wall has no derivable centerline (e.g. it carries no B-rep or has an unsupported profile)
ts
const [wall] = await snaptrude.design.query.listWalls();
const centerline = await snaptrude.design.query.geometry.getCenterline(wall);
if (centerline) {
  const length = await snaptrude.core.geom.query.curve.getLength(centerline);
}

Spaces

Space-specific reads (a space is a room mass). Accessed via snaptrude.design.query.spaces.

Only the space queries feasible against the engine today are exposed here. getFloor / listBoundingWalls (space↔wall topology) are deferred — they need engine work that does not exist yet. listAdjacent stays deferred because the shipped surfaces already answer it with value semantics: per-space via the adjacency field of getProperties, in bulk via program.adjacency.getMatrix.

Functions

get(space, properties)

Get selected properties of a space — the selective multi-property read. Only the properties listed in properties are returned; unlisted properties are undefined in the result. This is the canonical home of the read formerly at entity.space.get (now removed). Adjacency is not part of this read — it is an entity property: read it via the adjacency field of getProperties.

  • Parameters:
    • space: ComponentHandle — The space (room mass) to read
    • properties: PluginDesignQuerySpacesGetProperty[] — Property names to retrieve (value tables below).
  • Returns: PluginDesignQuerySpacesGetResult — Partial record containing only the requested properties
  • Throws: If the space does not exist or the component is not a space/mass
ts
const [space] = await snaptrude.design.query.listSpaces();
const info = await snaptrude.design.query.spaces.get(space, ["name", "area", "position"]);
console.log(info.name, info.area, info.position);

Available properties (PluginDesignQuerySpacesGetProperty):

Basic:

ValueReturn TypeDescription
"id"stringUnique space identifier
"type"stringComponent type
"room_type"stringRoom type classification
"name"stringDisplay name of the space

Derived from parametric data:

ValueReturn TypeDescription
"area"numberBottom face area (from areas_bottomFace)
"breadth"numberBreadth dimension
"depth"numberDepth dimension
"height"numberHeight dimension
"massType"string | nullMass type classification
"spaceType"PluginSpaceType | nullSpace type classification (Room, Balcony, etc.)
"areaClass"PluginAreaClassEffective area classification ("NET", "GROSS", or "EXCLUDED"), resolving any per-space override then the space-type default. Never null.
"storey"number | nullStory the space belongs to
"departmentId"string | nullAssigned department ID
"departmentName"stringAssigned department name
"departmentColor"stringAssigned department color (hex/CSS)

Derived from mesh:

ValueReturn TypeDescription
"position"Vec3ComponentsLocal position relative to parent
"absolutePosition"Vec3ComponentsAbsolute position in the scene
"rotation"Vec3ComponentsEuler rotation angles (radians)
"rotationQuaternion"QuatComponents | nullQuaternion rotation, or null if unset

Derived from brep:

ValueReturn TypeDescription
"planPoints"Vec3Components[]Bottom outer profile points in world space with y = 0 (2D plan). No closing duplicate point.
"profile"CurveHandle[]Bottom outer profile curves in world space, as opaque curve handles. Read coordinates via the core.geom.curve read API.
"innerProfiles"CurveHandle[][]Inner (hole) profile curve loops in world space — one loop per hole, [] when the space has none. Each curve is an opaque handle.
"innerPlanPoints"Vec3Components[][]Inner (hole) profile points in world space with y = 0 — one loop per hole, no closing duplicate, [] when none.

getFootprint(space)

Get the footprint of a space — its bottom-face contour (outer profile + holes) as a reusable ContourHandle. Equivalent to getBottomContour narrowed to spaces.

  • Parameters:
    • space: ComponentHandle — The space (room mass) to read
  • Returns: ContourHandle | null — The footprint contour, or null if the space has no extractable footprint
ts
const [space] = await snaptrude.design.query.listSpaces();
const footprint = await snaptrude.design.query.spaces.getFootprint(space);

Errors

Failed calls reject with a typed PluginError — see Error Handling. Conditions specific to this namespace:

CodeThrown byWhendetails
HANDLE_INVALIDgetLabel, getEntityRef, listChildren, getHost, getProperties, geometry.*, spaces.getFootprintThe component handle cannot be resolved
HANDLE_INVALIDall list*filter.overlaps names an unresolvable id — this fails loudly rather than silently returning []
HANDLE_INVALIDspaces.getThe id does not resolve to a live space/mass (not-found and wrong-kind collapse to the one code)
PRECONDITION_FAILEDspaces.getA brep-derived property (planPoints, innerPlanPoints) is requested on a space without B-rep geometry; or the not-yet-wired profile/innerProfiles properties are requestedproperty — the offending property, handles — the space

The probe-style reads are deliberately total: getById/getEntityType/measure return null and exists returns false for a gone id, getBoundingBox skips unresolvable members (null only when none resolve), and the geometry.* / getFootprint reads return null for a resolvable component that lacks the requested geometry (no B-rep, no bottom face, no derivable centerline) — none of these throw.