IFClite TypeScript API
    Preparing search index...

    Interface EntityFingerprint<TRef>

    One entity's identity + fingerprints within a single model, as supplied by a store adapter. The engine is store-agnostic: adapters extract these, the engine matches and classifies.

    interface EntityFingerprint<TRef = unknown> {
        aabb?: EntityAabb;
        components?: Record<string, string>;
        container?: string;
        dataHash: string;
        geometryHash?: GeometryHash;
        ifcType: string;
        key: string;
        ref: TRef;
        volume?: number;
    }

    Type Parameters

    • TRef = unknown

      opaque, adapter-defined handle used to locate the entity downstream (e.g. a local express id or a federated global id). It is never inspected by the engine — it flows straight through to DiffEntry.

    Index
    aabb?: EntityAabb

    Optional world-space bounding box, in the caller's units and frame (see EntityAabb). Used only by the content-keyed matching pass (DiffOptions.matchUnpairedByContent), where it separates a move from a reshape and lets a group of same-content entities be paired by position. Absent on either side, that pass falls back to reporting a geometry-hash difference as a bare moved.

    components?: Record<string, string>

    Opt-in per-componentKey sub-hashes (attr:core, pset:<Name>, qset:<Name>, type-assignment). Build with buildComponentFingerprints. When both sides of a diff carry them, DiffEntry.changedComponents reports which components differ.

    container?: string

    Optional spatial container of the entity as a stable NAME path — the names of the spatial structure elements from the project down to the containing storey or space, joined by / (Project/Building/Level 2/ Room 204). Never GlobalIds: a from-scratch re-export re-GUIDs the storeys too. Both revisions must be resolved by the same adapter so the paths agree.

    Consumed two ways:

    • the successor stage's position profile (DiffOptions.detectSuccessors), which pairs two entities only when both carry a non-empty container and they are equal;
    • the key-matched pass in diffModels, which reports a 'container' DiffChangeKind when both sides carry a non-empty container and they differ (issue #5214). Either way, absent on either side is not evidence and is skipped rather than counted as a change — a container this adapter could not resolve is not proof the entity moved.
    dataHash: string

    Canonical hash of the entity's data (attributes + property sets + quantity sets + type assignments). Build with buildDataFingerprint.

    geometryHash?: GeometryHash

    Geometry fingerprint, or undefined when the entity has no geometry.

    A one-sided undefined on a matched entity is a geometry change (geometry added or removed) — unless one whole revision carries no geometry hashes at all while the other does, which is a capability difference between two fingerprinting runs rather than a model change. Geometry then classifies nothing, in both matching passes; see DiffScope.

    ifcType: string

    IFC type name, compared verbatim (keep both sides in one casing).

    key: string

    Stable cross-revision identity. Typically the IFC GlobalId.

    ref: TRef

    Adapter handle passed through to the diff entry.

    volume?: number

    Optional enclosed volume of the entity's geometry, in the caller's units cubed and — like aabb — measured by the same pipeline on both revisions. Used only by the split/merge detector (DiffOptions.detectSplitMerge).

    Absent means NOT PROVED, never zero and never "differs". The producer this contract was written against (MeshCollection.geometryVolumeValues) emits a value only where the meshed geometry was provably a single closed, orientable, single-component solid; an open shell, a material-layered wall or a multi-item assembly correctly reports nothing. Roughly a third of a real model's elements carry no volume, by design.

    The engine treats that asymmetrically, which is the whole reason the field can be sparse and still be useful: a volume is required to be COMPLETE before it can confirm a claim, but a PARTIAL sum can already refute one — if the volumes we do know already exceed the whole, the unknowns cannot bring the total back down.

    A NaN, a zero or a negative value here is not a volume and the engine ignores it exactly as if the field were absent. Resolve your producer's absent-sentinel at the boundary rather than passing one through.