@ifc-lite/data 3.5.1 → 4.0.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/color.d.ts +17 -0
- package/dist/color.d.ts.map +1 -0
- package/dist/color.js +24 -0
- package/dist/color.js.map +1 -0
- package/dist/decomposition.d.ts +32 -0
- package/dist/decomposition.d.ts.map +1 -0
- package/dist/decomposition.js +57 -0
- package/dist/decomposition.js.map +1 -0
- package/dist/group-property-sets.d.ts +15 -0
- package/dist/group-property-sets.d.ts.map +1 -0
- package/dist/group-property-sets.js +33 -0
- package/dist/group-property-sets.js.map +1 -0
- package/dist/group-quantity-sets.d.ts +17 -0
- package/dist/group-quantity-sets.d.ts.map +1 -0
- package/dist/group-quantity-sets.js +37 -0
- package/dist/group-quantity-sets.js.map +1 -0
- package/dist/ifc-schema/descendants.d.ts +20 -0
- package/dist/ifc-schema/descendants.d.ts.map +1 -0
- package/dist/ifc-schema/descendants.js +279 -0
- package/dist/ifc-schema/descendants.js.map +1 -0
- package/dist/ifc-schema/entity-aliases.d.ts +61 -0
- package/dist/ifc-schema/entity-aliases.d.ts.map +1 -0
- package/dist/ifc-schema/entity-aliases.js +71 -0
- package/dist/ifc-schema/entity-aliases.js.map +1 -0
- package/dist/ifc-schema/index.d.ts +1 -0
- package/dist/ifc-schema/index.d.ts.map +1 -1
- package/dist/ifc-schema/index.js +4 -1
- package/dist/ifc-schema/index.js.map +1 -1
- package/dist/index.d.ts +9 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -1
- package/dist/index.js.map +1 -1
- package/dist/property-table.d.ts.map +1 -1
- package/dist/property-table.js +2 -16
- package/dist/property-table.js.map +1 -1
- package/dist/quantity-table.d.ts +5 -0
- package/dist/quantity-table.d.ts.map +1 -1
- package/dist/quantity-table.js +8 -18
- package/dist/quantity-table.js.map +1 -1
- package/dist/relationship-graph-helpers.d.ts +68 -0
- package/dist/relationship-graph-helpers.d.ts.map +1 -0
- package/dist/relationship-graph-helpers.js +100 -0
- package/dist/relationship-graph-helpers.js.map +1 -0
- package/dist/relationship-graph.d.ts +59 -8
- package/dist/relationship-graph.d.ts.map +1 -1
- package/dist/relationship-graph.js +99 -26
- package/dist/relationship-graph.js.map +1 -1
- package/dist/step-serializers.d.ts +20 -0
- package/dist/step-serializers.d.ts.map +1 -1
- package/dist/step-serializers.js +4 -4
- package/dist/step-serializers.js.map +1 -1
- package/package.json +3 -3
package/dist/color.d.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Colour-space helpers shared by every glTF/GLB reader in this repo.
|
|
3
|
+
*
|
|
4
|
+
* glTF's `baseColorFactor`/`emissiveFactor` are defined in linear-light space
|
|
5
|
+
* (per the glTF 2.0 spec), while IFC colours (and the mesh colours the viewer
|
|
6
|
+
* consumes) are sRGB-encoded (IEC 61966-2-1). The Rust GLB exporter and the
|
|
7
|
+
* TypeScript `@ifc-lite/export` GLTFExporter both decode sRGB into linear on
|
|
8
|
+
* write; every GLB reader in this repo must apply the exact inverse on read
|
|
9
|
+
* so an export -> re-import round-trip is lossless and any spec-conformant
|
|
10
|
+
* external GLB is interpreted correctly.
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* Encode a single linear-light channel value to sRGB, clamped to [0, 1].
|
|
14
|
+
* Inverse of the exporters' sRGB-to-linear conversion.
|
|
15
|
+
*/
|
|
16
|
+
export declare function linearToSrgb(c: number): number;
|
|
17
|
+
//# sourceMappingURL=color.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"color.d.ts","sourceRoot":"","sources":["../src/color.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;GAUG;AAEH;;;GAGG;AACH,wBAAgB,YAAY,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAI9C"}
|
package/dist/color.js
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
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
|
+
* Colour-space helpers shared by every glTF/GLB reader in this repo.
|
|
6
|
+
*
|
|
7
|
+
* glTF's `baseColorFactor`/`emissiveFactor` are defined in linear-light space
|
|
8
|
+
* (per the glTF 2.0 spec), while IFC colours (and the mesh colours the viewer
|
|
9
|
+
* consumes) are sRGB-encoded (IEC 61966-2-1). The Rust GLB exporter and the
|
|
10
|
+
* TypeScript `@ifc-lite/export` GLTFExporter both decode sRGB into linear on
|
|
11
|
+
* write; every GLB reader in this repo must apply the exact inverse on read
|
|
12
|
+
* so an export -> re-import round-trip is lossless and any spec-conformant
|
|
13
|
+
* external GLB is interpreted correctly.
|
|
14
|
+
*/
|
|
15
|
+
/**
|
|
16
|
+
* Encode a single linear-light channel value to sRGB, clamped to [0, 1].
|
|
17
|
+
* Inverse of the exporters' sRGB-to-linear conversion.
|
|
18
|
+
*/
|
|
19
|
+
export function linearToSrgb(c) {
|
|
20
|
+
const x = c <= 0 ? 0 : c >= 1 ? 1 : c;
|
|
21
|
+
const encoded = x <= 0.0031308 ? x * 12.92 : 1.055 * Math.pow(x, 1 / 2.4) - 0.055;
|
|
22
|
+
return encoded < 0 ? 0 : encoded > 1 ? 1 : encoded;
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=color.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"color.js","sourceRoot":"","sources":["../src/color.ts"],"names":[],"mappings":"AAAA;;+DAE+D;AAE/D;;;;;;;;;;GAUG;AAEH;;;GAGG;AACH,MAAM,UAAU,YAAY,CAAC,CAAS;IACpC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACtC,MAAM,OAAO,GAAG,CAAC,IAAI,SAAS,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,GAAG,KAAK,CAAC;IAClF,OAAO,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;AACrD,CAAC"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `IfcRelAggregates` decomposition traversal.
|
|
3
|
+
*
|
|
4
|
+
* An assembly — `IfcElementAssembly`, an `IfcStair`/`IfcRoof`/`IfcRamp` used
|
|
5
|
+
* as a container, a wall with `IfcBuildingElementPart`s — often carries no
|
|
6
|
+
* mesh of its own; its parts (stair flights, railings, landing slabs, …)
|
|
7
|
+
* hang off it via `IfcRelAggregates`. Any consumer that resolves a selector
|
|
8
|
+
* to a container id and hands that straight to a mesh-keyed sink (a
|
|
9
|
+
* highlight set, a visibility override, a bounding-box lookup) sees nothing,
|
|
10
|
+
* because the container itself is never a key in that sink. This module is
|
|
11
|
+
* the single traversal both `apps/viewer` (which additionally knows which
|
|
12
|
+
* ids actually rendered, and filters to those) and `packages/mcp` (which
|
|
13
|
+
* does not have that live rendering information and instead passes the full
|
|
14
|
+
* decomposition closure through, safe because the mesh-keyed sinks already
|
|
15
|
+
* no-op on ids they never rendered) build their own expansion on top of.
|
|
16
|
+
*/
|
|
17
|
+
import { RelationshipType } from './types.js';
|
|
18
|
+
/** Structural view of the relationship graph — both the parser's
|
|
19
|
+
* `RelationshipGraph` and a cache-rebuilt or test-double graph satisfy it. */
|
|
20
|
+
export interface DecompositionRelationships {
|
|
21
|
+
getRelated(entityId: number, relType: RelationshipType, direction: 'forward' | 'inverse'): number[];
|
|
22
|
+
}
|
|
23
|
+
/** Direct `IfcRelAggregates` children of `expressId` (one level down). */
|
|
24
|
+
export declare function getAggregatedChildren(relationships: DecompositionRelationships | undefined, expressId: number): number[];
|
|
25
|
+
/**
|
|
26
|
+
* All decomposition descendants of `rootId` via `IfcRelAggregates`, depth-first
|
|
27
|
+
* and excluding `rootId` itself. Cycle-guarded against malformed files
|
|
28
|
+
* (A aggregates B, B aggregates A) so it always terminates. Order is a stable
|
|
29
|
+
* pre-order so callers can rely on it for display.
|
|
30
|
+
*/
|
|
31
|
+
export declare function collectAggregatedDescendants(relationships: DecompositionRelationships | undefined, rootId: number): number[];
|
|
32
|
+
//# sourceMappingURL=decomposition.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decomposition.d.ts","sourceRoot":"","sources":["../src/decomposition.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAE9C;+EAC+E;AAC/E,MAAM,WAAW,0BAA0B;IACzC,UAAU,CACR,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,gBAAgB,EACzB,SAAS,EAAE,SAAS,GAAG,SAAS,GAC/B,MAAM,EAAE,CAAC;CACb;AAED,0EAA0E;AAC1E,wBAAgB,qBAAqB,CACnC,aAAa,EAAE,0BAA0B,GAAG,SAAS,EACrD,SAAS,EAAE,MAAM,GAChB,MAAM,EAAE,CAGV;AAED;;;;;GAKG;AACH,wBAAgB,4BAA4B,CAC1C,aAAa,EAAE,0BAA0B,GAAG,SAAS,EACrD,MAAM,EAAE,MAAM,GACb,MAAM,EAAE,CAoBV"}
|
|
@@ -0,0 +1,57 @@
|
|
|
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
|
+
* `IfcRelAggregates` decomposition traversal.
|
|
6
|
+
*
|
|
7
|
+
* An assembly — `IfcElementAssembly`, an `IfcStair`/`IfcRoof`/`IfcRamp` used
|
|
8
|
+
* as a container, a wall with `IfcBuildingElementPart`s — often carries no
|
|
9
|
+
* mesh of its own; its parts (stair flights, railings, landing slabs, …)
|
|
10
|
+
* hang off it via `IfcRelAggregates`. Any consumer that resolves a selector
|
|
11
|
+
* to a container id and hands that straight to a mesh-keyed sink (a
|
|
12
|
+
* highlight set, a visibility override, a bounding-box lookup) sees nothing,
|
|
13
|
+
* because the container itself is never a key in that sink. This module is
|
|
14
|
+
* the single traversal both `apps/viewer` (which additionally knows which
|
|
15
|
+
* ids actually rendered, and filters to those) and `packages/mcp` (which
|
|
16
|
+
* does not have that live rendering information and instead passes the full
|
|
17
|
+
* decomposition closure through, safe because the mesh-keyed sinks already
|
|
18
|
+
* no-op on ids they never rendered) build their own expansion on top of.
|
|
19
|
+
*/
|
|
20
|
+
import { RelationshipType } from './types.js';
|
|
21
|
+
/** Direct `IfcRelAggregates` children of `expressId` (one level down). */
|
|
22
|
+
export function getAggregatedChildren(relationships, expressId) {
|
|
23
|
+
if (!relationships)
|
|
24
|
+
return [];
|
|
25
|
+
return relationships.getRelated(expressId, RelationshipType.Aggregates, 'forward');
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* All decomposition descendants of `rootId` via `IfcRelAggregates`, depth-first
|
|
29
|
+
* and excluding `rootId` itself. Cycle-guarded against malformed files
|
|
30
|
+
* (A aggregates B, B aggregates A) so it always terminates. Order is a stable
|
|
31
|
+
* pre-order so callers can rely on it for display.
|
|
32
|
+
*/
|
|
33
|
+
export function collectAggregatedDescendants(relationships, rootId) {
|
|
34
|
+
if (!relationships)
|
|
35
|
+
return [];
|
|
36
|
+
const out = [];
|
|
37
|
+
const seen = new Set([rootId]);
|
|
38
|
+
// DFS with an explicit stack; push children in reverse so siblings keep
|
|
39
|
+
// their authored order in the pre-order output.
|
|
40
|
+
const stack = [];
|
|
41
|
+
const pushChildren = (parentId) => {
|
|
42
|
+
const kids = relationships.getRelated(parentId, RelationshipType.Aggregates, 'forward');
|
|
43
|
+
for (let i = kids.length - 1; i >= 0; i--)
|
|
44
|
+
stack.push(kids[i]);
|
|
45
|
+
};
|
|
46
|
+
pushChildren(rootId);
|
|
47
|
+
while (stack.length > 0) {
|
|
48
|
+
const id = stack.pop();
|
|
49
|
+
if (seen.has(id))
|
|
50
|
+
continue;
|
|
51
|
+
seen.add(id);
|
|
52
|
+
out.push(id);
|
|
53
|
+
pushChildren(id);
|
|
54
|
+
}
|
|
55
|
+
return out;
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=decomposition.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decomposition.js","sourceRoot":"","sources":["../src/decomposition.ts"],"names":[],"mappings":"AAAA;;+DAE+D;AAE/D;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAY9C,0EAA0E;AAC1E,MAAM,UAAU,qBAAqB,CACnC,aAAqD,EACrD,SAAiB;IAEjB,IAAI,CAAC,aAAa;QAAE,OAAO,EAAE,CAAC;IAC9B,OAAO,aAAa,CAAC,UAAU,CAAC,SAAS,EAAE,gBAAgB,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC;AACrF,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,4BAA4B,CAC1C,aAAqD,EACrD,MAAc;IAEd,IAAI,CAAC,aAAa;QAAE,OAAO,EAAE,CAAC;IAC9B,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,MAAM,IAAI,GAAG,IAAI,GAAG,CAAS,CAAC,MAAM,CAAC,CAAC,CAAC;IACvC,wEAAwE;IACxE,gDAAgD;IAChD,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,MAAM,YAAY,GAAG,CAAC,QAAgB,EAAE,EAAE;QACxC,MAAM,IAAI,GAAG,aAAa,CAAC,UAAU,CAAC,QAAQ,EAAE,gBAAgB,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC;QACxF,KAAK,IAAI,CAAC,GAAG,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE;YAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;IACjE,CAAC,CAAC;IACF,YAAY,CAAC,MAAM,CAAC,CAAC;IACrB,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxB,MAAM,EAAE,GAAG,KAAK,CAAC,GAAG,EAAG,CAAC;QACxB,IAAI,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;YAAE,SAAS;QAC3B,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACb,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACb,YAAY,CAAC,EAAE,CAAC,CAAC;IACnB,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { StringTable } from './string-table.js';
|
|
2
|
+
import type { PropertySet, PropertyValue } from './property-table.js';
|
|
3
|
+
/**
|
|
4
|
+
* Group a row-index list into `PropertySet`s keyed on `(psetName, psetGlobalId)`,
|
|
5
|
+
* not name alone -- two `IfcPropertySet` instances that share a literal name
|
|
6
|
+
* (a federated merge, or an exporter emitting the same Pset_ twice on one
|
|
7
|
+
* element) must stay distinct, or the second instance's properties come back
|
|
8
|
+
* attributed to the first instance's GlobalId. Shared by the live
|
|
9
|
+
* `PropertyTable.getForEntity` (in `property-table.ts`) and by
|
|
10
|
+
* `@ifc-lite/cache`'s cache-rehydrated `readProperties`, which reads the same
|
|
11
|
+
* columnar arrays back from the binary cache -- a single grouping algorithm
|
|
12
|
+
* keeps the two paths from re-diverging.
|
|
13
|
+
*/
|
|
14
|
+
export declare function groupPropertySetsByInstance(rowIndices: readonly number[], psetName: Uint32Array, psetGlobalId: Uint32Array, propName: Uint32Array, propType: Uint8Array, strings: StringTable, getValue: (idx: number) => PropertyValue): PropertySet[];
|
|
15
|
+
//# sourceMappingURL=group-property-sets.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"group-property-sets.d.ts","sourceRoot":"","sources":["../src/group-property-sets.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEtE;;;;;;;;;;GAUG;AACH,wBAAgB,2BAA2B,CACzC,UAAU,EAAE,SAAS,MAAM,EAAE,EAC7B,QAAQ,EAAE,WAAW,EACrB,YAAY,EAAE,WAAW,EACzB,QAAQ,EAAE,WAAW,EACrB,QAAQ,EAAE,UAAU,EACpB,OAAO,EAAE,WAAW,EACpB,QAAQ,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,aAAa,GACvC,WAAW,EAAE,CAiBf"}
|
|
@@ -0,0 +1,33 @@
|
|
|
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
|
+
* Group a row-index list into `PropertySet`s keyed on `(psetName, psetGlobalId)`,
|
|
6
|
+
* not name alone -- two `IfcPropertySet` instances that share a literal name
|
|
7
|
+
* (a federated merge, or an exporter emitting the same Pset_ twice on one
|
|
8
|
+
* element) must stay distinct, or the second instance's properties come back
|
|
9
|
+
* attributed to the first instance's GlobalId. Shared by the live
|
|
10
|
+
* `PropertyTable.getForEntity` (in `property-table.ts`) and by
|
|
11
|
+
* `@ifc-lite/cache`'s cache-rehydrated `readProperties`, which reads the same
|
|
12
|
+
* columnar arrays back from the binary cache -- a single grouping algorithm
|
|
13
|
+
* keeps the two paths from re-diverging.
|
|
14
|
+
*/
|
|
15
|
+
export function groupPropertySetsByInstance(rowIndices, psetName, psetGlobalId, propName, propType, strings, getValue) {
|
|
16
|
+
const psets = new Map();
|
|
17
|
+
for (const idx of rowIndices) {
|
|
18
|
+
const psetNameStr = strings.get(psetName[idx]), psetGlobalIdStr = strings.get(psetGlobalId[idx]);
|
|
19
|
+
const key = psetNameStr + '\u0000' + psetGlobalIdStr;
|
|
20
|
+
if (!psets.has(key)) {
|
|
21
|
+
psets.set(key, { name: psetNameStr, globalId: psetGlobalIdStr, properties: [] });
|
|
22
|
+
}
|
|
23
|
+
const pset = psets.get(key);
|
|
24
|
+
const propNameStr = strings.get(propName[idx]);
|
|
25
|
+
pset.properties.push({
|
|
26
|
+
name: propNameStr,
|
|
27
|
+
type: propType[idx],
|
|
28
|
+
value: getValue(idx),
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
return Array.from(psets.values());
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=group-property-sets.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"group-property-sets.js","sourceRoot":"","sources":["../src/group-property-sets.ts"],"names":[],"mappings":"AAAA;;+DAE+D;AAK/D;;;;;;;;;;GAUG;AACH,MAAM,UAAU,2BAA2B,CACzC,UAA6B,EAC7B,QAAqB,EACrB,YAAyB,EACzB,QAAqB,EACrB,QAAoB,EACpB,OAAoB,EACpB,QAAwC;IAExC,MAAM,KAAK,GAAG,IAAI,GAAG,EAAuB,CAAC;IAC7C,KAAK,MAAM,GAAG,IAAI,UAAU,EAAE,CAAC;QAC7B,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC;QACjG,MAAM,GAAG,GAAG,WAAW,GAAG,QAAQ,GAAG,eAAe,CAAC;QACrD,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;YACpB,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,QAAQ,EAAE,eAAe,EAAE,UAAU,EAAE,EAAE,EAAE,CAAC,CAAC;QACnF,CAAC;QACD,MAAM,IAAI,GAAG,KAAK,CAAC,GAAG,CAAC,GAAG,CAAE,CAAC;QAC7B,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC;QAC/C,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;YACnB,IAAI,EAAE,WAAW;YACjB,IAAI,EAAE,QAAQ,CAAC,GAAG,CAAC;YACnB,KAAK,EAAE,QAAQ,CAAC,GAAG,CAAC;SACrB,CAAC,CAAC;IACL,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;AACpC,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { StringTable } from './string-table.js';
|
|
2
|
+
import type { QuantitySet } from './quantity-table.js';
|
|
3
|
+
/**
|
|
4
|
+
* Group a row-index list into `QuantitySet`s keyed on `(qsetName, qsetGlobalId)`,
|
|
5
|
+
* not name alone -- two `IfcElementQuantity` instances that share a literal
|
|
6
|
+
* name (a federated merge, or an exporter emitting the same Qto_ set twice on
|
|
7
|
+
* one element) must stay distinct, or the second instance's quantities come
|
|
8
|
+
* back attributed to the first instance's GlobalId. Mirrors
|
|
9
|
+
* `groupPropertySetsByInstance` (same defect, same fix, on the property
|
|
10
|
+
* side). Shared by the live `QuantityTable.getForEntity` (in
|
|
11
|
+
* `quantity-table.ts`) and by `@ifc-lite/cache`'s cache-rehydrated
|
|
12
|
+
* `readQuantities`, which reads the same columnar arrays back from the
|
|
13
|
+
* binary cache -- a single grouping algorithm keeps the two paths from
|
|
14
|
+
* diverging.
|
|
15
|
+
*/
|
|
16
|
+
export declare function groupQuantitySetsByInstance(rowIndices: readonly number[], qsetName: Uint32Array, qsetGlobalId: Uint32Array, quantityName: Uint32Array, quantityType: Uint8Array, value: Float64Array, formula: Uint32Array, strings: StringTable): QuantitySet[];
|
|
17
|
+
//# sourceMappingURL=group-quantity-sets.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"group-quantity-sets.d.ts","sourceRoot":"","sources":["../src/group-quantity-sets.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,KAAK,EAAE,WAAW,EAAY,MAAM,qBAAqB,CAAC;AAGjE;;;;;;;;;;;;GAYG;AACH,wBAAgB,2BAA2B,CACzC,UAAU,EAAE,SAAS,MAAM,EAAE,EAC7B,QAAQ,EAAE,WAAW,EACrB,YAAY,EAAE,WAAW,EACzB,YAAY,EAAE,WAAW,EACzB,YAAY,EAAE,UAAU,EACxB,KAAK,EAAE,YAAY,EACnB,OAAO,EAAE,WAAW,EACpB,OAAO,EAAE,WAAW,GACnB,WAAW,EAAE,CAmBf"}
|
|
@@ -0,0 +1,37 @@
|
|
|
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
|
+
* Group a row-index list into `QuantitySet`s keyed on `(qsetName, qsetGlobalId)`,
|
|
6
|
+
* not name alone -- two `IfcElementQuantity` instances that share a literal
|
|
7
|
+
* name (a federated merge, or an exporter emitting the same Qto_ set twice on
|
|
8
|
+
* one element) must stay distinct, or the second instance's quantities come
|
|
9
|
+
* back attributed to the first instance's GlobalId. Mirrors
|
|
10
|
+
* `groupPropertySetsByInstance` (same defect, same fix, on the property
|
|
11
|
+
* side). Shared by the live `QuantityTable.getForEntity` (in
|
|
12
|
+
* `quantity-table.ts`) and by `@ifc-lite/cache`'s cache-rehydrated
|
|
13
|
+
* `readQuantities`, which reads the same columnar arrays back from the
|
|
14
|
+
* binary cache -- a single grouping algorithm keeps the two paths from
|
|
15
|
+
* diverging.
|
|
16
|
+
*/
|
|
17
|
+
export function groupQuantitySetsByInstance(rowIndices, qsetName, qsetGlobalId, quantityName, quantityType, value, formula, strings) {
|
|
18
|
+
const qsets = new Map();
|
|
19
|
+
for (const idx of rowIndices) {
|
|
20
|
+
const qsetNameStr = strings.get(qsetName[idx]);
|
|
21
|
+
const qsetGlobalIdStr = strings.get(qsetGlobalId[idx]);
|
|
22
|
+
const key = qsetNameStr + '\u0000' + qsetGlobalIdStr;
|
|
23
|
+
if (!qsets.has(key)) {
|
|
24
|
+
qsets.set(key, { name: qsetNameStr, globalId: qsetGlobalIdStr, quantities: [] });
|
|
25
|
+
}
|
|
26
|
+
const qset = qsets.get(key);
|
|
27
|
+
const quant = {
|
|
28
|
+
name: strings.get(quantityName[idx]),
|
|
29
|
+
type: quantityType[idx],
|
|
30
|
+
value: value[idx],
|
|
31
|
+
formula: formula[idx] > 0 ? strings.get(formula[idx]) : undefined,
|
|
32
|
+
};
|
|
33
|
+
qset.quantities.push(quant);
|
|
34
|
+
}
|
|
35
|
+
return Array.from(qsets.values());
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=group-quantity-sets.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"group-quantity-sets.js","sourceRoot":"","sources":["../src/group-quantity-sets.ts"],"names":[],"mappings":"AAAA;;+DAE+D;AAM/D;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,2BAA2B,CACzC,UAA6B,EAC7B,QAAqB,EACrB,YAAyB,EACzB,YAAyB,EACzB,YAAwB,EACxB,KAAmB,EACnB,OAAoB,EACpB,OAAoB;IAEpB,MAAM,KAAK,GAAG,IAAI,GAAG,EAAuB,CAAC;IAC7C,KAAK,MAAM,GAAG,IAAI,UAAU,EAAE,CAAC;QAC7B,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC;QAC/C,MAAM,eAAe,GAAG,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC;QACvD,MAAM,GAAG,GAAG,WAAW,GAAG,QAAQ,GAAG,eAAe,CAAC;QACrD,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;YACpB,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,QAAQ,EAAE,eAAe,EAAE,UAAU,EAAE,EAAE,EAAE,CAAC,CAAC;QACnF,CAAC;QACD,MAAM,IAAI,GAAG,KAAK,CAAC,GAAG,CAAC,GAAG,CAAE,CAAC;QAC7B,MAAM,KAAK,GAAa;YACtB,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC;YACpC,IAAI,EAAE,YAAY,CAAC,GAAG,CAAiB;YACvC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC;YACjB,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS;SAClE,CAAC;QACF,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC9B,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;AACpC,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { IfcSchemaVersion } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Expand a caller's type list to every descendant each type has for a file
|
|
4
|
+
* written in `schemaVersion` — see the module doc for what that admits.
|
|
5
|
+
* Case-insensitive input; UPPERCASE output, deduplicated across the whole
|
|
6
|
+
* list, each requested type immediately ahead of its own sorted descendants.
|
|
7
|
+
*
|
|
8
|
+
* `schemaVersion` is required and should be the queried model's own
|
|
9
|
+
* `store.schemaVersion`. It is what keeps a re-parented entity out of the
|
|
10
|
+
* answer, so there is no sensible default: an omitted version would silently
|
|
11
|
+
* mean "IFC4", and on an IFC2X3 model that answer is wrong rather than
|
|
12
|
+
* approximate. Values with no bundled table fall back as documented on
|
|
13
|
+
* `resolveSchemaVersion`.
|
|
14
|
+
*
|
|
15
|
+
* A type unknown to every bundled table (a typo, a vendor extension) comes
|
|
16
|
+
* back as itself, so the caller's list keeps its shape rather than silently
|
|
17
|
+
* losing an entry.
|
|
18
|
+
*/
|
|
19
|
+
export declare function expandTypeNamesToDescendants(types: readonly string[], schemaVersion: IfcSchemaVersion | string | undefined): string[];
|
|
20
|
+
//# sourceMappingURL=descendants.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"descendants.d.ts","sourceRoot":"","sources":["../../src/ifc-schema/descendants.ts"],"names":[],"mappings":"AAsDA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAwOnD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,4BAA4B,CAC1C,KAAK,EAAE,SAAS,MAAM,EAAE,EACxB,aAAa,EAAE,gBAAgB,GAAG,MAAM,GAAG,SAAS,GACnD,MAAM,EAAE,CAYV"}
|
|
@@ -0,0 +1,279 @@
|
|
|
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
|
+
* Descendant-closure resolution for entity-type queries.
|
|
6
|
+
*
|
|
7
|
+
* `getInheritanceChain`/`isEntitySubtypeOf` in `./index.ts` walk the EXPRESS
|
|
8
|
+
* hierarchy leaf → root (a type plus its ancestors). Every `BimBackend`'s
|
|
9
|
+
* `byType()` query needs the opposite direction: given a type name, every
|
|
10
|
+
* type that HAS it as an ancestor, so that asking for an abstract supertype
|
|
11
|
+
* (`IfcBuildingElement`, `IfcElement`) — never a literal STEP entity type —
|
|
12
|
+
* finds the concrete leaves a real file actually contains, instead of
|
|
13
|
+
* silently answering zero.
|
|
14
|
+
*
|
|
15
|
+
* Neither one schema table alone nor a plain union across the three is the
|
|
16
|
+
* right authority, and the two failure modes are opposite:
|
|
17
|
+
*
|
|
18
|
+
* - One table alone NARROWS. `entityIndex.byType` is keyed by the names the
|
|
19
|
+
* FILE contains, and those need not belong to the version its
|
|
20
|
+
* `FILE_SCHEMA` header claims: converters and hand-edits produce
|
|
21
|
+
* IFC4X3-headered files still carrying `IFCSLABSTANDARDCASE`, a name only
|
|
22
|
+
* the IFC4 table declares. Resolving per header made the header, not the
|
|
23
|
+
* content, decide what a query found.
|
|
24
|
+
* - A plain union MISFILES. buildingSMART re-parented entities between
|
|
25
|
+
* versions, so a name can sit under a different base in a schema the file
|
|
26
|
+
* is not written in: `IfcReinforcingBar` is an `IfcBuildingElement` in
|
|
27
|
+
* IFC2X3 and an `IfcElementComponent` in IFC4, `IfcProject` is an
|
|
28
|
+
* `IfcObject` in IFC2X3 and an `IfcContext` from IFC4 on, `IfcZone` is an
|
|
29
|
+
* `IfcSystem` in IFC4 and an `IfcGroup` in IFC2X3. Unioning made
|
|
30
|
+
* `byType('IfcBuildingElement')` on an IFC4 file answer with reinforcing
|
|
31
|
+
* bars — 45 such (supertype, schema) pairs.
|
|
32
|
+
*
|
|
33
|
+
* So the closure for a file is:
|
|
34
|
+
*
|
|
35
|
+
* (a) the descendants of the requested type in the file's OWN schema table;
|
|
36
|
+
* (b) plus names from the other tables that the file's schema does not
|
|
37
|
+
* define AT ALL and that are descendants of the requested type in the
|
|
38
|
+
* table that does define them — the legacy and newer leaf spellings
|
|
39
|
+
* (`IFCSLABSTANDARDCASE` on an IFC4X3 file, `IFCFURNITURE` on an IFC2X3
|
|
40
|
+
* one). A name the file's own schema defines is never added, and if it
|
|
41
|
+
* defines that name under a DIFFERENT parent the walk does not descend
|
|
42
|
+
* through it either — both halves are what keep (b) from re-opening the
|
|
43
|
+
* union's misfiling;
|
|
44
|
+
* (c) plus the two alias relations in `./entity-aliases.js`: the
|
|
45
|
+
* cross-schema rename equality, and the narrowing for leaves no bundled
|
|
46
|
+
* table declares.
|
|
47
|
+
*/
|
|
48
|
+
import { ENTITY_NAME_ALIASES, CROSS_SCHEMA_RENAMES } from './entity-aliases.js';
|
|
49
|
+
// The same per-version map `getEntities` answers from. Shared rather than
|
|
50
|
+
// re-declared here: a second copy would let a future schema version reach one
|
|
51
|
+
// of the two and give `getEntities` and this resolver different worlds.
|
|
52
|
+
import { ENTITIES_BY_VERSION } from './index.js';
|
|
53
|
+
const ALL_VERSIONS = ['IFC2X3', 'IFC4', 'IFC4X3'];
|
|
54
|
+
const tableCache = new Map();
|
|
55
|
+
function tableFor(v) {
|
|
56
|
+
const cached = tableCache.get(v);
|
|
57
|
+
if (cached)
|
|
58
|
+
return cached;
|
|
59
|
+
const children = new Map();
|
|
60
|
+
const names = new Set();
|
|
61
|
+
for (const entity of ENTITIES_BY_VERSION[v]) {
|
|
62
|
+
const name = entity.name.toUpperCase();
|
|
63
|
+
names.add(name);
|
|
64
|
+
if (!entity.parent)
|
|
65
|
+
continue;
|
|
66
|
+
const parent = entity.parent.toUpperCase();
|
|
67
|
+
const bucket = children.get(parent);
|
|
68
|
+
if (bucket)
|
|
69
|
+
bucket.push(name);
|
|
70
|
+
else
|
|
71
|
+
children.set(parent, [name]);
|
|
72
|
+
}
|
|
73
|
+
const table = { children, names };
|
|
74
|
+
tableCache.set(v, table);
|
|
75
|
+
return table;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Narrow a raw schema-version string (a store's `schemaVersion`, which
|
|
79
|
+
* carries values like `'IFC5'` these tables do not cover) to a version with a
|
|
80
|
+
* bundled table.
|
|
81
|
+
*
|
|
82
|
+
* Deliberately the same mapping as `narrowSchemaVersion` in
|
|
83
|
+
* `packages/ids/src/bridge/schema-version.ts` — IFC5 has no published EXPRESS
|
|
84
|
+
* schema, and IFC4X3 is its nearest — pinned from that side in
|
|
85
|
+
* `schema-version.test.ts`, since `@ifc-lite/ids` depends on this package and
|
|
86
|
+
* not the other way round. Two resolvers that disagreed about IFC5 is what
|
|
87
|
+
* this replaces.
|
|
88
|
+
*/
|
|
89
|
+
function resolveSchemaVersion(schemaVersion) {
|
|
90
|
+
switch (schemaVersion?.toUpperCase()) {
|
|
91
|
+
case 'IFC2X3':
|
|
92
|
+
return 'IFC2X3';
|
|
93
|
+
case 'IFC4X3':
|
|
94
|
+
case 'IFC4X3_ADD2':
|
|
95
|
+
case 'IFC5':
|
|
96
|
+
return 'IFC4X3';
|
|
97
|
+
default:
|
|
98
|
+
return 'IFC4';
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* The names a query for `type` also means, before any schema is consulted:
|
|
103
|
+
* the type itself plus the other spelling of a cross-schema rename.
|
|
104
|
+
*
|
|
105
|
+
* The rename is an equality, not a subtype relation, so both spellings are
|
|
106
|
+
* kept in the answer: a file written under either schema may hold records
|
|
107
|
+
* under either name, and a name the file does not contain matches an empty
|
|
108
|
+
* bucket.
|
|
109
|
+
*/
|
|
110
|
+
function renameGroup(upper) {
|
|
111
|
+
const group = [upper];
|
|
112
|
+
for (const pair of CROSS_SCHEMA_RENAMES) {
|
|
113
|
+
if (!pair.includes(upper))
|
|
114
|
+
continue;
|
|
115
|
+
for (const name of pair)
|
|
116
|
+
if (!group.includes(name))
|
|
117
|
+
group.push(name);
|
|
118
|
+
}
|
|
119
|
+
return group;
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* `ENTITY_NAME_ALIASES` as UPPERCASE `[leaf, supertype]` rows, uppercased once
|
|
123
|
+
* at module load rather than on every call. The table is read-only.
|
|
124
|
+
*/
|
|
125
|
+
const ALIAS_ROWS = Object.entries(ENTITY_NAME_ALIASES).map(([leaf, supertype]) => [leaf.toUpperCase(), supertype.toUpperCase()]);
|
|
126
|
+
/**
|
|
127
|
+
* Transitive descendants of `seeds` within one schema table, seeds excluded.
|
|
128
|
+
*
|
|
129
|
+
* `own` is the file's own schema's verdict, passed when `table` is a foreign
|
|
130
|
+
* one; it is what implements rule (b). When the own table has an opinion about
|
|
131
|
+
* this subtree, a name it declares is never returned — that table is the
|
|
132
|
+
* authority on where it sits — and when it puts that name OUTSIDE the requested
|
|
133
|
+
* subtree, the walk does not descend through it either. When `own.active` is
|
|
134
|
+
* false the own table has no opinion at all, so neither half applies and the
|
|
135
|
+
* foreign table's answer is kept whole: `IfcSpatialElement` on IFC2X3 must
|
|
136
|
+
* still find `IFCBUILDING` and `IFCSPACE`, names IFC2X3 declares but places
|
|
137
|
+
* under a supertype it has no equivalent of.
|
|
138
|
+
*
|
|
139
|
+
* That second half is not decoration. `IfcTendonConduit` is IFC4X3-only and
|
|
140
|
+
* sits under `IfcReinforcingElement` there; IFC2X3 declares
|
|
141
|
+
* `IfcReinforcingElement` under `IfcBuildingElement`, nowhere near
|
|
142
|
+
* `IfcElementComponent`. Skipping the re-parented node but still walking
|
|
143
|
+
* through it put `IFCTENDONCONDUIT` in `byType('IfcElementComponent')` on an
|
|
144
|
+
* IFC2X3 file — the union's misfiling, one level down.
|
|
145
|
+
*
|
|
146
|
+
* The test is subtree membership, not same-parent: the IFC4X3 rename moved
|
|
147
|
+
* every element from `IfcBuildingElement` to `IfcBuiltElement`, so comparing
|
|
148
|
+
* declared parents reads the whole hierarchy as re-parented and drops
|
|
149
|
+
* `IFCSLABSTANDARDCASE` from `byType('IfcBuiltElement')` on IFC4X3 — the
|
|
150
|
+
* headline case this resolver exists for. `IfcSlab` sits under both spellings,
|
|
151
|
+
* so it is inside the subtree and the walk continues through it.
|
|
152
|
+
*/
|
|
153
|
+
function descendantsInTable(table, seeds, own) {
|
|
154
|
+
const found = new Set();
|
|
155
|
+
const stack = [...seeds];
|
|
156
|
+
const visited = new Set(seeds);
|
|
157
|
+
while (stack.length > 0) {
|
|
158
|
+
for (const child of table.children.get(stack.pop()) ?? []) {
|
|
159
|
+
if (visited.has(child))
|
|
160
|
+
continue;
|
|
161
|
+
visited.add(child);
|
|
162
|
+
if (own?.active && own.table.names.has(child)) {
|
|
163
|
+
// Own declares it AND has an opinion about this subtree, so it is
|
|
164
|
+
// never added here: own's own walk already returned it if own agrees
|
|
165
|
+
// it belongs. Descend only if own agrees.
|
|
166
|
+
if (own.subtree.has(child))
|
|
167
|
+
stack.push(child);
|
|
168
|
+
continue;
|
|
169
|
+
}
|
|
170
|
+
found.add(child);
|
|
171
|
+
stack.push(child);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
return found;
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* One type's descendant set for a file written in `v`: itself, plus every
|
|
178
|
+
* type the rule in the module doc admits, UPPERCASE and deduplicated.
|
|
179
|
+
*
|
|
180
|
+
* Order: the requested type first, then the rest sorted. Callers page results
|
|
181
|
+
* with `offset`/`limit`, so a traversal-dependent order would shift a caller's
|
|
182
|
+
* page whenever the schema tables were regenerated. Depth-first pop order did
|
|
183
|
+
* exactly that; sorted does not.
|
|
184
|
+
*
|
|
185
|
+
* Memoized per (version, type). Three table walks plus a sort of the result is
|
|
186
|
+
* 0.3 ms for `IfcRoot` on IFC4, and `expandTypeNamesToDescendants` is public
|
|
187
|
+
* API, so a consumer outside `@ifc-lite/parser` — whose own memo is keyed on
|
|
188
|
+
* the whole ordered list, and so misses whenever that list is reordered —
|
|
189
|
+
* would otherwise pay that on every call. The cached array never leaves this
|
|
190
|
+
* module: the only caller copies names out of it into a fresh list.
|
|
191
|
+
*/
|
|
192
|
+
const descendantCache = new Map();
|
|
193
|
+
/**
|
|
194
|
+
* Bound on every memo in this resolver's path. The keys are caller-supplied
|
|
195
|
+
* type names, and the MCP server and the viewer are long-lived processes where
|
|
196
|
+
* those come from an agent or an SDK script, so an unbounded map grows on
|
|
197
|
+
* typos and vendor namespaces forever. Clearing wholesale rather than evicting
|
|
198
|
+
* one entry costs a recompute on the next call and needs no bookkeeping; the
|
|
199
|
+
* bundled schemas declare ~1160 names, so a real workload never reaches it.
|
|
200
|
+
*/
|
|
201
|
+
const CACHE_LIMIT = 4096;
|
|
202
|
+
function descendantsOf(type, v) {
|
|
203
|
+
const upper = type.toUpperCase();
|
|
204
|
+
const key = `${v}\u0000${upper}`;
|
|
205
|
+
const cached = descendantCache.get(key);
|
|
206
|
+
if (cached)
|
|
207
|
+
return cached;
|
|
208
|
+
const computed = computeDescendantsOf(upper, v);
|
|
209
|
+
if (descendantCache.size >= CACHE_LIMIT)
|
|
210
|
+
descendantCache.clear();
|
|
211
|
+
descendantCache.set(key, computed);
|
|
212
|
+
return computed;
|
|
213
|
+
}
|
|
214
|
+
function computeDescendantsOf(upper, v) {
|
|
215
|
+
const seeds = renameGroup(upper);
|
|
216
|
+
const own = tableFor(v);
|
|
217
|
+
const ownDescendants = descendantsInTable(own, seeds);
|
|
218
|
+
const found = new Set(seeds.slice(1));
|
|
219
|
+
for (const name of ownDescendants)
|
|
220
|
+
found.add(name);
|
|
221
|
+
// (b) A leaf spelling this schema has no opinion about at all. The own
|
|
222
|
+
// table's verdict is handed to the walk, which is what keeps a name this
|
|
223
|
+
// schema declares out of the answer, and what stops the walk from descending
|
|
224
|
+
// through one this schema places outside the requested subtree. See
|
|
225
|
+
// `descendantsInTable`.
|
|
226
|
+
const verdict = {
|
|
227
|
+
table: own,
|
|
228
|
+
subtree: new Set([...seeds, ...ownDescendants]),
|
|
229
|
+
active: seeds.some((seed) => own.names.has(seed)),
|
|
230
|
+
};
|
|
231
|
+
for (const other of ALL_VERSIONS) {
|
|
232
|
+
const table = tableFor(other);
|
|
233
|
+
if (table === own)
|
|
234
|
+
continue;
|
|
235
|
+
for (const name of descendantsInTable(table, seeds, verdict))
|
|
236
|
+
found.add(name);
|
|
237
|
+
}
|
|
238
|
+
// (c) The narrowing: a leaf no bundled table declares hangs off its nearest
|
|
239
|
+
// schema-known supertype. One direction only, so `IfcGeotechnicalStratum`
|
|
240
|
+
// gains `IfcSolidStratum` while `IfcSolidStratum` does not gain its siblings.
|
|
241
|
+
for (const [leaf, parent] of ALIAS_ROWS) {
|
|
242
|
+
if (parent === upper || found.has(parent))
|
|
243
|
+
found.add(leaf);
|
|
244
|
+
}
|
|
245
|
+
found.delete(upper);
|
|
246
|
+
return [upper, ...[...found].sort()];
|
|
247
|
+
}
|
|
248
|
+
/**
|
|
249
|
+
* Expand a caller's type list to every descendant each type has for a file
|
|
250
|
+
* written in `schemaVersion` — see the module doc for what that admits.
|
|
251
|
+
* Case-insensitive input; UPPERCASE output, deduplicated across the whole
|
|
252
|
+
* list, each requested type immediately ahead of its own sorted descendants.
|
|
253
|
+
*
|
|
254
|
+
* `schemaVersion` is required and should be the queried model's own
|
|
255
|
+
* `store.schemaVersion`. It is what keeps a re-parented entity out of the
|
|
256
|
+
* answer, so there is no sensible default: an omitted version would silently
|
|
257
|
+
* mean "IFC4", and on an IFC2X3 model that answer is wrong rather than
|
|
258
|
+
* approximate. Values with no bundled table fall back as documented on
|
|
259
|
+
* `resolveSchemaVersion`.
|
|
260
|
+
*
|
|
261
|
+
* A type unknown to every bundled table (a typo, a vendor extension) comes
|
|
262
|
+
* back as itself, so the caller's list keeps its shape rather than silently
|
|
263
|
+
* losing an entry.
|
|
264
|
+
*/
|
|
265
|
+
export function expandTypeNamesToDescendants(types, schemaVersion) {
|
|
266
|
+
const v = resolveSchemaVersion(schemaVersion);
|
|
267
|
+
const out = [];
|
|
268
|
+
const seen = new Set();
|
|
269
|
+
for (const type of types) {
|
|
270
|
+
for (const name of descendantsOf(type, v)) {
|
|
271
|
+
if (seen.has(name))
|
|
272
|
+
continue;
|
|
273
|
+
seen.add(name);
|
|
274
|
+
out.push(name);
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
return out;
|
|
278
|
+
}
|
|
279
|
+
//# sourceMappingURL=descendants.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"descendants.js","sourceRoot":"","sources":["../../src/ifc-schema/descendants.ts"],"names":[],"mappings":"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"}
|