@ifc-lite/export 2.5.3 → 2.7.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-real-slots.d.ts +53 -0
- package/dist/attribute-real-slots.d.ts.map +1 -0
- package/dist/attribute-real-slots.js +99 -0
- package/dist/attribute-real-slots.js.map +1 -0
- package/dist/demesh-prune.d.ts +24 -0
- package/dist/demesh-prune.d.ts.map +1 -0
- package/dist/demesh-prune.js +185 -0
- package/dist/demesh-prune.js.map +1 -0
- package/dist/demesh-session.d.ts +136 -0
- package/dist/demesh-session.d.ts.map +1 -0
- package/dist/demesh-session.js +273 -0
- package/dist/demesh-session.js.map +1 -0
- package/dist/demesh-writer.d.ts +84 -0
- package/dist/demesh-writer.d.ts.map +1 -0
- package/dist/demesh-writer.js +240 -0
- package/dist/demesh-writer.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/reference-collector.d.ts +6 -0
- package/dist/reference-collector.d.ts.map +1 -1
- package/dist/reference-collector.js +36 -1
- package/dist/reference-collector.js.map +1 -1
- package/dist/schema-converter.d.ts +22 -1
- package/dist/schema-converter.d.ts.map +1 -1
- package/dist/schema-converter.js +5 -2
- package/dist/schema-converter.js.map +1 -1
- package/dist/select-qualification.d.ts +9 -0
- package/dist/select-qualification.d.ts.map +1 -0
- package/dist/select-qualification.js +156 -0
- package/dist/select-qualification.js.map +1 -0
- package/dist/step-exporter.d.ts +34 -1
- package/dist/step-exporter.d.ts.map +1 -1
- package/dist/step-exporter.js +44 -19
- package/dist/step-exporter.js.map +1 -1
- package/dist/step-serialization.d.ts +39 -6
- package/dist/step-serialization.d.ts.map +1 -1
- package/dist/step-serialization.js +129 -10
- package/dist/step-serialization.js.map +1 -1
- package/package.json +8 -8
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Schema-aware detection of REAL-typed STEP attribute slots.
|
|
3
|
+
*
|
|
4
|
+
* ISO 10303-21 requires a REAL-typed attribute (`IfcLengthMeasure` and every
|
|
5
|
+
* other `<real>`-backed defined type) to carry a decimal point — `450.`, never
|
|
6
|
+
* `450`. A bare JavaScript number is ambiguous at the value level (it could be
|
|
7
|
+
* an `IfcInteger`), so `serializeStepValue` defaults to emitting whole numbers
|
|
8
|
+
* as STEP INTEGER literals. That default silently produces strict-invalid files
|
|
9
|
+
* whenever a whole number lands in a REAL slot — the natural
|
|
10
|
+
* `setPositionalAttribute(profId, 3, 450)` call, `addEntity` args, and the
|
|
11
|
+
* geometry the in-store builders emit themselves (millimetre models round to
|
|
12
|
+
* whole numbers, making this the common case). See LTplus-AG/ifc-lite#1839.
|
|
13
|
+
*
|
|
14
|
+
* The slot's declared type is statically known from the schema registry, so we
|
|
15
|
+
* resolve it once per (entity, version) and force a REAL literal on those slots
|
|
16
|
+
* at serialization time — no caller change, no `{ real }` marker required.
|
|
17
|
+
*/
|
|
18
|
+
import type { IfcAttributeValue } from '@ifc-lite/parser';
|
|
19
|
+
import type { IfcSchemaVersion } from './schema-converter.js';
|
|
20
|
+
/**
|
|
21
|
+
* True for the write-only `{ real }` / `{ typed }` markers — an explicit caller
|
|
22
|
+
* intent that `serializeStepValue` handles directly and that must bypass the
|
|
23
|
+
* schema-driven SELECT/REAL inference below.
|
|
24
|
+
*/
|
|
25
|
+
export declare function isTypedMarker(value: IfcAttributeValue): boolean;
|
|
26
|
+
/**
|
|
27
|
+
* Serialize one positional attribute slot to its STEP token, composing the
|
|
28
|
+
* schema-aware passes in priority order:
|
|
29
|
+
* 1. an explicit `{ real }` / `{ typed }` marker wins outright;
|
|
30
|
+
* 2. a SELECT slot auto-qualifies an unambiguous bare value (`IFCBOOLEAN(.T.)`);
|
|
31
|
+
* 3. otherwise a REAL-backed slot forces a decimal point (#1839);
|
|
32
|
+
* 4. otherwise the default value serialization.
|
|
33
|
+
*/
|
|
34
|
+
export declare function serializeAttributeSlot(entityType: string, index: number, value: IfcAttributeValue, version: IfcSchemaVersion): string;
|
|
35
|
+
/**
|
|
36
|
+
* The set of zero-based positional attribute indices on `entityType` whose
|
|
37
|
+
* declared type is unambiguously REAL-backed (`xs:double`, and NOT also
|
|
38
|
+
* `xs:integer`). An index that also admits an integer — a genuine
|
|
39
|
+
* `SELECT(IfcInteger, IfcReal)` — stays out of the set: it is truly ambiguous,
|
|
40
|
+
* and the explicit `{ real }` marker is the caller's way to disambiguate it.
|
|
41
|
+
*
|
|
42
|
+
* Returns an empty set for entities the registry does not know (vendor
|
|
43
|
+
* extensions, unmapped schema), preserving the historical default there.
|
|
44
|
+
*/
|
|
45
|
+
export declare function getRealTypedSlots(entityType: string, version: IfcSchemaVersion): Set<number>;
|
|
46
|
+
/**
|
|
47
|
+
* Serialize a full positional attribute list for an entity to a STEP body,
|
|
48
|
+
* schema-aware per slot (SELECT qualification + REAL forcing). Used for
|
|
49
|
+
* freshly-emitted overlay entities (`addEntity`, the in-store builders) whose
|
|
50
|
+
* numbers never pass through a source token.
|
|
51
|
+
*/
|
|
52
|
+
export declare function serializeEntityArgs(entityType: string, values: readonly IfcAttributeValue[], version: IfcSchemaVersion): string;
|
|
53
|
+
//# sourceMappingURL=attribute-real-slots.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"attribute-real-slots.d.ts","sourceRoot":"","sources":["../src/attribute-real-slots.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAG1D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAI9D;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,iBAAiB,GAAG,OAAO,CAO/D;AAED;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CACpC,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,iBAAiB,EACxB,OAAO,EAAE,gBAAgB,GACxB,MAAM,CAKR;AA0BD;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,gBAAgB,GAAG,GAAG,CAAC,MAAM,CAAC,CAsB5F;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CACjC,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,SAAS,iBAAiB,EAAE,EACpC,OAAO,EAAE,gBAAgB,GACxB,MAAM,CAER"}
|
|
@@ -0,0 +1,99 @@
|
|
|
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 { getAttributeNamesAcrossSchemas } from '@ifc-lite/parser';
|
|
5
|
+
import { getAttributeXsdTypes } from '@ifc-lite/data';
|
|
6
|
+
import { serializeStepValue } from './step-serialization.js';
|
|
7
|
+
import { serializeQualifiedSelectSlot } from './select-qualification.js';
|
|
8
|
+
/**
|
|
9
|
+
* True for the write-only `{ real }` / `{ typed }` markers — an explicit caller
|
|
10
|
+
* intent that `serializeStepValue` handles directly and that must bypass the
|
|
11
|
+
* schema-driven SELECT/REAL inference below.
|
|
12
|
+
*/
|
|
13
|
+
export function isTypedMarker(value) {
|
|
14
|
+
return (typeof value === 'object' &&
|
|
15
|
+
value !== null &&
|
|
16
|
+
!Array.isArray(value) &&
|
|
17
|
+
('real' in value || 'typed' in value));
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Serialize one positional attribute slot to its STEP token, composing the
|
|
21
|
+
* schema-aware passes in priority order:
|
|
22
|
+
* 1. an explicit `{ real }` / `{ typed }` marker wins outright;
|
|
23
|
+
* 2. a SELECT slot auto-qualifies an unambiguous bare value (`IFCBOOLEAN(.T.)`);
|
|
24
|
+
* 3. otherwise a REAL-backed slot forces a decimal point (#1839);
|
|
25
|
+
* 4. otherwise the default value serialization.
|
|
26
|
+
*/
|
|
27
|
+
export function serializeAttributeSlot(entityType, index, value, version) {
|
|
28
|
+
if (isTypedMarker(value))
|
|
29
|
+
return serializeStepValue(value);
|
|
30
|
+
const qualified = serializeQualifiedSelectSlot(entityType, index, value);
|
|
31
|
+
if (qualified !== null)
|
|
32
|
+
return qualified;
|
|
33
|
+
return serializeStepValue(value, getRealTypedSlots(entityType, version).has(index));
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Map the exporter's schema tag to the version the attribute XSD index is keyed
|
|
37
|
+
* by. `IFC4X3_ADD2` is not an exporter tag; `IFC5` has no bundled XSD table.
|
|
38
|
+
* REAL-vs-INTEGER of a geometry slot is version-invariant, so any unmapped tag
|
|
39
|
+
* falls back to IFC4 — a slot missing from that version simply won't be forced.
|
|
40
|
+
*/
|
|
41
|
+
function toDataSchemaVersion(v) {
|
|
42
|
+
switch (v) {
|
|
43
|
+
case 'IFC2X3':
|
|
44
|
+
return 'IFC2X3';
|
|
45
|
+
case 'IFC4X3':
|
|
46
|
+
return 'IFC4X3';
|
|
47
|
+
case 'IFC4':
|
|
48
|
+
return 'IFC4';
|
|
49
|
+
default:
|
|
50
|
+
return 'IFC4';
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
// Memoized `version|ENTITY` → set of positional slot indices that are
|
|
54
|
+
// unambiguously REAL-backed. Keyed by upper-case type so `IfcColumn`/`IFCCOLUMN`
|
|
55
|
+
// collapse to one entry.
|
|
56
|
+
const realSlotCache = new Map();
|
|
57
|
+
/**
|
|
58
|
+
* The set of zero-based positional attribute indices on `entityType` whose
|
|
59
|
+
* declared type is unambiguously REAL-backed (`xs:double`, and NOT also
|
|
60
|
+
* `xs:integer`). An index that also admits an integer — a genuine
|
|
61
|
+
* `SELECT(IfcInteger, IfcReal)` — stays out of the set: it is truly ambiguous,
|
|
62
|
+
* and the explicit `{ real }` marker is the caller's way to disambiguate it.
|
|
63
|
+
*
|
|
64
|
+
* Returns an empty set for entities the registry does not know (vendor
|
|
65
|
+
* extensions, unmapped schema), preserving the historical default there.
|
|
66
|
+
*/
|
|
67
|
+
export function getRealTypedSlots(entityType, version) {
|
|
68
|
+
const dataVersion = toDataSchemaVersion(version);
|
|
69
|
+
const upperType = entityType.toUpperCase();
|
|
70
|
+
const key = `${dataVersion}|${upperType}`;
|
|
71
|
+
const cached = realSlotCache.get(key);
|
|
72
|
+
if (cached)
|
|
73
|
+
return cached;
|
|
74
|
+
// Resolve positional names across the bundled schema union (2X3 + 4 + 4X3),
|
|
75
|
+
// not just the parser's IFC4-pinned registry — otherwise IFC4X3-only leaves
|
|
76
|
+
// (IfcAlignmentHorizontalSegment and the civil/alignment geometry this fix
|
|
77
|
+
// targets) return no names, and their REAL slots (StartDirection,
|
|
78
|
+
// SegmentLength, …) would still emit bare INTEGER literals.
|
|
79
|
+
const names = getAttributeNamesAcrossSchemas(entityType);
|
|
80
|
+
const slots = new Set();
|
|
81
|
+
for (let i = 0; i < names.length; i++) {
|
|
82
|
+
const xsd = getAttributeXsdTypes(dataVersion, upperType, names[i]);
|
|
83
|
+
if (xsd && xsd.includes('xs:double') && !xsd.includes('xs:integer')) {
|
|
84
|
+
slots.add(i);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
realSlotCache.set(key, slots);
|
|
88
|
+
return slots;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Serialize a full positional attribute list for an entity to a STEP body,
|
|
92
|
+
* schema-aware per slot (SELECT qualification + REAL forcing). Used for
|
|
93
|
+
* freshly-emitted overlay entities (`addEntity`, the in-store builders) whose
|
|
94
|
+
* numbers never pass through a source token.
|
|
95
|
+
*/
|
|
96
|
+
export function serializeEntityArgs(entityType, values, version) {
|
|
97
|
+
return values.map((value, i) => serializeAttributeSlot(entityType, i, value, version)).join(',');
|
|
98
|
+
}
|
|
99
|
+
//# sourceMappingURL=attribute-real-slots.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"attribute-real-slots.js","sourceRoot":"","sources":["../src/attribute-real-slots.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Demesher prune: ONE global reverse-reference mark-and-sweep over the
|
|
3
|
+
* replaced products' detached geometry subgraphs (see `demesh-writer.ts` for
|
|
4
|
+
* the authoring side). An old geometry entity is tombstoned only when every
|
|
5
|
+
* entity that references it is itself being tombstoned, so shared
|
|
6
|
+
* representations (`IfcMappedItem` sources, an `IfcProductDefinitionShape`
|
|
7
|
+
* shared by several products) and type-library geometry survive partial
|
|
8
|
+
* selections by construction.
|
|
9
|
+
*
|
|
10
|
+
* The reverse index is built from the UNMODIFIED source bytes via the
|
|
11
|
+
* string-literal-aware `#N` scanner in `reference-collector.ts`; overlay
|
|
12
|
+
* entities added by the writer are invisible to it, which is why shared
|
|
13
|
+
* infrastructure (`PROTECTED_TYPES`) must never fall even when orphaned.
|
|
14
|
+
*/
|
|
15
|
+
import { type IfcDataStore } from '@ifc-lite/parser';
|
|
16
|
+
import type { DemeshApplyReport, DemeshEditorLike } from './demesh-writer.js';
|
|
17
|
+
/**
|
|
18
|
+
* Global reverse-reference mark-and-sweep over the replaced products' old
|
|
19
|
+
* geometry subgraphs (see the module doc). Also strips void relationships
|
|
20
|
+
* for replaced hosts and filters `IfcPresentationLayerAssignment` item
|
|
21
|
+
* lists that pointed at pruned geometry.
|
|
22
|
+
*/
|
|
23
|
+
export declare function pruneReplacedSubgraphs(store: IfcDataStore, editor: DemeshEditorLike, replacedOldRep: Map<number, number | null>, stripOpenings: boolean, report: DemeshApplyReport): void;
|
|
24
|
+
//# sourceMappingURL=demesh-prune.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"demesh-prune.d.ts","sourceRoot":"","sources":["../src/demesh-prune.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAmB,KAAK,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAEtE,OAAO,KAAK,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAqB9E;;;;;GAKG;AACH,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,YAAY,EACnB,MAAM,EAAE,gBAAgB,EACxB,cAAc,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,EAC1C,aAAa,EAAE,OAAO,EACtB,MAAM,EAAE,iBAAiB,GACxB,IAAI,CAqIN"}
|
|
@@ -0,0 +1,185 @@
|
|
|
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
|
+
* Demesher prune: ONE global reverse-reference mark-and-sweep over the
|
|
6
|
+
* replaced products' detached geometry subgraphs (see `demesh-writer.ts` for
|
|
7
|
+
* the authoring side). An old geometry entity is tombstoned only when every
|
|
8
|
+
* entity that references it is itself being tombstoned, so shared
|
|
9
|
+
* representations (`IfcMappedItem` sources, an `IfcProductDefinitionShape`
|
|
10
|
+
* shared by several products) and type-library geometry survive partial
|
|
11
|
+
* selections by construction.
|
|
12
|
+
*
|
|
13
|
+
* The reverse index is built from the UNMODIFIED source bytes via the
|
|
14
|
+
* string-literal-aware `#N` scanner in `reference-collector.ts`; overlay
|
|
15
|
+
* entities added by the writer are invisible to it, which is why shared
|
|
16
|
+
* infrastructure (`PROTECTED_TYPES`) must never fall even when orphaned.
|
|
17
|
+
*/
|
|
18
|
+
import { EntityExtractor } from '@ifc-lite/parser';
|
|
19
|
+
import { collectReferencedEntityIds, collectRefsInByteRange } from './reference-collector.js';
|
|
20
|
+
/**
|
|
21
|
+
* Entity types the sweep must never tombstone even when they fall inside a
|
|
22
|
+
* replaced subgraph's closure: shared model infrastructure that the NEW
|
|
23
|
+
* overlay entities (invisible to the source-byte reverse index) or the rest
|
|
24
|
+
* of the file may reference.
|
|
25
|
+
*/
|
|
26
|
+
const PROTECTED_TYPES = new Set([
|
|
27
|
+
'IFCGEOMETRICREPRESENTATIONCONTEXT',
|
|
28
|
+
'IFCGEOMETRICREPRESENTATIONSUBCONTEXT',
|
|
29
|
+
'IFCUNITASSIGNMENT',
|
|
30
|
+
'IFCSIUNIT',
|
|
31
|
+
'IFCCONVERSIONBASEDUNIT',
|
|
32
|
+
'IFCOWNERHISTORY',
|
|
33
|
+
'IFCPERSON',
|
|
34
|
+
'IFCORGANIZATION',
|
|
35
|
+
'IFCPERSONANDORGANIZATION',
|
|
36
|
+
'IFCAPPLICATION',
|
|
37
|
+
]);
|
|
38
|
+
/**
|
|
39
|
+
* Global reverse-reference mark-and-sweep over the replaced products' old
|
|
40
|
+
* geometry subgraphs (see the module doc). Also strips void relationships
|
|
41
|
+
* for replaced hosts and filters `IfcPresentationLayerAssignment` item
|
|
42
|
+
* lists that pointed at pruned geometry.
|
|
43
|
+
*/
|
|
44
|
+
export function pruneReplacedSubgraphs(store, editor, replacedOldRep, stripOpenings, report) {
|
|
45
|
+
const source = store.source;
|
|
46
|
+
const byId = store.entityIndex.byId;
|
|
47
|
+
const extractor = new EntityExtractor(source);
|
|
48
|
+
const indexAdapter = {
|
|
49
|
+
get: (id) => byId.get(id),
|
|
50
|
+
has: (id) => byId.has(id),
|
|
51
|
+
};
|
|
52
|
+
// -- Roots: the detached representation subgraphs.
|
|
53
|
+
const roots = new Set();
|
|
54
|
+
for (const oldRep of replacedOldRep.values()) {
|
|
55
|
+
if (oldRep !== null && byId.has(oldRep))
|
|
56
|
+
roots.add(oldRep);
|
|
57
|
+
}
|
|
58
|
+
// -- Openings of replaced hosts: the rel is deleted outright (its cut is
|
|
59
|
+
// baked into the new mesh); the opening element and its geometry join the
|
|
60
|
+
// candidate closure and fall to the ordinary sweep.
|
|
61
|
+
const deleted = new Set();
|
|
62
|
+
if (stripOpenings) {
|
|
63
|
+
for (const [id, ref] of byId) {
|
|
64
|
+
if (ref.type.toUpperCase() !== 'IFCRELVOIDSELEMENT')
|
|
65
|
+
continue;
|
|
66
|
+
const rel = extractor.extractEntity(ref);
|
|
67
|
+
const relating = rel?.attributes?.[4];
|
|
68
|
+
const opening = rel?.attributes?.[5];
|
|
69
|
+
if (typeof relating !== 'number' || !replacedOldRep.has(relating))
|
|
70
|
+
continue;
|
|
71
|
+
deleted.add(id);
|
|
72
|
+
if (typeof opening === 'number' && byId.has(opening)) {
|
|
73
|
+
roots.add(opening);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
if (roots.size === 0 && deleted.size === 0)
|
|
78
|
+
return;
|
|
79
|
+
// -- Candidate closure: everything transitively reachable from the roots.
|
|
80
|
+
const closure = collectReferencedEntityIds(roots, source, indexAdapter);
|
|
81
|
+
// Style/annotation entities hang OFF the geometry (IfcStyledItem.Item →
|
|
82
|
+
// geometry item), so forward reachability misses them; pull in styled
|
|
83
|
+
// items whose target is in the closure, plus what they reference (shared
|
|
84
|
+
// surface styles survive via their other referrers).
|
|
85
|
+
const styledItemRoots = new Set();
|
|
86
|
+
for (const [id, ref] of byId) {
|
|
87
|
+
if (closure.has(id) || ref.type.toUpperCase() !== 'IFCSTYLEDITEM')
|
|
88
|
+
continue;
|
|
89
|
+
const refs = collectRefsInByteRange(source, ref.byteOffset, ref.byteLength);
|
|
90
|
+
if (refs.some((target) => target !== id && closure.has(target))) {
|
|
91
|
+
styledItemRoots.add(id);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
if (styledItemRoots.size > 0) {
|
|
95
|
+
for (const id of collectReferencedEntityIds(styledItemRoots, source, indexAdapter)) {
|
|
96
|
+
closure.add(id);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
// -- Reverse-reference index, restricted to edges INTO the closure.
|
|
100
|
+
const referrers = new Map();
|
|
101
|
+
for (const [id, ref] of byId) {
|
|
102
|
+
// Presentation layers ANNOTATE geometry, they don't own it: counting
|
|
103
|
+
// their edges as referrers would keep replaced geometry alive forever
|
|
104
|
+
// (the layer itself is outside the closure and never falls), defeating
|
|
105
|
+
// the AssignedItems filtering below. Skip them so layer-only-referenced
|
|
106
|
+
// geometry prunes and the filter then cleans the surviving layer's list.
|
|
107
|
+
if (ref.type.toUpperCase() === 'IFCPRESENTATIONLAYERASSIGNMENT')
|
|
108
|
+
continue;
|
|
109
|
+
const refs = collectRefsInByteRange(source, ref.byteOffset, ref.byteLength);
|
|
110
|
+
for (const target of refs) {
|
|
111
|
+
if (target === id || !closure.has(target))
|
|
112
|
+
continue;
|
|
113
|
+
let set = referrers.get(target);
|
|
114
|
+
if (!set) {
|
|
115
|
+
set = new Set();
|
|
116
|
+
referrers.set(target, set);
|
|
117
|
+
}
|
|
118
|
+
set.add(id);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
// The representation swap detached product → old-PDS: remove those edges
|
|
122
|
+
// (the reverse index was built from the unmodified source bytes).
|
|
123
|
+
for (const [productId, oldRep] of replacedOldRep) {
|
|
124
|
+
if (oldRep !== null)
|
|
125
|
+
referrers.get(oldRep)?.delete(productId);
|
|
126
|
+
}
|
|
127
|
+
// -- Sweep to fixpoint: tombstone an entity once every referrer is
|
|
128
|
+
// tombstoned. Protected infrastructure never falls, even if orphaned.
|
|
129
|
+
let changed = true;
|
|
130
|
+
while (changed) {
|
|
131
|
+
changed = false;
|
|
132
|
+
for (const id of closure) {
|
|
133
|
+
if (deleted.has(id))
|
|
134
|
+
continue;
|
|
135
|
+
const ref = byId.get(id);
|
|
136
|
+
if (!ref || PROTECTED_TYPES.has(ref.type.toUpperCase()))
|
|
137
|
+
continue;
|
|
138
|
+
const incoming = referrers.get(id);
|
|
139
|
+
let live = false;
|
|
140
|
+
if (incoming) {
|
|
141
|
+
for (const from of incoming) {
|
|
142
|
+
if (!deleted.has(from)) {
|
|
143
|
+
live = true;
|
|
144
|
+
break;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
if (!live) {
|
|
149
|
+
deleted.add(id);
|
|
150
|
+
changed = true;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
// -- Apply tombstones.
|
|
155
|
+
let openingCount = 0;
|
|
156
|
+
for (const id of deleted) {
|
|
157
|
+
const type = byId.get(id)?.type.toUpperCase();
|
|
158
|
+
if (type === 'IFCRELVOIDSELEMENT' || type === 'IFCOPENINGELEMENT')
|
|
159
|
+
openingCount++;
|
|
160
|
+
if (editor.removeEntity(id))
|
|
161
|
+
report.prunedEntityCount++;
|
|
162
|
+
}
|
|
163
|
+
report.strippedOpeningCount = openingCount;
|
|
164
|
+
// -- Presentation layers: filter tombstoned items out of AssignedItems;
|
|
165
|
+
// a layer left empty is tombstoned too (an empty list is schema-invalid).
|
|
166
|
+
for (const [id, ref] of byId) {
|
|
167
|
+
if (deleted.has(id) || ref.type.toUpperCase() !== 'IFCPRESENTATIONLAYERASSIGNMENT')
|
|
168
|
+
continue;
|
|
169
|
+
const layer = extractor.extractEntity(ref);
|
|
170
|
+
const items = layer?.attributes?.[2];
|
|
171
|
+
if (!Array.isArray(items))
|
|
172
|
+
continue;
|
|
173
|
+
const kept = items.filter((item) => typeof item === 'number' && !deleted.has(item));
|
|
174
|
+
if (kept.length === items.length)
|
|
175
|
+
continue;
|
|
176
|
+
if (kept.length === 0) {
|
|
177
|
+
if (editor.removeEntity(id))
|
|
178
|
+
report.prunedEntityCount++;
|
|
179
|
+
}
|
|
180
|
+
else {
|
|
181
|
+
editor.setPositionalAttribute(id, 2, kept.map((item) => `#${item}`));
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
//# sourceMappingURL=demesh-prune.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"demesh-prune.js","sourceRoot":"","sources":["../src/demesh-prune.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DemeshSession — interactive selective mesh simplification with deferred
|
|
3
|
+
* IFC export (the "demesher").
|
|
4
|
+
*
|
|
5
|
+
* Workflow (one session per loaded model):
|
|
6
|
+
* 1. `simplify(expressIds)` — each call escalates the selection one level
|
|
7
|
+
* (1-4 = cavity removal + vertex-clustering decimation at
|
|
8
|
+
* 0.5/0.25/0.10/0.03 triangle ratio, 5 = bounding box). Simplification
|
|
9
|
+
* ALWAYS re-runs from the ORIGINAL meshes at the new level — quality
|
|
10
|
+
* never degrades cumulatively, and `reset()` is trivial. The returned
|
|
11
|
+
* render meshes go straight into the scene:
|
|
12
|
+
* `scene.removeMeshesForEntities(ids)` + `scene.addMeshes(renderMeshes)`.
|
|
13
|
+
* 2. `exportIfc()` — separately, when the user is done: loads the original
|
|
14
|
+
* bytes into a store, swaps each simplified element's representation
|
|
15
|
+
* for an `IfcTriangulatedFaceSet` (via `applySimplifiedGeometry`),
|
|
16
|
+
* prunes the orphaned geometry, and writes the lighter IFC. IFC2X3
|
|
17
|
+
* sources are upconverted to IFC4 first (`IfcTriangulatedFaceSet` is
|
|
18
|
+
* IFC4+).
|
|
19
|
+
*
|
|
20
|
+
* The model file is parsed at most twice per session (once for meshes unless
|
|
21
|
+
* the caller supplies the ones it already holds, once at export); button
|
|
22
|
+
* presses between those touch only mesh data in wasm.
|
|
23
|
+
*/
|
|
24
|
+
import { GeometryProcessor, type MeshData } from '@ifc-lite/geometry';
|
|
25
|
+
import { type DemeshApplyReport } from './demesh-writer.js';
|
|
26
|
+
export interface DemeshSessionOptions {
|
|
27
|
+
/**
|
|
28
|
+
* Already-produced meshes for this model (the viewer's `MeshData[]`) —
|
|
29
|
+
* supply them together with `originShift` from the load's
|
|
30
|
+
* `coordinateInfo` to skip the session's own meshing pass. When omitted,
|
|
31
|
+
* the session meshes the bytes itself on first use.
|
|
32
|
+
*/
|
|
33
|
+
meshes?: MeshData[];
|
|
34
|
+
/** `coordinateInfo.originShift` of the load that produced `meshes`. */
|
|
35
|
+
originShift?: {
|
|
36
|
+
x: number;
|
|
37
|
+
y: number;
|
|
38
|
+
z: number;
|
|
39
|
+
};
|
|
40
|
+
/** Metres per project length unit; extracted from the file when omitted. */
|
|
41
|
+
unitScale?: number;
|
|
42
|
+
/** Reuse the app's initialized GeometryProcessor instead of creating one. */
|
|
43
|
+
geometryProcessor?: GeometryProcessor;
|
|
44
|
+
}
|
|
45
|
+
export interface DemeshSimplifyResult {
|
|
46
|
+
/** Replacement render meshes for the scene (one per simplified element). */
|
|
47
|
+
renderMeshes: MeshData[];
|
|
48
|
+
/** Per-element outcome, including the level now applied. */
|
|
49
|
+
elements: Array<{
|
|
50
|
+
expressId: number;
|
|
51
|
+
level: number;
|
|
52
|
+
trisBefore: number;
|
|
53
|
+
trisAfter: number;
|
|
54
|
+
cavitiesDropped: number;
|
|
55
|
+
}>;
|
|
56
|
+
/** Elements that could not be simplified (keep their original meshes). */
|
|
57
|
+
skipped: Array<{
|
|
58
|
+
expressId: number;
|
|
59
|
+
reason: string;
|
|
60
|
+
}>;
|
|
61
|
+
}
|
|
62
|
+
export interface DemeshExportResult {
|
|
63
|
+
bytes: Uint8Array;
|
|
64
|
+
report: DemeshApplyReport;
|
|
65
|
+
/** True when an IFC2X3 source was upconverted to IFC4 for the export. */
|
|
66
|
+
upconverted: boolean;
|
|
67
|
+
bytesBefore: number;
|
|
68
|
+
bytesAfter: number;
|
|
69
|
+
}
|
|
70
|
+
export declare class DemeshSession {
|
|
71
|
+
private readonly source;
|
|
72
|
+
private readonly options;
|
|
73
|
+
private gp;
|
|
74
|
+
private ownsGp;
|
|
75
|
+
private meshes;
|
|
76
|
+
private originShift;
|
|
77
|
+
private unitScale;
|
|
78
|
+
private gpPromise;
|
|
79
|
+
private meshesPromise;
|
|
80
|
+
private unitScalePromise;
|
|
81
|
+
/** expressId -> state of the CURRENT simplification (from-original). */
|
|
82
|
+
private readonly applied;
|
|
83
|
+
constructor(source: Uint8Array | ArrayBuffer, options?: DemeshSessionOptions);
|
|
84
|
+
/** The level currently applied to an element (0 = untouched). */
|
|
85
|
+
levelOf(expressId: number): number;
|
|
86
|
+
/**
|
|
87
|
+
* The coordinate-frame shift of the meshes this session works with (the
|
|
88
|
+
* supplied `originShift`, or the session's own load's after self-meshing).
|
|
89
|
+
* A viewer whose scene uses a different anchor (multi-model federation
|
|
90
|
+
* with a shared RTC) translates render-mesh origins by the difference.
|
|
91
|
+
*/
|
|
92
|
+
getOriginShift(): {
|
|
93
|
+
x: number;
|
|
94
|
+
y: number;
|
|
95
|
+
z: number;
|
|
96
|
+
};
|
|
97
|
+
/**
|
|
98
|
+
* The ORIGINAL mesh records of `expressIds` (session frame, untouched by
|
|
99
|
+
* any simplification) — lets a viewer restore an element's real geometry
|
|
100
|
+
* in the scene after `reset()`. Meshes the source on first use.
|
|
101
|
+
*/
|
|
102
|
+
originalMeshesFor(expressIds: number[]): Promise<MeshData[]>;
|
|
103
|
+
/** Express ids currently carrying simplified geometry. */
|
|
104
|
+
simplifiedIds(): number[];
|
|
105
|
+
/**
|
|
106
|
+
* Simplify `expressIds` at `level`, or — when `level` is omitted — one
|
|
107
|
+
* level past each element's current one (the button behavior: press,
|
|
108
|
+
* press again, ...; capped at 5).
|
|
109
|
+
*/
|
|
110
|
+
simplify(expressIds: number[], level?: number): Promise<DemeshSimplifyResult>;
|
|
111
|
+
/**
|
|
112
|
+
* Forget the simplification state for `expressIds` (all when omitted).
|
|
113
|
+
* The caller restores the elements' original meshes in the scene.
|
|
114
|
+
*/
|
|
115
|
+
reset(expressIds?: number[]): void;
|
|
116
|
+
/**
|
|
117
|
+
* The `n` heaviest elements by triangle count — demesh candidates for the
|
|
118
|
+
* UI. Requires meshes (supplied or produced on first `simplify`).
|
|
119
|
+
*/
|
|
120
|
+
heaviest(n: number): Promise<Array<{
|
|
121
|
+
expressId: number;
|
|
122
|
+
triangles: number;
|
|
123
|
+
}>>;
|
|
124
|
+
/**
|
|
125
|
+
* Write the lighter IFC: original bytes + tessellated replacements for
|
|
126
|
+
* every currently simplified element. Does not mutate session state — the
|
|
127
|
+
* user can keep simplifying and export again.
|
|
128
|
+
*/
|
|
129
|
+
exportIfc(): Promise<DemeshExportResult>;
|
|
130
|
+
/** Release the session's own GeometryProcessor (a shared one is untouched). */
|
|
131
|
+
destroy(): void;
|
|
132
|
+
private ensureProcessor;
|
|
133
|
+
private ensureMeshes;
|
|
134
|
+
private ensureUnitScale;
|
|
135
|
+
}
|
|
136
|
+
//# sourceMappingURL=demesh-session.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"demesh-session.d.ts","sourceRoot":"","sources":["../src/demesh-session.ts"],"names":[],"mappings":"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"}
|