The owning project's express id, or undefined when the file has
zero or one IFCPROJECT (nothing to resolve) or the walk can't reach one
(e.g. a resource-level entity with no containment, a cyclic/malformed
graph). Callers should fall back to the file's default project on
undefined, matching prior single-project behaviour.
Resolve the express id of the
IFCPROJECTthat ownsexpressId, for files that legitimately contain more than oneIFCPROJECT— the shapeMergedExporter's documentedautounit-reconciliation mode produces for a federated merge of differently-unit'd models (see issue #1332). An ordinary IFC file has exactly oneIFCPROJECTby EXPRESS invariant, so this is a no-op fast path there.extractLengthUnitScale/extractProjectUnitsresolve the file's FIRSTIFCPROJECTonly unless given an explicitprojectId; every entity belonging to a LATER project in a multi-project file was silently read against the first project's units. Callers needing per-entity correctness (both resolveEntityLengthUnitScale in unit-extractor.ts and@ifc-lite/ids's area/volume resolution, which needs the project id itself rather than just a length scale) resolve this id first and pass it on toextractLengthUnitScale/extractProjectUnits'sprojectIdparameter.Walks the entity's real spatial containment up to its own project:
IfcRelContainedInSpatialStructure(element → structure), thenIfcRelAggregates(child → parent, repeated to the project), with anIfcRelDefinesByType(type → one of the objects it defines) hop for a type entity that has no containment of its own. Containment is tried first since it's the one-hop case for the common "element straight into its storey" shape.