@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
|
@@ -0,0 +1,310 @@
|
|
|
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
|
+
/**
|
|
5
|
+
* Structural analysis extractor — parses IfcStructuralAnalysisModel,
|
|
6
|
+
* IfcStructuralMember / IfcStructuralConnection subtypes, IfcStructuralAction /
|
|
7
|
+
* IfcStructuralReaction subtypes, IfcStructuralLoadGroup / IfcStructuralLoadCase,
|
|
8
|
+
* IfcStructuralResultGroup, IfcBoundaryCondition, IfcRelConnectsStructuralMember,
|
|
9
|
+
* IfcRelConnectsStructuralActivity and IfcRelAssignsToGroup from a parsed
|
|
10
|
+
* IfcDataStore into a connected `StructuralExtraction`.
|
|
11
|
+
*
|
|
12
|
+
* On-demand, like the schedule extractor: nothing here runs during a normal
|
|
13
|
+
* parse, and a model with no structural entity costs one `byType` sweep.
|
|
14
|
+
*
|
|
15
|
+
* The two structural connects-relationships are read from the type index
|
|
16
|
+
* directly rather than from the relationship graph, because that graph's
|
|
17
|
+
* `REL_TYPE_MAP` carries neither of them — the rows are retained, but nothing
|
|
18
|
+
* indexes member↔connection or item↔activity edges for a query traversal to
|
|
19
|
+
* follow.
|
|
20
|
+
*
|
|
21
|
+
* Two things are schema-derived rather than hand-tabulated, because the
|
|
22
|
+
* alternative is a table that silently mis-reads the next subtype to appear:
|
|
23
|
+
*
|
|
24
|
+
* - **Which types count.** Every `IFCSTRUCTURAL*` key in the type index is
|
|
25
|
+
* classified by its inheritance chain, so `IfcStructuralCurveMemberVarying`
|
|
26
|
+
* is a member and `IfcStructuralLinearAction` is an action without either
|
|
27
|
+
* being named here.
|
|
28
|
+
* - **Where each attribute sits.** Positions come from the generated registry
|
|
29
|
+
* by EXPRESS attribute name, never from a literal index.
|
|
30
|
+
*
|
|
31
|
+
* IFC2X3 support is best-effort and the divergences are known, not assumed:
|
|
32
|
+
* 2X3 has no IfcStructuralCurveAction, IfcStructuralSurfaceAction,
|
|
33
|
+
* IfcStructuralCurveReaction, IfcStructuralLoadCase or
|
|
34
|
+
* IfcStructuralLoadConfiguration at all, and its IfcStructuralCurveMember has
|
|
35
|
+
* no `Axis`. Positions resolve against the parser's IFC4 registry pin, which
|
|
36
|
+
* agrees with 2X3 on the attributes both schemas share for every type read
|
|
37
|
+
* here; a 2X3-only attribute reads as absent rather than as the wrong slot.
|
|
38
|
+
*/
|
|
39
|
+
import { EntityExtractor } from './entity-extractor.js';
|
|
40
|
+
import { getInheritanceChain } from './ifc-schema.js';
|
|
41
|
+
import { extractBoundaryCondition, extractStructuralLoad, } from './structural-load-extractor.js';
|
|
42
|
+
import { addUnique, asBoolean, asEnum, asNumber, asNumberList, asRef, asRefList, asString, readAttr, readEntities, } from './structural-step-values.js';
|
|
43
|
+
function emptyExtraction() {
|
|
44
|
+
return {
|
|
45
|
+
analysisModels: [],
|
|
46
|
+
members: [],
|
|
47
|
+
connections: [],
|
|
48
|
+
activities: [],
|
|
49
|
+
loadGroups: [],
|
|
50
|
+
resultGroups: [],
|
|
51
|
+
hasStructural: false,
|
|
52
|
+
loadsTruncated: false,
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
/** Chain marker → role. Every marker is disjoint, so match order is not load-bearing. */
|
|
56
|
+
const ROLE_BY_SUPERTYPE = [
|
|
57
|
+
['IFCSTRUCTURALANALYSISMODEL', 'analysisModel'],
|
|
58
|
+
['IFCSTRUCTURALRESULTGROUP', 'resultGroup'],
|
|
59
|
+
['IFCSTRUCTURALLOADGROUP', 'loadGroup'],
|
|
60
|
+
['IFCSTRUCTURALMEMBER', 'member'],
|
|
61
|
+
['IFCSTRUCTURALCONNECTION', 'connection'],
|
|
62
|
+
['IFCSTRUCTURALACTIVITY', 'activity'],
|
|
63
|
+
];
|
|
64
|
+
/**
|
|
65
|
+
* Classify a concrete type by inheritance, not by name. Returns undefined for
|
|
66
|
+
* an `IFCSTRUCTURAL*` type that is none of the six roles — `IfcStructuralLoad`
|
|
67
|
+
* leaves and `IfcStructuralProfileProperties` reach here and are read through
|
|
68
|
+
* their owners instead.
|
|
69
|
+
*/
|
|
70
|
+
function roleOf(type) {
|
|
71
|
+
const chain = getInheritanceChain(type).map((c) => c.toUpperCase());
|
|
72
|
+
for (const [marker, role] of ROLE_BY_SUPERTYPE) {
|
|
73
|
+
if (chain.includes(marker))
|
|
74
|
+
return role;
|
|
75
|
+
}
|
|
76
|
+
return undefined;
|
|
77
|
+
}
|
|
78
|
+
function activityKind(type) {
|
|
79
|
+
const chain = getInheritanceChain(type).map((c) => c.toUpperCase());
|
|
80
|
+
if (chain.includes('IFCSTRUCTURALACTION'))
|
|
81
|
+
return 'Action';
|
|
82
|
+
if (chain.includes('IFCSTRUCTURALREACTION'))
|
|
83
|
+
return 'Reaction';
|
|
84
|
+
return 'Unknown';
|
|
85
|
+
}
|
|
86
|
+
/** IfcRoot attribute 2 is Name, 3 Description; IfcObject adds ObjectType at 4. */
|
|
87
|
+
function rootFields(e) {
|
|
88
|
+
return {
|
|
89
|
+
name: asString(e.attrs[2]),
|
|
90
|
+
description: asString(e.attrs[3]),
|
|
91
|
+
objectType: asString(e.attrs[4]),
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Extract all structural analysis data from a parsed IFC store.
|
|
96
|
+
*/
|
|
97
|
+
export function extractStructuralOnDemand(store) {
|
|
98
|
+
if (!store.source?.length)
|
|
99
|
+
return emptyExtraction();
|
|
100
|
+
const byType = store.entityIndex.byType;
|
|
101
|
+
// Partition every IFCSTRUCTURAL* type present into the six roles.
|
|
102
|
+
const idsByRole = new Map();
|
|
103
|
+
for (const [typeKey, ids] of byType) {
|
|
104
|
+
if (!typeKey.startsWith('IFCSTRUCTURAL'))
|
|
105
|
+
continue;
|
|
106
|
+
const role = roleOf(typeKey);
|
|
107
|
+
if (!role)
|
|
108
|
+
continue;
|
|
109
|
+
const bucket = idsByRole.get(role);
|
|
110
|
+
if (bucket)
|
|
111
|
+
bucket.push(...ids);
|
|
112
|
+
else
|
|
113
|
+
idsByRole.set(role, [...ids]);
|
|
114
|
+
}
|
|
115
|
+
const relMemberIds = byType.get('IFCRELCONNECTSSTRUCTURALMEMBER') ?? [];
|
|
116
|
+
const relActivityIds = byType.get('IFCRELCONNECTSSTRUCTURALACTIVITY') ?? [];
|
|
117
|
+
const relGroupIds = byType.get('IFCRELASSIGNSTOGROUP') ?? [];
|
|
118
|
+
// Behaviour-neutral early-out, not a guard: with no structural entity the
|
|
119
|
+
// passes below already produce an empty extraction. It exists so the common
|
|
120
|
+
// case — a model with no structural analysis at all — never constructs an
|
|
121
|
+
// EntityExtractor over the whole source buffer.
|
|
122
|
+
if (idsByRole.size === 0)
|
|
123
|
+
return emptyExtraction();
|
|
124
|
+
const extractor = new EntityExtractor(store.source);
|
|
125
|
+
const read = (role) => readEntities(extractor, store, idsByRole.get(role) ?? []);
|
|
126
|
+
const memberRaw = read('member');
|
|
127
|
+
const connectionRaw = read('connection');
|
|
128
|
+
const activityRaw = read('activity');
|
|
129
|
+
const loadGroupRaw = read('loadGroup');
|
|
130
|
+
const resultGroupRaw = read('resultGroup');
|
|
131
|
+
const analysisModelRaw = read('analysisModel');
|
|
132
|
+
/** expressId → globalId, over every structural entity we resolved. */
|
|
133
|
+
const globalIdById = new Map();
|
|
134
|
+
for (const list of [
|
|
135
|
+
memberRaw,
|
|
136
|
+
connectionRaw,
|
|
137
|
+
activityRaw,
|
|
138
|
+
loadGroupRaw,
|
|
139
|
+
resultGroupRaw,
|
|
140
|
+
analysisModelRaw,
|
|
141
|
+
]) {
|
|
142
|
+
for (const e of list)
|
|
143
|
+
if (e.globalId)
|
|
144
|
+
globalIdById.set(e.expressId, e.globalId);
|
|
145
|
+
}
|
|
146
|
+
// ── Relationship passes ────────────────────────────────────────────────
|
|
147
|
+
const connectionsOfMember = new Map();
|
|
148
|
+
const membersOfConnection = new Map();
|
|
149
|
+
for (const rel of readEntities(extractor, store, relMemberIds)) {
|
|
150
|
+
const memberId = asRef(readAttr(rel.type, rel.attrs, 'RelatingStructuralMember'));
|
|
151
|
+
const connectionId = asRef(readAttr(rel.type, rel.attrs, 'RelatedStructuralConnection'));
|
|
152
|
+
if (memberId === undefined || connectionId === undefined)
|
|
153
|
+
continue;
|
|
154
|
+
const memberGid = globalIdById.get(memberId);
|
|
155
|
+
const connectionGid = globalIdById.get(connectionId);
|
|
156
|
+
if (connectionGid)
|
|
157
|
+
addUnique(connectionsOfMember, memberId, connectionGid);
|
|
158
|
+
if (memberGid)
|
|
159
|
+
addUnique(membersOfConnection, connectionId, memberGid);
|
|
160
|
+
}
|
|
161
|
+
const activitiesOfItem = new Map();
|
|
162
|
+
/** activity expressId → the item globalId it applies to. */
|
|
163
|
+
const itemOfActivity = new Map();
|
|
164
|
+
for (const rel of readEntities(extractor, store, relActivityIds)) {
|
|
165
|
+
const itemId = asRef(readAttr(rel.type, rel.attrs, 'RelatingElement'));
|
|
166
|
+
const activityId = asRef(readAttr(rel.type, rel.attrs, 'RelatedStructuralActivity'));
|
|
167
|
+
if (itemId === undefined || activityId === undefined)
|
|
168
|
+
continue;
|
|
169
|
+
const activityGid = globalIdById.get(activityId);
|
|
170
|
+
const itemGid = globalIdById.get(itemId);
|
|
171
|
+
if (activityGid)
|
|
172
|
+
addUnique(activitiesOfItem, itemId, activityGid);
|
|
173
|
+
if (itemGid)
|
|
174
|
+
itemOfActivity.set(activityId, itemGid);
|
|
175
|
+
}
|
|
176
|
+
// IfcRelAssignsToGroup is shared with every other grouping in the file, so
|
|
177
|
+
// only the rows whose RelatingGroup is a structural group are read.
|
|
178
|
+
const groupsOfObject = new Map();
|
|
179
|
+
const objectsOfGroup = new Map();
|
|
180
|
+
for (const rel of readEntities(extractor, store, relGroupIds)) {
|
|
181
|
+
const groupId = asRef(readAttr(rel.type, rel.attrs, 'RelatingGroup'));
|
|
182
|
+
if (groupId === undefined)
|
|
183
|
+
continue;
|
|
184
|
+
const groupGid = globalIdById.get(groupId);
|
|
185
|
+
if (!groupGid)
|
|
186
|
+
continue;
|
|
187
|
+
for (const objectId of asRefList(readAttr(rel.type, rel.attrs, 'RelatedObjects'))) {
|
|
188
|
+
addUnique(groupsOfObject, objectId, groupGid);
|
|
189
|
+
const objectGid = globalIdById.get(objectId);
|
|
190
|
+
if (objectGid)
|
|
191
|
+
addUnique(objectsOfGroup, groupId, objectGid);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* A group's `RelatedObjects` may hold anything, and IfcRelAssignsToGroup is
|
|
196
|
+
* not structural-specific, so each of the three directions below is narrowed
|
|
197
|
+
* to the role its field name promises rather than reporting the raw set.
|
|
198
|
+
*/
|
|
199
|
+
const gidsOf = (lists) => new Set(lists.flat().map((e) => e.globalId).filter((g) => g.length > 0));
|
|
200
|
+
const analysisModelGids = gidsOf([analysisModelRaw]);
|
|
201
|
+
const activityGids = gidsOf([activityRaw]);
|
|
202
|
+
const itemGids = gidsOf([memberRaw, connectionRaw]);
|
|
203
|
+
/** Only those of `expressId`'s groups that are analysis models. */
|
|
204
|
+
const modelsOf = (expressId) => (groupsOfObject.get(expressId) ?? []).filter((g) => analysisModelGids.has(g));
|
|
205
|
+
/** Only the activities assigned into the group `expressId`. */
|
|
206
|
+
const activitiesIn = (expressId) => (objectsOfGroup.get(expressId) ?? []).filter((g) => activityGids.has(g));
|
|
207
|
+
/** Only the members and connections assigned into the group `expressId`. */
|
|
208
|
+
const itemsIn = (expressId) => (objectsOfGroup.get(expressId) ?? []).filter((g) => itemGids.has(g));
|
|
209
|
+
const resolveGids = (value) => asRefList(value)
|
|
210
|
+
.map((id) => globalIdById.get(id))
|
|
211
|
+
.filter((g) => g !== undefined);
|
|
212
|
+
// ── Assemble ───────────────────────────────────────────────────────────
|
|
213
|
+
const members = memberRaw.map((e) => ({
|
|
214
|
+
expressId: e.expressId,
|
|
215
|
+
globalId: e.globalId,
|
|
216
|
+
type: e.type,
|
|
217
|
+
...rootFields(e),
|
|
218
|
+
predefinedType: asEnum(readAttr(e.type, e.attrs, 'PredefinedType')),
|
|
219
|
+
thickness: asNumber(readAttr(e.type, e.attrs, 'Thickness')),
|
|
220
|
+
connectionGlobalIds: connectionsOfMember.get(e.expressId) ?? [],
|
|
221
|
+
activityGlobalIds: activitiesOfItem.get(e.expressId) ?? [],
|
|
222
|
+
analysisModelGlobalIds: modelsOf(e.expressId),
|
|
223
|
+
}));
|
|
224
|
+
const connections = connectionRaw.map((e) => {
|
|
225
|
+
const conditionId = asRef(readAttr(e.type, e.attrs, 'AppliedCondition'));
|
|
226
|
+
return {
|
|
227
|
+
expressId: e.expressId,
|
|
228
|
+
globalId: e.globalId,
|
|
229
|
+
type: e.type,
|
|
230
|
+
...rootFields(e),
|
|
231
|
+
appliedCondition: conditionId === undefined
|
|
232
|
+
? undefined
|
|
233
|
+
: extractBoundaryCondition(extractor, store, conditionId),
|
|
234
|
+
memberGlobalIds: membersOfConnection.get(e.expressId) ?? [],
|
|
235
|
+
activityGlobalIds: activitiesOfItem.get(e.expressId) ?? [],
|
|
236
|
+
analysisModelGlobalIds: modelsOf(e.expressId),
|
|
237
|
+
};
|
|
238
|
+
});
|
|
239
|
+
const activities = activityRaw.map((e) => {
|
|
240
|
+
const loadId = asRef(readAttr(e.type, e.attrs, 'AppliedLoad'));
|
|
241
|
+
return {
|
|
242
|
+
expressId: e.expressId,
|
|
243
|
+
globalId: e.globalId,
|
|
244
|
+
type: e.type,
|
|
245
|
+
kind: activityKind(e.type),
|
|
246
|
+
...rootFields(e),
|
|
247
|
+
predefinedType: asEnum(readAttr(e.type, e.attrs, 'PredefinedType')),
|
|
248
|
+
globalOrLocal: asEnum(readAttr(e.type, e.attrs, 'GlobalOrLocal')),
|
|
249
|
+
destabilizingLoad: asBoolean(readAttr(e.type, e.attrs, 'DestabilizingLoad')),
|
|
250
|
+
appliedLoad: loadId === undefined ? undefined : extractStructuralLoad(extractor, store, loadId),
|
|
251
|
+
appliesToGlobalId: itemOfActivity.get(e.expressId),
|
|
252
|
+
groupGlobalIds: groupsOfObject.get(e.expressId) ?? [],
|
|
253
|
+
};
|
|
254
|
+
});
|
|
255
|
+
const loadGroups = loadGroupRaw.map((e) => ({
|
|
256
|
+
expressId: e.expressId,
|
|
257
|
+
globalId: e.globalId,
|
|
258
|
+
type: e.type,
|
|
259
|
+
...rootFields(e),
|
|
260
|
+
predefinedType: asEnum(readAttr(e.type, e.attrs, 'PredefinedType')),
|
|
261
|
+
actionType: asEnum(readAttr(e.type, e.attrs, 'ActionType')),
|
|
262
|
+
actionSource: asEnum(readAttr(e.type, e.attrs, 'ActionSource')),
|
|
263
|
+
coefficient: asNumber(readAttr(e.type, e.attrs, 'Coefficient')),
|
|
264
|
+
purpose: asString(readAttr(e.type, e.attrs, 'Purpose')),
|
|
265
|
+
selfWeightCoefficients: asNumberList(readAttr(e.type, e.attrs, 'SelfWeightCoefficients')),
|
|
266
|
+
activityGlobalIds: activitiesIn(e.expressId),
|
|
267
|
+
}));
|
|
268
|
+
const resultGroups = resultGroupRaw.map((e) => {
|
|
269
|
+
const forLoadGroup = asRef(readAttr(e.type, e.attrs, 'ResultForLoadGroup'));
|
|
270
|
+
return {
|
|
271
|
+
expressId: e.expressId,
|
|
272
|
+
globalId: e.globalId,
|
|
273
|
+
...rootFields(e),
|
|
274
|
+
theoryType: asEnum(readAttr(e.type, e.attrs, 'TheoryType')),
|
|
275
|
+
isLinear: asBoolean(readAttr(e.type, e.attrs, 'IsLinear')),
|
|
276
|
+
resultForLoadGroupGlobalId: forLoadGroup === undefined ? undefined : globalIdById.get(forLoadGroup),
|
|
277
|
+
activityGlobalIds: activitiesIn(e.expressId),
|
|
278
|
+
};
|
|
279
|
+
});
|
|
280
|
+
const analysisModels = analysisModelRaw.map((e) => ({
|
|
281
|
+
expressId: e.expressId,
|
|
282
|
+
globalId: e.globalId,
|
|
283
|
+
...rootFields(e),
|
|
284
|
+
predefinedType: asEnum(readAttr(e.type, e.attrs, 'PredefinedType')),
|
|
285
|
+
loadGroupGlobalIds: resolveGids(readAttr(e.type, e.attrs, 'LoadedBy')),
|
|
286
|
+
resultGroupGlobalIds: resolveGids(readAttr(e.type, e.attrs, 'HasResults')),
|
|
287
|
+
itemGlobalIds: itemsIn(e.expressId),
|
|
288
|
+
}));
|
|
289
|
+
return {
|
|
290
|
+
analysisModels,
|
|
291
|
+
members,
|
|
292
|
+
connections,
|
|
293
|
+
activities,
|
|
294
|
+
loadGroups,
|
|
295
|
+
resultGroups,
|
|
296
|
+
hasStructural: analysisModels.length +
|
|
297
|
+
members.length +
|
|
298
|
+
connections.length +
|
|
299
|
+
activities.length +
|
|
300
|
+
loadGroups.length +
|
|
301
|
+
resultGroups.length >
|
|
302
|
+
0,
|
|
303
|
+
// Derived from the loads rather than tracked alongside them, so the
|
|
304
|
+
// extraction cannot claim a completeness its own tree contradicts. A
|
|
305
|
+
// nested configuration propagates its truncation to its parent, so the
|
|
306
|
+
// top-level load carries the whole subtree's answer.
|
|
307
|
+
loadsTruncated: activities.some((a) => a.appliedLoad?.configuration?.truncated === true),
|
|
308
|
+
};
|
|
309
|
+
}
|
|
310
|
+
//# sourceMappingURL=structural-extractor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"structural-extractor.js","sourceRoot":"","sources":["../src/structural-extractor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Structural load and boundary-condition readers — the leaf resources an
|
|
3
|
+
* activity's `AppliedLoad` and a connection's `AppliedCondition` point at.
|
|
4
|
+
*
|
|
5
|
+
* Both readers are **schema-derived**: they ask the generated registry for the
|
|
6
|
+
* entity's attribute names in STEP positional order and emit every numeric
|
|
7
|
+
* component under its exact EXPRESS name, rather than carrying a hand-written
|
|
8
|
+
* table per `IfcStructuralLoadStatic` / `IfcBoundaryCondition` subtype. A
|
|
9
|
+
* subtype the registry knows therefore reads correctly the day it appears in a
|
|
10
|
+
* file, and `IfcStructuralLoadSingleForceWarping.WarpingMoment` needs no
|
|
11
|
+
* separate case from `IfcStructuralLoadSingleForce.ForceX`.
|
|
12
|
+
*/
|
|
13
|
+
import type { EntityExtractor } from './entity-extractor.js';
|
|
14
|
+
import type { IfcDataStore } from './columnar-parser.js';
|
|
15
|
+
/**
|
|
16
|
+
* One `IfcStructuralLoadOrResult` leaf — a force, displacement, temperature or
|
|
17
|
+
* planar/linear force — reduced to its named numeric components.
|
|
18
|
+
*/
|
|
19
|
+
export interface StructuralLoadInfo {
|
|
20
|
+
expressId: number;
|
|
21
|
+
/** Canonical EXPRESS type name, e.g. `IfcStructuralLoadSingleForce`. */
|
|
22
|
+
type: string;
|
|
23
|
+
name?: string;
|
|
24
|
+
/**
|
|
25
|
+
* Numeric components keyed by their exact EXPRESS attribute name
|
|
26
|
+
* (`ForceX`, `MomentZ`, `DisplacementY`, `DeltaTConstant`, …). Only
|
|
27
|
+
* attributes the file actually carries a finite number for appear; an
|
|
28
|
+
* omitted (`$`) optional is absent rather than zero, because zero is a
|
|
29
|
+
* meaningful load value and conflating the two would invent data.
|
|
30
|
+
*/
|
|
31
|
+
components: Record<string, number>;
|
|
32
|
+
/**
|
|
33
|
+
* Present only for `IfcStructuralLoadConfiguration`: the nested loads and
|
|
34
|
+
* the parametric locations they apply at, as {@link StructuralLoadConfigurationInfo}.
|
|
35
|
+
*/
|
|
36
|
+
configuration?: StructuralLoadConfigurationInfo;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Why one `Values` slot carries no nested load.
|
|
40
|
+
*
|
|
41
|
+
* The first three are **our** bounds firing — the file may hold more than we
|
|
42
|
+
* agreed to read, and {@link StructuralLoadConfigurationInfo.truncated} is set.
|
|
43
|
+
* The last three are the file's own data: there is nothing further to read, so
|
|
44
|
+
* they are not truncation.
|
|
45
|
+
*/
|
|
46
|
+
export type StructuralLoadDropReason =
|
|
47
|
+
/** Below the nesting cap: the chain is longer than this reader follows. */
|
|
48
|
+
'depth'
|
|
49
|
+
/** The slot re-enters a configuration already open on this path. */
|
|
50
|
+
| 'cycle'
|
|
51
|
+
/** The node budget for this top-level load was spent before this slot. */
|
|
52
|
+
| 'budget'
|
|
53
|
+
/** The slot is not an entity reference at all (`$`, an inline value, …). */
|
|
54
|
+
| 'invalid-reference'
|
|
55
|
+
/** The referenced expressId is in no index — a dangling reference. */
|
|
56
|
+
| 'unresolved'
|
|
57
|
+
/** The referenced record is indexed but did not parse. */
|
|
58
|
+
| 'unreadable';
|
|
59
|
+
/** One `Values` slot of an `IfcStructuralLoadConfiguration`, with its location. */
|
|
60
|
+
export interface StructuralLoadConfigurationEntry {
|
|
61
|
+
/** The nested load, absent when the slot could not be read. */
|
|
62
|
+
value?: StructuralLoadInfo;
|
|
63
|
+
/** Why {@link value} is absent; absent whenever `value` is present. */
|
|
64
|
+
dropped?: StructuralLoadDropReason;
|
|
65
|
+
/**
|
|
66
|
+
* The `Locations` row at this same slot, when the file carries one. Absent
|
|
67
|
+
* when the file omits the optional `Locations`, lists fewer rows than
|
|
68
|
+
* `Values` has slots, or writes this row as `$` / with a non-numeric cell
|
|
69
|
+
* (the row keeps its position as an empty placeholder in `locations`).
|
|
70
|
+
*/
|
|
71
|
+
location?: number[];
|
|
72
|
+
}
|
|
73
|
+
/** The `Values`/`Locations` pair of an `IfcStructuralLoadConfiguration`. */
|
|
74
|
+
export interface StructuralLoadConfigurationInfo {
|
|
75
|
+
/**
|
|
76
|
+
* One entry per `Values` slot, in file order. The pairing the schema
|
|
77
|
+
* requires — the i-th location positions the i-th value — is carried inside
|
|
78
|
+
* the entry rather than across two arrays, so a slot this reader could not
|
|
79
|
+
* resolve keeps its place with `value` absent and `dropped` naming why. A
|
|
80
|
+
* dropped slot that instead shifted its successors left would report a later
|
|
81
|
+
* load as applied at an earlier station, which reads as real data.
|
|
82
|
+
*/
|
|
83
|
+
entries: StructuralLoadConfigurationEntry[];
|
|
84
|
+
/**
|
|
85
|
+
* `Locations` as the file writes it, absent when the file omits it or writes
|
|
86
|
+
* it unusably. Kept beside {@link entries} for the malformed case where it is
|
|
87
|
+
* longer than `Values`: those extra rows belong to no slot and would
|
|
88
|
+
* otherwise be lost. Consumers pairing a load with its station read
|
|
89
|
+
* `entries[i].location`, never this list.
|
|
90
|
+
*/
|
|
91
|
+
locations?: number[][];
|
|
92
|
+
/**
|
|
93
|
+
* True when a bound of this reader — the depth cap, the node budget, or the
|
|
94
|
+
* cycle guard — dropped a slot in this configuration or anywhere beneath it.
|
|
95
|
+
* It separates "the file holds no more" from "we stopped reading", which a
|
|
96
|
+
* truncated tree otherwise reports identically to a genuinely small one.
|
|
97
|
+
*/
|
|
98
|
+
truncated: boolean;
|
|
99
|
+
}
|
|
100
|
+
/** An `IfcBoundaryCondition` leaf reduced to its named stiffness components. */
|
|
101
|
+
export interface BoundaryConditionInfo {
|
|
102
|
+
expressId: number;
|
|
103
|
+
/** Canonical EXPRESS type name, e.g. `IfcBoundaryNodeCondition`. */
|
|
104
|
+
type: string;
|
|
105
|
+
name?: string;
|
|
106
|
+
/**
|
|
107
|
+
* Stiffness components keyed by their exact EXPRESS attribute name
|
|
108
|
+
* (`TranslationalStiffnessX`, `RotationalStiffnessZ`, …).
|
|
109
|
+
*
|
|
110
|
+
* The value is a number when the file gives a stiffness magnitude, and a
|
|
111
|
+
* boolean when it uses the select's `IfcBoolean` branch — which is how a
|
|
112
|
+
* fully fixed or fully free degree of freedom is written (`.T.` = fixed).
|
|
113
|
+
* Collapsing the boolean branch to a number would report a rigid support as
|
|
114
|
+
* stiffness 1.
|
|
115
|
+
*/
|
|
116
|
+
components: Record<string, number | boolean>;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Read one `IfcStructuralLoad` entity by expressId, resolving an
|
|
120
|
+
* `IfcStructuralLoadConfiguration` down through the loads its `Values` name.
|
|
121
|
+
*
|
|
122
|
+
* The `Values` edge is the only recursive one here, and it is
|
|
123
|
+
* exporter-controlled, so it is bounded three ways — none of which is
|
|
124
|
+
* redundant:
|
|
125
|
+
*
|
|
126
|
+
* - a **path-local** cycle set stops a configuration that reaches itself. It
|
|
127
|
+
* has to be path-local rather than shared across siblings, because `Values`
|
|
128
|
+
* is a LIST and may legitimately name one load twice; a shared set would
|
|
129
|
+
* suppress the repeat as if it were a cycle and report one load where the
|
|
130
|
+
* file applies two.
|
|
131
|
+
* - a **depth cap** bounds one chain's length, which the cycle set alone does
|
|
132
|
+
* not for a long acyclic chain.
|
|
133
|
+
* - a **node budget** bounds total work. The first two still admit `k`
|
|
134
|
+
* children each recursing `k` deep, which is O(k^depth) — an abort turned
|
|
135
|
+
* into a hang, and a hang reports nothing.
|
|
136
|
+
*
|
|
137
|
+
* All three bounds, and every reference this reader cannot follow for the
|
|
138
|
+
* file's own reasons, keep the `Values` slot they gave up on: the slot becomes
|
|
139
|
+
* an entry with no `value` and a `dropped` reason naming which it was, so
|
|
140
|
+
* the station a `Locations` row names still belongs to the load the file put
|
|
141
|
+
* there. Only the three bounds set `truncated`, since only they mean the file
|
|
142
|
+
* holds more than this reader agreed to walk.
|
|
143
|
+
*/
|
|
144
|
+
export declare function extractStructuralLoad(extractor: EntityExtractor, store: IfcDataStore, expressId: number): StructuralLoadInfo | undefined;
|
|
145
|
+
/** Read one `IfcBoundaryCondition` entity by expressId. */
|
|
146
|
+
export declare function extractBoundaryCondition(extractor: EntityExtractor, store: IfcDataStore, expressId: number): BoundaryConditionInfo | undefined;
|
|
147
|
+
//# sourceMappingURL=structural-load-extractor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"structural-load-extractor.d.ts","sourceRoot":"","sources":["../src/structural-load-extractor.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAkBzD;;;GAGG;AACH,MAAM,WAAW,kBAAkB;IACjC,SAAS,EAAE,MAAM,CAAC;IAClB,wEAAwE;IACxE,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;;;OAMG;IACH,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC;;;OAGG;IACH,aAAa,CAAC,EAAE,+BAA+B,CAAC;CACjD;AAED;;;;;;;GAOG;AACH,MAAM,MAAM,wBAAwB;AAClC,2EAA2E;AACzE,OAAO;AACT,oEAAoE;GAClE,OAAO;AACT,0EAA0E;GACxE,QAAQ;AACV,4EAA4E;GAC1E,mBAAmB;AACrB,sEAAsE;GACpE,YAAY;AACd,0DAA0D;GACxD,YAAY,CAAC;AAEjB,mFAAmF;AACnF,MAAM,WAAW,gCAAgC;IAC/C,+DAA+D;IAC/D,KAAK,CAAC,EAAE,kBAAkB,CAAC;IAC3B,uEAAuE;IACvE,OAAO,CAAC,EAAE,wBAAwB,CAAC;IACnC;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;CACrB;AAED,4EAA4E;AAC5E,MAAM,WAAW,+BAA+B;IAC9C;;;;;;;OAOG;IACH,OAAO,EAAE,gCAAgC,EAAE,CAAC;IAC5C;;;;;;OAMG;IACH,SAAS,CAAC,EAAE,MAAM,EAAE,EAAE,CAAC;IACvB;;;;;OAKG;IACH,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,gFAAgF;AAChF,MAAM,WAAW,qBAAqB;IACpC,SAAS,EAAE,MAAM,CAAC;IAClB,oEAAoE;IACpE,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;;;;;;OASG;IACH,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC;CAC9C;AA0BD;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,qBAAqB,CACnC,SAAS,EAAE,eAAe,EAC1B,KAAK,EAAE,YAAY,EACnB,SAAS,EAAE,MAAM,GAChB,kBAAkB,GAAG,SAAS,CAEhC;AA8FD,2DAA2D;AAC3D,wBAAgB,wBAAwB,CACtC,SAAS,EAAE,eAAe,EAC1B,KAAK,EAAE,YAAY,EACnB,SAAS,EAAE,MAAM,GAChB,qBAAqB,GAAG,SAAS,CA0BnC"}
|
|
@@ -0,0 +1,178 @@
|
|
|
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 { getAttributeNames, normalizeIfcTypeName } from './ifc-schema.js';
|
|
5
|
+
import { asBoolean, asNumber, asString } from './structural-step-values.js';
|
|
6
|
+
/** Attributes that every load/condition carries from its supertype, not a component. */
|
|
7
|
+
const NAME_ATTR = 'Name';
|
|
8
|
+
/**
|
|
9
|
+
* `IfcStructuralLoadConfiguration` positional attributes. Named here rather
|
|
10
|
+
* than resolved by name because this is the one load whose components are
|
|
11
|
+
* references and lists instead of measures.
|
|
12
|
+
*/
|
|
13
|
+
const LOAD_CONFIGURATION_ATTR = {
|
|
14
|
+
Name: 0,
|
|
15
|
+
Values: 1,
|
|
16
|
+
Locations: 2,
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Read the `Locations` attribute of an `IfcStructuralLoadConfiguration`: a
|
|
20
|
+
* list of 1..2-element lists of `IfcLengthMeasure`.
|
|
21
|
+
*/
|
|
22
|
+
function readLocations(value) {
|
|
23
|
+
if (!Array.isArray(value))
|
|
24
|
+
return undefined;
|
|
25
|
+
// A flat scalar list (`(0.,4.5)` instead of `((0.),(4.5))`) is unusable as
|
|
26
|
+
// a whole. Otherwise keep one row per slot so `Values[i]` still pairs with
|
|
27
|
+
// `Locations[i]`: a `$` row or a row with a non-numeric cell becomes an
|
|
28
|
+
// EMPTY placeholder rather than being dropped (which would shift every
|
|
29
|
+
// later row onto the wrong slot) or compacted.
|
|
30
|
+
if (!value.some((row) => Array.isArray(row)))
|
|
31
|
+
return undefined;
|
|
32
|
+
return value.map((row) => {
|
|
33
|
+
if (!Array.isArray(row))
|
|
34
|
+
return [];
|
|
35
|
+
const nums = row.map(asNumber);
|
|
36
|
+
return nums.every((n) => n !== undefined) ? nums : [];
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
/** Longest chain of nested configurations followed before giving up. */
|
|
40
|
+
const MAX_LOAD_DEPTH = 4;
|
|
41
|
+
/** Ceiling on entities expanded by one top-level load read. */
|
|
42
|
+
const MAX_LOAD_NODES = 256;
|
|
43
|
+
/**
|
|
44
|
+
* Read one `IfcStructuralLoad` entity by expressId, resolving an
|
|
45
|
+
* `IfcStructuralLoadConfiguration` down through the loads its `Values` name.
|
|
46
|
+
*
|
|
47
|
+
* The `Values` edge is the only recursive one here, and it is
|
|
48
|
+
* exporter-controlled, so it is bounded three ways — none of which is
|
|
49
|
+
* redundant:
|
|
50
|
+
*
|
|
51
|
+
* - a **path-local** cycle set stops a configuration that reaches itself. It
|
|
52
|
+
* has to be path-local rather than shared across siblings, because `Values`
|
|
53
|
+
* is a LIST and may legitimately name one load twice; a shared set would
|
|
54
|
+
* suppress the repeat as if it were a cycle and report one load where the
|
|
55
|
+
* file applies two.
|
|
56
|
+
* - a **depth cap** bounds one chain's length, which the cycle set alone does
|
|
57
|
+
* not for a long acyclic chain.
|
|
58
|
+
* - a **node budget** bounds total work. The first two still admit `k`
|
|
59
|
+
* children each recursing `k` deep, which is O(k^depth) — an abort turned
|
|
60
|
+
* into a hang, and a hang reports nothing.
|
|
61
|
+
*
|
|
62
|
+
* All three bounds, and every reference this reader cannot follow for the
|
|
63
|
+
* file's own reasons, keep the `Values` slot they gave up on: the slot becomes
|
|
64
|
+
* an entry with no `value` and a `dropped` reason naming which it was, so
|
|
65
|
+
* the station a `Locations` row names still belongs to the load the file put
|
|
66
|
+
* there. Only the three bounds set `truncated`, since only they mean the file
|
|
67
|
+
* holds more than this reader agreed to walk.
|
|
68
|
+
*/
|
|
69
|
+
export function extractStructuralLoad(extractor, store, expressId) {
|
|
70
|
+
return readLoad(extractor, store, expressId, new Set(), { remaining: MAX_LOAD_NODES }, 0).value;
|
|
71
|
+
}
|
|
72
|
+
function readLoad(extractor, store, expressId, path, budget, depth) {
|
|
73
|
+
if (depth > MAX_LOAD_DEPTH)
|
|
74
|
+
return { dropped: 'depth', truncated: true };
|
|
75
|
+
if (path.has(expressId))
|
|
76
|
+
return { dropped: 'cycle', truncated: true };
|
|
77
|
+
if (budget.remaining <= 0)
|
|
78
|
+
return { dropped: 'budget', truncated: true };
|
|
79
|
+
const ref = store.entityIndex.byId.get(expressId);
|
|
80
|
+
if (!ref)
|
|
81
|
+
return { dropped: 'unresolved', truncated: false };
|
|
82
|
+
const entity = extractor.extractEntity(ref);
|
|
83
|
+
if (!entity)
|
|
84
|
+
return { dropped: 'unreadable', truncated: false };
|
|
85
|
+
budget.remaining--;
|
|
86
|
+
const type = normalizeIfcTypeName(entity.type);
|
|
87
|
+
const attrs = entity.attributes || [];
|
|
88
|
+
if (type.toUpperCase() === 'IFCSTRUCTURALLOADCONFIGURATION') {
|
|
89
|
+
const locations = readLocations(attrs[LOAD_CONFIGURATION_ATTR.Locations]);
|
|
90
|
+
const entries = [];
|
|
91
|
+
let truncated = false;
|
|
92
|
+
const values = attrs[LOAD_CONFIGURATION_ATTR.Values];
|
|
93
|
+
if (Array.isArray(values)) {
|
|
94
|
+
// On this node's path only — removed again below so a sibling that
|
|
95
|
+
// names the same load still reads it.
|
|
96
|
+
path.add(expressId);
|
|
97
|
+
for (let i = 0; i < values.length; i++) {
|
|
98
|
+
const v = values[i];
|
|
99
|
+
const row = locations?.[i];
|
|
100
|
+
const location = row && row.length > 0 ? row : undefined; // empty = placeholder for an unusable row
|
|
101
|
+
const slot = typeof v === 'number' && Number.isInteger(v) && v > 0
|
|
102
|
+
? readLoad(extractor, store, v, path, budget, depth + 1)
|
|
103
|
+
: { dropped: 'invalid-reference', truncated: false };
|
|
104
|
+
if (slot.truncated)
|
|
105
|
+
truncated = true;
|
|
106
|
+
entries.push({ value: slot.value, dropped: slot.dropped, location });
|
|
107
|
+
}
|
|
108
|
+
path.delete(expressId);
|
|
109
|
+
}
|
|
110
|
+
return {
|
|
111
|
+
value: {
|
|
112
|
+
expressId,
|
|
113
|
+
type,
|
|
114
|
+
name: asString(attrs[LOAD_CONFIGURATION_ATTR.Name]),
|
|
115
|
+
components: {},
|
|
116
|
+
configuration: { entries, locations, truncated },
|
|
117
|
+
},
|
|
118
|
+
truncated,
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
return {
|
|
122
|
+
value: {
|
|
123
|
+
expressId,
|
|
124
|
+
type,
|
|
125
|
+
name: asString(attrs[0]),
|
|
126
|
+
components: readNumericComponents(type, attrs),
|
|
127
|
+
},
|
|
128
|
+
truncated: false,
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Every attribute the registry names for `type`, except the inherited `Name`,
|
|
133
|
+
* that the record carries a finite number for.
|
|
134
|
+
*/
|
|
135
|
+
function readNumericComponents(type, attrs) {
|
|
136
|
+
const components = {};
|
|
137
|
+
const names = getAttributeNames(type);
|
|
138
|
+
for (let i = 0; i < names.length; i++) {
|
|
139
|
+
const attrName = names[i];
|
|
140
|
+
if (attrName === NAME_ATTR)
|
|
141
|
+
continue;
|
|
142
|
+
const n = asNumber(attrs[i]);
|
|
143
|
+
if (n !== undefined)
|
|
144
|
+
components[attrName] = n;
|
|
145
|
+
}
|
|
146
|
+
return components;
|
|
147
|
+
}
|
|
148
|
+
/** Read one `IfcBoundaryCondition` entity by expressId. */
|
|
149
|
+
export function extractBoundaryCondition(extractor, store, expressId) {
|
|
150
|
+
const ref = store.entityIndex.byId.get(expressId);
|
|
151
|
+
if (!ref)
|
|
152
|
+
return undefined;
|
|
153
|
+
const entity = extractor.extractEntity(ref);
|
|
154
|
+
if (!entity)
|
|
155
|
+
return undefined;
|
|
156
|
+
const type = normalizeIfcTypeName(entity.type);
|
|
157
|
+
const attrs = entity.attributes || [];
|
|
158
|
+
const components = {};
|
|
159
|
+
const names = getAttributeNames(type);
|
|
160
|
+
for (let i = 0; i < names.length; i++) {
|
|
161
|
+
const attrName = names[i];
|
|
162
|
+
if (attrName === NAME_ATTR)
|
|
163
|
+
continue;
|
|
164
|
+
// The stiffness selects admit either a measure or IfcBoolean; read the
|
|
165
|
+
// boolean branch first, since a bare `.T.` would not survive the numeric
|
|
166
|
+
// test and a number is never a valid boolean token.
|
|
167
|
+
const b = asBoolean(attrs[i]);
|
|
168
|
+
if (b !== undefined) {
|
|
169
|
+
components[attrName] = b;
|
|
170
|
+
continue;
|
|
171
|
+
}
|
|
172
|
+
const n = asNumber(attrs[i]);
|
|
173
|
+
if (n !== undefined)
|
|
174
|
+
components[attrName] = n;
|
|
175
|
+
}
|
|
176
|
+
return { expressId, type, name: asString(attrs[0]), components };
|
|
177
|
+
}
|
|
178
|
+
//# sourceMappingURL=structural-load-extractor.js.map
|