@ifc-lite/parser 4.3.2 → 5.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/attribute-helpers.d.ts +38 -4
- package/dist/attribute-helpers.d.ts.map +1 -1
- package/dist/attribute-helpers.js +71 -4
- package/dist/attribute-helpers.js.map +1 -1
- package/dist/classification-resolver.d.ts +28 -2
- package/dist/classification-resolver.d.ts.map +1 -1
- package/dist/classification-resolver.js +24 -6
- package/dist/classification-resolver.js.map +1 -1
- package/dist/columnar-parser-attributes.d.ts.map +1 -1
- package/dist/columnar-parser-attributes.js +35 -5
- package/dist/columnar-parser-attributes.js.map +1 -1
- package/dist/columnar-parser-indexes.d.ts.map +1 -1
- package/dist/columnar-parser-indexes.js +14 -2
- package/dist/columnar-parser-indexes.js.map +1 -1
- package/dist/columnar-parser-relationships.d.ts.map +1 -1
- package/dist/columnar-parser-relationships.js +6 -1
- package/dist/columnar-parser-relationships.js.map +1 -1
- package/dist/columnar-parser.d.ts +4 -2
- package/dist/columnar-parser.d.ts.map +1 -1
- package/dist/columnar-parser.js +18 -56
- package/dist/columnar-parser.js.map +1 -1
- package/dist/compact-entity-index-transport.d.ts +23 -0
- package/dist/compact-entity-index-transport.d.ts.map +1 -0
- package/dist/compact-entity-index-transport.js +28 -0
- package/dist/compact-entity-index-transport.js.map +1 -0
- package/dist/compact-entity-index.d.ts +1 -10
- package/dist/compact-entity-index.d.ts.map +1 -1
- package/dist/compact-entity-index.js +29 -26
- package/dist/compact-entity-index.js.map +1 -1
- package/dist/data-store-transport.d.ts +9 -26
- package/dist/data-store-transport.d.ts.map +1 -1
- package/dist/data-store-transport.js +16 -35
- package/dist/data-store-transport.js.map +1 -1
- package/dist/entity-extractor.d.ts.map +1 -1
- package/dist/entity-extractor.js +101 -6
- package/dist/entity-extractor.js.map +1 -1
- package/dist/entity-refs-from-index.d.ts.map +1 -1
- package/dist/entity-refs-from-index.js +24 -15
- package/dist/entity-refs-from-index.js.map +1 -1
- package/dist/entity-scanner.d.ts +63 -0
- package/dist/entity-scanner.d.ts.map +1 -1
- package/dist/entity-scanner.js +79 -2
- package/dist/entity-scanner.js.map +1 -1
- package/dist/express-id.d.ts +47 -0
- package/dist/express-id.d.ts.map +1 -0
- package/dist/express-id.js +57 -0
- package/dist/express-id.js.map +1 -0
- package/dist/generated/entities.d.ts +1 -1
- package/dist/generated/entities.d.ts.map +1 -1
- package/dist/generated/schema-registry.js +146 -146
- package/dist/generated/schema-registry.js.map +1 -1
- package/dist/georef-epset.d.ts +25 -0
- package/dist/georef-epset.d.ts.map +1 -0
- package/dist/georef-epset.js +214 -0
- package/dist/georef-epset.js.map +1 -0
- package/dist/georef-extractor.d.ts.map +1 -1
- package/dist/georef-extractor.js +38 -175
- package/dist/georef-extractor.js.map +1 -1
- package/dist/georef-map-conversion.d.ts +29 -0
- package/dist/georef-map-conversion.d.ts.map +1 -0
- package/dist/georef-map-conversion.js +75 -0
- package/dist/georef-map-conversion.js.map +1 -0
- package/dist/ifc-schema.d.ts +4 -2
- package/dist/ifc-schema.d.ts.map +1 -1
- package/dist/ifc-schema.js +15 -5
- package/dist/ifc-schema.js.map +1 -1
- package/dist/index.d.ts +5 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -2
- package/dist/index.js.map +1 -1
- package/dist/material-extractor.d.ts +2 -17
- package/dist/material-extractor.d.ts.map +1 -1
- package/dist/material-extractor.js +12 -37
- package/dist/material-extractor.js.map +1 -1
- package/dist/material-layer-reader.d.ts +45 -0
- package/dist/material-layer-reader.d.ts.map +1 -0
- package/dist/material-layer-reader.js +63 -0
- package/dist/material-layer-reader.js.map +1 -0
- package/dist/material-resolver.d.ts.map +1 -1
- package/dist/material-resolver.js +14 -14
- package/dist/material-resolver.js.map +1 -1
- package/dist/measure-unit-scale.d.ts +41 -0
- package/dist/measure-unit-scale.d.ts.map +1 -0
- package/dist/measure-unit-scale.js +53 -0
- package/dist/measure-unit-scale.js.map +1 -0
- package/dist/on-demand-extractors.d.ts +4 -20
- package/dist/on-demand-extractors.d.ts.map +1 -1
- package/dist/on-demand-extractors.js +54 -264
- package/dist/on-demand-extractors.js.map +1 -1
- package/dist/on-demand-georeferencing.d.ts +3 -3
- package/dist/on-demand-georeferencing.js +27 -4
- package/dist/on-demand-georeferencing.js.map +1 -1
- package/dist/owning-project.d.ts +54 -0
- package/dist/owning-project.d.ts.map +1 -0
- package/dist/owning-project.js +76 -0
- package/dist/owning-project.js.map +1 -0
- package/dist/parser.worker.d.ts +14 -0
- package/dist/parser.worker.d.ts.map +1 -1
- package/dist/parser.worker.js +16 -3
- package/dist/parser.worker.js.map +1 -1
- package/dist/project-units-symbols.d.ts +33 -0
- package/dist/project-units-symbols.d.ts.map +1 -0
- package/dist/project-units-symbols.js +265 -0
- package/dist/project-units-symbols.js.map +1 -0
- package/dist/project-units.d.ts +11 -19
- package/dist/project-units.d.ts.map +1 -1
- package/dist/project-units.js +9 -267
- package/dist/project-units.js.map +1 -1
- package/dist/property-set-merge.d.ts +65 -8
- package/dist/property-set-merge.d.ts.map +1 -1
- package/dist/property-set-merge.js +130 -29
- package/dist/property-set-merge.js.map +1 -1
- package/dist/property-value-parser.d.ts +55 -0
- package/dist/property-value-parser.d.ts.map +1 -0
- package/dist/property-value-parser.js +277 -0
- package/dist/property-value-parser.js.map +1 -0
- package/dist/quantity-collect.d.ts +42 -3
- package/dist/quantity-collect.d.ts.map +1 -1
- package/dist/quantity-collect.js +114 -7
- package/dist/quantity-collect.js.map +1 -1
- package/dist/query-backend-maps.d.ts +5 -8
- package/dist/query-backend-maps.d.ts.map +1 -1
- package/dist/query-backend-maps.js +155 -15
- package/dist/query-backend-maps.js.map +1 -1
- package/dist/relationship-extractor.d.ts.map +1 -1
- package/dist/relationship-extractor.js +18 -0
- package/dist/relationship-extractor.js.map +1 -1
- package/dist/scan-entities-balanced.d.ts +38 -0
- package/dist/scan-entities-balanced.d.ts.map +1 -0
- package/dist/scan-entities-balanced.js +258 -0
- package/dist/scan-entities-balanced.js.map +1 -0
- package/dist/scan-worker-inline.d.ts +17 -11
- package/dist/scan-worker-inline.d.ts.map +1 -1
- package/dist/scan-worker-inline.js +9 -235
- package/dist/scan-worker-inline.js.map +1 -1
- package/dist/scan-worker-source.d.ts +9 -0
- package/dist/scan-worker-source.d.ts.map +1 -0
- package/dist/scan-worker-source.js +383 -0
- package/dist/scan-worker-source.js.map +1 -0
- package/dist/spatial-hierarchy-builder.js +3 -3
- package/dist/spatial-hierarchy-builder.js.map +1 -1
- package/dist/step-lexing.d.ts +2 -0
- package/dist/step-lexing.d.ts.map +1 -1
- package/dist/step-lexing.js +116 -18
- package/dist/step-lexing.js.map +1 -1
- package/dist/step-trivia.d.ts +60 -0
- package/dist/step-trivia.d.ts.map +1 -0
- package/dist/step-trivia.js +63 -0
- package/dist/step-trivia.js.map +1 -0
- package/dist/tokenizer.d.ts +20 -21
- package/dist/tokenizer.d.ts.map +1 -1
- package/dist/tokenizer.js +164 -203
- package/dist/tokenizer.js.map +1 -1
- package/dist/unit-extractor.d.ts +43 -1
- package/dist/unit-extractor.d.ts.map +1 -1
- package/dist/unit-extractor.js +63 -4
- package/dist/unit-extractor.js.map +1 -1
- package/dist/worker-parser.d.ts +11 -1
- package/dist/worker-parser.d.ts.map +1 -1
- package/dist/worker-parser.js +25 -5
- package/dist/worker-parser.js.map +1 -1
- package/package.json +6 -6
|
@@ -2,30 +2,27 @@
|
|
|
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
4
|
/**
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
* `Pset_CoveringCommon` holding `IsExternal`/`Reference` on the occurrence and
|
|
11
|
-
* `SurfaceSpreadOfFlame`/`Combustible` on the type is a plain Revit export.
|
|
12
|
-
* Dropping the whole inherited set on a name collision makes every type-only
|
|
13
|
-
* property in it invisible, which is what made IDS report a present property as
|
|
14
|
-
* missing (#1913). Where both define the same property name, the occurrence
|
|
15
|
-
* wins — it is the more specific definition.
|
|
5
|
+
* How property/quantity sets coming from two different sources compose: an
|
|
6
|
+
* occurrence's own sets with the ones it inherits from its `IfcTypeProduct`
|
|
7
|
+
* ({@link mergeInheritedPropertySets}, {@link mergeInheritedQuantitySets}),
|
|
8
|
+
* and a type's `HasPropertySets` list with the sets attached to it by
|
|
9
|
+
* `IfcRelDefinesByProperties` ({@link appendSetsFromSecondSource}).
|
|
16
10
|
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
*
|
|
23
|
-
*
|
|
11
|
+
* Their own module rather than a corner of `on-demand-extractors.ts`: the rules
|
|
12
|
+
* are independent of how either side was extracted, and every consumer that
|
|
13
|
+
* resolves sets from more than one source needs the same answer.
|
|
14
|
+
*/
|
|
15
|
+
/**
|
|
16
|
+
* Compose an occurrence's own named sets with those it inherits from its
|
|
17
|
+
* `IfcTypeProduct`, the way IFC defines the inheritance: **per item (property
|
|
18
|
+
* or quantity), not per set**. Shared core for {@link mergeInheritedPropertySets}
|
|
19
|
+
* and {@link mergeInheritedQuantitySets} — see those for the rule this
|
|
20
|
+
* implements and why.
|
|
24
21
|
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
22
|
+
* `getItems`/`withItems` isolate the one difference between the two: which
|
|
23
|
+
* field holds the named children (`properties` vs `quantities`).
|
|
27
24
|
*/
|
|
28
|
-
|
|
25
|
+
function mergeInheritedNamedSets(ownSets, inheritedSets, getItems, withItems) {
|
|
29
26
|
if (inheritedSets.length === 0)
|
|
30
27
|
return ownSets.slice();
|
|
31
28
|
const merged = ownSets.slice();
|
|
@@ -38,7 +35,13 @@ export function mergeInheritedPropertySets(ownSets, inheritedSets) {
|
|
|
38
35
|
indicesByName.set(merged[i].name, [i]);
|
|
39
36
|
}
|
|
40
37
|
for (const inherited of inheritedSets) {
|
|
41
|
-
|
|
38
|
+
// An UNNAMED set matches nothing: since #3530 every set the source left
|
|
39
|
+
// without a Name reports `''`, so keying on it would fold an unnamed
|
|
40
|
+
// inherited set into an unrelated unnamed occurrence set and lose any
|
|
41
|
+
// item the two happen to share. Before #3530 the two carried distinct
|
|
42
|
+
// placeholder names and were kept apart here; an absent name is
|
|
43
|
+
// evidence of nothing, least of all of sameness.
|
|
44
|
+
const indices = inherited.name ? indicesByName.get(inherited.name) : undefined;
|
|
42
45
|
if (!indices) {
|
|
43
46
|
// Appended as-is, and deliberately NOT recorded in `indicesByName`:
|
|
44
47
|
// that index tracks OCCURRENCE sets only. Recording it would make a
|
|
@@ -50,17 +53,115 @@ export function mergeInheritedPropertySets(ownSets, inheritedSets) {
|
|
|
50
53
|
}
|
|
51
54
|
for (const index of indices) {
|
|
52
55
|
const own = merged[index];
|
|
53
|
-
const
|
|
54
|
-
const
|
|
56
|
+
const ownItems = getItems(own);
|
|
57
|
+
const ownNames = new Set(ownItems.map((p) => p.name));
|
|
58
|
+
const additions = getItems(inherited).filter((p) => !ownNames.has(p.name));
|
|
55
59
|
if (additions.length === 0)
|
|
56
60
|
continue;
|
|
57
|
-
|
|
58
|
-
// only `properties` with a superset of the same element type, but
|
|
59
|
-
// TypeScript cannot narrow a spread of an unresolved generic back
|
|
60
|
-
// to that generic.
|
|
61
|
-
merged[index] = { ...own, properties: [...own.properties, ...additions] };
|
|
61
|
+
merged[index] = withItems(own, [...ownItems, ...additions]);
|
|
62
62
|
}
|
|
63
63
|
}
|
|
64
64
|
return merged;
|
|
65
65
|
}
|
|
66
|
+
/**
|
|
67
|
+
* Compose an occurrence's own property sets with those it inherits from its
|
|
68
|
+
* `IfcTypeProduct`, the way IFC defines the inheritance: **per property, not
|
|
69
|
+
* per property set**.
|
|
70
|
+
*
|
|
71
|
+
* An occurrence and its type routinely both carry a set of the same name —
|
|
72
|
+
* `Pset_CoveringCommon` holding `IsExternal`/`Reference` on the occurrence and
|
|
73
|
+
* `SurfaceSpreadOfFlame`/`Combustible` on the type is a plain Revit export.
|
|
74
|
+
* Dropping the whole inherited set on a name collision makes every type-only
|
|
75
|
+
* property in it invisible, which is what made IDS report a present property as
|
|
76
|
+
* missing (#1913). Where both define the same property name, the occurrence
|
|
77
|
+
* wins — it is the more specific definition.
|
|
78
|
+
*
|
|
79
|
+
* An occurrence may carry **several** sets of one name (one per
|
|
80
|
+
* `IfcRelDefinesByProperties`; nothing dedupes them, and merged/federated
|
|
81
|
+
* exports produce them). Inherited properties are merged into *every* one of
|
|
82
|
+
* them, not just the first: IDS requires every set matching the facet's
|
|
83
|
+
* `propertySet` constraint to satisfy it, so augmenting one and leaving its
|
|
84
|
+
* twin bare would reintroduce the same false "not found" this rule exists to
|
|
85
|
+
* prevent.
|
|
86
|
+
*
|
|
87
|
+
* Neither input is mutated: a set that gains inherited properties is returned
|
|
88
|
+
* as a new object, so cached extractor results stay intact.
|
|
89
|
+
*/
|
|
90
|
+
export function mergeInheritedPropertySets(ownSets, inheritedSets) {
|
|
91
|
+
return mergeInheritedNamedSets(ownSets, inheritedSets, (set) => set.properties,
|
|
92
|
+
// `as T`: the spread reproduces every field of `set` and replaces only
|
|
93
|
+
// `properties` with a superset of the same element type, but
|
|
94
|
+
// TypeScript cannot narrow a spread of an unresolved generic back to
|
|
95
|
+
// that generic.
|
|
96
|
+
(set, properties) => ({ ...set, properties }));
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Compose an occurrence's own quantity sets (`IfcElementQuantity`) with those
|
|
100
|
+
* it inherits from its `IfcTypeProduct`, applying the same per-item rule
|
|
101
|
+
* {@link mergeInheritedPropertySets} applies to property sets: a same-named
|
|
102
|
+
* set does not replace or get replaced wholesale, it is topped up quantity by
|
|
103
|
+
* quantity, and the occurrence wins a same-named-quantity collision.
|
|
104
|
+
*
|
|
105
|
+
* IFC does not distinguish properties from quantities for this purpose —
|
|
106
|
+
* both live in the type's `HasPropertySets` list alongside each other — so a
|
|
107
|
+
* consumer that resolves inherited properties this way but resolves
|
|
108
|
+
* quantities by only ever looking at the occurrence's own sets silently
|
|
109
|
+
* drops every quantity a type-level `Qto_*` set carries (e.g.
|
|
110
|
+
* `Qto_WallBaseQuantities` attached to `IfcWallType` rather than each wall).
|
|
111
|
+
*/
|
|
112
|
+
export function mergeInheritedQuantitySets(ownSets, inheritedSets) {
|
|
113
|
+
return mergeInheritedNamedSets(ownSets, inheritedSets, (set) => set.quantities, (set, quantities) => ({ ...set, quantities }));
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Identity key for a property/quantity set: `(name, globalId)` joined with a
|
|
117
|
+
* NUL separator, the same convention `groupPropertySetsByInstance`/
|
|
118
|
+
* `groupQuantitySetsByInstance` (`@ifc-lite/data`) use for the occurrence-level
|
|
119
|
+
* `PropertyTable`/`QuantityTable` (#3603, #3606). A name alone is only a proxy
|
|
120
|
+
* for identity: two distinct `IfcPropertySet`/`IfcElementQuantity` instances
|
|
121
|
+
* routinely share a literal name (a federated merge, or an exporter emitting
|
|
122
|
+
* the same `Qto_` set twice), and a name-only key folds one into the other,
|
|
123
|
+
* silently dropping whichever loses (#3722). Those helpers operate on
|
|
124
|
+
* columnar `Uint32Array` string-table indices and this module on
|
|
125
|
+
* already-extracted set objects, so the identity-key SHAPE is shared but not
|
|
126
|
+
* the function itself.
|
|
127
|
+
*/
|
|
128
|
+
export function setIdentityKey(set) {
|
|
129
|
+
return set.name + '\u0000' + (set.globalId ?? '');
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Append the sets a type carries via `IfcRelDefinesByProperties` to the ones
|
|
133
|
+
* already collected from its `HasPropertySets` attribute, listing a set that is
|
|
134
|
+
* reachable BOTH ways only once.
|
|
135
|
+
*
|
|
136
|
+
* The dedupe is by express id first. A name is only a proxy for identity, and
|
|
137
|
+
* since #3530 it stopped being even that: every set the source left unnamed
|
|
138
|
+
* now reports `''`, so a name-only check would fold every unnamed set from the
|
|
139
|
+
* second source into the first unnamed one from the first and drop its
|
|
140
|
+
* properties outright. The identity-key check ({@link setIdentityKey}) is still
|
|
141
|
+
* applied on top for genuinely named sets, where an empty set from one source
|
|
142
|
+
* must not shadow a populated same-named set from the other -- but it keys on
|
|
143
|
+
* `(name, globalId)`, not name alone, so two distinct same-named instances
|
|
144
|
+
* (different GlobalId) both survive (#3722); only a second row of the SAME
|
|
145
|
+
* instance still collapses.
|
|
146
|
+
*
|
|
147
|
+
* `extract` is called at most once, with the ids the first source did not
|
|
148
|
+
* already contribute.
|
|
149
|
+
*/
|
|
150
|
+
export function appendSetsFromSecondSource(into, firstSourceIds, firstSourceKeys, candidateIds, extract) {
|
|
151
|
+
const fresh = candidateIds.filter((id) => !firstSourceIds.has(id));
|
|
152
|
+
if (fresh.length === 0)
|
|
153
|
+
return;
|
|
154
|
+
const acceptedKeys = new Set();
|
|
155
|
+
for (const set of extract(fresh)) {
|
|
156
|
+
// A set with either a name or a globalId has an identity worth
|
|
157
|
+
// deduplicating on; only a set with neither passes through unkeyed.
|
|
158
|
+
if (set.name || set.globalId) {
|
|
159
|
+
const key = setIdentityKey(set);
|
|
160
|
+
if (firstSourceKeys.has(key) || acceptedKeys.has(key))
|
|
161
|
+
continue;
|
|
162
|
+
acceptedKeys.add(key);
|
|
163
|
+
}
|
|
164
|
+
into.push(set);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
66
167
|
//# sourceMappingURL=property-set-merge.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"property-set-merge.js","sourceRoot":"","sources":["../src/property-set-merge.ts"],"names":[],"mappings":"AAAA;;+DAE+D;
|
|
1
|
+
{"version":3,"file":"property-set-merge.js","sourceRoot":"","sources":["../src/property-set-merge.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Property VALUE parsing for the on-demand STEP extraction path: decodes a
|
|
3
|
+
* single `IfcProperty` subtype entity (IfcPropertySingleValue,
|
|
4
|
+
* IfcPropertyEnumeratedValue, IfcPropertyBoundedValue, IfcPropertyListValue,
|
|
5
|
+
* IfcPropertyTableValue, IfcPropertyReferenceValue, IfcComplexProperty) into
|
|
6
|
+
* the `{ type, value, values?, dataType? }` shape the property panel/query
|
|
7
|
+
* layer consumes. Split out of on-demand-extractors.ts to stay under the
|
|
8
|
+
* module-size budget.
|
|
9
|
+
*/
|
|
10
|
+
import type { IfcEntity } from './types.js';
|
|
11
|
+
import type { EntityExtractor } from './entity-extractor.js';
|
|
12
|
+
import type { PropertyValue } from '@ifc-lite/data';
|
|
13
|
+
import type { IfcDataStore } from './columnar-parser.js';
|
|
14
|
+
/**
|
|
15
|
+
* Parse a property entity's value based on its IFC type.
|
|
16
|
+
* Handles all 6 IfcProperty subtypes:
|
|
17
|
+
* - IfcPropertySingleValue: direct value
|
|
18
|
+
* - IfcPropertyEnumeratedValue: list of enum values → joined string
|
|
19
|
+
* - IfcPropertyBoundedValue: upper/lower bounds → "value [min – max]"
|
|
20
|
+
* - IfcPropertyListValue: list of values → joined string
|
|
21
|
+
* - IfcPropertyTableValue: defining/defined value pairs → "Table(N rows)"
|
|
22
|
+
* - IfcPropertyReferenceValue: entity reference → "Reference #ID"
|
|
23
|
+
*/
|
|
24
|
+
export declare function parsePropertyValue(propEntity: IfcEntity): {
|
|
25
|
+
type: number;
|
|
26
|
+
value: PropertyValue;
|
|
27
|
+
values?: string[];
|
|
28
|
+
dataType?: string;
|
|
29
|
+
};
|
|
30
|
+
/** Extract a numeric value from a possibly typed STEP value. */
|
|
31
|
+
export declare function extractNumericValue(attr: unknown): number | null;
|
|
32
|
+
/**
|
|
33
|
+
* Resolve an `IfcComplexProperty`'s nested `HasProperties` (EXPRESS:
|
|
34
|
+
* `[Name, Description, UsageName, HasProperties]`, index 3) into a display
|
|
35
|
+
* value plus a flat `values` candidate list, recursing into any further
|
|
36
|
+
* nested `IfcComplexProperty`. Without this, {@link parsePropertyValue}'s
|
|
37
|
+
* default branch reads attribute index 2 as if it were a `NominalValue`,
|
|
38
|
+
* which for `IfcComplexProperty` is `UsageName` — a label, not a value — and
|
|
39
|
+
* every nested property silently vanishes from the panel/query output.
|
|
40
|
+
*/
|
|
41
|
+
export declare function resolveComplexPropertyValue(store: IfcDataStore, extractor: EntityExtractor, propEntity: IfcEntity, depth?: number): {
|
|
42
|
+
type: number;
|
|
43
|
+
value: PropertyValue;
|
|
44
|
+
values?: string[];
|
|
45
|
+
dataType?: string;
|
|
46
|
+
};
|
|
47
|
+
/** Dispatch a pset member to {@link resolveComplexPropertyValue} for
|
|
48
|
+
* `IfcComplexProperty`, else the single-entity {@link parsePropertyValue}. */
|
|
49
|
+
export declare function parsePropertyValueWithComplex(store: IfcDataStore, extractor: EntityExtractor, propEntity: IfcEntity): {
|
|
50
|
+
type: number;
|
|
51
|
+
value: PropertyValue;
|
|
52
|
+
values?: string[];
|
|
53
|
+
dataType?: string;
|
|
54
|
+
};
|
|
55
|
+
//# sourceMappingURL=property-value-parser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"property-value-parser.d.ts","sourceRoot":"","sources":["../src/property-value-parser.ts"],"names":[],"mappings":"AAIA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAE7D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AACpD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAMzD;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,SAAS,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,aAAa,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,CA4LtI;AAED,gEAAgE;AAChE,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAIhE;AAOD;;;;;;;;GAQG;AACH,wBAAgB,2BAA2B,CACvC,KAAK,EAAE,YAAY,EACnB,SAAS,EAAE,eAAe,EAC1B,UAAU,EAAE,SAAS,EACrB,KAAK,SAAI,GACV;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,aAAa,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,CAoC9E;AAED;+EAC+E;AAC/E,wBAAgB,6BAA6B,CACzC,KAAK,EAAE,YAAY,EACnB,SAAS,EAAE,eAAe,EAC1B,UAAU,EAAE,SAAS,GACtB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,aAAa,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,CAK9E"}
|
|
@@ -0,0 +1,277 @@
|
|
|
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 { PropertyValueType } from '@ifc-lite/data';
|
|
5
|
+
// ============================================================================
|
|
6
|
+
// Property Value Parsing Helpers
|
|
7
|
+
// ============================================================================
|
|
8
|
+
/**
|
|
9
|
+
* Parse a property entity's value based on its IFC type.
|
|
10
|
+
* Handles all 6 IfcProperty subtypes:
|
|
11
|
+
* - IfcPropertySingleValue: direct value
|
|
12
|
+
* - IfcPropertyEnumeratedValue: list of enum values → joined string
|
|
13
|
+
* - IfcPropertyBoundedValue: upper/lower bounds → "value [min – max]"
|
|
14
|
+
* - IfcPropertyListValue: list of values → joined string
|
|
15
|
+
* - IfcPropertyTableValue: defining/defined value pairs → "Table(N rows)"
|
|
16
|
+
* - IfcPropertyReferenceValue: entity reference → "Reference #ID"
|
|
17
|
+
*/
|
|
18
|
+
export function parsePropertyValue(propEntity) {
|
|
19
|
+
const attrs = propEntity.attributes || [];
|
|
20
|
+
const typeUpper = propEntity.type.toUpperCase();
|
|
21
|
+
switch (typeUpper) {
|
|
22
|
+
case 'IFCPROPERTYENUMERATEDVALUE': {
|
|
23
|
+
// [Name, Description, EnumerationValues (list), EnumerationReference]
|
|
24
|
+
const enumValues = attrs[2];
|
|
25
|
+
if (Array.isArray(enumValues)) {
|
|
26
|
+
const values = enumValues.map(v => {
|
|
27
|
+
if (Array.isArray(v) && v.length === 2)
|
|
28
|
+
return String(v[1]); // Typed value
|
|
29
|
+
return String(v);
|
|
30
|
+
}).filter(v => v !== 'null' && v !== 'undefined');
|
|
31
|
+
// Surface the raw value list separately so IDS facet
|
|
32
|
+
// checks can iterate "any matching value passes". The
|
|
33
|
+
// joined display string remains the primary `value`
|
|
34
|
+
// for visualisation/property-table consumers.
|
|
35
|
+
return { type: 0, value: values.join(', ') || null, values };
|
|
36
|
+
}
|
|
37
|
+
return { type: 0, value: null };
|
|
38
|
+
}
|
|
39
|
+
case 'IFCPROPERTYBOUNDEDVALUE': {
|
|
40
|
+
// [Name, Description, UpperBoundValue, LowerBoundValue, Unit, SetPointValue]
|
|
41
|
+
const upper = extractNumericValue(attrs[2]);
|
|
42
|
+
const lower = extractNumericValue(attrs[3]);
|
|
43
|
+
const setPoint = extractNumericValue(attrs[5]);
|
|
44
|
+
const displayValue = setPoint ?? upper ?? lower;
|
|
45
|
+
let display = displayValue != null ? String(displayValue) : '';
|
|
46
|
+
if (lower != null && upper != null) {
|
|
47
|
+
display += ` [${lower} – ${upper}]`;
|
|
48
|
+
}
|
|
49
|
+
// Surface every defined bound as a candidate value — IDS
|
|
50
|
+
// bounded-property checks pass when ANY of the bounds /
|
|
51
|
+
// setpoint matches the constraint, per upstream ifctester.
|
|
52
|
+
const candidates = [];
|
|
53
|
+
if (lower != null)
|
|
54
|
+
candidates.push(String(lower));
|
|
55
|
+
if (upper != null && upper !== lower)
|
|
56
|
+
candidates.push(String(upper));
|
|
57
|
+
if (setPoint != null && setPoint !== lower && setPoint !== upper) {
|
|
58
|
+
candidates.push(String(setPoint));
|
|
59
|
+
}
|
|
60
|
+
// Carry the IFC-declared measure tag so the IDS-side data
|
|
61
|
+
// type comparison and unit conversion both work.
|
|
62
|
+
const inferDataType = (attr) => {
|
|
63
|
+
if (Array.isArray(attr) && attr.length === 2) {
|
|
64
|
+
return String(attr[0]).toUpperCase();
|
|
65
|
+
}
|
|
66
|
+
return undefined;
|
|
67
|
+
};
|
|
68
|
+
const dataType = inferDataType(attrs[5]) ||
|
|
69
|
+
inferDataType(attrs[2]) ||
|
|
70
|
+
inferDataType(attrs[3]);
|
|
71
|
+
return {
|
|
72
|
+
type: displayValue != null ? 1 : 0,
|
|
73
|
+
value: display || null,
|
|
74
|
+
...(candidates.length > 0 ? { values: candidates } : {}),
|
|
75
|
+
...(dataType ? { dataType } : {}),
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
case 'IFCPROPERTYLISTVALUE': {
|
|
79
|
+
// [Name, Description, ListValues (list), Unit]
|
|
80
|
+
const listValues = attrs[2];
|
|
81
|
+
if (Array.isArray(listValues)) {
|
|
82
|
+
const values = listValues.map(v => {
|
|
83
|
+
if (Array.isArray(v) && v.length === 2)
|
|
84
|
+
return String(v[1]);
|
|
85
|
+
return String(v);
|
|
86
|
+
}).filter(v => v !== 'null' && v !== 'undefined');
|
|
87
|
+
return { type: 0, value: values.join(', ') || null, values };
|
|
88
|
+
}
|
|
89
|
+
return { type: 0, value: null };
|
|
90
|
+
}
|
|
91
|
+
case 'IFCPROPERTYTABLEVALUE': {
|
|
92
|
+
// [Name, Description, DefiningValues, DefinedValues, ...]
|
|
93
|
+
const definingValues = attrs[2];
|
|
94
|
+
const definedValues = attrs[3];
|
|
95
|
+
const rowCount = Array.isArray(definingValues) ? definingValues.length : 0;
|
|
96
|
+
if (rowCount > 0 && Array.isArray(definedValues) && Array.isArray(definingValues)) {
|
|
97
|
+
// Surface both defining and defined values as candidate
|
|
98
|
+
// matches — IDS table-value checks pass when ANY entry
|
|
99
|
+
// matches the constraint (per upstream ifctester).
|
|
100
|
+
const stringify = (v) => {
|
|
101
|
+
if (Array.isArray(v) && v.length === 2)
|
|
102
|
+
return String(v[1]);
|
|
103
|
+
return String(v);
|
|
104
|
+
};
|
|
105
|
+
const values = [
|
|
106
|
+
...definingValues.map(stringify),
|
|
107
|
+
...definedValues.map(stringify),
|
|
108
|
+
].filter(v => v !== 'null' && v !== 'undefined');
|
|
109
|
+
// Tables mix types per column (label / length / …),
|
|
110
|
+
// so we can't surface a single representative
|
|
111
|
+
// dataType. Leaving it unset lets the IDS check fall
|
|
112
|
+
// through to a pure value match against any of the
|
|
113
|
+
// candidates — which is what upstream ifctester does
|
|
114
|
+
// for table values.
|
|
115
|
+
return {
|
|
116
|
+
type: 0,
|
|
117
|
+
value: `Table (${rowCount} rows)`,
|
|
118
|
+
values,
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
return { type: 0, value: null };
|
|
122
|
+
}
|
|
123
|
+
case 'IFCPROPERTYREFERENCEVALUE': {
|
|
124
|
+
// [Name, Description, PropertyReference]
|
|
125
|
+
const refValue = attrs[2];
|
|
126
|
+
if (typeof refValue === 'number') {
|
|
127
|
+
return { type: 0, value: `#${refValue}` };
|
|
128
|
+
}
|
|
129
|
+
return { type: 0, value: null };
|
|
130
|
+
}
|
|
131
|
+
default: {
|
|
132
|
+
// IfcPropertySingleValue and fallback: [Name, Description, NominalValue, Unit]
|
|
133
|
+
const nominalValue = attrs[2];
|
|
134
|
+
let type = PropertyValueType.String;
|
|
135
|
+
let value = nominalValue;
|
|
136
|
+
let dataType;
|
|
137
|
+
// Handle typed values like IFCBOOLEAN(.T.), IFCREAL(1.5)
|
|
138
|
+
if (Array.isArray(nominalValue) && nominalValue.length === 2) {
|
|
139
|
+
const innerValue = nominalValue[1];
|
|
140
|
+
const typeName = String(nominalValue[0]).toUpperCase();
|
|
141
|
+
dataType = typeName;
|
|
142
|
+
if (typeName.includes('BOOLEAN')) {
|
|
143
|
+
type = PropertyValueType.Boolean;
|
|
144
|
+
value = innerValue === '.T.' || innerValue === true;
|
|
145
|
+
}
|
|
146
|
+
else if (typeName.includes('LOGICAL')) {
|
|
147
|
+
type = PropertyValueType.Logical;
|
|
148
|
+
// Preserve .U. (unknown) as null; .T./.F. as boolean
|
|
149
|
+
if (innerValue === '.U.' || innerValue === '.X.') {
|
|
150
|
+
value = null;
|
|
151
|
+
}
|
|
152
|
+
else {
|
|
153
|
+
value = innerValue === '.T.' || innerValue === true;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
else if (typeof innerValue === 'number') {
|
|
157
|
+
// Preserve the IFC-declared numeric measure (IFCREAL,
|
|
158
|
+
// IFCINTEGER, IFCLENGTHMEASURE, IFCAREAMEASURE, …) —
|
|
159
|
+
// the source explicitly tagged the value, so don't
|
|
160
|
+
// re-infer from JS number-ness (which would
|
|
161
|
+
// misclassify e.g. `IFCREAL(0.0)` as integer).
|
|
162
|
+
if (typeName === 'IFCINTEGER' || typeName === 'IFCCOUNTMEASURE') {
|
|
163
|
+
type = PropertyValueType.Integer;
|
|
164
|
+
}
|
|
165
|
+
else if (typeName === 'IFCREAL' ||
|
|
166
|
+
typeName.endsWith('MEASURE') ||
|
|
167
|
+
typeName.endsWith('RATIO')) {
|
|
168
|
+
type = PropertyValueType.Real;
|
|
169
|
+
}
|
|
170
|
+
else if (Number.isInteger(innerValue)) {
|
|
171
|
+
type = PropertyValueType.Integer;
|
|
172
|
+
}
|
|
173
|
+
else {
|
|
174
|
+
type = PropertyValueType.Real;
|
|
175
|
+
}
|
|
176
|
+
value = innerValue;
|
|
177
|
+
}
|
|
178
|
+
else {
|
|
179
|
+
type = PropertyValueType.String;
|
|
180
|
+
value = String(innerValue);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
else if (typeof nominalValue === 'number') {
|
|
184
|
+
type = Number.isInteger(nominalValue) ? PropertyValueType.Integer : PropertyValueType.Real;
|
|
185
|
+
}
|
|
186
|
+
else if (typeof nominalValue === 'boolean') {
|
|
187
|
+
type = PropertyValueType.Boolean;
|
|
188
|
+
}
|
|
189
|
+
else if (nominalValue !== null && nominalValue !== undefined) {
|
|
190
|
+
// Normalize untagged STEP enumeration tokens. Conformant IFC wraps
|
|
191
|
+
// booleans as IFCBOOLEAN(.T.) (handled above), but some authoring
|
|
192
|
+
// tools emit the bare tokens directly in the NominalValue slot.
|
|
193
|
+
if (nominalValue === '.T.') {
|
|
194
|
+
type = PropertyValueType.Boolean;
|
|
195
|
+
value = true;
|
|
196
|
+
}
|
|
197
|
+
else if (nominalValue === '.F.') {
|
|
198
|
+
type = PropertyValueType.Boolean;
|
|
199
|
+
value = false;
|
|
200
|
+
}
|
|
201
|
+
else if (nominalValue === '.U.' || nominalValue === '.X.') {
|
|
202
|
+
type = PropertyValueType.Logical;
|
|
203
|
+
value = null;
|
|
204
|
+
}
|
|
205
|
+
else {
|
|
206
|
+
value = String(nominalValue);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
return { type, value, ...(dataType ? { dataType } : {}) };
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
/** Extract a numeric value from a possibly typed STEP value. */
|
|
214
|
+
export function extractNumericValue(attr) {
|
|
215
|
+
if (typeof attr === 'number')
|
|
216
|
+
return attr;
|
|
217
|
+
if (Array.isArray(attr) && attr.length === 2 && typeof attr[1] === 'number')
|
|
218
|
+
return attr[1];
|
|
219
|
+
return null;
|
|
220
|
+
}
|
|
221
|
+
/** Guards {@link resolveComplexPropertyValue} against a pathological/cyclic
|
|
222
|
+
* HasProperties chain; real IFC nests IfcComplexProperty at most a couple of
|
|
223
|
+
* levels deep (e.g. Pset "sub-properties"). */
|
|
224
|
+
const MAX_COMPLEX_PROPERTY_DEPTH = 8;
|
|
225
|
+
/**
|
|
226
|
+
* Resolve an `IfcComplexProperty`'s nested `HasProperties` (EXPRESS:
|
|
227
|
+
* `[Name, Description, UsageName, HasProperties]`, index 3) into a display
|
|
228
|
+
* value plus a flat `values` candidate list, recursing into any further
|
|
229
|
+
* nested `IfcComplexProperty`. Without this, {@link parsePropertyValue}'s
|
|
230
|
+
* default branch reads attribute index 2 as if it were a `NominalValue`,
|
|
231
|
+
* which for `IfcComplexProperty` is `UsageName` — a label, not a value — and
|
|
232
|
+
* every nested property silently vanishes from the panel/query output.
|
|
233
|
+
*/
|
|
234
|
+
export function resolveComplexPropertyValue(store, extractor, propEntity, depth = 0) {
|
|
235
|
+
const attrs = propEntity.attributes || [];
|
|
236
|
+
const usageName = typeof attrs[2] === 'string' ? attrs[2] : '';
|
|
237
|
+
const hasProperties = attrs[3];
|
|
238
|
+
if (!Array.isArray(hasProperties) || depth >= MAX_COMPLEX_PROPERTY_DEPTH) {
|
|
239
|
+
return { type: PropertyValueType.String, value: usageName || null };
|
|
240
|
+
}
|
|
241
|
+
const parts = [];
|
|
242
|
+
const values = [];
|
|
243
|
+
for (const ref of hasProperties) {
|
|
244
|
+
if (typeof ref !== 'number')
|
|
245
|
+
continue;
|
|
246
|
+
const nestedRef = store.entityIndex.byId.get(ref) ?? store.deferredEntityIndex?.get(ref);
|
|
247
|
+
if (!nestedRef)
|
|
248
|
+
continue;
|
|
249
|
+
const nestedEntity = extractor.extractEntity(nestedRef);
|
|
250
|
+
if (!nestedEntity)
|
|
251
|
+
continue;
|
|
252
|
+
const nestedAttrs = nestedEntity.attributes || [];
|
|
253
|
+
const nestedName = typeof nestedAttrs[0] === 'string' ? nestedAttrs[0] : '';
|
|
254
|
+
const nestedParsed = nestedEntity.type.toUpperCase() === 'IFCCOMPLEXPROPERTY'
|
|
255
|
+
? resolveComplexPropertyValue(store, extractor, nestedEntity, depth + 1)
|
|
256
|
+
: parsePropertyValue(nestedEntity);
|
|
257
|
+
const display = nestedParsed.value != null ? String(nestedParsed.value) : '';
|
|
258
|
+
if (!display)
|
|
259
|
+
continue;
|
|
260
|
+
parts.push(nestedName ? `${nestedName}: ${display}` : display);
|
|
261
|
+
values.push(display);
|
|
262
|
+
}
|
|
263
|
+
return {
|
|
264
|
+
type: PropertyValueType.String,
|
|
265
|
+
value: parts.length > 0 ? parts.join(', ') : (usageName || null),
|
|
266
|
+
...(values.length > 0 ? { values } : {}),
|
|
267
|
+
};
|
|
268
|
+
}
|
|
269
|
+
/** Dispatch a pset member to {@link resolveComplexPropertyValue} for
|
|
270
|
+
* `IfcComplexProperty`, else the single-entity {@link parsePropertyValue}. */
|
|
271
|
+
export function parsePropertyValueWithComplex(store, extractor, propEntity) {
|
|
272
|
+
if (propEntity.type.toUpperCase() === 'IFCCOMPLEXPROPERTY') {
|
|
273
|
+
return resolveComplexPropertyValue(store, extractor, propEntity);
|
|
274
|
+
}
|
|
275
|
+
return parsePropertyValue(propEntity);
|
|
276
|
+
}
|
|
277
|
+
//# sourceMappingURL=property-value-parser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"property-value-parser.js","sourceRoot":"","sources":["../src/property-value-parser.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
import type { EntityRef } from './types.js';
|
|
2
2
|
import type { EntityExtractor } from './entity-extractor.js';
|
|
3
|
+
import { type ProjectUnits } from './project-units.js';
|
|
3
4
|
/** One extracted quantity, in the shape both call sites report. */
|
|
4
5
|
export interface CollectedQuantity {
|
|
5
6
|
name: string;
|
|
6
7
|
type: number;
|
|
7
8
|
value: number;
|
|
9
|
+
/** SI factor of this quantity's explicit `Unit`, when it declares one.
|
|
10
|
+
* An omitted unit inherits the project's unit assignment. */
|
|
11
|
+
explicitUnitSiScale?: number;
|
|
8
12
|
}
|
|
9
13
|
/**
|
|
10
14
|
* The part of `IfcDataStore` this walk needs, declared structurally so the
|
|
@@ -65,6 +69,8 @@ export declare function collectQuantitiesFromRefs(store: QuantityLookupStore, ex
|
|
|
65
69
|
/** One extracted quantity set, in the shape both call sites report. */
|
|
66
70
|
export interface CollectedQuantitySet {
|
|
67
71
|
name: string;
|
|
72
|
+
/** `GlobalId` of the source `IfcElementQuantity` instance, when read as a string. */
|
|
73
|
+
globalId?: string;
|
|
68
74
|
quantities: CollectedQuantity[];
|
|
69
75
|
}
|
|
70
76
|
/**
|
|
@@ -80,17 +86,50 @@ export interface CollectedQuantitySet {
|
|
|
80
86
|
*
|
|
81
87
|
* `SET [1:?]` admits no empty set, so a set that walks to zero quantities —
|
|
82
88
|
* written empty, or filled only with members this reader cannot report, such as
|
|
83
|
-
* an unresolvable reference
|
|
84
|
-
* non-conformant data. Reporting it anyway would assert "this element has
|
|
89
|
+
* an unresolvable reference, an `IfcPhysicalComplexQuantity` (#3254), or a
|
|
90
|
+
* measure outside the IEEE-754 double range — is non-conformant data. Reporting it anyway would assert "this element has
|
|
85
91
|
* quantities" on the strength of a name alone, and the consumers act on exactly
|
|
86
92
|
* that: `validate` counts the element as quantified in its quantity-completeness
|
|
87
93
|
* figure, an IDS quantity-set existence check passes, and the viewer's fallback
|
|
88
94
|
* to the element's TYPE quantities is suppressed by the phantom occurrence set,
|
|
89
95
|
* hiding the real numbers the type carries. So it is dropped (#3259).
|
|
90
96
|
*
|
|
97
|
+
* That applies unchanged when every member was dropped for being
|
|
98
|
+
* unrepresentable: the set then vanishes rather than surviving empty. Keeping
|
|
99
|
+
* an empty shell would make exactly the claim #3259 removed — "this element is
|
|
100
|
+
* quantified" — while carrying no number to back it, and it would still
|
|
101
|
+
* suppress the type-quantity fallback. The reason each quantity went is on the
|
|
102
|
+
* console; the reason the set went is that nothing in it survived.
|
|
103
|
+
*
|
|
91
104
|
* The instance path and the type path both go through here, so the drop cannot
|
|
92
105
|
* come apart between them again: it used to be inlined at each site, and the
|
|
93
106
|
* type site dropped while the instance site kept.
|
|
94
107
|
*/
|
|
95
|
-
export declare function readQuantitySet(store: QuantityLookupStore, extractor: EntityExtractor, qsetRef: EntityRef
|
|
108
|
+
export declare function readQuantitySet(store: QuantityLookupStore, extractor: EntityExtractor, qsetRef: EntityRef): CollectedQuantitySet | null;
|
|
109
|
+
/**
|
|
110
|
+
* SI scale factor for a `Qto_` value, preferring its explicit `Unit` and then
|
|
111
|
+
* resolving against the project's declared units.
|
|
112
|
+
*
|
|
113
|
+
* An `IfcQuantityLength`/`Area`/`Volume` is stored in the project's raw
|
|
114
|
+
* author unit exactly like an `IfcPropertySingleValue` of the matching
|
|
115
|
+
* measure type — the value is not pre-converted to SI by the exporter. A
|
|
116
|
+
* consumer that hashes or otherwise compares `CollectedQuantity.value`
|
|
117
|
+
* across two files (or against a base-SI literal) as-is therefore reads a
|
|
118
|
+
* project's choice of length unit as a change in the design itself: the
|
|
119
|
+
* same 2 m wall authored in millimetres carries the raw value `2000`
|
|
120
|
+
* instead of `2`.
|
|
121
|
+
*
|
|
122
|
+
* `1` for `Count`/`Weight`/`Time`/`Number` — this only scales the three
|
|
123
|
+
* quantity types that are themselves `IfcLengthMeasure`-family measures.
|
|
124
|
+
*
|
|
125
|
+
* Area and Volume scale by the SQUARE and CUBE of the length factor (a
|
|
126
|
+
* millimetre-authored 1 m² is stored as `1e6`, not `1e3`) — but only as a
|
|
127
|
+
* FALLBACK: `IFC` lets a project declare an explicit `AREAUNIT`/`VOLUMEUNIT`
|
|
128
|
+
* with no arithmetic relationship to `LENGTHUNIT`, so the file's own
|
|
129
|
+
* declaration is preferred and the length-derived power is used only when
|
|
130
|
+
* the project declares none. An explicit member `Unit` always wins; IFC uses
|
|
131
|
+
* it specifically to let a quantity depart from its containing project's
|
|
132
|
+
* assignment.
|
|
133
|
+
*/
|
|
134
|
+
export declare function quantitySiScale(quantity: CollectedQuantity, units: ProjectUnits): number;
|
|
96
135
|
//# sourceMappingURL=quantity-collect.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"quantity-collect.d.ts","sourceRoot":"","sources":["../src/quantity-collect.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAG7D,mEAAmE;AACnE,MAAM,WAAW,iBAAiB;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"quantity-collect.d.ts","sourceRoot":"","sources":["../src/quantity-collect.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAG7D,OAAO,EAAoB,KAAK,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEzE,mEAAmE;AACnE,MAAM,WAAW,iBAAiB;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd;kEAC8D;IAC9D,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAChC;AAED;;;;GAIG;AACH,MAAM,WAAW,mBAAmB;IAChC,WAAW,EAAE;QAAE,IAAI,EAAE;YAAE,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS,CAAA;SAAE,CAAA;KAAE,CAAC;IAClE,mBAAmB,CAAC,EAAE;QAAE,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS,CAAA;KAAE,CAAC;CACpE;AA2BD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AACH,wBAAgB,yBAAyB,CACrC,KAAK,EAAE,mBAAmB,EAC1B,SAAS,EAAE,eAAe,EAC1B,IAAI,EAAE,OAAO,GACd,iBAAiB,EAAE,CA2ErB;AAUD,uEAAuE;AACvE,MAAM,WAAW,oBAAoB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,qFAAqF;IACrF,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,iBAAiB,EAAE,CAAC;CACnC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,wBAAgB,eAAe,CAC3B,KAAK,EAAE,mBAAmB,EAC1B,SAAS,EAAE,eAAe,EAC1B,OAAO,EAAE,SAAS,GACnB,oBAAoB,GAAG,IAAI,CAe7B;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,iBAAiB,EAAE,KAAK,EAAE,YAAY,GAAG,MAAM,CAqBxF"}
|