@ifc-lite/export 2.5.3 → 2.6.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.
@@ -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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"}
@@ -0,0 +1,273 @@
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
+ * DemeshSession — interactive selective mesh simplification with deferred
6
+ * IFC export (the "demesher").
7
+ *
8
+ * Workflow (one session per loaded model):
9
+ * 1. `simplify(expressIds)` — each call escalates the selection one level
10
+ * (1-4 = cavity removal + vertex-clustering decimation at
11
+ * 0.5/0.25/0.10/0.03 triangle ratio, 5 = bounding box). Simplification
12
+ * ALWAYS re-runs from the ORIGINAL meshes at the new level — quality
13
+ * never degrades cumulatively, and `reset()` is trivial. The returned
14
+ * render meshes go straight into the scene:
15
+ * `scene.removeMeshesForEntities(ids)` + `scene.addMeshes(renderMeshes)`.
16
+ * 2. `exportIfc()` — separately, when the user is done: loads the original
17
+ * bytes into a store, swaps each simplified element's representation
18
+ * for an `IfcTriangulatedFaceSet` (via `applySimplifiedGeometry`),
19
+ * prunes the orphaned geometry, and writes the lighter IFC. IFC2X3
20
+ * sources are upconverted to IFC4 first (`IfcTriangulatedFaceSet` is
21
+ * IFC4+).
22
+ *
23
+ * The model file is parsed at most twice per session (once for meshes unless
24
+ * the caller supplies the ones it already holds, once at export); button
25
+ * presses between those touch only mesh data in wasm.
26
+ */
27
+ import { GeometryProcessor, } from '@ifc-lite/geometry';
28
+ import { IfcParser } from '@ifc-lite/parser';
29
+ import { MutablePropertyView, StoreEditor } from '@ifc-lite/mutations';
30
+ import { StepExporter } from './step-exporter.js';
31
+ import { applySimplifiedGeometry, } from './demesh-writer.js';
32
+ export class DemeshSession {
33
+ source;
34
+ options;
35
+ gp = null;
36
+ ownsGp = false;
37
+ meshes = null;
38
+ originShift;
39
+ unitScale;
40
+ // Single-flight guards: concurrent calls (rapid button presses) must share
41
+ // ONE processor init / meshing pass / unit-scale scan. The promises are
42
+ // sticky on rejection too — a fatal wasm init failure stays terminal for
43
+ // the session instead of spawning a second doomed processor.
44
+ gpPromise = null;
45
+ meshesPromise = null;
46
+ unitScalePromise = null;
47
+ /** expressId -> state of the CURRENT simplification (from-original). */
48
+ applied = new Map();
49
+ constructor(source, options = {}) {
50
+ this.source = source instanceof Uint8Array ? source : new Uint8Array(source);
51
+ this.options = options;
52
+ this.meshes = options.meshes ?? null;
53
+ this.originShift = options.originShift ?? { x: 0, y: 0, z: 0 };
54
+ this.unitScale = options.unitScale ?? null;
55
+ }
56
+ /** The level currently applied to an element (0 = untouched). */
57
+ levelOf(expressId) {
58
+ return this.applied.get(expressId)?.level ?? 0;
59
+ }
60
+ /**
61
+ * The coordinate-frame shift of the meshes this session works with (the
62
+ * supplied `originShift`, or the session's own load's after self-meshing).
63
+ * A viewer whose scene uses a different anchor (multi-model federation
64
+ * with a shared RTC) translates render-mesh origins by the difference.
65
+ */
66
+ getOriginShift() {
67
+ return { ...this.originShift };
68
+ }
69
+ /**
70
+ * The ORIGINAL mesh records of `expressIds` (session frame, untouched by
71
+ * any simplification) — lets a viewer restore an element's real geometry
72
+ * in the scene after `reset()`. Meshes the source on first use.
73
+ */
74
+ async originalMeshesFor(expressIds) {
75
+ const meshes = await this.ensureMeshes();
76
+ const wanted = new Set(expressIds);
77
+ return meshes.filter((m) => wanted.has(m.expressId));
78
+ }
79
+ /** Express ids currently carrying simplified geometry. */
80
+ simplifiedIds() {
81
+ return [...this.applied.keys()];
82
+ }
83
+ /**
84
+ * Simplify `expressIds` at `level`, or — when `level` is omitted — one
85
+ * level past each element's current one (the button behavior: press,
86
+ * press again, ...; capped at 5).
87
+ */
88
+ async simplify(expressIds, level) {
89
+ const meshes = await this.ensureMeshes();
90
+ const unitScale = await this.ensureUnitScale();
91
+ const gp = await this.ensureProcessor();
92
+ const levels = new Map();
93
+ for (const id of expressIds) {
94
+ levels.set(id, Math.min(5, level ?? this.levelOf(id) + 1));
95
+ }
96
+ const targetIds = new Set(levels.keys());
97
+ // Always simplify from the ORIGINAL records of the selection.
98
+ const records = meshes.filter((m) => targetIds.has(m.expressId));
99
+ const out = gp.simplifyMeshes(records, levels, {
100
+ originShift: this.originShift,
101
+ unitScale,
102
+ });
103
+ if (!out) {
104
+ throw new Error('DemeshSession.simplify: geometry processor is not initialized');
105
+ }
106
+ const result = { renderMeshes: [], elements: [], skipped: out.skipped };
107
+ for (const el of out.elements) {
108
+ this.applied.set(el.expressId, el);
109
+ result.renderMeshes.push(el.render);
110
+ result.elements.push({
111
+ expressId: el.expressId,
112
+ level: el.level,
113
+ trisBefore: el.trisBefore,
114
+ trisAfter: el.trisAfter,
115
+ cavitiesDropped: el.cavitiesDropped,
116
+ });
117
+ }
118
+ return result;
119
+ }
120
+ /**
121
+ * Forget the simplification state for `expressIds` (all when omitted).
122
+ * The caller restores the elements' original meshes in the scene.
123
+ */
124
+ reset(expressIds) {
125
+ if (!expressIds) {
126
+ this.applied.clear();
127
+ return;
128
+ }
129
+ for (const id of expressIds)
130
+ this.applied.delete(id);
131
+ }
132
+ /**
133
+ * The `n` heaviest elements by triangle count — demesh candidates for the
134
+ * UI. Requires meshes (supplied or produced on first `simplify`).
135
+ */
136
+ async heaviest(n) {
137
+ const meshes = await this.ensureMeshes();
138
+ const byElement = new Map();
139
+ for (const m of meshes) {
140
+ if ((m.geometryClass ?? 0) !== 0)
141
+ continue;
142
+ byElement.set(m.expressId, (byElement.get(m.expressId) ?? 0) + m.indices.length / 3);
143
+ }
144
+ return [...byElement.entries()]
145
+ .map(([expressId, triangles]) => ({ expressId, triangles }))
146
+ .sort((a, b) => b.triangles - a.triangles)
147
+ .slice(0, Math.max(0, n));
148
+ }
149
+ /**
150
+ * Write the lighter IFC: original bytes + tessellated replacements for
151
+ * every currently simplified element. Does not mutate session state — the
152
+ * user can keep simplifying and export again.
153
+ */
154
+ async exportIfc() {
155
+ if (this.applied.size === 0) {
156
+ throw new Error('DemeshSession.exportIfc: nothing simplified yet');
157
+ }
158
+ // Load (and upconvert when needed) the store the mutations apply to.
159
+ let sourceBytes = this.source;
160
+ let upconverted = false;
161
+ let store = await new IfcParser().parseColumnar(toArrayBuffer(sourceBytes), {
162
+ disableWorkerScan: true,
163
+ });
164
+ if ((store.schemaVersion ?? 'IFC4').toUpperCase() === 'IFC2X3') {
165
+ // IfcTriangulatedFaceSet is IFC4+. The schema conversion is a
166
+ // line-faithful rewrite (express ids preserved), so the session's
167
+ // element ids stay valid against the converted buffer.
168
+ const converted = new StepExporter(store).export({ schema: 'IFC4' });
169
+ sourceBytes = converted.content;
170
+ store = await new IfcParser().parseColumnar(toArrayBuffer(sourceBytes), {
171
+ disableWorkerScan: true,
172
+ });
173
+ upconverted = true;
174
+ }
175
+ const view = new MutablePropertyView(null, 'default');
176
+ const editor = new StoreEditor(store, view);
177
+ const elements = [...this.applied.values()].map((el) => ({
178
+ expressId: el.expressId,
179
+ positions: el.localPositions,
180
+ indices: el.localIndices,
181
+ color: el.render.color,
182
+ }));
183
+ const report = applySimplifiedGeometry(store, editor, elements);
184
+ const schema = ((store.schemaVersion ?? 'IFC4').toUpperCase() === 'IFC2X3' ? 'IFC4' : (store.schemaVersion ?? 'IFC4'));
185
+ const result = new StepExporter(store, view).export({ schema, applyMutations: true });
186
+ return {
187
+ bytes: result.content,
188
+ report,
189
+ upconverted,
190
+ bytesBefore: this.source.byteLength,
191
+ bytesAfter: result.content.byteLength,
192
+ };
193
+ }
194
+ /** Release the session's own GeometryProcessor (a shared one is untouched). */
195
+ destroy() {
196
+ if (this.ownsGp && this.gp) {
197
+ this.gp.dispose();
198
+ }
199
+ this.gp = null;
200
+ this.gpPromise = null;
201
+ this.meshes = null;
202
+ this.meshesPromise = null;
203
+ this.unitScalePromise = null;
204
+ this.applied.clear();
205
+ }
206
+ ensureProcessor() {
207
+ this.gpPromise ??= (async () => {
208
+ if (this.options.geometryProcessor) {
209
+ this.gp = this.options.geometryProcessor;
210
+ return this.gp;
211
+ }
212
+ const gp = new GeometryProcessor();
213
+ // Track before init so destroy() during a pending init still disposes.
214
+ this.gp = gp;
215
+ this.ownsGp = true;
216
+ await gp.init();
217
+ return gp;
218
+ })();
219
+ return this.gpPromise;
220
+ }
221
+ ensureMeshes() {
222
+ this.meshesPromise ??= (async () => {
223
+ if (this.meshes)
224
+ return this.meshes;
225
+ const gp = await this.ensureProcessor();
226
+ const meshes = [];
227
+ for await (const event of gp.processAdaptive(this.source, { sizeThreshold: 0 })) {
228
+ if (event.type === 'batch') {
229
+ meshes.push(...event.meshes);
230
+ if (event.coordinateInfo)
231
+ this.originShift = event.coordinateInfo.originShift;
232
+ }
233
+ else if (event.type === 'complete' && event.coordinateInfo) {
234
+ this.originShift = event.coordinateInfo.originShift;
235
+ }
236
+ }
237
+ this.meshes = meshes;
238
+ return meshes;
239
+ })();
240
+ return this.meshesPromise;
241
+ }
242
+ ensureUnitScale() {
243
+ this.unitScalePromise ??= (async () => {
244
+ if (this.unitScale !== null)
245
+ return this.unitScale;
246
+ const { scanIfcEntities, extractLengthUnitScale } = await import('@ifc-lite/parser');
247
+ const { entityRefs } = await scanIfcEntities(toArrayBuffer(this.source));
248
+ const byId = new Map();
249
+ const byType = new Map();
250
+ for (const ref of entityRefs) {
251
+ byId.set(ref.expressId, ref);
252
+ const type = String(ref.type || '').toUpperCase();
253
+ const list = byType.get(type);
254
+ if (list)
255
+ list.push(ref.expressId);
256
+ else
257
+ byType.set(type, [ref.expressId]);
258
+ }
259
+ this.unitScale = extractLengthUnitScale(this.source, { byId, byType });
260
+ return this.unitScale;
261
+ })();
262
+ return this.unitScalePromise;
263
+ }
264
+ }
265
+ function toArrayBuffer(bytes) {
266
+ if (bytes.byteOffset === 0 && bytes.byteLength === bytes.buffer.byteLength && bytes.buffer instanceof ArrayBuffer) {
267
+ return bytes.buffer;
268
+ }
269
+ const copy = new ArrayBuffer(bytes.byteLength);
270
+ new Uint8Array(copy).set(bytes);
271
+ return copy;
272
+ }
273
+ //# sourceMappingURL=demesh-session.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"demesh-session.js","sourceRoot":"","sources":["../src/demesh-session.ts"],"names":[],"mappings":"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"}