@ifc-lite/parser 3.3.1 → 3.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,24 +1,54 @@
1
1
  /**
2
- * Spatial hierarchy builder - builds project/building/storey tree
2
+ * Spatial hierarchy builder - builds the project/site/building/storey tree.
3
+ *
4
+ * Single source for spatial-hierarchy construction. There are two entry points
5
+ * over one shared `buildNode`:
6
+ * - `build(...)` fresh parse: extracts storey elevations from the source
7
+ * buffer. Throws if there is no IfcProject.
8
+ * - `buildFromCache` cache restore: no source buffer, so storey elevations
9
+ * stay empty. Returns undefined if there is no IfcProject.
10
+ * Both paths get the same cycle guard, aggregate-descendant storey mapping, and
11
+ * spatial-child promotion, so they cannot drift.
3
12
  */
4
13
  import type { EntityTable, StringTable, RelationshipGraph, SpatialHierarchy } from '@ifc-lite/data';
5
14
  import type { EntityRef } from './types.js';
6
15
  export declare class SpatialHierarchyBuilder {
7
16
  /**
8
- * Build spatial hierarchy from entities and relationships
17
+ * Fresh-parse build. Extracts storey elevations from the source buffer.
18
+ * Throws if no IfcProject is present.
9
19
  *
10
- * @param lengthUnitScale - Scale factor to convert IFC length values to meters (e.g., 0.001 for millimeters)
20
+ * @param lengthUnitScale - Scale to convert IFC length values to meters (e.g. 0.001 for millimeters).
11
21
  */
12
- build(entities: EntityTable, relationships: RelationshipGraph, strings: StringTable, source: Uint8Array, entityIndex: {
22
+ build(entities: EntityTable, relationships: RelationshipGraph, _strings: StringTable, source: Uint8Array, entityIndex: {
13
23
  byId: {
14
24
  get(expressId: number): EntityRef | undefined;
15
25
  };
16
26
  }, lengthUnitScale?: number): SpatialHierarchy;
27
+ /**
28
+ * Cache-restore build. No source buffer, so storey elevations stay empty
29
+ * (`getStoreyByElevation` returns null). Returns undefined if no IfcProject.
30
+ */
31
+ buildFromCache(entities: EntityTable, relationships: RelationshipGraph): SpatialHierarchy | undefined;
32
+ private assemble;
17
33
  private buildNode;
18
34
  /**
19
- * Extract elevation from IfcBuildingStorey entity
20
- * Elevation is at attribute index 9 in IFC4 (after GlobalId, OwnerHistory, Name, Description, ObjectType, ObjectPlacement, Representation, LongName, CompositionType)
35
+ * Extract elevation from an IfcBuildingStorey. Elevation is attribute index 9
36
+ * in both IFC2x3 and IFC4 (GlobalId, OwnerHistory, Name, Description,
37
+ * ObjectType, ObjectPlacement, Representation, LongName, CompositionType,
38
+ * Elevation).
21
39
  */
22
40
  private extractElevation;
41
+ /**
42
+ * Resolve a storey's elevation from its ObjectPlacement, used as a fallback when
43
+ * the Elevation attribute is null. Walks
44
+ * IfcBuildingStorey.ObjectPlacement (IfcLocalPlacement)
45
+ * -> RelativePlacement (IfcAxis2Placement3D)
46
+ * -> Location (IfcCartesianPoint).Coordinates[2]
47
+ * i.e. the storey's Z relative to its parent spatial container, which matches
48
+ * the semantics of the Elevation attribute and avoids folding in any site-level
49
+ * georeferencing Z. Returns the raw (unscaled) Z, or undefined when the chain
50
+ * can't be resolved.
51
+ */
52
+ private extractPlacementElevation;
23
53
  }
24
54
  //# sourceMappingURL=spatial-hierarchy-builder.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"spatial-hierarchy-builder.d.ts","sourceRoot":"","sources":["../src/spatial-hierarchy-builder.ts"],"names":[],"mappings":"AAIA;;GAEG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,iBAAiB,EAAE,gBAAgB,EAAe,MAAM,gBAAgB,CAAC;AAUjH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAK5C,qBAAa,uBAAuB;IAClC;;;;OAIG;IACH,KAAK,CACH,QAAQ,EAAE,WAAW,EACrB,aAAa,EAAE,iBAAiB,EAChC,OAAO,EAAE,WAAW,EACpB,MAAM,EAAE,UAAU,EAClB,WAAW,EAAE;QAAE,IAAI,EAAE;YAAE,GAAG,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS,CAAA;SAAE,CAAA;KAAE,EACxE,eAAe,GAAE,MAAY,GAC5B,gBAAgB;IA6HnB,OAAO,CAAC,SAAS;IAuJjB;;;OAGG;IACH,OAAO,CAAC,gBAAgB;CAsDzB"}
1
+ {"version":3,"file":"spatial-hierarchy-builder.d.ts","sourceRoot":"","sources":["../src/spatial-hierarchy-builder.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,iBAAiB,EAAE,gBAAgB,EAAe,MAAM,gBAAgB,CAAC;AAUjH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AA0B5C,qBAAa,uBAAuB;IAClC;;;;;OAKG;IACH,KAAK,CACH,QAAQ,EAAE,WAAW,EACrB,aAAa,EAAE,iBAAiB,EAChC,QAAQ,EAAE,WAAW,EACrB,MAAM,EAAE,UAAU,EAClB,WAAW,EAAE;QAAE,IAAI,EAAE;YAAE,GAAG,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS,CAAA;SAAE,CAAA;KAAE,EACxE,eAAe,GAAE,MAAY,GAC5B,gBAAgB;IAMnB;;;OAGG;IACH,cAAc,CACZ,QAAQ,EAAE,WAAW,EACrB,aAAa,EAAE,iBAAiB,GAC/B,gBAAgB,GAAG,SAAS;IAI/B,OAAO,CAAC,QAAQ;IAwGhB,OAAO,CAAC,SAAS;IAqHjB;;;;;OAKG;IACH,OAAO,CAAC,gBAAgB;IA2CxB;;;;;;;;;;OAUG;IACH,OAAO,CAAC,yBAAyB;CA0ClC"}
@@ -6,54 +6,74 @@ import { EntityExtractor } from './entity-extractor.js';
6
6
  const log = createLogger('SpatialHierarchy');
7
7
  export class SpatialHierarchyBuilder {
8
8
  /**
9
- * Build spatial hierarchy from entities and relationships
9
+ * Fresh-parse build. Extracts storey elevations from the source buffer.
10
+ * Throws if no IfcProject is present.
10
11
  *
11
- * @param lengthUnitScale - Scale factor to convert IFC length values to meters (e.g., 0.001 for millimeters)
12
+ * @param lengthUnitScale - Scale to convert IFC length values to meters (e.g. 0.001 for millimeters).
12
13
  */
13
- build(entities, relationships, strings, source, entityIndex, lengthUnitScale = 1.0) {
14
- const byStorey = new Map();
15
- const byBuilding = new Map();
16
- const bySite = new Map();
17
- const bySpace = new Map();
18
- const storeyElevations = new Map();
19
- const storeyHeights = new Map();
20
- const elementToStorey = new Map();
21
- // PRE-BUILD INDEX MAP: O(n) once, then O(1) lookups
22
- // This eliminates O(n²) when getTypeEnum is called for every spatial node
23
- const entityTypeMap = new Map();
24
- for (let i = 0; i < entities.count; i++) {
25
- entityTypeMap.set(entities.expressId[i], entities.typeEnum[i]);
26
- }
27
- // Find IfcProject (should be only one)
14
+ build(entities, relationships, _strings, source, entityIndex, lengthUnitScale = 1.0) {
15
+ const hierarchy = this.assemble(entities, relationships, { source, entityIndex, lengthUnitScale }, true);
16
+ // assemble only returns undefined when throwOnNoProject is false.
17
+ return hierarchy;
18
+ }
19
+ /**
20
+ * Cache-restore build. No source buffer, so storey elevations stay empty
21
+ * (`getStoreyByElevation` returns null). Returns undefined if no IfcProject.
22
+ */
23
+ buildFromCache(entities, relationships) {
24
+ return this.assemble(entities, relationships, undefined, false);
25
+ }
26
+ assemble(entities, relationships, elevation, throwOnNoProject) {
27
+ const ctx = {
28
+ entities,
29
+ relationships,
30
+ byStorey: new Map(),
31
+ byBuilding: new Map(),
32
+ bySite: new Map(),
33
+ bySpace: new Map(),
34
+ storeyElevations: new Map(),
35
+ elementToStorey: new Map(),
36
+ visited: new Set(),
37
+ elevation,
38
+ };
28
39
  const projectIds = entities.getByType(IfcTypeEnum.IfcProject);
29
40
  if (projectIds.length === 0) {
30
41
  console.warn('[SpatialHierarchyBuilder] No IfcProject found in IFC file');
31
- throw new Error('No IfcProject found in IFC file');
42
+ if (throwOnNoProject) {
43
+ throw new Error('No IfcProject found in IFC file');
44
+ }
45
+ return undefined;
32
46
  }
33
- const projectId = projectIds[0];
34
- // Build project node
35
- const projectNode = this.buildNode(projectId, entities, relationships, strings, source, entityIndex, byStorey, byBuilding, bySite, bySpace, storeyElevations, elementToStorey, entityTypeMap, lengthUnitScale, new Set());
36
- // Note: storeyHeights remains empty for client path - uses on-demand property extraction
37
- // Validation: log warnings if maps are empty
38
- if (byStorey.size === 0) {
47
+ const projectNode = this.buildNode(projectIds[0], ctx);
48
+ if (ctx.byStorey.size === 0) {
39
49
  console.warn('[SpatialHierarchyBuilder] No storeys found in spatial hierarchy');
40
50
  }
41
- if (byBuilding.size === 0) {
51
+ if (ctx.byBuilding.size === 0) {
42
52
  console.warn('[SpatialHierarchyBuilder] No buildings found in spatial hierarchy');
43
53
  }
44
- const hierarchy = {
54
+ const { byStorey, byBuilding, bySite, bySpace, storeyElevations, elementToStorey } = ctx;
55
+ // Pre-build the element -> space lookup for O(1) getContainingSpace.
56
+ const elementToSpace = new Map();
57
+ for (const [spaceId, elementIds] of bySpace) {
58
+ for (const elementId of elementIds) {
59
+ elementToSpace.set(elementId, spaceId);
60
+ }
61
+ }
62
+ return {
45
63
  project: projectNode,
46
64
  byStorey,
47
65
  byBuilding,
48
66
  bySite,
49
67
  bySpace,
50
68
  storeyElevations,
51
- storeyHeights,
69
+ // storeyHeights stays empty: both paths use on-demand property extraction.
70
+ storeyHeights: new Map(),
52
71
  elementToStorey,
53
72
  getStoreyElements(storeyId) {
54
73
  return byStorey.get(storeyId) ?? [];
55
74
  },
56
75
  getStoreyByElevation(z) {
76
+ // With an empty storeyElevations map (cache path) this returns null.
57
77
  let closestStorey = null;
58
78
  let closestDistance = Infinity;
59
79
  for (const [storeyId, elevation] of storeyElevations) {
@@ -63,34 +83,26 @@ export class SpatialHierarchyBuilder {
63
83
  closestStorey = storeyId;
64
84
  }
65
85
  }
66
- // Only return if within reasonable distance (1 meter)
86
+ // Only return if within a reasonable distance (1 meter).
67
87
  return closestDistance < 1.0 ? closestStorey : null;
68
88
  },
69
89
  getContainingSpace(elementId) {
70
- // Check if element is directly contained in a space
71
- for (const [spaceId, elementIds] of bySpace) {
72
- if (elementIds.includes(elementId)) {
73
- return spaceId;
74
- }
75
- }
76
- return null;
90
+ return elementToSpace.get(elementId) ?? null;
77
91
  },
78
92
  getPath(elementId) {
79
93
  const path = [];
80
- // Build path from project to element
81
94
  const findPath = (node, targetId) => {
82
95
  path.push(node);
83
- // Check if this node contains the target
84
- if (node.elements.includes(targetId)) {
96
+ // Match the node itself (so a promoted space/zone resolves) or one of
97
+ // its contained elements.
98
+ if (node.expressId === targetId || node.elements.includes(targetId)) {
85
99
  return true;
86
100
  }
87
- // Recursively search children
88
101
  for (const child of node.children) {
89
102
  if (findPath(child, targetId)) {
90
103
  return true;
91
104
  }
92
105
  }
93
- // Backtrack
94
106
  path.pop();
95
107
  return false;
96
108
  };
@@ -98,120 +110,127 @@ export class SpatialHierarchyBuilder {
98
110
  return path;
99
111
  },
100
112
  };
101
- return hierarchy;
102
113
  }
103
- buildNode(expressId, entities, relationships, strings, source, entityIndex, byStorey, byBuilding, bySite, bySpace, storeyElevations, elementToStorey, entityTypeMap, lengthUnitScale, visited) {
104
- const typeEnum = entityTypeMap.get(expressId) ?? IfcTypeEnum.Unknown;
105
- const name = entities.getName(expressId);
106
- // Guard against cyclic IfcRelAggregates chains (A aggregates B, B aggregates A),
107
- // which would otherwise recurse unbounded and overflow the stack. A revisited node
108
- // is returned as a leaf so the rest of the hierarchy still builds.
109
- if (visited.has(expressId)) {
110
- return {
111
- expressId,
112
- type: typeEnum,
113
- name,
114
- elevation: undefined,
115
- children: [],
116
- elements: [],
117
- };
114
+ buildNode(expressId, ctx) {
115
+ const { entities, relationships } = ctx;
116
+ const typeEnum = entities.getTypeEnum(expressId);
117
+ const name = entities.getName(expressId) || `Entity #${expressId}`;
118
+ // Guard against cyclic IfcRelAggregates chains (A aggregates B, B aggregates
119
+ // A), which would otherwise recurse unbounded and overflow the stack. A
120
+ // revisited node is returned as a leaf so the rest of the hierarchy still
121
+ // builds.
122
+ if (ctx.visited.has(expressId)) {
123
+ return { expressId, type: typeEnum, name, elevation: undefined, children: [], elements: [] };
118
124
  }
119
- visited.add(expressId);
120
- // Extract elevation for storeys (apply unit scale to convert to meters)
125
+ ctx.visited.add(expressId);
126
+ // Storey elevation (fresh path only): apply unit scale to convert to meters.
121
127
  let elevation;
122
- if (typeEnum === IfcTypeEnum.IfcBuildingStorey) {
123
- const rawElevation = this.extractElevation(expressId, source, entityIndex);
128
+ if (typeEnum === IfcTypeEnum.IfcBuildingStorey && ctx.elevation) {
129
+ const { source, entityIndex, lengthUnitScale } = ctx.elevation;
130
+ let rawElevation = this.extractElevation(expressId, source, entityIndex);
131
+ if (rawElevation === undefined) {
132
+ // Elevation is optional and frequently null (Revit / ArchiCAD). Fall back
133
+ // to the storey's Z from its ObjectPlacement so it still orders + lifts in
134
+ // Exploded mode instead of collapsing to a single floor (#1289).
135
+ rawElevation = this.extractPlacementElevation(expressId, source, entityIndex);
136
+ }
124
137
  if (rawElevation !== undefined) {
125
- // Apply unit scale to convert to meters
126
138
  elevation = rawElevation * lengthUnitScale;
127
- storeyElevations.set(expressId, elevation);
139
+ ctx.storeyElevations.set(expressId, elevation);
128
140
  }
129
141
  }
130
- // Get direct contained elements via IfcRelContainedInSpatialStructure
142
+ // Direct contained elements via IfcRelContainedInSpatialStructure.
131
143
  const rawContainedElements = relationships.getRelated(expressId, RelationshipType.ContainsElements, 'forward');
132
- // Keep entities whose type isn't in the EntityTable (e.g. IFC4x3 leaves the
133
- // categorizer skipped). The filter's purpose is to peel off spatial-structure
134
- // children those become recursive nodes via the aggregates branch — not to
135
- // gate on whether the EntityTable happened to record the type. Dropping
136
- // missing entities silently hides every IfcReferent/IfcSignal/IfcAlignment
137
- // under an IfcRailway/IfcRoad even though the relationship graph has them.
138
- // A contained spatial element — an IfcSpace / IfcSpatialZone attached to a
139
- // storey via IfcRelContainedInSpatialStructure, which is what Revit Family +
140
- // Dynamo emit instead of IfcRelAggregates — is a tree NODE, not a contained
141
- // product. Split it out here and promote it below; without this it was
142
- // filtered out and vanished from the hierarchy (#1075). Unknown-typed
143
- // entities (not in the EntityTable, e.g. some IFC4x3 leaves) stay elements.
144
+ // Split contained refs into real (non-spatial) elements vs spatial-structure
145
+ // children. Unknown types stay elements (getTypeEnum returns Unknown for both
146
+ // missing and unrecognized entities, and isSpatialStructureType(Unknown) is
147
+ // false). A contained IfcSpace / IfcSpatialZone (what Revit Family + Dynamo
148
+ // emit instead of IfcRelAggregates) is a tree NODE, not a product: promote it
149
+ // below so it shows in the hierarchy instead of vanishing (#1075).
144
150
  const containedElements = [];
145
151
  const containedSpatialChildren = [];
146
152
  for (const id of rawContainedElements) {
147
- const childType = entityTypeMap.get(id);
148
- if (childType !== undefined && isSpatialStructureType(childType) && childType !== IfcTypeEnum.IfcProject) {
153
+ const childType = entities.getTypeEnum(id);
154
+ if (isSpatialStructureType(childType) && childType !== IfcTypeEnum.IfcProject) {
149
155
  containedSpatialChildren.push(id);
150
156
  }
151
157
  else {
152
158
  containedElements.push(id);
153
159
  }
154
160
  }
155
- // Get child spatial elements via IfcRelAggregates (inverse - who aggregates this?)
156
- // Actually, we want forward - what does this element aggregate?
161
+ // Forward IfcRelAggregates: what does this element aggregate?
157
162
  const aggregatedChildren = relationships.getRelated(expressId, RelationshipType.Aggregates, 'forward');
158
163
  // Spatial child nodes come from BOTH aggregation and containment. Dedupe so a
159
- // space referenced by both relationships isn't built twice (which `visited`
160
- // would otherwise reduce to a duplicate leaf node).
164
+ // space referenced by both relationships isn't built twice.
161
165
  const childNodes = [];
162
166
  const spatialChildIds = new Set();
163
167
  const addSpatialChild = (childId) => {
164
168
  if (spatialChildIds.has(childId))
165
169
  return;
166
- const childType = entityTypeMap.get(childId) ?? IfcTypeEnum.Unknown;
170
+ const childType = entities.getTypeEnum(childId);
167
171
  if (isSpatialStructureType(childType) && childType !== IfcTypeEnum.IfcProject) {
168
172
  spatialChildIds.add(childId);
169
- childNodes.push(this.buildNode(childId, entities, relationships, strings, source, entityIndex, byStorey, byBuilding, bySite, bySpace, storeyElevations, elementToStorey, entityTypeMap, lengthUnitScale, visited));
173
+ childNodes.push(this.buildNode(childId, ctx));
170
174
  }
171
175
  };
172
176
  for (const childId of aggregatedChildren)
173
177
  addSpatialChild(childId);
174
178
  for (const childId of containedSpatialChildren)
175
179
  addSpatialChild(childId);
176
- // Add elements to appropriate maps
180
+ // Roll contained elements up to the appropriate map.
177
181
  if (isStoreyLikeSpatialType(typeEnum)) {
178
- byStorey.set(expressId, containedElements);
182
+ ctx.byStorey.set(expressId, containedElements);
179
183
  }
180
184
  else if (isBuildingLikeSpatialType(typeEnum)) {
181
- byBuilding.set(expressId, containedElements);
185
+ ctx.byBuilding.set(expressId, containedElements);
182
186
  }
183
187
  else if (typeEnum === IfcTypeEnum.IfcSite) {
184
- bySite.set(expressId, containedElements);
188
+ ctx.bySite.set(expressId, containedElements);
185
189
  }
186
190
  else if (isSpaceLikeSpatialType(typeEnum)) {
187
191
  // IfcSpace and IfcSpatialZone both roll up their contained elements here.
188
- bySpace.set(expressId, containedElements);
192
+ ctx.bySpace.set(expressId, containedElements);
189
193
  }
190
194
  if (isStoreyLikeSpatialType(typeEnum)) {
191
195
  for (const elementId of containedElements) {
192
- elementToStorey.set(elementId, expressId);
196
+ ctx.elementToStorey.set(elementId, expressId);
197
+ // Propagate the storey assignment to aggregated descendants (e.g. an
198
+ // IfcBuildingElementPart child of an IfcWall). Without this, parts have no
199
+ // reverse-lookup entry even though the renderer emits them as standalone
200
+ // meshes. Direct storey containment wins (only set if not already mapped);
201
+ // `seen` guards against aggregate cycles.
202
+ const stack = [elementId];
203
+ const seen = new Set([elementId]);
204
+ while (stack.length > 0) {
205
+ const current = stack.pop();
206
+ const aggregatedKids = relationships.getRelated(current, RelationshipType.Aggregates, 'forward');
207
+ for (const kid of aggregatedKids) {
208
+ if (seen.has(kid))
209
+ continue;
210
+ seen.add(kid);
211
+ if (!ctx.elementToStorey.has(kid)) {
212
+ ctx.elementToStorey.set(kid, expressId);
213
+ }
214
+ stack.push(kid);
215
+ }
216
+ }
193
217
  }
194
- // Map the storey's spatial children (IfcSpace / IfcSpatialZone) to it too,
195
- // so a selected space resolves "which storey it's on" the space itself
196
- // is a child node, not in containedElements (#1075).
218
+ // Map the storey's spatial children (IfcSpace / IfcSpatialZone) to it too, so
219
+ // a selected space resolves "which storey it's on" - the space is a child
220
+ // node, not in containedElements (#1075).
197
221
  for (const childId of spatialChildIds) {
198
- if (!elementToStorey.has(childId)) {
199
- elementToStorey.set(childId, expressId);
222
+ if (!ctx.elementToStorey.has(childId)) {
223
+ ctx.elementToStorey.set(childId, expressId);
200
224
  }
201
225
  }
202
226
  }
203
- return {
204
- expressId,
205
- type: typeEnum,
206
- name,
207
- elevation,
208
- children: childNodes,
209
- elements: containedElements,
210
- };
227
+ return { expressId, type: typeEnum, name, elevation, children: childNodes, elements: containedElements };
211
228
  }
212
229
  /**
213
- * Extract elevation from IfcBuildingStorey entity
214
- * Elevation is at attribute index 9 in IFC4 (after GlobalId, OwnerHistory, Name, Description, ObjectType, ObjectPlacement, Representation, LongName, CompositionType)
230
+ * Extract elevation from an IfcBuildingStorey. Elevation is attribute index 9
231
+ * in both IFC2x3 and IFC4 (GlobalId, OwnerHistory, Name, Description,
232
+ * ObjectType, ObjectPlacement, Representation, LongName, CompositionType,
233
+ * Elevation).
215
234
  */
216
235
  extractElevation(expressId, source, entityIndex) {
217
236
  const ref = entityIndex.byId.get(expressId);
@@ -223,37 +242,25 @@ export class SpatialHierarchyBuilder {
223
242
  if (!entity)
224
243
  return undefined;
225
244
  const attrs = entity.attributes || [];
226
- // Helper to extract number from raw value or typed value like ['IFCLENGTHMEASURE', 3.0]
245
+ // Number from a raw value or a typed value like ['IFCLENGTHMEASURE', 3.0].
227
246
  const extractNumber = (val) => {
228
247
  if (typeof val === 'number')
229
248
  return val;
230
249
  if (Array.isArray(val) && val.length === 2 && typeof val[1] === 'number') {
231
- return val[1]; // Typed value: ['IFCLENGTHMEASURE', 3.0]
250
+ return val[1];
232
251
  }
233
252
  return undefined;
234
253
  };
235
- // Try index 9 first (correct index for IfcBuildingStorey.Elevation in IFC4)
254
+ // Read ONLY slot 9: a previous "scan every attribute for a number < 10000"
255
+ // fallback wrongly treated reference attributes (parsed as bare express-id
256
+ // numbers, e.g. OwnerHistory #3628 -> 3628) as elevations, so a storey with
257
+ // a null Elevation got a garbage value instead of falling through to the
258
+ // ObjectPlacement-Z fallback below (#1289).
236
259
  if (attrs.length > 9) {
237
- const elev = extractNumber(attrs[9]);
238
- if (elev !== undefined)
239
- return elev;
240
- }
241
- // Try index 8 (in case of schema variations)
242
- if (attrs.length > 8) {
243
- const elev = extractNumber(attrs[8]);
244
- if (elev !== undefined)
245
- return elev;
246
- }
247
- // Fallback: search for first numeric value that looks like an elevation
248
- for (let i = 0; i < attrs.length; i++) {
249
- const elev = extractNumber(attrs[i]);
250
- if (elev !== undefined && Math.abs(elev) < 10000) {
251
- return elev;
252
- }
260
+ return extractNumber(attrs[9]);
253
261
  }
254
262
  }
255
263
  catch (error) {
256
- // Elevation extraction is optional - log for debugging but don't fail
257
264
  log.caught('Failed to extract elevation', error, {
258
265
  operation: 'extractElevation',
259
266
  entityId: expressId,
@@ -262,5 +269,54 @@ export class SpatialHierarchyBuilder {
262
269
  }
263
270
  return undefined;
264
271
  }
272
+ /**
273
+ * Resolve a storey's elevation from its ObjectPlacement, used as a fallback when
274
+ * the Elevation attribute is null. Walks
275
+ * IfcBuildingStorey.ObjectPlacement (IfcLocalPlacement)
276
+ * -> RelativePlacement (IfcAxis2Placement3D)
277
+ * -> Location (IfcCartesianPoint).Coordinates[2]
278
+ * i.e. the storey's Z relative to its parent spatial container, which matches
279
+ * the semantics of the Elevation attribute and avoids folding in any site-level
280
+ * georeferencing Z. Returns the raw (unscaled) Z, or undefined when the chain
281
+ * can't be resolved.
282
+ */
283
+ extractPlacementElevation(expressId, source, entityIndex) {
284
+ try {
285
+ const extractor = new EntityExtractor(source);
286
+ const readAttrs = (id) => {
287
+ const ref = entityIndex.byId.get(id);
288
+ if (!ref)
289
+ return undefined;
290
+ return extractor.extractEntity(ref)?.attributes ?? undefined;
291
+ };
292
+ // IfcBuildingStorey.ObjectPlacement is attribute index 5.
293
+ const placementId = readAttrs(expressId)?.[5];
294
+ if (typeof placementId !== 'number')
295
+ return undefined;
296
+ // IfcLocalPlacement(PlacementRelTo, RelativePlacement) - RelativePlacement
297
+ // (index 1) is the IfcAxis2Placement3D carrying this storey's own offset.
298
+ const axisId = readAttrs(placementId)?.[1];
299
+ if (typeof axisId !== 'number')
300
+ return undefined;
301
+ // IfcAxis2Placement3D(Location, Axis, RefDirection) - Location (index 0) is
302
+ // an IfcCartesianPoint.
303
+ const locationId = readAttrs(axisId)?.[0];
304
+ if (typeof locationId !== 'number')
305
+ return undefined;
306
+ // IfcCartesianPoint.Coordinates (index 0) is a list [x, y, z].
307
+ const coords = readAttrs(locationId)?.[0];
308
+ if (Array.isArray(coords) && coords.length >= 3 && typeof coords[2] === 'number') {
309
+ return coords[2];
310
+ }
311
+ }
312
+ catch (error) {
313
+ log.caught('Failed to extract placement elevation', error, {
314
+ operation: 'extractPlacementElevation',
315
+ entityId: expressId,
316
+ entityType: 'IfcBuildingStorey',
317
+ });
318
+ }
319
+ return undefined;
320
+ }
265
321
  }
266
322
  //# sourceMappingURL=spatial-hierarchy-builder.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"spatial-hierarchy-builder.js","sourceRoot":"","sources":["../src/spatial-hierarchy-builder.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"spatial-hierarchy-builder.js","sourceRoot":"","sources":["../src/spatial-hierarchy-builder.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ifc-lite/parser",
3
- "version": "3.3.1",
3
+ "version": "3.4.0",
4
4
  "description": "IFC/STEP parser for IFC-Lite",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -17,14 +17,14 @@
17
17
  }
18
18
  },
19
19
  "dependencies": {
20
- "@ifc-lite/data": "^2.1.0",
20
+ "@ifc-lite/data": "^2.2.0",
21
21
  "@ifc-lite/encoding": "^1.14.7",
22
22
  "@ifc-lite/ifcx": "^2.1.5",
23
- "@ifc-lite/wasm": "^2.9.1"
23
+ "@ifc-lite/wasm": "^2.13.2"
24
24
  },
25
25
  "devDependencies": {
26
26
  "typescript": "^6.0.3",
27
- "vitest": "^4.1.0"
27
+ "vitest": "^4.1.9"
28
28
  },
29
29
  "license": "MPL-2.0",
30
30
  "author": "Louis True",