@ifc-lite/rules 0.2.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/LICENSE +373 -0
- package/README.md +45 -0
- package/dist/engine/rule-engine-chunk.d.ts +25 -0
- package/dist/engine/rule-engine-chunk.d.ts.map +1 -0
- package/dist/engine/rule-engine-chunk.js +43 -0
- package/dist/engine/rule-engine-chunk.js.map +1 -0
- package/dist/engine/rule-engine-compare.d.ts +17 -0
- package/dist/engine/rule-engine-compare.d.ts.map +1 -0
- package/dist/engine/rule-engine-compare.js +69 -0
- package/dist/engine/rule-engine-compare.js.map +1 -0
- package/dist/engine/rule-engine-requirements.d.ts +37 -0
- package/dist/engine/rule-engine-requirements.d.ts.map +1 -0
- package/dist/engine/rule-engine-requirements.js +293 -0
- package/dist/engine/rule-engine-requirements.js.map +1 -0
- package/dist/engine/rule-engine-sets.d.ts +46 -0
- package/dist/engine/rule-engine-sets.d.ts.map +1 -0
- package/dist/engine/rule-engine-sets.js +298 -0
- package/dist/engine/rule-engine-sets.js.map +1 -0
- package/dist/engine/rule-engine-unit.d.ts +23 -0
- package/dist/engine/rule-engine-unit.d.ts.map +1 -0
- package/dist/engine/rule-engine-unit.js +64 -0
- package/dist/engine/rule-engine-unit.js.map +1 -0
- package/dist/engine/rule-engine.d.ts +29 -0
- package/dist/engine/rule-engine.d.ts.map +1 -0
- package/dist/engine/rule-engine.js +244 -0
- package/dist/engine/rule-engine.js.map +1 -0
- package/dist/filter/effective-filter-fields.d.ts +13 -0
- package/dist/filter/effective-filter-fields.d.ts.map +1 -0
- package/dist/filter/effective-filter-fields.js +44 -0
- package/dist/filter/effective-filter-fields.js.map +1 -0
- package/dist/filter/entity-predefined-type.d.ts +24 -0
- package/dist/filter/entity-predefined-type.d.ts.map +1 -0
- package/dist/filter/entity-predefined-type.js +34 -0
- package/dist/filter/entity-predefined-type.js.map +1 -0
- package/dist/filter/filter-evaluate-groups.d.ts +36 -0
- package/dist/filter/filter-evaluate-groups.d.ts.map +1 -0
- package/dist/filter/filter-evaluate-groups.js +111 -0
- package/dist/filter/filter-evaluate-groups.js.map +1 -0
- package/dist/filter/filter-evaluate-model-tag.d.ts +22 -0
- package/dist/filter/filter-evaluate-model-tag.d.ts.map +1 -0
- package/dist/filter/filter-evaluate-model-tag.js +35 -0
- package/dist/filter/filter-evaluate-model-tag.js.map +1 -0
- package/dist/filter/filter-evaluate-mutations.d.ts +51 -0
- package/dist/filter/filter-evaluate-mutations.d.ts.map +1 -0
- package/dist/filter/filter-evaluate-mutations.js +111 -0
- package/dist/filter/filter-evaluate-mutations.js.map +1 -0
- package/dist/filter/filter-evaluate-yield.d.ts +9 -0
- package/dist/filter/filter-evaluate-yield.d.ts.map +1 -0
- package/dist/filter/filter-evaluate-yield.js +32 -0
- package/dist/filter/filter-evaluate-yield.js.map +1 -0
- package/dist/filter/filter-evaluate.d.ts +120 -0
- package/dist/filter/filter-evaluate.d.ts.map +1 -0
- package/dist/filter/filter-evaluate.js +408 -0
- package/dist/filter/filter-evaluate.js.map +1 -0
- package/dist/filter/filter-group-rule.d.ts +23 -0
- package/dist/filter/filter-group-rule.d.ts.map +1 -0
- package/dist/filter/filter-group-rule.js +69 -0
- package/dist/filter/filter-group-rule.js.map +1 -0
- package/dist/filter/filter-groups.d.ts +65 -0
- package/dist/filter/filter-groups.d.ts.map +1 -0
- package/dist/filter/filter-groups.js +136 -0
- package/dist/filter/filter-groups.js.map +1 -0
- package/dist/filter/filter-iteration-source.d.ts +26 -0
- package/dist/filter/filter-iteration-source.d.ts.map +1 -0
- package/dist/filter/filter-iteration-source.js +154 -0
- package/dist/filter/filter-iteration-source.js.map +1 -0
- package/dist/filter/filter-iteration.d.ts +5 -0
- package/dist/filter/filter-iteration.d.ts.map +1 -0
- package/dist/filter/filter-iteration.js +25 -0
- package/dist/filter/filter-iteration.js.map +1 -0
- package/dist/filter/filter-match.d.ts +114 -0
- package/dist/filter/filter-match.d.ts.map +1 -0
- package/dist/filter/filter-match.js +302 -0
- package/dist/filter/filter-match.js.map +1 -0
- package/dist/filter/filter-ops.d.ts +90 -0
- package/dist/filter/filter-ops.d.ts.map +1 -0
- package/dist/filter/filter-ops.js +202 -0
- package/dist/filter/filter-ops.js.map +1 -0
- package/dist/filter/filter-rule-guards.d.ts +4 -0
- package/dist/filter/filter-rule-guards.d.ts.map +1 -0
- package/dist/filter/filter-rule-guards.js +74 -0
- package/dist/filter/filter-rule-guards.js.map +1 -0
- package/dist/filter/filter-rules.d.ts +275 -0
- package/dist/filter/filter-rules.d.ts.map +1 -0
- package/dist/filter/filter-rules.js +68 -0
- package/dist/filter/filter-rules.js.map +1 -0
- package/dist/filter/lens-material-names.d.ts +13 -0
- package/dist/filter/lens-material-names.d.ts.map +1 -0
- package/dist/filter/lens-material-names.js +36 -0
- package/dist/filter/lens-material-names.js.map +1 -0
- package/dist/filter/measure-units.d.ts +29 -0
- package/dist/filter/measure-units.d.ts.map +1 -0
- package/dist/filter/measure-units.js +72 -0
- package/dist/filter/measure-units.js.map +1 -0
- package/dist/filter/model-tag.d.ts +65 -0
- package/dist/filter/model-tag.d.ts.map +1 -0
- package/dist/filter/model-tag.js +57 -0
- package/dist/filter/model-tag.js.map +1 -0
- package/dist/filter/read-measure-subject.d.ts +28 -0
- package/dist/filter/read-measure-subject.d.ts.map +1 -0
- package/dist/filter/read-measure-subject.js +116 -0
- package/dist/filter/read-measure-subject.js.map +1 -0
- package/dist/filter/read-subject.d.ts +72 -0
- package/dist/filter/read-subject.d.ts.map +1 -0
- package/dist/filter/read-subject.js +128 -0
- package/dist/filter/read-subject.js.map +1 -0
- package/dist/filter/subject-match.d.ts +27 -0
- package/dist/filter/subject-match.d.ts.map +1 -0
- package/dist/filter/subject-match.js +52 -0
- package/dist/filter/subject-match.js.map +1 -0
- package/dist/filter/subject-read-options.d.ts +33 -0
- package/dist/filter/subject-read-options.d.ts.map +1 -0
- package/dist/filter/subject-read-options.js +8 -0
- package/dist/filter/subject-read-options.js.map +1 -0
- package/dist/ids/ids-facet-to-rules.d.ts +20 -0
- package/dist/ids/ids-facet-to-rules.d.ts.map +1 -0
- package/dist/ids/ids-facet-to-rules.js +230 -0
- package/dist/ids/ids-facet-to-rules.js.map +1 -0
- package/dist/ids/ids-regex.d.ts +44 -0
- package/dist/ids/ids-regex.d.ts.map +1 -0
- package/dist/ids/ids-regex.js +334 -0
- package/dist/ids/ids-regex.js.map +1 -0
- package/dist/ids/ids-to-rule-set.d.ts +39 -0
- package/dist/ids/ids-to-rule-set.d.ts.map +1 -0
- package/dist/ids/ids-to-rule-set.js +103 -0
- package/dist/ids/ids-to-rule-set.js.map +1 -0
- package/dist/ids/ids-xml-writer.d.ts +11 -0
- package/dist/ids/ids-xml-writer.d.ts.map +1 -0
- package/dist/ids/ids-xml-writer.js +172 -0
- package/dist/ids/ids-xml-writer.js.map +1 -0
- package/dist/ids/rule-set-to-ids.d.ts +45 -0
- package/dist/ids/rule-set-to-ids.d.ts.map +1 -0
- package/dist/ids/rule-set-to-ids.js +140 -0
- package/dist/ids/rule-set-to-ids.js.map +1 -0
- package/dist/ids/rule-to-ids-facets.d.ts +52 -0
- package/dist/ids/rule-to-ids-facets.d.ts.map +1 -0
- package/dist/ids/rule-to-ids-facets.js +291 -0
- package/dist/ids/rule-to-ids-facets.js.map +1 -0
- package/dist/ids/stored-unit-scale.d.ts +15 -0
- package/dist/ids/stored-unit-scale.d.ts.map +1 -0
- package/dist/ids/stored-unit-scale.js +64 -0
- package/dist/ids/stored-unit-scale.js.map +1 -0
- package/dist/index.d.ts +39 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +46 -0
- package/dist/index.js.map +1 -0
- package/dist/rule-set/between-chip.d.ts +54 -0
- package/dist/rule-set/between-chip.d.ts.map +1 -0
- package/dist/rule-set/between-chip.js +95 -0
- package/dist/rule-set/between-chip.js.map +1 -0
- package/dist/rule-set/requirement-invariants.d.ts +25 -0
- package/dist/rule-set/requirement-invariants.d.ts.map +1 -0
- package/dist/rule-set/requirement-invariants.js +29 -0
- package/dist/rule-set/requirement-invariants.js.map +1 -0
- package/dist/rule-set/requirement-text.d.ts +20 -0
- package/dist/rule-set/requirement-text.d.ts.map +1 -0
- package/dist/rule-set/requirement-text.js +179 -0
- package/dist/rule-set/requirement-text.js.map +1 -0
- package/dist/rule-set/rule-set-io-requirement.d.ts +22 -0
- package/dist/rule-set/rule-set-io-requirement.d.ts.map +1 -0
- package/dist/rule-set/rule-set-io-requirement.js +140 -0
- package/dist/rule-set/rule-set-io-requirement.js.map +1 -0
- package/dist/rule-set/rule-set-io-shared.d.ts +24 -0
- package/dist/rule-set/rule-set-io-shared.d.ts.map +1 -0
- package/dist/rule-set/rule-set-io-shared.js +48 -0
- package/dist/rule-set/rule-set-io-shared.js.map +1 -0
- package/dist/rule-set/rule-set-io-subject.d.ts +10 -0
- package/dist/rule-set/rule-set-io-subject.d.ts.map +1 -0
- package/dist/rule-set/rule-set-io-subject.js +67 -0
- package/dist/rule-set/rule-set-io-subject.js.map +1 -0
- package/dist/rule-set/rule-set-io.d.ts +37 -0
- package/dist/rule-set/rule-set-io.d.ts.map +1 -0
- package/dist/rule-set/rule-set-io.js +142 -0
- package/dist/rule-set/rule-set-io.js.map +1 -0
- package/dist/rule-set/rule-set.d.ts +109 -0
- package/dist/rule-set/rule-set.d.ts.map +1 -0
- package/dist/rule-set/rule-set.js +5 -0
- package/dist/rule-set/rule-set.js.map +1 -0
- package/package.json +59 -0
|
@@ -0,0 +1,74 @@
|
|
|
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
|
+
* JSON guards for `FilterRule` (saved filters, URL state, presets).
|
|
6
|
+
*
|
|
7
|
+
* Split out of `filter-rules.ts` (which keeps the taxonomy itself — the
|
|
8
|
+
* interfaces and the `Rule` convenience constructors) to stay under the
|
|
9
|
+
* module size cap, the same way `filter-match.ts`/`filter-iteration-source.ts`
|
|
10
|
+
* split out of `filter-evaluate.ts`. Re-exported from `filter-rules.ts` so
|
|
11
|
+
* every existing `import { isFilterRule } from './filter-rules.js'` keeps
|
|
12
|
+
* working unchanged.
|
|
13
|
+
*/
|
|
14
|
+
import { isModelTagOp } from './model-tag.js';
|
|
15
|
+
const STRING_OPS = new Set([
|
|
16
|
+
'eq', 'ne', 'contains', 'notContains', 'startsWith', 'matches', 'notMatches',
|
|
17
|
+
]);
|
|
18
|
+
const CLASSIFICATION_OPS = new Set([
|
|
19
|
+
'eq', 'ne', 'contains', 'notContains', 'matches', 'notMatches', 'isSet', 'isNotSet',
|
|
20
|
+
]);
|
|
21
|
+
export function isFilterRule(value) {
|
|
22
|
+
if (typeof value !== 'object' || value === null)
|
|
23
|
+
return false;
|
|
24
|
+
const kind = value.kind;
|
|
25
|
+
if (kind === 'modelTag') {
|
|
26
|
+
// Structural: a bad op or a non-string id must not reach the evaluator.
|
|
27
|
+
const r = value;
|
|
28
|
+
return isModelTagOp(r.op) && Array.isArray(r.tagIds) && r.tagIds.every((t) => typeof t === 'string');
|
|
29
|
+
}
|
|
30
|
+
if (kind === 'parent') {
|
|
31
|
+
// Structural: `matchParentRule` lower-cases `value` per ancestor, so a
|
|
32
|
+
// persisted non-string value (or an unknown op) must not reach it.
|
|
33
|
+
const r = value;
|
|
34
|
+
return (STRING_OPS.has(r.op) &&
|
|
35
|
+
typeof r.value === 'string' &&
|
|
36
|
+
(r.valueKind === undefined || r.valueKind === 'literal' || r.valueKind === 'regex'));
|
|
37
|
+
}
|
|
38
|
+
if (kind === 'group') {
|
|
39
|
+
// Structural, like `parent`: `matchGroupRule` reads `value` as text and
|
|
40
|
+
// `groupClass` as a class name, so neither may arrive as anything else.
|
|
41
|
+
const r = value;
|
|
42
|
+
return (CLASSIFICATION_OPS.has(r.op) &&
|
|
43
|
+
typeof r.value === 'string' &&
|
|
44
|
+
(r.groupClass === undefined || typeof r.groupClass === 'string') &&
|
|
45
|
+
(r.valueKind === undefined || r.valueKind === 'literal' || r.valueKind === 'regex'));
|
|
46
|
+
}
|
|
47
|
+
if ((kind === 'property' || kind === 'quantity') && !validReadOptions(value))
|
|
48
|
+
return false;
|
|
49
|
+
return (kind === 'model' ||
|
|
50
|
+
kind === 'storey' ||
|
|
51
|
+
kind === 'ifcType' ||
|
|
52
|
+
kind === 'predefinedType' ||
|
|
53
|
+
kind === 'name' ||
|
|
54
|
+
kind === 'globalId' ||
|
|
55
|
+
kind === 'attribute' ||
|
|
56
|
+
kind === 'property' ||
|
|
57
|
+
kind === 'quantity' ||
|
|
58
|
+
kind === 'material' ||
|
|
59
|
+
kind === 'classification' ||
|
|
60
|
+
kind === 'elevation' ||
|
|
61
|
+
kind === 'type');
|
|
62
|
+
}
|
|
63
|
+
/** `SubjectReadOptions` fields, when present, must hold a value the engine knows. */
|
|
64
|
+
function validReadOptions(value) {
|
|
65
|
+
const r = value;
|
|
66
|
+
return (r.valueUnit === undefined || r.valueUnit === 'si')
|
|
67
|
+
&& (r.inherit === undefined || r.inherit === 'type' || r.inherit === 'aggregation');
|
|
68
|
+
}
|
|
69
|
+
export function parseFilterRules(raw) {
|
|
70
|
+
if (!Array.isArray(raw))
|
|
71
|
+
return [];
|
|
72
|
+
return raw.filter(isFilterRule);
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=filter-rule-guards.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"filter-rule-guards.js","sourceRoot":"","sources":["../../src/filter/filter-rule-guards.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unified filter rule taxonomy.
|
|
3
|
+
*
|
|
4
|
+
* Ported from the Tauri-side `filter.rs` engine and consumed by the
|
|
5
|
+
* in-memory path-B runtime evaluator (`filter-evaluate.ts`). The
|
|
6
|
+
* discriminated-union shape lets the chip UI serialise any rule as a
|
|
7
|
+
* JSON object with a `"kind"` discriminator, mirroring serde's tagged
|
|
8
|
+
* enum encoding. We use `kind` rather than `type` because `type`
|
|
9
|
+
* collides with the IFC `type` attribute name on element rows.
|
|
10
|
+
*/
|
|
11
|
+
import { type ModelTagOp } from './model-tag.js';
|
|
12
|
+
import { groupRule, type GroupRule } from './filter-group-rule.js';
|
|
13
|
+
import type { SubjectReadOptions } from './subject-read-options.js';
|
|
14
|
+
/** Set-membership: storey, ifcType, predefinedType. */
|
|
15
|
+
export type SetOp = 'in' | 'notIn';
|
|
16
|
+
/** String comparisons (Name rule). */
|
|
17
|
+
export type StringOp = 'eq' | 'ne' | 'contains' | 'notContains' | 'startsWith' | 'matches' | 'notMatches';
|
|
18
|
+
/** Numeric comparisons (Quantity rule). */
|
|
19
|
+
export type NumericOp = 'eq' | 'ne' | 'gt' | 'gte' | 'lt' | 'lte';
|
|
20
|
+
/** Mixed string+numeric+presence ops for Property values. */
|
|
21
|
+
export type ValueOp = 'eq' | 'ne' | 'gt' | 'gte' | 'lt' | 'lte' | 'contains' | 'notContains' | 'matches' | 'notMatches' | 'isSet' | 'isNotSet';
|
|
22
|
+
/** Classification value+presence ops. A classification is matched against
|
|
23
|
+
* its code / name string, so this is the StringOp comparison subset plus
|
|
24
|
+
* presence — numeric ops don't apply. */
|
|
25
|
+
export type ClassificationOp = 'eq' | 'ne' | 'contains' | 'notContains' | 'matches' | 'notMatches' | 'isSet' | 'isNotSet';
|
|
26
|
+
/** Top-level rule combinator. */
|
|
27
|
+
export type Combinator = 'AND' | 'OR';
|
|
28
|
+
/**
|
|
29
|
+
* How a rule reads one of its strings — the producer saying so, because the
|
|
30
|
+
* string itself cannot.
|
|
31
|
+
*
|
|
32
|
+
* `'regex'` is a regular-expression SOURCE: the WHOLE string is the pattern,
|
|
33
|
+
* slashes included. `'literal'` is exact text that is never a pattern, however
|
|
34
|
+
* it happens to be spelled. Absent means free text a human typed into a chip
|
|
35
|
+
* field, which keeps the Lists-panel convention (#1591): a `/body/flags`
|
|
36
|
+
* literal is a pattern, anything else is plain text.
|
|
37
|
+
*
|
|
38
|
+
* Guessing this back out of the text is the #4091 defect class — matched the
|
|
39
|
+
* wrong thing, said nothing — reappearing at the adapter seam. The selector
|
|
40
|
+
* grammar knows which it parsed: quoting is its ONLY escape hatch for a
|
|
41
|
+
* literal name, so `"/Wall/".FireRating` is the plain name `/Wall/`, and
|
|
42
|
+
* `Name=/\/tmp\//` is the source `/tmp/`. Sniffed for slashes, the first
|
|
43
|
+
* matches every `…Wall…` set and the second matches `tmp`.
|
|
44
|
+
*
|
|
45
|
+
* A property-set or property NAME has no operator beside it, so both kinds
|
|
46
|
+
* have to be declared. A VALUE's op already says whether it is a pattern, so
|
|
47
|
+
* only `'regex'` is ever recorded there.
|
|
48
|
+
*/
|
|
49
|
+
export type TextKind = 'literal' | 'regex';
|
|
50
|
+
export interface StoreyRule {
|
|
51
|
+
kind: 'storey';
|
|
52
|
+
values: string[];
|
|
53
|
+
op: SetOp;
|
|
54
|
+
/**
|
|
55
|
+
* Optional exact storey identity, set only when the rule was mirrored
|
|
56
|
+
* from a HierarchyPanel click (which holds the real `(modelId,
|
|
57
|
+
* expressId)` of the storey the user selected). `IfcBuildingStorey.Name`
|
|
58
|
+
* is optional and not unique — two distinct storeys, even within one
|
|
59
|
+
* model, routinely share a Name (repeated "Level 1" across wings, or
|
|
60
|
+
* federated buildings). When `refs` is present, the evaluator matches
|
|
61
|
+
* an element's storey by this exact identity instead of by name, so
|
|
62
|
+
* clicking one storey never silently pulls in a same-named sibling.
|
|
63
|
+
* Undefined for manually authored/typed rules (the chip UI only offers
|
|
64
|
+
* names to type against), which keep matching by name as before.
|
|
65
|
+
*/
|
|
66
|
+
refs?: ReadonlyArray<{
|
|
67
|
+
modelId: string;
|
|
68
|
+
expressId: number;
|
|
69
|
+
}>;
|
|
70
|
+
}
|
|
71
|
+
/** Match the loaded model that owns an element. Values use a durable source
|
|
72
|
+
* fingerprint so saved filters survive the fresh runtime ids minted on reload. */
|
|
73
|
+
export interface ModelRule {
|
|
74
|
+
kind: 'model';
|
|
75
|
+
values: string[];
|
|
76
|
+
op: SetOp;
|
|
77
|
+
}
|
|
78
|
+
/** Match the owning model by its user-facing MODEL TAGS (#4215). `tagIds` are ids
|
|
79
|
+
* (stable across renames); an id that no longer exists is unresolved → matches nothing. */
|
|
80
|
+
export interface ModelTagRule {
|
|
81
|
+
kind: 'modelTag';
|
|
82
|
+
op: ModelTagOp;
|
|
83
|
+
tagIds: string[];
|
|
84
|
+
}
|
|
85
|
+
export interface IfcTypeRule {
|
|
86
|
+
kind: 'ifcType';
|
|
87
|
+
values: string[];
|
|
88
|
+
op: SetOp;
|
|
89
|
+
/** Exact-class applicability, no subtype expansion (bSI #356, deferred by
|
|
90
|
+
* IDS to "Future 2.0+"). Default false/absent = today's behaviour
|
|
91
|
+
* (`values` already come pre-expanded through `expandTypes` at the
|
|
92
|
+
* chip/selector layer). Type-only here: the search evaluator
|
|
93
|
+
* (`filter-match.ts`) has no reason to read it, only the validation
|
|
94
|
+
* engine (#5138 PR 3) does. */
|
|
95
|
+
exactClass?: boolean;
|
|
96
|
+
}
|
|
97
|
+
export interface PredefinedTypeRule {
|
|
98
|
+
kind: 'predefinedType';
|
|
99
|
+
values: string[];
|
|
100
|
+
op: SetOp;
|
|
101
|
+
}
|
|
102
|
+
export interface NameRule {
|
|
103
|
+
kind: 'name';
|
|
104
|
+
op: StringOp;
|
|
105
|
+
value: string;
|
|
106
|
+
/** How `value` reads. Only consulted by the `matches` / `notMatches` ops. */
|
|
107
|
+
valueKind?: TextKind;
|
|
108
|
+
}
|
|
109
|
+
/** `325Q7Fhnf67OZC$$r43uzK` / `! 325Q7Fhnf67OZC$$r43uzK` — one element, by
|
|
110
|
+
* GlobalId. Multi-valued like `ifcType`/`storey` so several bare-GlobalId
|
|
111
|
+
* terms (or a Ctrl-click accumulation) fold into one rule; matching is
|
|
112
|
+
* case-SENSITIVE (`values` are 22-character base64 IFC GlobalIds, where
|
|
113
|
+
* case is significant), unlike every other set-membership rule here. */
|
|
114
|
+
export interface GlobalIdRule {
|
|
115
|
+
kind: 'globalId';
|
|
116
|
+
values: string[];
|
|
117
|
+
op: SetOp;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* `Description=Foo`, `ObjectType != NULL`, … — an IFC attribute other than
|
|
121
|
+
* Name or PredefinedType, which each have their own rule kind. `name` is the
|
|
122
|
+
* schema attribute name (matched case-insensitively against what the source
|
|
123
|
+
* buffer's schema-driven extraction returns); a `GlobalId` name is rejected
|
|
124
|
+
* at the selector adapter rather than reaching here — `extractAllEntityAttributes`
|
|
125
|
+
* never surfaces it (it's a structural/display attribute the parser skips),
|
|
126
|
+
* so routing it here would silently match nothing instead of finding the
|
|
127
|
+
* element the bare-GlobalId term already exists to find.
|
|
128
|
+
*/
|
|
129
|
+
export interface AttributeRule {
|
|
130
|
+
kind: 'attribute';
|
|
131
|
+
name: string;
|
|
132
|
+
op: ValueOp;
|
|
133
|
+
/** Raw user input. Numeric ops parse as f64; isSet/isNotSet ignore. */
|
|
134
|
+
value: string;
|
|
135
|
+
/** How `value` reads. Only consulted by the `matches` / `notMatches` ops. */
|
|
136
|
+
valueKind?: TextKind;
|
|
137
|
+
}
|
|
138
|
+
export interface PropertyRule extends SubjectReadOptions {
|
|
139
|
+
kind: 'property';
|
|
140
|
+
setName: string;
|
|
141
|
+
/** How `setName` reads — a regex set name is what lets one rule reach both
|
|
142
|
+
* `Pset_WallCommon` and `Pset_SlabCommon`. */
|
|
143
|
+
setNameKind?: TextKind;
|
|
144
|
+
propertyName: string;
|
|
145
|
+
/** How `propertyName` reads. */
|
|
146
|
+
propertyNameKind?: TextKind;
|
|
147
|
+
op: ValueOp;
|
|
148
|
+
/** Raw user input. Numeric ops parse as f64; isSet/isNotSet ignore. */
|
|
149
|
+
value: string;
|
|
150
|
+
/** How `value` reads. Only consulted by the `matches` / `notMatches` ops. */
|
|
151
|
+
valueKind?: TextKind;
|
|
152
|
+
}
|
|
153
|
+
export interface QuantityRule extends SubjectReadOptions {
|
|
154
|
+
kind: 'quantity';
|
|
155
|
+
setName: string;
|
|
156
|
+
/** How `setName` reads. */
|
|
157
|
+
setNameKind?: TextKind;
|
|
158
|
+
quantityName: string;
|
|
159
|
+
/** How `quantityName` reads. */
|
|
160
|
+
quantityNameKind?: TextKind;
|
|
161
|
+
op: NumericOp;
|
|
162
|
+
value: number;
|
|
163
|
+
}
|
|
164
|
+
/** Match against an element's material name(s) — top-level material,
|
|
165
|
+
* layer / constituent / profile names, list members — AND Category (#4094).
|
|
166
|
+
* Multi-valued: the evaluator matches if ANY candidate satisfies a positive
|
|
167
|
+
* op, or NONE violates a negative op (ne / notContains). */
|
|
168
|
+
export interface MaterialRule {
|
|
169
|
+
kind: 'material';
|
|
170
|
+
op: StringOp;
|
|
171
|
+
value: string;
|
|
172
|
+
/** How `value` reads. Only consulted by the `matches` / `notMatches` ops. */
|
|
173
|
+
valueKind?: TextKind;
|
|
174
|
+
}
|
|
175
|
+
/** Match against an element's classification references (e.g. Uniclass,
|
|
176
|
+
* OmniClass). `system` optionally scopes to one classification system;
|
|
177
|
+
* the value matches a reference's code (identification) OR name. */
|
|
178
|
+
export interface ClassificationRule {
|
|
179
|
+
kind: 'classification';
|
|
180
|
+
/** Optional system scope (e.g. "Uniclass 2015"). Empty = any system. */
|
|
181
|
+
system?: string;
|
|
182
|
+
op: ClassificationOp;
|
|
183
|
+
/** Matched against identification (code) OR name. Ignored for isSet/isNotSet. */
|
|
184
|
+
value: string;
|
|
185
|
+
/** How `value` reads. Only consulted by the `matches` / `notMatches` ops. */
|
|
186
|
+
valueKind?: TextKind;
|
|
187
|
+
}
|
|
188
|
+
/** Match against an element's elevation in metres — derived from the
|
|
189
|
+
* elevation of the building storey the element belongs to. */
|
|
190
|
+
export interface ElevationRule {
|
|
191
|
+
kind: 'elevation';
|
|
192
|
+
op: NumericOp;
|
|
193
|
+
/** Threshold in metres. */
|
|
194
|
+
value: number;
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* `type=WT01` (IfcOpenShell selector syntax) — match against the Name of
|
|
198
|
+
* the element's RELATING TYPE, reached via `IfcRelDefinesByType`. This is
|
|
199
|
+
* a different dimension from {@link IfcTypeRule}, which matches the
|
|
200
|
+
* element's own IFC *class* (`IfcWall`); `type=` instead matches the type
|
|
201
|
+
* OBJECT's `Name` attribute (e.g. `IfcWallType.Name`, "WT01"). An element
|
|
202
|
+
* with no `IfcRelDefinesByType` relation never matches. #4094.
|
|
203
|
+
*/
|
|
204
|
+
export interface TypeNameRule {
|
|
205
|
+
kind: 'type';
|
|
206
|
+
op: StringOp;
|
|
207
|
+
value: string;
|
|
208
|
+
/** How `value` reads. Only consulted by the `matches` / `notMatches` ops. */
|
|
209
|
+
valueKind?: TextKind;
|
|
210
|
+
}
|
|
211
|
+
/** `parent=Foo` (#4903) — direct or indirect spatial-hierarchy child of an
|
|
212
|
+
* element named `Foo`; walks containment AND aggregation, any depth, via
|
|
213
|
+
* `@ifc-lite/data`'s shared `collectSpatialAncestors` (see
|
|
214
|
+
* `filter-match.ts`'s `matchParentRule`). Multi-valued like `material`:
|
|
215
|
+
* ANY ancestor Name matching a positive op, or NONE violating a negative
|
|
216
|
+
* one; no (matching) ancestors satisfies neither op — EMPTY, not "no filter". */
|
|
217
|
+
export interface ParentRule {
|
|
218
|
+
kind: 'parent';
|
|
219
|
+
op: StringOp;
|
|
220
|
+
value: string;
|
|
221
|
+
/** How `value` reads. Only consulted by the `matches` / `notMatches` ops. */
|
|
222
|
+
valueKind?: TextKind;
|
|
223
|
+
}
|
|
224
|
+
export type FilterRule = ModelRule | ModelTagRule | StoreyRule | IfcTypeRule | PredefinedTypeRule | NameRule | GlobalIdRule | AttributeRule | PropertyRule | QuantityRule | MaterialRule | ClassificationRule | ElevationRule | TypeNameRule | ParentRule | GroupRule;
|
|
225
|
+
/** Combine an array of per-rule booleans according to AND/OR semantics. */
|
|
226
|
+
export declare function combineRuleResults(combinator: Combinator, results: readonly boolean[]): boolean;
|
|
227
|
+
/** Dedupe-merge two `StoreyRule.refs` lists by (modelId, expressId), used
|
|
228
|
+
* when a Ctrl-click accumulates another storey into an existing filter
|
|
229
|
+
* (HierarchyPanel). */
|
|
230
|
+
export declare function mergeStoreyRefs(prior: ReadonlyArray<{
|
|
231
|
+
modelId: string;
|
|
232
|
+
expressId: number;
|
|
233
|
+
}>, next: ReadonlyArray<{
|
|
234
|
+
modelId: string;
|
|
235
|
+
expressId: number;
|
|
236
|
+
}>): Array<{
|
|
237
|
+
modelId: string;
|
|
238
|
+
expressId: number;
|
|
239
|
+
}>;
|
|
240
|
+
/** Add a HierarchyPanel storey click to its mirrored `op:in` rule.
|
|
241
|
+
*
|
|
242
|
+
* A rule created by the hierarchy carries exact refs. A manually authored
|
|
243
|
+
* rule has no refs and deliberately matches by its names; changing that rule
|
|
244
|
+
* to ref mode would discard every existing manual selection. Keep it in name
|
|
245
|
+
* mode when extending it, while hierarchy-originated rules retain exact refs.
|
|
246
|
+
*/
|
|
247
|
+
export declare function addHierarchyStoreyToRule(prior: StoreyRule | undefined, name: string, refs: ReadonlyArray<{
|
|
248
|
+
modelId: string;
|
|
249
|
+
expressId: number;
|
|
250
|
+
}>): StoreyRule;
|
|
251
|
+
export declare const Rule: {
|
|
252
|
+
readonly model: (values: string[], op?: SetOp) => ModelRule;
|
|
253
|
+
readonly modelTag: (op: ModelTagOp, tagIds: string[]) => ModelTagRule;
|
|
254
|
+
readonly storey: (values: string[], op?: SetOp, refs?: ReadonlyArray<{
|
|
255
|
+
modelId: string;
|
|
256
|
+
expressId: number;
|
|
257
|
+
}>) => StoreyRule;
|
|
258
|
+
readonly ifcType: (values: string[], op?: SetOp) => IfcTypeRule;
|
|
259
|
+
readonly predefinedType: (values: string[], op?: SetOp) => PredefinedTypeRule;
|
|
260
|
+
readonly name: (op: StringOp, value: string, valueKind?: TextKind) => NameRule;
|
|
261
|
+
readonly globalId: (values: string[], op?: SetOp) => GlobalIdRule;
|
|
262
|
+
readonly attribute: (name: string, op: ValueOp, value: string, valueKind?: TextKind) => AttributeRule;
|
|
263
|
+
readonly property: (setName: string, propertyName: string, op: ValueOp, value: string, kinds?: Pick<PropertyRule, "setNameKind" | "propertyNameKind" | "valueKind">) => PropertyRule;
|
|
264
|
+
readonly quantity: (setName: string, quantityName: string, op: NumericOp, value: number, kinds?: Pick<QuantityRule, "setNameKind" | "quantityNameKind">) => QuantityRule;
|
|
265
|
+
readonly material: (op: StringOp, value: string, valueKind?: TextKind) => MaterialRule;
|
|
266
|
+
readonly classification: (system: string, op: ClassificationOp, value: string, valueKind?: TextKind) => ClassificationRule;
|
|
267
|
+
readonly elevation: (op: NumericOp, value: number) => ElevationRule;
|
|
268
|
+
readonly typeName: (op: StringOp, value: string, valueKind?: TextKind) => TypeNameRule;
|
|
269
|
+
readonly parent: (op: StringOp, value: string, valueKind?: TextKind) => ParentRule;
|
|
270
|
+
readonly group: typeof groupRule;
|
|
271
|
+
};
|
|
272
|
+
export { isFilterRule, parseFilterRules } from './filter-rule-guards.js';
|
|
273
|
+
export type { GroupRule } from './filter-group-rule.js';
|
|
274
|
+
export { activeGroupRules } from './filter-groups.js';
|
|
275
|
+
//# sourceMappingURL=filter-rules.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"filter-rules.d.ts","sourceRoot":"","sources":["../../src/filter/filter-rules.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,68 @@
|
|
|
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 { groupRule } from './filter-group-rule.js';
|
|
5
|
+
// ── Combinator helpers ────────────────────────────────────────────────────────
|
|
6
|
+
/** Combine an array of per-rule booleans according to AND/OR semantics. */
|
|
7
|
+
export function combineRuleResults(combinator, results) {
|
|
8
|
+
if (results.length === 0)
|
|
9
|
+
return false;
|
|
10
|
+
return combinator === 'AND' ? results.every((r) => r) : results.some((r) => r);
|
|
11
|
+
}
|
|
12
|
+
/** Dedupe-merge two `StoreyRule.refs` lists by (modelId, expressId), used
|
|
13
|
+
* when a Ctrl-click accumulates another storey into an existing filter
|
|
14
|
+
* (HierarchyPanel). */
|
|
15
|
+
export function mergeStoreyRefs(prior, next) {
|
|
16
|
+
const seen = new Set(prior.map((r) => `${r.modelId}:${r.expressId}`));
|
|
17
|
+
const merged = [...prior];
|
|
18
|
+
for (const r of next) {
|
|
19
|
+
const key = `${r.modelId}:${r.expressId}`;
|
|
20
|
+
if (!seen.has(key)) {
|
|
21
|
+
seen.add(key);
|
|
22
|
+
merged.push(r);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
return merged;
|
|
26
|
+
}
|
|
27
|
+
/** Add a HierarchyPanel storey click to its mirrored `op:in` rule.
|
|
28
|
+
*
|
|
29
|
+
* A rule created by the hierarchy carries exact refs. A manually authored
|
|
30
|
+
* rule has no refs and deliberately matches by its names; changing that rule
|
|
31
|
+
* to ref mode would discard every existing manual selection. Keep it in name
|
|
32
|
+
* mode when extending it, while hierarchy-originated rules retain exact refs.
|
|
33
|
+
*/
|
|
34
|
+
export function addHierarchyStoreyToRule(prior, name, refs) {
|
|
35
|
+
const values = Array.from(new Set([...(prior?.values ?? []), name]));
|
|
36
|
+
if (prior && !prior.refs)
|
|
37
|
+
return Rule.storey(values, 'in');
|
|
38
|
+
return Rule.storey(values, 'in', mergeStoreyRefs(prior?.refs ?? [], refs));
|
|
39
|
+
}
|
|
40
|
+
// ── Convenience constructors ──────────────────────────────────────────────────
|
|
41
|
+
//
|
|
42
|
+
// The chip UI builds rules via `set*` slice actions (see searchSlice.ts);
|
|
43
|
+
// these helpers exist primarily for tests and for code paths that synthesize
|
|
44
|
+
// rules from a different representation (URL state, presets).
|
|
45
|
+
export const Rule = {
|
|
46
|
+
model: (values, op = 'in') => ({ kind: 'model', values, op }),
|
|
47
|
+
modelTag: (op, tagIds) => ({ kind: 'modelTag', op, tagIds }),
|
|
48
|
+
storey: (values, op = 'in', refs) => ({ kind: 'storey', values, op, ...(refs ? { refs } : {}) }),
|
|
49
|
+
ifcType: (values, op = 'in') => ({ kind: 'ifcType', values, op }),
|
|
50
|
+
predefinedType: (values, op = 'in') => ({ kind: 'predefinedType', values, op }),
|
|
51
|
+
name: (op, value, valueKind) => ({ kind: 'name', op, value, ...(valueKind ? { valueKind } : {}) }),
|
|
52
|
+
globalId: (values, op = 'in') => ({ kind: 'globalId', values, op }),
|
|
53
|
+
attribute: (name, op, value, valueKind) => ({ kind: 'attribute', name, op, value, ...(valueKind ? { valueKind } : {}) }),
|
|
54
|
+
property: (setName, propertyName, op, value, kinds = {}) => ({ kind: 'property', setName, propertyName, op, value, ...kinds }),
|
|
55
|
+
quantity: (setName, quantityName, op, value, kinds = {}) => ({ kind: 'quantity', setName, quantityName, op, value, ...kinds }),
|
|
56
|
+
material: (op, value, valueKind) => ({ kind: 'material', op, value, ...(valueKind ? { valueKind } : {}) }),
|
|
57
|
+
classification: (system, op, value, valueKind) => ({ kind: 'classification', system: system || undefined, op, value, ...(valueKind ? { valueKind } : {}) }),
|
|
58
|
+
elevation: (op, value) => ({ kind: 'elevation', op, value }),
|
|
59
|
+
typeName: (op, value, valueKind) => ({ kind: 'type', op, value, ...(valueKind ? { valueKind } : {}) }),
|
|
60
|
+
parent: (op, value, valueKind) => ({ kind: 'parent', op, value, ...(valueKind ? { valueKind } : {}) }),
|
|
61
|
+
group: groupRule,
|
|
62
|
+
};
|
|
63
|
+
// ── JSON guards (`filter-rule-guards.ts`, re-exported for existing imports) ─
|
|
64
|
+
export { isFilterRule, parseFilterRules } from './filter-rule-guards.js';
|
|
65
|
+
// Re-exported so existing `from './filter-rules.js'` imports (HierarchyPanel,
|
|
66
|
+
// etc.) can pull in the groups helper too without a second import line (#4904).
|
|
67
|
+
export { activeGroupRules } from './filter-groups.js';
|
|
68
|
+
//# sourceMappingURL=filter-rules.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"filter-rules.js","sourceRoot":"","sources":["../../src/filter/filter-rules.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { MaterialInfo } from '@ifc-lite/parser';
|
|
2
|
+
/**
|
|
3
|
+
* Collect the distinct *individual* material names for an element from its
|
|
4
|
+
* resolved {@link MaterialInfo} — each layer / constituent / profile / list
|
|
5
|
+
* material. Deliberately excludes the layer-set / usage name (`info.name`,
|
|
6
|
+
* which for Revit exports is the family+type, not a material) UNLESS the
|
|
7
|
+
* element has no sub-structure, in which case the top-level name IS the single
|
|
8
|
+
* material. Order-preserving and de-duplicated, so a wall layered
|
|
9
|
+
* gypsumboard / insulation / gypsumboard yields `["gypsumboard", "insulation"]`
|
|
10
|
+
* and the element can be grouped/selected under each material. (#1366)
|
|
11
|
+
*/
|
|
12
|
+
export declare function lensMaterialNames(info: MaterialInfo | null | undefined): string[];
|
|
13
|
+
//# sourceMappingURL=lens-material-names.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lens-material-names.d.ts","sourceRoot":"","sources":["../../src/filter/lens-material-names.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAErD;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,YAAY,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,EAAE,CAcjF"}
|
|
@@ -0,0 +1,36 @@
|
|
|
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
|
+
* Collect the distinct *individual* material names for an element from its
|
|
6
|
+
* resolved {@link MaterialInfo} — each layer / constituent / profile / list
|
|
7
|
+
* material. Deliberately excludes the layer-set / usage name (`info.name`,
|
|
8
|
+
* which for Revit exports is the family+type, not a material) UNLESS the
|
|
9
|
+
* element has no sub-structure, in which case the top-level name IS the single
|
|
10
|
+
* material. Order-preserving and de-duplicated, so a wall layered
|
|
11
|
+
* gypsumboard / insulation / gypsumboard yields `["gypsumboard", "insulation"]`
|
|
12
|
+
* and the element can be grouped/selected under each material. (#1366)
|
|
13
|
+
*/
|
|
14
|
+
export function lensMaterialNames(info) {
|
|
15
|
+
if (!info)
|
|
16
|
+
return [];
|
|
17
|
+
const seen = new Set();
|
|
18
|
+
const add = (s) => {
|
|
19
|
+
const t = s?.trim();
|
|
20
|
+
if (t)
|
|
21
|
+
seen.add(t);
|
|
22
|
+
};
|
|
23
|
+
for (const l of info.layers ?? [])
|
|
24
|
+
add(l.materialName);
|
|
25
|
+
for (const c of info.constituents ?? [])
|
|
26
|
+
add(c.materialName);
|
|
27
|
+
for (const p of info.profiles ?? [])
|
|
28
|
+
add(p.materialName);
|
|
29
|
+
for (const m of info.materials ?? [])
|
|
30
|
+
add(m.name);
|
|
31
|
+
// No sub-structure → the element carries a single plain material.
|
|
32
|
+
if (seen.size === 0)
|
|
33
|
+
add(info.name);
|
|
34
|
+
return [...seen];
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=lens-material-names.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lens-material-names.js","sourceRoot":"","sources":["../../src/filter/lens-material-names.ts"],"names":[],"mappings":"AAAA;;+DAE+D;AAI/D;;;;;;;;;GASG;AACH,MAAM,UAAU,iBAAiB,CAAC,IAAqC;IACrE,IAAI,CAAC,IAAI;QAAE,OAAO,EAAE,CAAC;IACrB,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,MAAM,GAAG,GAAG,CAAC,CAAU,EAAE,EAAE;QACzB,MAAM,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,CAAC;QACpB,IAAI,CAAC;YAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IACrB,CAAC,CAAC;IACF,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,MAAM,IAAI,EAAE;QAAE,GAAG,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC;IACvD,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,YAAY,IAAI,EAAE;QAAE,GAAG,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC;IAC7D,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,QAAQ,IAAI,EAAE;QAAE,GAAG,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC;IACzD,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,SAAS,IAAI,EAAE;QAAE,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IAClD,kEAAkE;IAClE,IAAI,IAAI,CAAC,IAAI,KAAK,CAAC;QAAE,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACpC,OAAO,CAAC,GAAG,IAAI,CAAC,CAAC;AACnB,CAAC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The project-unit lookups `readSubject` needs to say what unit a property
|
|
3
|
+
* or quantity value is recorded in (#5300) and what factor turns it into SI
|
|
4
|
+
* (#5225). One memoised `ProjectUnits` per store, from the same
|
|
5
|
+
* `extractProjectUnits` resolver that backs unit display and the IDS
|
|
6
|
+
* bridge's scaling.
|
|
7
|
+
*/
|
|
8
|
+
import { type IfcDataStore, type ProjectUnits } from '@ifc-lite/parser';
|
|
9
|
+
import { QuantityType } from '@ifc-lite/data';
|
|
10
|
+
/** `store`'s project units, or `null` when the store has no source to read them from. */
|
|
11
|
+
export declare function projectUnitsOf(store: IfcDataStore): ProjectUnits | null;
|
|
12
|
+
export declare const QUANTITY_MEASURE_TYPE: Partial<Record<QuantityType, string>>;
|
|
13
|
+
/** The project's display unit for IFC measure type `measureType`, if any. */
|
|
14
|
+
export declare function projectUnitSymbol(store: IfcDataStore, measureType: string | undefined): string | undefined;
|
|
15
|
+
/**
|
|
16
|
+
* SI factor of a value of IFC measure type `measureType` recorded in the
|
|
17
|
+
* project's units, or `undefined` when the type has no unit (a label, a
|
|
18
|
+
* count, a ratio). Area and volume use the project's declared AREAUNIT /
|
|
19
|
+
* VOLUMEUNIT and fall back to the length unit squared / cubed, the rule
|
|
20
|
+
* `quantitySiScale` and the IDS bridge already apply.
|
|
21
|
+
*/
|
|
22
|
+
export declare function projectSiScale(store: IfcDataStore, measureType: string | undefined): number | undefined;
|
|
23
|
+
/** SI factor of one collected quantity: its explicit `Unit`, else the project unit for its type. */
|
|
24
|
+
export declare function quantityValueSiScale(store: IfcDataStore, quantity: {
|
|
25
|
+
type: number;
|
|
26
|
+
value: number;
|
|
27
|
+
explicitUnitSiScale?: number;
|
|
28
|
+
}): number | undefined;
|
|
29
|
+
//# sourceMappingURL=measure-units.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"measure-units.d.ts","sourceRoot":"","sources":["../../src/filter/measure-units.ts"],"names":[],"mappings":"AAIA;;;;;;GAMG;AAEH,OAAO,EAGL,KAAK,YAAY,EACjB,KAAK,YAAY,EAClB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAI9C,yFAAyF;AACzF,wBAAgB,cAAc,CAAC,KAAK,EAAE,YAAY,GAAG,YAAY,GAAG,IAAI,CAOvE;AAED,eAAO,MAAM,qBAAqB,EAAE,OAAO,CAAC,MAAM,CAAC,YAAY,EAAE,MAAM,CAAC,CAMvE,CAAC;AAEF,6EAA6E;AAC7E,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAG1G;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CASvG;AAED,oGAAoG;AACpG,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,YAAY,EACnB,QAAQ,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,mBAAmB,CAAC,EAAE,MAAM,CAAA;CAAE,GACtE,MAAM,GAAG,SAAS,CAUpB"}
|
|
@@ -0,0 +1,72 @@
|
|
|
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
|
+
* The project-unit lookups `readSubject` needs to say what unit a property
|
|
6
|
+
* or quantity value is recorded in (#5300) and what factor turns it into SI
|
|
7
|
+
* (#5225). One memoised `ProjectUnits` per store, from the same
|
|
8
|
+
* `extractProjectUnits` resolver that backs unit display and the IDS
|
|
9
|
+
* bridge's scaling.
|
|
10
|
+
*/
|
|
11
|
+
import { extractProjectUnits, quantitySiScale, } from '@ifc-lite/parser';
|
|
12
|
+
import { QuantityType } from '@ifc-lite/data';
|
|
13
|
+
const projectUnitsCache = new WeakMap();
|
|
14
|
+
/** `store`'s project units, or `null` when the store has no source to read them from. */
|
|
15
|
+
export function projectUnitsOf(store) {
|
|
16
|
+
let units = projectUnitsCache.get(store);
|
|
17
|
+
if (units === undefined) {
|
|
18
|
+
units = store.source?.length && store.entityIndex ? extractProjectUnits(store.source, store.entityIndex) : null;
|
|
19
|
+
projectUnitsCache.set(store, units);
|
|
20
|
+
}
|
|
21
|
+
return units;
|
|
22
|
+
}
|
|
23
|
+
export const QUANTITY_MEASURE_TYPE = {
|
|
24
|
+
[QuantityType.Length]: 'IfcLengthMeasure',
|
|
25
|
+
[QuantityType.Area]: 'IfcAreaMeasure',
|
|
26
|
+
[QuantityType.Volume]: 'IfcVolumeMeasure',
|
|
27
|
+
[QuantityType.Weight]: 'IfcMassMeasure',
|
|
28
|
+
[QuantityType.Time]: 'IfcTimeMeasure',
|
|
29
|
+
};
|
|
30
|
+
/** The project's display unit for IFC measure type `measureType`, if any. */
|
|
31
|
+
export function projectUnitSymbol(store, measureType) {
|
|
32
|
+
if (!measureType)
|
|
33
|
+
return undefined;
|
|
34
|
+
return projectUnitsOf(store)?.unitForMeasure(measureType)?.symbol;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* SI factor of a value of IFC measure type `measureType` recorded in the
|
|
38
|
+
* project's units, or `undefined` when the type has no unit (a label, a
|
|
39
|
+
* count, a ratio). Area and volume use the project's declared AREAUNIT /
|
|
40
|
+
* VOLUMEUNIT and fall back to the length unit squared / cubed, the rule
|
|
41
|
+
* `quantitySiScale` and the IDS bridge already apply.
|
|
42
|
+
*/
|
|
43
|
+
export function projectSiScale(store, measureType) {
|
|
44
|
+
if (!measureType)
|
|
45
|
+
return undefined;
|
|
46
|
+
const units = projectUnitsOf(store);
|
|
47
|
+
if (!units)
|
|
48
|
+
return undefined;
|
|
49
|
+
const upper = measureType.toUpperCase();
|
|
50
|
+
const length = () => units.unitForMeasure('IfcLengthMeasure')?.siScale ?? 1;
|
|
51
|
+
if (upper === 'IFCAREAMEASURE')
|
|
52
|
+
return units.resolvedForUnitType('AREAUNIT')?.siScale ?? length() ** 2;
|
|
53
|
+
if (upper === 'IFCVOLUMEMEASURE')
|
|
54
|
+
return units.resolvedForUnitType('VOLUMEUNIT')?.siScale ?? length() ** 3;
|
|
55
|
+
return units.unitForMeasure(measureType)?.siScale;
|
|
56
|
+
}
|
|
57
|
+
/** SI factor of one collected quantity: its explicit `Unit`, else the project unit for its type. */
|
|
58
|
+
export function quantityValueSiScale(store, quantity) {
|
|
59
|
+
if (quantity.explicitUnitSiScale !== undefined)
|
|
60
|
+
return quantity.explicitUnitSiScale;
|
|
61
|
+
const measureType = QUANTITY_MEASURE_TYPE[quantity.type];
|
|
62
|
+
if (!measureType)
|
|
63
|
+
return undefined;
|
|
64
|
+
const units = projectUnitsOf(store);
|
|
65
|
+
if (!units)
|
|
66
|
+
return undefined;
|
|
67
|
+
if (quantity.type === QuantityType.Length || quantity.type === QuantityType.Area || quantity.type === QuantityType.Volume) {
|
|
68
|
+
return quantitySiScale({ name: '', ...quantity }, units);
|
|
69
|
+
}
|
|
70
|
+
return projectSiScale(store, measureType);
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=measure-units.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"measure-units.js","sourceRoot":"","sources":["../../src/filter/measure-units.ts"],"names":[],"mappings":"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"}
|