Skip to content

Releases: LTplus-AG/ifc-lite

@ifc-lite/wasm@2.9.1

17 Jun 14:14
730490b

Choose a tag to compare

Patch Changes

  • #1131 b7353ab Thanks @louistrue! - Content-affinity worker routing for boolean-heavy models. The streaming geometry
    pre-pass now tags each job with an affinity key — the exact 128-bit hash of the
    element's representation geometry — and the parallel dispatcher routes all jobs
    sharing a key to the same worker. Combined with the per-worker geometry-dedup
    cache, each unique geometry is meshed once per model instead of once per
    worker, so the workers partition the unique meshing instead of replicating it.
    Restores fast loads on models exported without IfcMappedItem (e.g.
    structural-steel detailers that emit thousands of byte-identical parts): a 19.5 MB
    steel model drops from ~32 s to ≈ the dedup floor split across the worker pool.
    Falls back to the previous interleaved split when no affinity data is present.

@ifc-lite/viewer@1.30.2

17 Jun 15:14
656da68

Choose a tag to compare

Patch Changes

  • #1159 39e0f82 Thanks @louistrue! - Add a ?geomWorkers=N override for the geometry worker pool, and document the
    per-tier worker caps as a memory-bandwidth ceiling.

    The parallel geometry pool picks a worker count from a cores/memory heuristic.
    A ?geomWorkers=N A/B sweep on a large (722 MB) georef model showed that, with
    the pure-Rust exact CSG kernel, geometry wall-time is bound by memory
    bandwidth
    , not CPU cores: 3→4→5 workers gave no geometry speedup (flat
    wall-time, higher peak memory) and progressively starved the co-running parser.
    So the existing caps are correct for this class of file and are left unchanged —
    only their rationale is updated in comments.

    The override (?geomWorkers=N, persisted to localStorage so it survives the
    reload a re-measure needs; ?geomWorkers=0/auto clears it) lets a user measure
    their own host's optimum, since the bandwidth ceiling is hardware-specific. It is
    threaded to computeWorkerCount, which honours it but still clamps to the memory
    budget, so the knob can never OOM the tab. Geometry output is byte-identical
    across worker counts (verified in the wild: identical mesh count at 3 and 4
    workers) — the count only repartitions which worker meshes which disjoint,
    deterministic element slice.

  • Updated dependencies [39e0f82, 2556677]:

    • @ifc-lite/geometry@2.7.5

@ifc-lite/viewer@1.30.1

17 Jun 14:14
730490b

Choose a tag to compare

Patch Changes

  • #1136 98457b8 Thanks @louistrue! - Show IfcElementAssembly / IfcStair parts in the spatial tree and make assemblies
    selectable (#1133). A decomposing assembly carries no geometry of its own — its
    stair flights, railings, landing slabs and virtual clearance volumes hang off it
    via IfcRelAggregates and hold the meshes — so the spatial panel previously
    listed the assembly as a childless leaf, the parts were unreachable, and
    clicking the assembly highlighted nothing. The hierarchy now nests an
    assembly's aggregated parts beneath it (recursively, cycle-guarded), clicking
    the assembly highlights and frames the whole thing, soloing a storey keeps the
    parts (they inherit the storey through the assembly), and IfcVirtualElement
    clearance volumes are hidden by default with a new "Virtual Elements"
    visibility toggle.
  • Updated dependencies [61bad47, bfd9004, 69e5425, 81a6cdf, ca8a856, bd585c7, 248f2c0, 200681b, ef8343b, ddae2b0]:
    • @ifc-lite/mutations@1.15.5
    • @ifc-lite/data@2.1.0
    • @ifc-lite/parser@3.3.0
    • @ifc-lite/geometry@2.7.3
    • @ifc-lite/renderer@1.28.2
    • @ifc-lite/sdk@1.19.0
    • @ifc-lite/sandbox@1.16.0
    • @ifc-lite/export@1.20.0
    • @ifc-lite/lens@1.15.3
    • @ifc-lite/lists@1.15.4
    • @ifc-lite/cache@2.0.4
    • @ifc-lite/ids@1.15.12

@ifc-lite/sdk@1.19.0

17 Jun 14:14
730490b

Choose a tag to compare

Minor Changes

  • #1152 ca8a856 Thanks @louistrue! - Add bim.query.matchingActiveFilter() — returns the entities matching the host's active advanced filter (or null when no filter is set). Backed by a new QueryBackendMethods.entitiesMatchingActiveFilter(). Lets scripted exports (e.g. the CSV quantity take-off) honour the current filtered view instead of always exporting the whole model (issue #1107).

Patch Changes

  • Updated dependencies [61bad47, bfd9004, 248f2c0, ddae2b0]:
    • @ifc-lite/mutations@1.15.5
    • @ifc-lite/data@2.1.0
    • @ifc-lite/parser@3.3.0
    • @ifc-lite/export@1.20.0
    • @ifc-lite/lens@1.15.3
    • @ifc-lite/lists@1.15.4
    • @ifc-lite/ids@1.15.12

@ifc-lite/sandbox@1.16.0

17 Jun 14:14
730490b

Choose a tag to compare

Minor Changes

  • #1152 ca8a856 Thanks @louistrue! - Add bim.query.matchingActiveFilter() — returns the entities matching the host's active advanced filter (or null when no filter is set). Backed by a new QueryBackendMethods.entitiesMatchingActiveFilter(). Lets scripted exports (e.g. the CSV quantity take-off) honour the current filtered view instead of always exporting the whole model (issue #1107).

Patch Changes

  • Updated dependencies [ca8a856]:
    • @ifc-lite/sdk@1.19.0

@ifc-lite/renderer@1.28.3

17 Jun 18:12
2e8ea66

Choose a tag to compare

Patch Changes

  • #1160 631511e Thanks @louistrue! - Restore per-layer slicing of single-solid walls/slabs with an IfcMaterialLayerSetUsage. Slicing turns one solid into one coloured sub-mesh per material layer (geometry_id = the layer's IfcMaterial) so the build-up is visible in 3D. The "Merge Multilayer Walls" toggle now does what its label promises for these walls too — "render walls as one solid": with the toggle on, the layer index is not attached, so each wall stays a single swept solid instead of slicing into layers (off, the default, shows the layered build-up).

    The slicing kernel stayed intact, but #874 (mesh-production unification) dropped the set_material_layer_index wiring from every pipeline, so the router's index was always None and try_layered_sub_meshes never fired — layered walls silently rendered as a plain single solid in the browser, native, and server paths. Re-wire it: build the MaterialLayerIndex once per load (cached on the IfcAPI for the streaming path, with a cheap substring bail-out so files with no layer set pay nothing) and attach it to every batch router. This also restores the "Merge Multilayer Walls" toggle for models whose sliceable walls carry their geometry as IfcBuildingElementParts — the merged parent now actually draws its sliced solid instead of leaving a gap.

    2D section now shows the layers too. The section cutter carries each sub-mesh's colour onto its cut segments (CPU and GPU paths), and the polygon builder splits one entity's cut into a polygon per material colour — single-material elements still produce one colourless polygon, so their existing per-ifcType / per-entity fill is unchanged. When the viewer shows IFC materials, each sliced layer fills with its own IfcMaterial colour instead of one colour for the whole wall, and the layer divisions are drawn as outlines — matching the 3D build-up.

    Two follow-on robustness fixes:

    • 3D layer glitch (z-fighting). Adjacent layer slabs share the parent wall's expressId, so the renderer's per-entity depth nudge (keyed on entityId) gave their coincident interior interface caps the SAME depth — under cullMode: 'none' + MSAA that z-fought into a flickering comb that read as "see inside / not solid". The shader now folds the per-draw baseColor into the depth-nudge hash; batches are keyed by colour, so abutting layers (distinct colours) land on distinct depths. Constant per draw, so flat faces stay flat and curved surfaces are unaffected.

    • Cap watertightness on irregular profiles. A layer slab's innermost cut is built by two successive plane clips; on a non-convex IfcArbitraryClosedProfileDef the two passes deposit geometrically-coincident section vertices that differ by ~1 ULP. cap_half_space_clip welded by exact f32 bits, so those twins stayed separate, the boundary chain dead-ended and a cap sub-loop was silently dropped — leaving open edges (a hole you could see through and a section with no fill there). The cap now welds on a spatial grid tied to its on-plane tolerance, collapsing the twins so the loop closes. Single-plane callers (opening cuts) have no such twins and are unaffected.

    • 3D section cut read hollow. The live 3D section cap (Section2DOverlayRenderer) filled each cut polygon with a naive convex fan over the outer ring only, ignoring holes — a long-standing KNOWN LIMITATION. On the concave cross-sections that arbitrary IFC profiles (and material-layer slabs) cut into, the fan inverts and leaves the cut face uncovered, so a sectioned wall read as a hollow shell. The fill now uses the renderer's existing hole-aware ear-clipping (the same one the annotation-fill path uses), so the cut face is solid. The cap also now honours a per-polygon colour: a material-layer wall fills each layer of its 3D section cut with that layer's IfcMaterial colour (matching the 3D solids and the 2D section), while single-material cuts keep the uniform cap style + hatch unchanged via a sentinel.

    • Solid layered 3D walls via backface culling. Rendering a material-layer wall as N thin coincident-faced layer solids made it shimmer / read as a hollow shell — adjacent layers' interface caps z-fight under the viewer's double-sided rendering (culling is globally off because general IFC winding is unreliable), and same-material adjacent layers can't be depth-separated. The layer slices DO have reliable outward winding, though, so they're now tagged geometryClass 3 and the renderer draws that class with a dedicated backface-culling pipeline: the build-up stays visible on the wall's faces and edges, but the interior coincident caps never rasterise, so the wall reads as a clean solid (and a section cut through it shows the interior material surface rather than a hollow shell). The 2D/section cut consumes the same class — it never culls — for its per-layer fills. Cache FORMAT_VERSION → 9 so stale caches re-mesh with the class-3 slices.

  • Updated dependencies [631511e]:

    • @ifc-lite/geometry@2.7.6

@ifc-lite/renderer@1.28.2

17 Jun 14:14
730490b

Choose a tag to compare

Patch Changes

  • #1148 81a6cdf Thanks @louistrue! - Add Camera.getSceneBounds() — an O(1) accessor for the cached scene bounds (the value last passed to setSceneBounds). The viewer uses it to anchor the orbit pivot to the scene centre on a raycast miss / large model, instead of the drifting camera target which made repeated rotation feel untethered (issue #1107).

  • #1161 ef8343b Thanks @louistrue! - Keep internal edges/facets visible on selected objects.

    The selection highlight painted every fragment a single flat blue (color = vec3(0.3, 0.6, 1.0)), discarding all lighting. Because the viewer's "internal lines" are really the per-face shading step of flat-shaded facets, that flat fill collapsed a selected object into one featureless silhouette — creases and bends disappeared the moment it was highlighted (the faint screen-space edge line alone could not stand in for the lost face-shading cue).

    The highlight now re-lights a selection-blue albedo with the scene's own lighting term instead of overwriting it. The base material colour never enters the result (no green-site / red-roof bleed-through, the reason the flat override existed), but the per-face brightness variation is preserved, so internal edges read on the highlight exactly as they do unselected. A multiplicative gain on the lighting luminance keeps sunlit faces at full selection-blue, with a floor/ceiling clamp so shadowed faces only dim and bright scenes never wash out.

  • Updated dependencies [69e5425, bd585c7, 200681b]:

    • @ifc-lite/geometry@2.7.3

@ifc-lite/parser@3.3.0

17 Jun 14:14
730490b

Choose a tag to compare

Minor Changes

  • #1143 248f2c0 Thanks @louistrue! - Preserve source IFC HEADER fields on round-trip export. Re-exporting an
    imported file previously regenerated a fresh ifc-lite header, silently dropping
    the source FILE_DESCRIPTION items (any ViewDefinition [...] label and vendor
    identifier / coordinate-reference strings) and flattening the exact
    FILE_SCHEMA token (e.g. IFC4X3_ADD2IFC4X3, which some toolchains
    reject).

    The parser now captures the verbatim HEADER onto a new
    IfcDataStore.sourceHeader (IfcSourceHeader, exported from @ifc-lite/data;
    parser also exports parseSourceHeader), threaded through the worker transport.
    StepExporter reproduces the source FILE_DESCRIPTION items and the exact
    FILE_SCHEMA token when not converting schemas, falling back to parsing the
    source bytes for cache-restored stores. Provenance stays honest:
    preprocessor_version is set to ifc-lite while the source authoring tool is
    kept as originating_system, and when mutations exist exactly one
    Re-exported by ifc-lite, N modification(s) item is appended without removing
    the source items. generateHeader now accepts description/author/organization
    arrays plus a free-form schema token and STEP-escapes all fields; it also emits
    a properly parenthesised FILE_DESCRIPTION list (the prior single-string form
    was malformed STEP). Created-from-scratch (IfcCreator) and federated/merged
    exports are unaffected — they keep their own provenance headers by design.

Patch Changes

  • #1151 bfd9004 Thanks @louistrue! - De-duplicate the STEP serializer into a single source of truth. The
    schema-agnostic STEP serialization logic (serializeValue, generateHeader,
    parseStepValue, ref/enumVal/isEntityRef/isEnumValue, and the
    registry-injected toStepLineWithRegistry / generateStepFileWithRegistry)
    previously existed as four hand-synced copies — the codegen template plus three
    generated serializers.ts files — which had already silently drifted (the
    runtime copy carried a ?? [] hardening the template lacked). It now lives once
    in @ifc-lite/data; the per-schema bundles (parser runtime + codegen outputs)
    are thin re-exports that only bind their own SCHEMA_REGISTRY to the
    registry-coupled helpers, so the copies can never diverge again. A codegen test
    asserts the generated bundle stays a thin re-export rather than re-inlining
    logic.

    Also fixes the broken generate:ifc4 script (it pointed at a non-existent
    schemas/IFC4.exp; the real file is schemas/IFC4_ADD2_TC1.exp). No public
    behaviour change: @ifc-lite/parser re-exports the same serializer symbols as
    before; @ifc-lite/data gains the shared primitives; @ifc-lite/codegen now
    declares @ifc-lite/data as a dependency since the generated bundle imports it.

  • #1145 ddae2b0 Thanks @louistrue! - Resolve names for IfcGroup-family entities and make zones/systems listable (#1075 follow-up).

    IfcZone, IfcGroup, IfcSystem and IfcDistributionSystem are not IfcProduct subtypes, so the columnar parser categorised them as CAT_SKIP and never added them to the EntityTable. As a result getName() returned '' (the UI showed "Group #"), getByType() could not find them (so they were absent from lists), and the "By Zone" lens fell back to an arbitrary first group because getTypeName() returned Unknown. IfcSpatialZone was in the table but its Name was never extracted.

    This routes the group family into the EntityTable with Name (falling back to LongName for systems/zones that leave Name empty) plus Description and ObjectType (the system designation), and extracts names for the previously-unnamed "other relevant" products (including IfcSpatialZone). New IfcSystem / IfcDistributionSystem IfcTypeEnum entries make systems addressable by getByType. Zones, spatial zones and systems are now selectable in the list builder and ship a "Zones & Systems" preset, the relationship card and "By Zone" lens legend show real names (with an ObjectType fallback for unnamed systems), and selecting a group surfaces its attributes.

    The cache FORMAT_VERSION is bumped (6 → 7) so models cached before the fix re-parse and pick up the resolved names.

  • Updated dependencies [bfd9004, 248f2c0, ddae2b0]:

    • @ifc-lite/data@2.1.0

@ifc-lite/mutations@1.15.5

17 Jun 14:14
730490b

Choose a tag to compare

Patch Changes

  • #1149 61bad47 Thanks @louistrue! - Treat a null/unset property value as present, not absent. A property may legitimately exist with no value (e.g. an IFC boolean added from bSDD, which now starts unset rather than defaulting to false), so MutablePropertyView no longer reads value === null as "property does not exist":

    • deleteProperty keys absence off existence (in-session pset membership), so an unset property is still deletable instead of the trash button being a silent no-op.
    • setProperty classifies a write as UPDATE_PROPERTY vs CREATE_PROPERTY by whether the property already existed (not by null value), so undoing an edit to an unset property restores its prior unset state instead of deleting the whole property.
  • Updated dependencies [bfd9004, 248f2c0, ddae2b0]:

    • @ifc-lite/data@2.1.0

@ifc-lite/lists@1.15.4

17 Jun 14:14
730490b

Choose a tag to compare

Patch Changes

  • #1145 ddae2b0 Thanks @louistrue! - Resolve names for IfcGroup-family entities and make zones/systems listable (#1075 follow-up).

    IfcZone, IfcGroup, IfcSystem and IfcDistributionSystem are not IfcProduct subtypes, so the columnar parser categorised them as CAT_SKIP and never added them to the EntityTable. As a result getName() returned '' (the UI showed "Group #"), getByType() could not find them (so they were absent from lists), and the "By Zone" lens fell back to an arbitrary first group because getTypeName() returned Unknown. IfcSpatialZone was in the table but its Name was never extracted.

    This routes the group family into the EntityTable with Name (falling back to LongName for systems/zones that leave Name empty) plus Description and ObjectType (the system designation), and extracts names for the previously-unnamed "other relevant" products (including IfcSpatialZone). New IfcSystem / IfcDistributionSystem IfcTypeEnum entries make systems addressable by getByType. Zones, spatial zones and systems are now selectable in the list builder and ship a "Zones & Systems" preset, the relationship card and "By Zone" lens legend show real names (with an ObjectType fallback for unnamed systems), and selecting a group surfaces its attributes.

    The cache FORMAT_VERSION is bumped (6 → 7) so models cached before the fix re-parse and pick up the resolved names.

  • Updated dependencies [bfd9004, 248f2c0, ddae2b0]:

    • @ifc-lite/data@2.1.0