@ifc-lite/parser 5.1.0 → 6.1.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.
- package/dist/classification-resolver.d.ts.map +1 -1
- package/dist/classification-resolver.js +35 -10
- package/dist/classification-resolver.js.map +1 -1
- package/dist/columnar-entity-preparation.d.ts +25 -0
- package/dist/columnar-entity-preparation.d.ts.map +1 -0
- package/dist/columnar-entity-preparation.js +282 -0
- package/dist/columnar-entity-preparation.js.map +1 -0
- package/dist/columnar-parser-indexes.d.ts +17 -1
- package/dist/columnar-parser-indexes.d.ts.map +1 -1
- package/dist/columnar-parser-indexes.js +31 -21
- package/dist/columnar-parser-indexes.js.map +1 -1
- package/dist/columnar-parser-root-attributes.d.ts +66 -0
- package/dist/columnar-parser-root-attributes.d.ts.map +1 -0
- package/dist/columnar-parser-root-attributes.js +245 -0
- package/dist/columnar-parser-root-attributes.js.map +1 -0
- package/dist/columnar-parser.d.ts +26 -63
- package/dist/columnar-parser.d.ts.map +1 -1
- package/dist/columnar-parser.js +384 -751
- package/dist/columnar-parser.js.map +1 -1
- package/dist/compact-entity-index-columns.d.ts +17 -0
- package/dist/compact-entity-index-columns.d.ts.map +1 -0
- package/dist/compact-entity-index-columns.js +15 -0
- package/dist/compact-entity-index-columns.js.map +1 -0
- package/dist/compact-entity-index-transport.d.ts +2 -12
- package/dist/compact-entity-index-transport.d.ts.map +1 -1
- package/dist/compact-entity-index-transport.js +1 -11
- package/dist/compact-entity-index-transport.js.map +1 -1
- package/dist/compact-entity-index.d.ts +6 -0
- package/dist/compact-entity-index.d.ts.map +1 -1
- package/dist/compact-entity-index.js +12 -20
- package/dist/compact-entity-index.js.map +1 -1
- package/dist/cost-extractor.d.ts +10 -0
- package/dist/cost-extractor.d.ts.map +1 -0
- package/dist/cost-extractor.js +369 -0
- package/dist/cost-extractor.js.map +1 -0
- package/dist/cost-schedule-2x3.d.ts +31 -0
- package/dist/cost-schedule-2x3.d.ts.map +1 -0
- package/dist/cost-schedule-2x3.js +75 -0
- package/dist/cost-schedule-2x3.js.map +1 -0
- package/dist/cost-types.d.ts +105 -0
- package/dist/cost-types.d.ts.map +1 -0
- package/dist/cost-types.js +5 -0
- package/dist/cost-types.js.map +1 -0
- package/dist/data-store-transport.d.ts +3 -2
- package/dist/data-store-transport.d.ts.map +1 -1
- package/dist/data-store-transport.js +10 -34
- package/dist/data-store-transport.js.map +1 -1
- package/dist/drop-census.d.ts +136 -0
- package/dist/drop-census.d.ts.map +1 -0
- package/dist/drop-census.js +53 -0
- package/dist/drop-census.js.map +1 -0
- package/dist/entity-refs-from-index.d.ts +10 -0
- package/dist/entity-refs-from-index.d.ts.map +1 -1
- package/dist/entity-refs-from-index.js +52 -36
- package/dist/entity-refs-from-index.js.map +1 -1
- package/dist/entity-scanner.d.ts +5 -0
- package/dist/entity-scanner.d.ts.map +1 -1
- package/dist/entity-scanner.js +30 -12
- package/dist/entity-scanner.js.map +1 -1
- package/dist/entity-type-byte-interner.d.ts +12 -0
- package/dist/entity-type-byte-interner.d.ts.map +1 -0
- package/dist/entity-type-byte-interner.js +66 -0
- package/dist/entity-type-byte-interner.js.map +1 -0
- package/dist/generated/ifc2x3/schema-registry.d.ts +50 -0
- package/dist/generated/ifc2x3/schema-registry.d.ts.map +1 -0
- package/dist/generated/ifc2x3/schema-registry.js +50052 -0
- package/dist/generated/ifc2x3/schema-registry.js.map +1 -0
- package/dist/generated/ifc4x3/schema-registry.d.ts +50 -0
- package/dist/generated/ifc4x3/schema-registry.d.ts.map +1 -0
- package/dist/generated/ifc4x3/schema-registry.js +71299 -0
- package/dist/generated/ifc4x3/schema-registry.js.map +1 -0
- package/dist/generated/schema-registry-by-version.d.ts +61 -0
- package/dist/generated/schema-registry-by-version.d.ts.map +1 -0
- package/dist/generated/schema-registry-by-version.js +86 -0
- package/dist/generated/schema-registry-by-version.js.map +1 -0
- package/dist/group-assignment-factor.d.ts +13 -0
- package/dist/group-assignment-factor.d.ts.map +1 -0
- package/dist/group-assignment-factor.js +30 -0
- package/dist/group-assignment-factor.js.map +1 -0
- package/dist/ifczip.d.ts +6 -0
- package/dist/ifczip.d.ts.map +1 -1
- package/dist/ifczip.js +20 -11
- package/dist/ifczip.js.map +1 -1
- package/dist/index.d.ts +10 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +17 -7
- package/dist/index.js.map +1 -1
- package/dist/on-demand-extractors.d.ts +1 -0
- package/dist/on-demand-extractors.d.ts.map +1 -1
- package/dist/on-demand-extractors.js +2 -1
- package/dist/on-demand-extractors.js.map +1 -1
- package/dist/parser.worker.d.ts +6 -3
- package/dist/parser.worker.d.ts.map +1 -1
- package/dist/parser.worker.js +24 -12
- package/dist/parser.worker.js.map +1 -1
- package/dist/prepass-source-fingerprint.d.ts +3 -0
- package/dist/prepass-source-fingerprint.d.ts.map +1 -0
- package/dist/prepass-source-fingerprint.js +13 -0
- package/dist/prepass-source-fingerprint.js.map +1 -0
- package/dist/property-value-parser.d.ts +10 -0
- package/dist/property-value-parser.d.ts.map +1 -1
- package/dist/property-value-parser.js +40 -1
- package/dist/property-value-parser.js.map +1 -1
- package/dist/scan-entities-balanced.d.ts.map +1 -1
- package/dist/scan-entities-balanced.js +8 -6
- package/dist/scan-entities-balanced.js.map +1 -1
- package/dist/scan-worker-lexing.d.ts +14 -0
- package/dist/scan-worker-lexing.d.ts.map +1 -0
- package/dist/scan-worker-lexing.js +101 -0
- package/dist/scan-worker-lexing.js.map +1 -0
- package/dist/scan-worker-source.d.ts +1 -1
- package/dist/scan-worker-source.d.ts.map +1 -1
- package/dist/scan-worker-source.js +61 -59
- package/dist/scan-worker-source.js.map +1 -1
- package/dist/schedule-extractor.d.ts +2 -80
- package/dist/schedule-extractor.d.ts.map +1 -1
- package/dist/schedule-extractor.js +100 -225
- package/dist/schedule-extractor.js.map +1 -1
- package/dist/schedule-serializer-builders.d.ts +28 -0
- package/dist/schedule-serializer-builders.d.ts.map +1 -0
- package/dist/schedule-serializer-builders.js +163 -0
- package/dist/schedule-serializer-builders.js.map +1 -0
- package/dist/schedule-serializer.d.ts +6 -0
- package/dist/schedule-serializer.d.ts.map +1 -1
- package/dist/schedule-serializer.js +26 -165
- package/dist/schedule-serializer.js.map +1 -1
- package/dist/schedule-types.d.ts +211 -0
- package/dist/schedule-types.d.ts.map +1 -0
- package/dist/schedule-types.js +221 -0
- package/dist/schedule-types.js.map +1 -0
- package/dist/select-entity-columns.d.ts +7 -0
- package/dist/select-entity-columns.d.ts.map +1 -0
- package/dist/select-entity-columns.js +43 -0
- package/dist/select-entity-columns.js.map +1 -0
- package/dist/spatial-hierarchy-ambiguity.d.ts +39 -0
- package/dist/spatial-hierarchy-ambiguity.d.ts.map +1 -0
- package/dist/spatial-hierarchy-ambiguity.js +25 -0
- package/dist/spatial-hierarchy-ambiguity.js.map +1 -0
- package/dist/spatial-hierarchy-attributes.d.ts +54 -0
- package/dist/spatial-hierarchy-attributes.d.ts.map +1 -0
- package/dist/spatial-hierarchy-attributes.js +145 -0
- package/dist/spatial-hierarchy-attributes.js.map +1 -0
- package/dist/spatial-hierarchy-builder.d.ts +6 -38
- package/dist/spatial-hierarchy-builder.d.ts.map +1 -1
- package/dist/spatial-hierarchy-builder.js +48 -166
- package/dist/spatial-hierarchy-builder.js.map +1 -1
- package/dist/spatial-hierarchy-canonical-parent.d.ts +86 -0
- package/dist/spatial-hierarchy-canonical-parent.d.ts.map +1 -0
- package/dist/spatial-hierarchy-canonical-parent.js +212 -0
- package/dist/spatial-hierarchy-canonical-parent.js.map +1 -0
- package/dist/step-lexing.d.ts +1 -1
- package/dist/step-lexing.d.ts.map +1 -1
- package/dist/step-lexing.js +1 -56
- package/dist/step-lexing.js.map +1 -1
- package/dist/step-record-boundary.d.ts +28 -0
- package/dist/step-record-boundary.d.ts.map +1 -0
- package/dist/step-record-boundary.js +108 -0
- package/dist/step-record-boundary.js.map +1 -0
- package/dist/step-record-boundary.vectors.d.ts +58 -0
- package/dist/step-record-boundary.vectors.d.ts.map +1 -0
- package/dist/step-record-boundary.vectors.js +80 -0
- package/dist/step-record-boundary.vectors.js.map +1 -0
- package/dist/structural-extractor.d.ts +9 -0
- package/dist/structural-extractor.d.ts.map +1 -0
- package/dist/structural-extractor.js +310 -0
- package/dist/structural-extractor.js.map +1 -0
- package/dist/structural-load-extractor.d.ts +147 -0
- package/dist/structural-load-extractor.d.ts.map +1 -0
- package/dist/structural-load-extractor.js +178 -0
- package/dist/structural-load-extractor.js.map +1 -0
- package/dist/structural-step-values.d.ts +51 -0
- package/dist/structural-step-values.d.ts.map +1 -0
- package/dist/structural-step-values.js +109 -0
- package/dist/structural-step-values.js.map +1 -0
- package/dist/structural-types.d.ts +145 -0
- package/dist/structural-types.d.ts.map +1 -0
- package/dist/structural-types.js +5 -0
- package/dist/structural-types.js.map +1 -0
- package/dist/tokenizer.d.ts +11 -5
- package/dist/tokenizer.d.ts.map +1 -1
- package/dist/tokenizer.js +75 -21
- package/dist/tokenizer.js.map +1 -1
- package/dist/wasm-init-retry.d.ts +6 -42
- package/dist/wasm-init-retry.d.ts.map +1 -1
- package/dist/wasm-init-retry.js +6 -99
- package/dist/wasm-init-retry.js.map +1 -1
- package/dist/wasm-panic-forward.d.ts +7 -63
- package/dist/wasm-panic-forward.d.ts.map +1 -1
- package/dist/wasm-panic-forward.js +7 -100
- package/dist/wasm-panic-forward.js.map +1 -1
- package/dist/worker-index-publication.d.ts +43 -0
- package/dist/worker-index-publication.d.ts.map +1 -0
- package/dist/worker-index-publication.js +129 -0
- package/dist/worker-index-publication.js.map +1 -0
- package/dist/worker-parser.d.ts +5 -2
- package/dist/worker-parser.d.ts.map +1 -1
- package/dist/worker-parser.js +22 -10
- package/dist/worker-parser.js.map +1 -1
- package/package.json +5 -4
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
2
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
3
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
|
4
|
-
import { IfcTypeEnum, RelationshipType,
|
|
4
|
+
import { IfcTypeEnum, RelationshipType, isBuildingLikeSpatialType, isSpaceLikeSpatialType, isSpatialStructureType, isStoreyLikeSpatialType, findStoreyByElevation, spatialLookups, } from '@ifc-lite/data';
|
|
5
5
|
import { EntityExtractor } from './entity-extractor.js';
|
|
6
|
-
import {
|
|
7
|
-
|
|
6
|
+
import { computeCanonicalParent, computeReachableSpatialNodes } from './spatial-hierarchy-canonical-parent.js';
|
|
7
|
+
import { extractLongName, extractElevation, extractPlacementElevation, } from './spatial-hierarchy-attributes.js';
|
|
8
|
+
import { computeAmbiguousStorey } from './spatial-hierarchy-ambiguity.js';
|
|
8
9
|
export class SpatialHierarchyBuilder {
|
|
9
10
|
/**
|
|
10
11
|
* Fresh-parse build. Extracts storey elevations from the source buffer.
|
|
@@ -36,6 +37,8 @@ export class SpatialHierarchyBuilder {
|
|
|
36
37
|
elementToStorey: new Map(),
|
|
37
38
|
elementToContainer: new Map(),
|
|
38
39
|
visited: new Set(),
|
|
40
|
+
canonicalParent: computeCanonicalParent(entities, relationships),
|
|
41
|
+
reachableSpatialNodes: new Set(), // filled in below once IfcProject is known
|
|
39
42
|
attrSource,
|
|
40
43
|
attrExtractor: attrSource ? new EntityExtractor(attrSource.source) : undefined,
|
|
41
44
|
};
|
|
@@ -47,6 +50,10 @@ export class SpatialHierarchyBuilder {
|
|
|
47
50
|
}
|
|
48
51
|
return undefined;
|
|
49
52
|
}
|
|
53
|
+
// Which storeys buildNode will actually recurse into, computed up front
|
|
54
|
+
// so ContainsElements resolution below never depends on this node's own
|
|
55
|
+
// position in the traversal (#4310) - see computeReachableSpatialNodes.
|
|
56
|
+
ctx.reachableSpatialNodes = computeReachableSpatialNodes(projectIds[0], ctx.canonicalParent);
|
|
50
57
|
const projectNode = this.buildNode(projectIds[0], ctx);
|
|
51
58
|
if (ctx.byStorey.size === 0) {
|
|
52
59
|
console.warn('[SpatialHierarchyBuilder] No storeys found in spatial hierarchy');
|
|
@@ -55,13 +62,6 @@ export class SpatialHierarchyBuilder {
|
|
|
55
62
|
console.warn('[SpatialHierarchyBuilder] No buildings found in spatial hierarchy');
|
|
56
63
|
}
|
|
57
64
|
const { byStorey, byBuilding, bySite, bySpace, storeyElevations, elementToStorey, elementToContainer } = ctx;
|
|
58
|
-
// Pre-build the element -> space lookup for O(1) getContainingSpace.
|
|
59
|
-
const elementToSpace = new Map();
|
|
60
|
-
for (const [spaceId, elementIds] of bySpace) {
|
|
61
|
-
for (const elementId of elementIds) {
|
|
62
|
-
elementToSpace.set(elementId, spaceId);
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
65
|
return {
|
|
66
66
|
project: projectNode,
|
|
67
67
|
byStorey,
|
|
@@ -73,6 +73,7 @@ export class SpatialHierarchyBuilder {
|
|
|
73
73
|
storeyHeights: new Map(),
|
|
74
74
|
elementToStorey,
|
|
75
75
|
elementToContainer,
|
|
76
|
+
ambiguousStorey: computeAmbiguousStorey(byStorey), // #4311
|
|
76
77
|
getStoreyElements(storeyId) {
|
|
77
78
|
return byStorey.get(storeyId) ?? [];
|
|
78
79
|
},
|
|
@@ -82,29 +83,7 @@ export class SpatialHierarchyBuilder {
|
|
|
82
83
|
// Z can never resolve to a different storey depending on entry path.
|
|
83
84
|
return findStoreyByElevation(storeyElevations, z);
|
|
84
85
|
},
|
|
85
|
-
|
|
86
|
-
return elementToSpace.get(elementId) ?? null;
|
|
87
|
-
},
|
|
88
|
-
getPath(elementId) {
|
|
89
|
-
const path = [];
|
|
90
|
-
const findPath = (node, targetId) => {
|
|
91
|
-
path.push(node);
|
|
92
|
-
// Match the node itself (so a promoted space/zone resolves) or one of
|
|
93
|
-
// its contained elements.
|
|
94
|
-
if (node.expressId === targetId || node.elements.includes(targetId)) {
|
|
95
|
-
return true;
|
|
96
|
-
}
|
|
97
|
-
for (const child of node.children) {
|
|
98
|
-
if (findPath(child, targetId)) {
|
|
99
|
-
return true;
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
path.pop();
|
|
103
|
-
return false;
|
|
104
|
-
};
|
|
105
|
-
findPath(projectNode, elementId);
|
|
106
|
-
return path;
|
|
107
|
-
},
|
|
86
|
+
...spatialLookups(projectNode, bySpace, elementToContainer),
|
|
108
87
|
};
|
|
109
88
|
}
|
|
110
89
|
buildNode(expressId, ctx) {
|
|
@@ -116,17 +95,23 @@ export class SpatialHierarchyBuilder {
|
|
|
116
95
|
// show both (issue #1634). It lives only in the raw record, so it needs the
|
|
117
96
|
// source bytes; the source-less buildFromCache fallback leaves it undefined,
|
|
118
97
|
// exactly like storey elevation.
|
|
119
|
-
const rawLongName =
|
|
98
|
+
const rawLongName = extractLongName(expressId, ctx.attrSource, ctx.attrExtractor);
|
|
120
99
|
// Fall back to LongName when Name is empty (common for IfcSpace). Left
|
|
121
100
|
// empty, not a fabricated `Entity #<id>` — it flows into the export layer.
|
|
122
101
|
const name = rawName || rawLongName || '';
|
|
123
102
|
// Only keep LongName as a distinct descriptor when it adds something beyond
|
|
124
103
|
// the primary label (never duplicate it into the secondary slot).
|
|
125
104
|
const longName = rawLongName && rawLongName !== name ? rawLongName : undefined;
|
|
126
|
-
//
|
|
127
|
-
//
|
|
128
|
-
//
|
|
129
|
-
//
|
|
105
|
+
// This is NOT what actually prevents unbounded recursion on a cyclic
|
|
106
|
+
// IfcRelAggregates chain (A aggregates B, B aggregates A) - it never
|
|
107
|
+
// fires today. Recursion here only ever follows a node's ONE canonical
|
|
108
|
+
// parent (computeCanonicalParent in spatial-hierarchy-canonical-parent.ts
|
|
109
|
+
// picks exactly one, and skips any candidate that would close a cycle
|
|
110
|
+
// back through the child, #4246), so a cycle can supply at most one
|
|
111
|
+
// recursion edge into any node - which structurally cannot loop. Kept as
|
|
112
|
+
// defence in depth in case that single-parent invariant is ever
|
|
113
|
+
// weakened; if it does fire, a revisited node is returned as a leaf so
|
|
114
|
+
// the rest of the hierarchy still builds.
|
|
130
115
|
if (ctx.visited.has(expressId)) {
|
|
131
116
|
return { expressId, type: typeEnum, name, longName, elevation: undefined, children: [], elements: [] };
|
|
132
117
|
}
|
|
@@ -135,12 +120,12 @@ export class SpatialHierarchyBuilder {
|
|
|
135
120
|
let elevation;
|
|
136
121
|
if (typeEnum === IfcTypeEnum.IfcBuildingStorey && ctx.attrSource) {
|
|
137
122
|
const { source, entityIndex, lengthUnitScale } = ctx.attrSource;
|
|
138
|
-
let rawElevation =
|
|
123
|
+
let rawElevation = extractElevation(expressId, source, entityIndex);
|
|
139
124
|
if (rawElevation === undefined) {
|
|
140
125
|
// Elevation is optional and frequently null (Revit / ArchiCAD). Fall back
|
|
141
126
|
// to the storey's Z from its ObjectPlacement so it still orders + lifts in
|
|
142
127
|
// Exploded mode instead of collapsing to a single floor (#1289).
|
|
143
|
-
rawElevation =
|
|
128
|
+
rawElevation = extractPlacementElevation(expressId, source, entityIndex);
|
|
144
129
|
}
|
|
145
130
|
if (rawElevation !== undefined) {
|
|
146
131
|
elevation = rawElevation * lengthUnitScale;
|
|
@@ -177,6 +162,8 @@ export class SpatialHierarchyBuilder {
|
|
|
177
162
|
return;
|
|
178
163
|
const childType = entities.getTypeEnum(childId);
|
|
179
164
|
if (isSpatialStructureType(childType) && childType !== IfcTypeEnum.IfcProject) {
|
|
165
|
+
if (ctx.canonicalParent.get(childId) !== expressId)
|
|
166
|
+
return; // canonical parent only, no phantom stub (#4095)
|
|
180
167
|
spatialChildIds.add(childId);
|
|
181
168
|
childNodes.push(this.buildNode(childId, ctx));
|
|
182
169
|
}
|
|
@@ -201,6 +188,27 @@ export class SpatialHierarchyBuilder {
|
|
|
201
188
|
}
|
|
202
189
|
if (isStoreyLikeSpatialType(typeEnum)) {
|
|
203
190
|
for (const elementId of containedElements) {
|
|
191
|
+
// First-declared wins on duplicate containment, matching containedIn()
|
|
192
|
+
// (#4248) - but only among storeys buildNode actually visits. A
|
|
193
|
+
// first-declared edge naming an unreachable storey (no path back to
|
|
194
|
+
// IfcProject, e.g. missing its own IfcRelAggregates edge) is not a
|
|
195
|
+
// real competing answer: buildNode never runs that storey's own
|
|
196
|
+
// branch, so nothing would ever claim the element there, and the
|
|
197
|
+
// element must not be dropped just because a later-declared but
|
|
198
|
+
// VIABLE storey lost a tie to a candidate that can't win (#4310).
|
|
199
|
+
// Only storey-like containers compete: a reachable IfcSpace edge
|
|
200
|
+
// declared first is not a storey answer, and letting it win here
|
|
201
|
+
// would leave the element with no elementToStorey entry at all
|
|
202
|
+
// (spaces never run this branch).
|
|
203
|
+
const containerEdges = relationships.inverse.getEdges(elementId, RelationshipType.ContainsElements);
|
|
204
|
+
const firstViableContainer = containerEdges.find((edge) => ctx.reachableSpatialNodes.has(edge.target) && isStoreyLikeSpatialType(entities.getTypeEnum(edge.target)));
|
|
205
|
+
// expressId is always reachable here (buildNode only runs on reachable
|
|
206
|
+
// nodes) and always has an edge to elementId (elementId came from THIS
|
|
207
|
+
// storey's own containedElements), so firstViableContainer is always
|
|
208
|
+
// defined - it can never fall through to the pre-#4310 "assign
|
|
209
|
+
// unconditionally" behavior by surprise.
|
|
210
|
+
if (firstViableContainer && firstViableContainer.target !== expressId)
|
|
211
|
+
continue; // a viable earlier-declared storey wins instead
|
|
204
212
|
ctx.elementToStorey.set(elementId, expressId);
|
|
205
213
|
// Propagate the storey assignment to aggregated descendants (e.g. an
|
|
206
214
|
// IfcBuildingElementPart child of an IfcWall). Without this, parts have no
|
|
@@ -262,131 +270,5 @@ export class SpatialHierarchyBuilder {
|
|
|
262
270
|
}
|
|
263
271
|
return { expressId, type: typeEnum, name, longName, elevation, children: childNodes, elements: containedElements };
|
|
264
272
|
}
|
|
265
|
-
/**
|
|
266
|
-
* Read an entity's LongName by schema attribute *name*. IfcSite / IfcBuilding /
|
|
267
|
-
* IfcBuildingStorey / IfcSpace (and the IFC4.3 facility/infra containers)
|
|
268
|
-
* declare LongName at index 7, but IfcProject carries it at a different slot,
|
|
269
|
-
* so resolving by name (not a fixed index) stays correct across the IfcRoot
|
|
270
|
-
* family. The lookup spans every bundled schema, so IFC4.3 leaves outside the
|
|
271
|
-
* parser's IFC4 codegen pin resolve too. Returns the trimmed value, or
|
|
272
|
-
* undefined when the type declares no LongName, it is empty, or no source
|
|
273
|
-
* buffer is available (the buildFromCache path).
|
|
274
|
-
*/
|
|
275
|
-
extractLongName(expressId, ctx) {
|
|
276
|
-
if (!ctx.attrSource || !ctx.attrExtractor)
|
|
277
|
-
return undefined;
|
|
278
|
-
const ref = ctx.attrSource.entityIndex.byId.get(expressId);
|
|
279
|
-
if (!ref)
|
|
280
|
-
return undefined;
|
|
281
|
-
try {
|
|
282
|
-
const entity = ctx.attrExtractor.extractEntity(ref);
|
|
283
|
-
if (!entity)
|
|
284
|
-
return undefined;
|
|
285
|
-
const idx = getAttributeNamesAcrossSchemas(entity.type).indexOf('LongName');
|
|
286
|
-
if (idx < 0)
|
|
287
|
-
return undefined;
|
|
288
|
-
const raw = (entity.attributes || [])[idx];
|
|
289
|
-
const value = typeof raw === 'string' ? raw.trim() : '';
|
|
290
|
-
return value.length > 0 ? value : undefined;
|
|
291
|
-
}
|
|
292
|
-
catch (error) {
|
|
293
|
-
log.caught('Failed to extract LongName', error, {
|
|
294
|
-
operation: 'extractLongName',
|
|
295
|
-
entityId: expressId,
|
|
296
|
-
});
|
|
297
|
-
return undefined;
|
|
298
|
-
}
|
|
299
|
-
}
|
|
300
|
-
/**
|
|
301
|
-
* Extract elevation from an IfcBuildingStorey. Elevation is attribute index 9
|
|
302
|
-
* in both IFC2x3 and IFC4 (GlobalId, OwnerHistory, Name, Description,
|
|
303
|
-
* ObjectType, ObjectPlacement, Representation, LongName, CompositionType,
|
|
304
|
-
* Elevation).
|
|
305
|
-
*/
|
|
306
|
-
extractElevation(expressId, source, entityIndex) {
|
|
307
|
-
const ref = entityIndex.byId.get(expressId);
|
|
308
|
-
if (!ref)
|
|
309
|
-
return undefined;
|
|
310
|
-
try {
|
|
311
|
-
const extractor = new EntityExtractor(source);
|
|
312
|
-
const entity = extractor.extractEntity(ref);
|
|
313
|
-
if (!entity)
|
|
314
|
-
return undefined;
|
|
315
|
-
const attrs = entity.attributes || [];
|
|
316
|
-
// Number from a raw value or a typed value like ['IFCLENGTHMEASURE', 3.0].
|
|
317
|
-
const extractNumber = (val) => {
|
|
318
|
-
if (typeof val === 'number')
|
|
319
|
-
return val;
|
|
320
|
-
if (Array.isArray(val) && val.length === 2 && typeof val[1] === 'number') {
|
|
321
|
-
return val[1];
|
|
322
|
-
}
|
|
323
|
-
return undefined;
|
|
324
|
-
};
|
|
325
|
-
// Read ONLY the Elevation slot: a previous "scan every attribute for a
|
|
326
|
-
// number < 10000" fallback wrongly treated reference attributes (parsed as
|
|
327
|
-
// bare express-id numbers, e.g. OwnerHistory #3628 -> 3628) as elevations,
|
|
328
|
-
// so a storey with a null Elevation got a garbage value instead of falling
|
|
329
|
-
// through to the ObjectPlacement-Z fallback below (#1289).
|
|
330
|
-
if (attrs.length > IFC_BUILDING_STOREY_ELEVATION_INDEX) {
|
|
331
|
-
return extractNumber(attrs[IFC_BUILDING_STOREY_ELEVATION_INDEX]);
|
|
332
|
-
}
|
|
333
|
-
}
|
|
334
|
-
catch (error) {
|
|
335
|
-
log.caught('Failed to extract elevation', error, {
|
|
336
|
-
operation: 'extractElevation',
|
|
337
|
-
entityId: expressId,
|
|
338
|
-
entityType: 'IfcBuildingStorey',
|
|
339
|
-
});
|
|
340
|
-
}
|
|
341
|
-
return undefined;
|
|
342
|
-
}
|
|
343
|
-
/**
|
|
344
|
-
* Resolve a storey's elevation from its ObjectPlacement, used as a fallback when
|
|
345
|
-
* the Elevation attribute is null. Walks
|
|
346
|
-
* IfcBuildingStorey.ObjectPlacement (IfcLocalPlacement)
|
|
347
|
-
* -> RelativePlacement (IfcAxis2Placement3D)
|
|
348
|
-
* -> Location (IfcCartesianPoint).Coordinates[2]
|
|
349
|
-
* i.e. the storey's Z relative to its parent spatial container, which matches
|
|
350
|
-
* the semantics of the Elevation attribute and avoids folding in any site-level
|
|
351
|
-
* georeferencing Z. Returns the raw (unscaled) Z, or undefined when the chain
|
|
352
|
-
* can't be resolved.
|
|
353
|
-
*/
|
|
354
|
-
extractPlacementElevation(expressId, source, entityIndex) {
|
|
355
|
-
try {
|
|
356
|
-
const extractor = new EntityExtractor(source);
|
|
357
|
-
const readAttrs = (id) => {
|
|
358
|
-
const ref = entityIndex.byId.get(id);
|
|
359
|
-
if (!ref)
|
|
360
|
-
return undefined;
|
|
361
|
-
return extractor.extractEntity(ref)?.attributes ?? undefined;
|
|
362
|
-
};
|
|
363
|
-
const placementId = readAttrs(expressId)?.[IFC_BUILDING_STOREY_PLACEMENT_INDEX];
|
|
364
|
-
if (typeof placementId !== 'number')
|
|
365
|
-
return undefined;
|
|
366
|
-
// IfcLocalPlacement(PlacementRelTo, RelativePlacement) - RelativePlacement
|
|
367
|
-
// (index 1) is the IfcAxis2Placement3D carrying this storey's own offset.
|
|
368
|
-
const axisId = readAttrs(placementId)?.[1];
|
|
369
|
-
if (typeof axisId !== 'number')
|
|
370
|
-
return undefined;
|
|
371
|
-
// IfcAxis2Placement3D(Location, Axis, RefDirection) - Location (index 0) is
|
|
372
|
-
// an IfcCartesianPoint.
|
|
373
|
-
const locationId = readAttrs(axisId)?.[0];
|
|
374
|
-
if (typeof locationId !== 'number')
|
|
375
|
-
return undefined;
|
|
376
|
-
// IfcCartesianPoint.Coordinates (index 0) is a list [x, y, z].
|
|
377
|
-
const coords = readAttrs(locationId)?.[0];
|
|
378
|
-
if (Array.isArray(coords) && coords.length >= 3 && typeof coords[2] === 'number') {
|
|
379
|
-
return coords[2];
|
|
380
|
-
}
|
|
381
|
-
}
|
|
382
|
-
catch (error) {
|
|
383
|
-
log.caught('Failed to extract placement elevation', error, {
|
|
384
|
-
operation: 'extractPlacementElevation',
|
|
385
|
-
entityId: expressId,
|
|
386
|
-
entityType: 'IfcBuildingStorey',
|
|
387
|
-
});
|
|
388
|
-
}
|
|
389
|
-
return undefined;
|
|
390
|
-
}
|
|
391
273
|
}
|
|
392
274
|
//# 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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"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Canonical-parent resolution for `SpatialHierarchyBuilder` (split out to stay
|
|
3
|
+
* under the module-size budget, #4095).
|
|
4
|
+
*/
|
|
5
|
+
import type { EntityTable, RelationshipGraph } from '@ifc-lite/data';
|
|
6
|
+
/**
|
|
7
|
+
* Is `candidateParent` reachable from `childId` by walking forward
|
|
8
|
+
* `IfcRelAggregates` edges (i.e. is `childId` an ANCESTOR of `candidateParent`
|
|
9
|
+
* in the raw, unresolved aggregation graph)? Used only to disqualify a tied
|
|
10
|
+
* candidate parent that would close a cycle back through the child itself -
|
|
11
|
+
* see the doc comment on `computeCanonicalParent` for why that specific shape
|
|
12
|
+
* needs a check at all. Bounded to `childId`'s own (raw) aggregation
|
|
13
|
+
* subtree, so it only costs anything on an already-malformed file where a
|
|
14
|
+
* child has more than one candidate Aggregates parent - the common case
|
|
15
|
+
* (one candidate) never calls this.
|
|
16
|
+
*/
|
|
17
|
+
/**
|
|
18
|
+
* Upper bound on aggregate-graph node visits spent on back-edge cycle checks
|
|
19
|
+
* for one file. The check only runs for children named by MORE THAN ONE
|
|
20
|
+
* IfcRelAggregates (already malformed), and costs one descendant walk per
|
|
21
|
+
* such child - O(V+E) each - so a crafted file with thousands of contested
|
|
22
|
+
* children could otherwise burn O(C·(V+E)). Past the budget the resolver
|
|
23
|
+
* falls back to plain first-declared-wins (the pre-#4285 behaviour) and says
|
|
24
|
+
* so once, instead of stalling the parse.
|
|
25
|
+
*/
|
|
26
|
+
export declare const CYCLE_CHECK_VISIT_BUDGET = 2000000;
|
|
27
|
+
/**
|
|
28
|
+
* Resolve each spatial-structure entity's ONE canonical parent, globally,
|
|
29
|
+
* before any recursion starts - so the result cannot depend on traversal
|
|
30
|
+
* order. Mirrors apps/server's `canonical_parent` (`spatial.rs`, #3973):
|
|
31
|
+
*
|
|
32
|
+
* 1. IfcRelAggregates always wins over mere containment. A child aggregated
|
|
33
|
+
* by more than one parent (a malformed file) resolves to the parent
|
|
34
|
+
* whose `IfcRelAggregates` was declared FIRST in the file - STEP does
|
|
35
|
+
* not require express ids to ascend with declaration position, so a
|
|
36
|
+
* lowest-express-id tie-break can disagree with declaration order (a
|
|
37
|
+
* legally-valid file can declare a high-id relationship before a
|
|
38
|
+
* low-id one). `relationships.inverse.getEdges` returns edges in
|
|
39
|
+
* declaration order: `RelationshipGraphBuilder.addEdge` is called by
|
|
40
|
+
* the parser while it scans `IfcRel*` records in file/byte order (see
|
|
41
|
+
* `columnar-parser.ts`'s relationship loop), and `buildCSR`'s counting
|
|
42
|
+
* sort is stable per key (`relationship-graph.ts`) - it scatters edges
|
|
43
|
+
* for the same child in the order they were appended, never
|
|
44
|
+
* reordering by id. So `edges[0]` for a given child is the
|
|
45
|
+
* first-declared parent edge; no id comparison is needed or correct -
|
|
46
|
+
* EXCEPT that a candidate closing a cycle back through the child is
|
|
47
|
+
* skipped first (see `aggregatedDescendants`, #4246): a mutual or
|
|
48
|
+
* longer aggregation back-edge cannot win a tie against a candidate that
|
|
49
|
+
* doesn't orphan the child's own subtree from itself. Each time that
|
|
50
|
+
* happens, a warning is logged (always-visible, like the existing
|
|
51
|
+
* "No storeys/buildings found" warnings below) naming the child and the
|
|
52
|
+
* disqualified candidate - the only signal a caller gets that a
|
|
53
|
+
* malformed back-edge was found and repaired, short of building a
|
|
54
|
+
* dedicated report (out of scope here; see the #4208 semantic drop
|
|
55
|
+
* census for that shape of reporting - a different layer: per-STEP-class
|
|
56
|
+
* scan/retain counts collected during columnar categorization, not a
|
|
57
|
+
* graph-repair event like this one).
|
|
58
|
+
* 2. Only when a child has NO aggregates edge at all does a containment edge
|
|
59
|
+
* (IfcRelContainedInSpatialStructure targeting a spatial-structure type -
|
|
60
|
+
* the Revit Family/Dynamo `IfcSpace`/`IfcSpatialZone` pattern, #1075)
|
|
61
|
+
* get to claim it, with the same first-declared tie-break.
|
|
62
|
+
*
|
|
63
|
+
* `SpatialHierarchyBuilder.buildNode`'s `addSpatialChild` then only recurses
|
|
64
|
+
* into a child from its canonical parent - every other parent that also
|
|
65
|
+
* names the child drops the edge instead of adding an empty-stub duplicate
|
|
66
|
+
* (#4095).
|
|
67
|
+
*/
|
|
68
|
+
export declare function computeCanonicalParent(entities: EntityTable, relationships: RelationshipGraph, options?: {
|
|
69
|
+
cycleCheckVisitBudget?: number;
|
|
70
|
+
}): Map<number, number>;
|
|
71
|
+
/**
|
|
72
|
+
* Which spatial-structure nodes will `SpatialHierarchyBuilder.buildNode`
|
|
73
|
+
* actually visit, starting from `projectId`? Mirrors `addSpatialChild`
|
|
74
|
+
* exactly: a node is visited iff it is `projectId` itself, or its
|
|
75
|
+
* `canonicalParent` entry points to an already-visited node - the same
|
|
76
|
+
* check `addSpatialChild` makes before recursing (`canonicalParent.get
|
|
77
|
+
* (childId) === expressId`). Computed as one forward walk over
|
|
78
|
+
* `canonicalParent` (childId -> parentId) up front, so a storey's
|
|
79
|
+
* reachability never depends on where in the traversal it happens to sit
|
|
80
|
+
* (#4310): a node named only by an unreachable storey - one with no path
|
|
81
|
+
* back to `projectId`, e.g. a malformed file where a storey has no
|
|
82
|
+
* `IfcRelAggregates` edge at all - is never in this set, exactly as
|
|
83
|
+
* `buildNode` would never recurse into it.
|
|
84
|
+
*/
|
|
85
|
+
export declare function computeReachableSpatialNodes(projectId: number, canonicalParent: Map<number, number>): Set<number>;
|
|
86
|
+
//# sourceMappingURL=spatial-hierarchy-canonical-parent.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spatial-hierarchy-canonical-parent.d.ts","sourceRoot":"","sources":["../src/spatial-hierarchy-canonical-parent.ts"],"names":[],"mappings":"AAIA;;;GAGG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAKrE;;;;;;;;;;GAUG;AACH;;;;;;;;GAQG;AACH,eAAO,MAAM,wBAAwB,UAAY,CAAC;AA4BlD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AACH,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,WAAW,EACrB,aAAa,EAAE,iBAAiB,EAChC,OAAO,GAAE;IAAE,qBAAqB,CAAC,EAAE,MAAM,CAAA;CAAO,GAC/C,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CA6FrB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,4BAA4B,CAC1C,SAAS,EAAE,MAAM,EACjB,eAAe,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GACnC,GAAG,CAAC,MAAM,CAAC,CAsBb"}
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
|
+
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
|
+
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
|
4
|
+
import { IfcTypeEnum, RelationshipType, createLogger, isSpatialStructureType } from '@ifc-lite/data';
|
|
5
|
+
const log = createLogger('SpatialHierarchy');
|
|
6
|
+
/**
|
|
7
|
+
* Is `candidateParent` reachable from `childId` by walking forward
|
|
8
|
+
* `IfcRelAggregates` edges (i.e. is `childId` an ANCESTOR of `candidateParent`
|
|
9
|
+
* in the raw, unresolved aggregation graph)? Used only to disqualify a tied
|
|
10
|
+
* candidate parent that would close a cycle back through the child itself -
|
|
11
|
+
* see the doc comment on `computeCanonicalParent` for why that specific shape
|
|
12
|
+
* needs a check at all. Bounded to `childId`'s own (raw) aggregation
|
|
13
|
+
* subtree, so it only costs anything on an already-malformed file where a
|
|
14
|
+
* child has more than one candidate Aggregates parent - the common case
|
|
15
|
+
* (one candidate) never calls this.
|
|
16
|
+
*/
|
|
17
|
+
/**
|
|
18
|
+
* Upper bound on aggregate-graph node visits spent on back-edge cycle checks
|
|
19
|
+
* for one file. The check only runs for children named by MORE THAN ONE
|
|
20
|
+
* IfcRelAggregates (already malformed), and costs one descendant walk per
|
|
21
|
+
* such child - O(V+E) each - so a crafted file with thousands of contested
|
|
22
|
+
* children could otherwise burn O(C·(V+E)). Past the budget the resolver
|
|
23
|
+
* falls back to plain first-declared-wins (the pre-#4285 behaviour) and says
|
|
24
|
+
* so once, instead of stalling the parse.
|
|
25
|
+
*/
|
|
26
|
+
export const CYCLE_CHECK_VISIT_BUDGET = 2_000_000;
|
|
27
|
+
/**
|
|
28
|
+
* Aggregated descendants of `childId` (transitive, forward `Aggregates`),
|
|
29
|
+
* charged against `budget`. Returns null when the budget ran out mid-walk
|
|
30
|
+
* (the partial set must not be used - a missing descendant reads as "no
|
|
31
|
+
* cycle", which is the wrong side to err on).
|
|
32
|
+
*/
|
|
33
|
+
function aggregatedDescendants(childId, relationships, budget) {
|
|
34
|
+
const visited = new Set([childId]);
|
|
35
|
+
const stack = [childId];
|
|
36
|
+
while (stack.length > 0) {
|
|
37
|
+
const current = stack.pop();
|
|
38
|
+
for (const kid of relationships.getRelated(current, RelationshipType.Aggregates, 'forward')) {
|
|
39
|
+
if (--budget.visits < 0)
|
|
40
|
+
return null;
|
|
41
|
+
if (!visited.has(kid)) {
|
|
42
|
+
visited.add(kid);
|
|
43
|
+
stack.push(kid);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return visited;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Resolve each spatial-structure entity's ONE canonical parent, globally,
|
|
51
|
+
* before any recursion starts - so the result cannot depend on traversal
|
|
52
|
+
* order. Mirrors apps/server's `canonical_parent` (`spatial.rs`, #3973):
|
|
53
|
+
*
|
|
54
|
+
* 1. IfcRelAggregates always wins over mere containment. A child aggregated
|
|
55
|
+
* by more than one parent (a malformed file) resolves to the parent
|
|
56
|
+
* whose `IfcRelAggregates` was declared FIRST in the file - STEP does
|
|
57
|
+
* not require express ids to ascend with declaration position, so a
|
|
58
|
+
* lowest-express-id tie-break can disagree with declaration order (a
|
|
59
|
+
* legally-valid file can declare a high-id relationship before a
|
|
60
|
+
* low-id one). `relationships.inverse.getEdges` returns edges in
|
|
61
|
+
* declaration order: `RelationshipGraphBuilder.addEdge` is called by
|
|
62
|
+
* the parser while it scans `IfcRel*` records in file/byte order (see
|
|
63
|
+
* `columnar-parser.ts`'s relationship loop), and `buildCSR`'s counting
|
|
64
|
+
* sort is stable per key (`relationship-graph.ts`) - it scatters edges
|
|
65
|
+
* for the same child in the order they were appended, never
|
|
66
|
+
* reordering by id. So `edges[0]` for a given child is the
|
|
67
|
+
* first-declared parent edge; no id comparison is needed or correct -
|
|
68
|
+
* EXCEPT that a candidate closing a cycle back through the child is
|
|
69
|
+
* skipped first (see `aggregatedDescendants`, #4246): a mutual or
|
|
70
|
+
* longer aggregation back-edge cannot win a tie against a candidate that
|
|
71
|
+
* doesn't orphan the child's own subtree from itself. Each time that
|
|
72
|
+
* happens, a warning is logged (always-visible, like the existing
|
|
73
|
+
* "No storeys/buildings found" warnings below) naming the child and the
|
|
74
|
+
* disqualified candidate - the only signal a caller gets that a
|
|
75
|
+
* malformed back-edge was found and repaired, short of building a
|
|
76
|
+
* dedicated report (out of scope here; see the #4208 semantic drop
|
|
77
|
+
* census for that shape of reporting - a different layer: per-STEP-class
|
|
78
|
+
* scan/retain counts collected during columnar categorization, not a
|
|
79
|
+
* graph-repair event like this one).
|
|
80
|
+
* 2. Only when a child has NO aggregates edge at all does a containment edge
|
|
81
|
+
* (IfcRelContainedInSpatialStructure targeting a spatial-structure type -
|
|
82
|
+
* the Revit Family/Dynamo `IfcSpace`/`IfcSpatialZone` pattern, #1075)
|
|
83
|
+
* get to claim it, with the same first-declared tie-break.
|
|
84
|
+
*
|
|
85
|
+
* `SpatialHierarchyBuilder.buildNode`'s `addSpatialChild` then only recurses
|
|
86
|
+
* into a child from its canonical parent - every other parent that also
|
|
87
|
+
* names the child drops the edge instead of adding an empty-stub duplicate
|
|
88
|
+
* (#4095).
|
|
89
|
+
*/
|
|
90
|
+
export function computeCanonicalParent(entities, relationships, options = {}) {
|
|
91
|
+
const canonicalParent = new Map();
|
|
92
|
+
const visitBudget = options.cycleCheckVisitBudget ?? CYCLE_CHECK_VISIT_BUDGET;
|
|
93
|
+
const cycleBudget = { visits: visitBudget };
|
|
94
|
+
let cycleBudgetExhausted = false;
|
|
95
|
+
const claimFirstDeclaredParent = (predicate, relType) => {
|
|
96
|
+
for (const childId of relationships.inverse.offsets.keys()) {
|
|
97
|
+
if (canonicalParent.has(childId) || !predicate(childId))
|
|
98
|
+
continue;
|
|
99
|
+
const edges = relationships.inverse.getEdges(childId, relType);
|
|
100
|
+
if (edges.length === 0)
|
|
101
|
+
continue;
|
|
102
|
+
// `edges[0]` is the first-declared edge of this type for this child -
|
|
103
|
+
// see the doc comment above for why the CSR preserves declaration
|
|
104
|
+
// order here. This mirrors apps/server's `canonical_parent`
|
|
105
|
+
// (`spatial.rs`), which does `entry(...).or_insert(...)` while
|
|
106
|
+
// iterating relationships in file-scan order: first occurrence wins.
|
|
107
|
+
let winner = edges[0];
|
|
108
|
+
if (relType === RelationshipType.Aggregates && edges.length > 1) {
|
|
109
|
+
// A child named as the target of more than one IfcRelAggregates is
|
|
110
|
+
// already a malformed file, but one shape needs a special rule: a
|
|
111
|
+
// BACK-EDGE, where a candidate parent P is itself a (possibly
|
|
112
|
+
// indirect) AGGREGATED DESCENDANT of this very child - i.e. taking P
|
|
113
|
+
// as childId's parent would close a cycle back through childId. That
|
|
114
|
+
// is the STEP-authoring-tool mistake of declaring an aggregation
|
|
115
|
+
// pair in both directions (#4246, the direct 2-node case; the same
|
|
116
|
+
// shape generalizes to a longer A->B->C->A chain). If the back-edge
|
|
117
|
+
// is declared before the real parent edge, plain first-declared-wins
|
|
118
|
+
// picks P as childId's canonical parent; P's own resolution (walking
|
|
119
|
+
// the SAME cycle) then independently lands back on a node inside the
|
|
120
|
+
// cycle too, so the whole cycle points at itself and none of it is
|
|
121
|
+
// reachable from IfcProject - orphaning whatever real subtree hung
|
|
122
|
+
// off any node in the cycle.
|
|
123
|
+
//
|
|
124
|
+
// Skip any candidate edge that closes a cycle through childId and
|
|
125
|
+
// take the first REMAINING candidate, still by declaration order -
|
|
126
|
+
// this changes nothing when a child has only one candidate (the
|
|
127
|
+
// overwhelmingly common case) or when none of its candidates close a
|
|
128
|
+
// cycle (the genuine multiple-real-parents case, #4095, which this
|
|
129
|
+
// loop never even sees more than one Aggregates edge for - #4095's
|
|
130
|
+
// contested child has exactly one Aggregates edge naming it; its
|
|
131
|
+
// OTHER "parent" only contains it). If EVERY candidate closes a
|
|
132
|
+
// cycle (a more degenerate file than anything observed), fall
|
|
133
|
+
// through to plain first-declared so the child is never left
|
|
134
|
+
// without a parent.
|
|
135
|
+
//
|
|
136
|
+
// One descendant walk per contested child (not per candidate), under a
|
|
137
|
+
// file-wide visit budget - see CYCLE_CHECK_VISIT_BUDGET.
|
|
138
|
+
const descendants = cycleBudgetExhausted ? null : aggregatedDescendants(childId, relationships, cycleBudget);
|
|
139
|
+
if (descendants === null) {
|
|
140
|
+
if (!cycleBudgetExhausted) {
|
|
141
|
+
cycleBudgetExhausted = true;
|
|
142
|
+
log.warn(`Aggregation back-edge cycle checks stopped after ${visitBudget} graph visits; ` +
|
|
143
|
+
'remaining multi-parent children resolve to their first-declared IfcRelAggregates edge');
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
else {
|
|
147
|
+
const rejected = [];
|
|
148
|
+
const nonCyclic = edges.find((edge) => {
|
|
149
|
+
const cyclic = descendants.has(edge.target);
|
|
150
|
+
if (cyclic)
|
|
151
|
+
rejected.push(edge.target);
|
|
152
|
+
return !cyclic;
|
|
153
|
+
});
|
|
154
|
+
if (nonCyclic && nonCyclic !== winner) {
|
|
155
|
+
log.warn(`Ignored ${rejected.length} aggregation back-edge cycle(s): #${childId} kept parent #${nonCyclic.target}, ` +
|
|
156
|
+
`not ${rejected.map((id) => `#${id}`).join(', ')} (each would have closed a cycle back through #${childId})`);
|
|
157
|
+
winner = nonCyclic;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
// Inverse edges flip source/target, so `target` here is the original
|
|
162
|
+
// relationship's `relating_id` (the parent).
|
|
163
|
+
canonicalParent.set(childId, winner.target);
|
|
164
|
+
}
|
|
165
|
+
};
|
|
166
|
+
// Pass 1: aggregation, unconditionally - it always wins.
|
|
167
|
+
claimFirstDeclaredParent(() => true, RelationshipType.Aggregates);
|
|
168
|
+
// Pass 2: promotion-by-containment, only for children aggregation left unclaimed.
|
|
169
|
+
claimFirstDeclaredParent((childId) => {
|
|
170
|
+
const childType = entities.getTypeEnum(childId);
|
|
171
|
+
return isSpatialStructureType(childType) && childType !== IfcTypeEnum.IfcProject;
|
|
172
|
+
}, RelationshipType.ContainsElements);
|
|
173
|
+
return canonicalParent;
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Which spatial-structure nodes will `SpatialHierarchyBuilder.buildNode`
|
|
177
|
+
* actually visit, starting from `projectId`? Mirrors `addSpatialChild`
|
|
178
|
+
* exactly: a node is visited iff it is `projectId` itself, or its
|
|
179
|
+
* `canonicalParent` entry points to an already-visited node - the same
|
|
180
|
+
* check `addSpatialChild` makes before recursing (`canonicalParent.get
|
|
181
|
+
* (childId) === expressId`). Computed as one forward walk over
|
|
182
|
+
* `canonicalParent` (childId -> parentId) up front, so a storey's
|
|
183
|
+
* reachability never depends on where in the traversal it happens to sit
|
|
184
|
+
* (#4310): a node named only by an unreachable storey - one with no path
|
|
185
|
+
* back to `projectId`, e.g. a malformed file where a storey has no
|
|
186
|
+
* `IfcRelAggregates` edge at all - is never in this set, exactly as
|
|
187
|
+
* `buildNode` would never recurse into it.
|
|
188
|
+
*/
|
|
189
|
+
export function computeReachableSpatialNodes(projectId, canonicalParent) {
|
|
190
|
+
const childrenOf = new Map();
|
|
191
|
+
for (const [childId, parentId] of canonicalParent) {
|
|
192
|
+
let siblings = childrenOf.get(parentId);
|
|
193
|
+
if (!siblings) {
|
|
194
|
+
siblings = [];
|
|
195
|
+
childrenOf.set(parentId, siblings);
|
|
196
|
+
}
|
|
197
|
+
siblings.push(childId);
|
|
198
|
+
}
|
|
199
|
+
const reachable = new Set([projectId]);
|
|
200
|
+
const stack = [projectId];
|
|
201
|
+
while (stack.length > 0) {
|
|
202
|
+
const current = stack.pop();
|
|
203
|
+
for (const childId of childrenOf.get(current) ?? []) {
|
|
204
|
+
if (reachable.has(childId))
|
|
205
|
+
continue; // also guards a canonicalParent cycle from looping forever
|
|
206
|
+
reachable.add(childId);
|
|
207
|
+
stack.push(childId);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
return reachable;
|
|
211
|
+
}
|
|
212
|
+
//# sourceMappingURL=spatial-hierarchy-canonical-parent.js.map
|