@ifc-lite/geometry 1.16.1 → 1.16.2

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.
@@ -40,29 +40,68 @@ self.onmessage = async (e) => {
40
40
  // Copy shared bytes to local buffer (Firefox requires this for typed array ops)
41
41
  const localBytes = new Uint8Array(sharedBuffer.byteLength);
42
42
  localBytes.set(new Uint8Array(sharedBuffer));
43
- // Call processGeometryBatch with pre-pass data
44
- const collection = api.processGeometryBatch(localBytes, jobsFlat, unitScale, rtcX, rtcY, rtcZ, needsShift, voidKeys, voidCounts, voidValues, styleIds, styleColors);
45
- const meshes = [];
46
- const transferBuffers = [];
47
- for (let i = 0; i < collection.length; i++) {
48
- const mesh = collection.get(i);
49
- if (!mesh)
50
- continue;
51
- const positions = new Float32Array(mesh.positions);
52
- const normals = new Float32Array(mesh.normals);
53
- const indices = new Uint32Array(mesh.indices);
54
- meshes.push({
55
- expressId: mesh.expressId,
56
- ifcType: mesh.ifcType,
57
- positions, normals, indices,
58
- color: [mesh.color[0], mesh.color[1], mesh.color[2], mesh.color[3]],
59
- });
60
- transferBuffers.push(positions.buffer, normals.buffer, indices.buffer);
61
- mesh.free();
62
- }
63
- collection.free();
64
- self.postMessage({ type: 'batch', meshes }, transferBuffers);
65
- self.postMessage({ type: 'complete', totalMeshes: meshes.length });
43
+ const allMeshes = [];
44
+ const allTransferBuffers = [];
45
+ /** Extract meshes from a MeshCollection into our arrays */
46
+ const collectMeshes = (collection) => {
47
+ for (let i = 0; i < collection.length; i++) {
48
+ const mesh = collection.get(i);
49
+ if (!mesh)
50
+ continue;
51
+ const positions = new Float32Array(mesh.positions);
52
+ const normals = new Float32Array(mesh.normals);
53
+ const indices = new Uint32Array(mesh.indices);
54
+ allMeshes.push({
55
+ expressId: mesh.expressId,
56
+ ifcType: mesh.ifcType,
57
+ positions, normals, indices,
58
+ color: [mesh.color[0], mesh.color[1], mesh.color[2], mesh.color[3]],
59
+ });
60
+ allTransferBuffers.push(positions.buffer, normals.buffer, indices.buffer);
61
+ mesh.free();
62
+ }
63
+ collection.free();
64
+ };
65
+ /**
66
+ * Process a slice of jobsFlat with automatic sub-batch splitting on failure.
67
+ * Uses binary-split strategy: try the whole slice, if it fails split in half
68
+ * and recurse. Only falls back to single-entity processing for the smallest
69
+ * failing chunk. This avoids rebuilding the entity index per-entity (expensive
70
+ * for large files — each rebuild scans the entire file).
71
+ */
72
+ const processBatch = async (jobs) => {
73
+ const numJobs = Math.floor(jobs.length / 3);
74
+ if (numJobs === 0)
75
+ return;
76
+ try {
77
+ if (!api) {
78
+ await init();
79
+ api = new IfcAPI();
80
+ }
81
+ const collection = api.processGeometryBatch(localBytes, jobs, unitScale, rtcX, rtcY, rtcZ, needsShift, voidKeys, voidCounts, voidValues, styleIds, styleColors);
82
+ collectMeshes(collection);
83
+ }
84
+ catch (err) {
85
+ const msg = err.message;
86
+ if (numJobs === 1) {
87
+ // Single entity failed — skip it
88
+ console.warn(`[Worker] Skipping entity #${jobs[0]}: ${msg}`);
89
+ // WASM instance may be corrupted after stack overflow — force re-init
90
+ api = null;
91
+ return;
92
+ }
93
+ // Split in half and retry each half
94
+ console.warn(`[Worker] Batch of ${numJobs} entities failed (${msg}), splitting…`);
95
+ // WASM may be corrupted — force re-init before retrying
96
+ api = null;
97
+ const mid = Math.floor(numJobs / 2) * 3;
98
+ await processBatch(jobs.slice(0, mid));
99
+ await processBatch(jobs.slice(mid));
100
+ }
101
+ };
102
+ await processBatch(jobsFlat);
103
+ self.postMessage({ type: 'batch', meshes: allMeshes }, allTransferBuffers);
104
+ self.postMessage({ type: 'complete', totalMeshes: allMeshes.length });
66
105
  }
67
106
  }
68
107
  catch (err) {
@@ -1 +1 @@
1
- {"version":3,"file":"geometry.worker.js","sourceRoot":"","sources":["../src/geometry.worker.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"geometry.worker.js","sourceRoot":"","sources":["../src/geometry.worker.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -335,7 +335,7 @@ export class GeometryProcessor {
335
335
  const sharedBuffer = new SharedArrayBuffer(buffer.byteLength);
336
336
  new Uint8Array(sharedBuffer).set(buffer);
337
337
  // ── PHASE 1: Full pre-pass in worker ──
338
- const makeWorker = () => new Worker(new URL('./geometry.worker.ts', import.meta.url), { type: 'module' });
338
+ const makeWorker = () => new Worker(new URL('./geometry.worker.js', import.meta.url), { type: 'module' });
339
339
  const prePassResult = await new Promise((resolve, reject) => {
340
340
  const w = makeWorker();
341
341
  w.onmessage = (e) => {
@@ -404,7 +404,7 @@ export class GeometryProcessor {
404
404
  continue;
405
405
  }
406
406
  const workerJobs = jobsFlat.slice(jobStart * 3, jobEnd * 3);
407
- const worker = new Worker(new URL('./geometry.worker.ts', import.meta.url), { type: 'module' });
407
+ const worker = new Worker(new URL('./geometry.worker.js', import.meta.url), { type: 'module' });
408
408
  workers.push(worker);
409
409
  worker.onmessage = (e) => {
410
410
  const msg = e.data;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ifc-lite/geometry",
3
- "version": "1.16.1",
3
+ "version": "1.16.2",
4
4
  "description": "Geometry processing bridge for IFC-Lite - 1.9x faster than web-ifc",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -12,8 +12,8 @@
12
12
  }
13
13
  },
14
14
  "dependencies": {
15
- "@ifc-lite/data": "^1.15.0",
16
- "@ifc-lite/wasm": "^1.16.0"
15
+ "@ifc-lite/data": "^1.15.1",
16
+ "@ifc-lite/wasm": "^1.16.1"
17
17
  },
18
18
  "optionalDependencies": {
19
19
  "@tauri-apps/api": "^2.0.0"
@@ -47,8 +47,8 @@
47
47
  "README.md"
48
48
  ],
49
49
  "scripts": {
50
- "build": "tsc",
51
- "dev": "tsc --watch",
50
+ "build": "pnpm exec tsc && node -e \"const f='dist/index.js';require('fs').writeFileSync(f,require('fs').readFileSync(f,'utf8').replace(/geometry\\.worker\\.ts/g,'geometry.worker.js'))\"",
51
+ "dev": "pnpm exec tsc --watch",
52
52
  "test": "vitest run"
53
53
  }
54
54
  }