@ifc-lite/viewer 1.18.0 → 1.19.1

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.
Files changed (61) hide show
  1. package/.turbo/turbo-build.log +19 -16
  2. package/.turbo/turbo-typecheck.log +1 -1
  3. package/CHANGELOG.md +444 -0
  4. package/dist/assets/basketViewActivator-CA2CTcVo.js +71 -0
  5. package/dist/assets/{bcf-DOG9_WPX.js → bcf-4K724hw0.js} +18 -18
  6. package/dist/assets/decode-worker-Collf_X_.js +1320 -0
  7. package/dist/assets/{exporters-B_OBqIyD.js → exporters-xbXqEDlO.js} +2547 -1958
  8. package/dist/assets/{geometry.worker-xHHy-9DV.js → geometry.worker-DQEZB2rB.js} +1 -1
  9. package/dist/assets/ids-2WdONLlu.js +2033 -0
  10. package/dist/assets/ifc-lite_bg-4yUkDRD8.wasm +0 -0
  11. package/dist/assets/index-BXeEKqJG.css +1 -0
  12. package/dist/assets/{index-BKq-M3Mk.js → index-D8Epw-e7.js} +51781 -32599
  13. package/dist/assets/index-XwKzDuw6.js +22 -0
  14. package/dist/assets/{native-bridge-SHXiQwFW.js → native-bridge-DKmx1z95.js} +2 -2
  15. package/dist/assets/{sandbox-jez21HtV.js → sandbox-tccwm5Bo.js} +1402 -1329
  16. package/dist/assets/{server-client-ncOQVNso.js → server-client-LoWPK1N2.js} +1 -1
  17. package/dist/assets/three-CDRZThFA.js +4057 -0
  18. package/dist/assets/{wasm-bridge-DyfBSB8z.js → wasm-bridge-BsJGgPMs.js} +1 -1
  19. package/dist/index.html +8 -7
  20. package/dist/samples/building-architecture.ifc +453 -0
  21. package/dist/samples/hello-wall.ifc +1054 -0
  22. package/dist/samples/infra-bridge.ifc +962 -0
  23. package/package.json +13 -7
  24. package/public/samples/building-architecture.ifc +453 -0
  25. package/public/samples/hello-wall.ifc +1054 -0
  26. package/public/samples/infra-bridge.ifc +962 -0
  27. package/src/App.tsx +37 -3
  28. package/src/components/mcp/HeroScene.tsx +876 -0
  29. package/src/components/mcp/McpLanding.tsx +1318 -0
  30. package/src/components/mcp/McpPlayground.tsx +524 -0
  31. package/src/components/mcp/PlaygroundChat.tsx +1097 -0
  32. package/src/components/mcp/PlaygroundViewer.tsx +815 -0
  33. package/src/components/mcp/README.md +171 -0
  34. package/src/components/mcp/data.ts +659 -0
  35. package/src/components/mcp/playground-dispatcher.ts +1649 -0
  36. package/src/components/mcp/playground-files.ts +107 -0
  37. package/src/components/mcp/playground-uploads.ts +122 -0
  38. package/src/components/mcp/types.ts +65 -0
  39. package/src/components/mcp/use-mcp-page.ts +109 -0
  40. package/src/components/viewer/MainToolbar.tsx +23 -2
  41. package/src/components/viewer/PointCloudPanel.tsx +174 -0
  42. package/src/components/viewer/Viewport.tsx +18 -1
  43. package/src/components/viewer/ViewportContainer.tsx +78 -9
  44. package/src/components/viewer/ViewportOverlays.tsx +13 -2
  45. package/src/components/viewer/tools/AddElementOverlay.tsx +43 -2
  46. package/src/components/viewer/usePointCloudLifecycle.ts +64 -0
  47. package/src/components/viewer/usePointCloudSync.ts +98 -0
  48. package/src/generated/mcp-catalog.json +82 -0
  49. package/src/hooks/ingest/pointCloudIngest.ts +391 -0
  50. package/src/hooks/ingest/viewerModelIngest.ts +32 -3
  51. package/src/hooks/useIfcFederation.ts +72 -3
  52. package/src/hooks/useIfcLoader.ts +67 -3
  53. package/src/services/file-dialog.ts +4 -2
  54. package/src/store/index.ts +10 -1
  55. package/src/store/slices/pointCloudSlice.ts +102 -0
  56. package/src/store/types.ts +7 -0
  57. package/vite.config.ts +7 -0
  58. package/dist/assets/basketViewActivator-Cm1QEk_R.js +0 -1
  59. package/dist/assets/ids-DQ5jY0E8.js +0 -1
  60. package/dist/assets/ifc-lite_bg-ADjKXSms.wasm +0 -0
  61. package/dist/assets/index-COnQRuqY.css +0 -1
@@ -0,0 +1,1320 @@
1
+ (async ()=>{
2
+ function Et(n) {
3
+ const t = n.positions.buffer, e = [
4
+ t
5
+ ], o = {
6
+ positions: t,
7
+ pointCount: n.pointCount,
8
+ bbox: n.bbox
9
+ };
10
+ if (n.colors) {
11
+ const r = n.colors.buffer;
12
+ o.colors = r, e.push(r);
13
+ }
14
+ if (n.classifications) {
15
+ const r = n.classifications.buffer;
16
+ o.classifications = r, e.push(r);
17
+ }
18
+ if (n.intensities) {
19
+ const r = n.intensities.buffer;
20
+ o.intensities = r, e.push(r);
21
+ }
22
+ return {
23
+ payload: o,
24
+ transfer: e
25
+ };
26
+ }
27
+ const Ft = 1179861324, rt = {
28
+ 0: 20,
29
+ 1: 28,
30
+ 2: 26,
31
+ 3: 34,
32
+ 4: 57,
33
+ 5: 63,
34
+ 6: 30,
35
+ 7: 36,
36
+ 8: 38,
37
+ 9: 59,
38
+ 10: 67
39
+ }, It = new Set([
40
+ 1,
41
+ 3,
42
+ 4,
43
+ 5,
44
+ 6,
45
+ 7,
46
+ 8,
47
+ 9,
48
+ 10
49
+ ]), At = new Set([
50
+ 2,
51
+ 3,
52
+ 5,
53
+ 7,
54
+ 8,
55
+ 10
56
+ ]);
57
+ function ft(n) {
58
+ const t = n instanceof Uint8Array ? n : new Uint8Array(n);
59
+ if (t.length < 227) throw new Error("LAS: header truncated");
60
+ const e = new DataView(t.buffer, t.byteOffset, t.byteLength);
61
+ if (e.getUint32(0, !0) !== Ft) throw new Error('LAS: bad magic — expected "LASF"');
62
+ const o = e.getUint8(24), r = e.getUint8(25), a = e.getUint16(94, !0), l = e.getUint32(96, !0), c = e.getUint32(100, !0), i = e.getUint8(104) & 63, s = e.getUint16(105, !0);
63
+ let g = e.getUint32(107, !0);
64
+ if (o >= 1 && r >= 4 && t.length >= 255) {
65
+ const x = Lt(e, 247);
66
+ x > 0 && (g = x);
67
+ }
68
+ if (!Number.isFinite(g) || g < 0) throw new Error("LAS: invalid point count");
69
+ const h = [
70
+ e.getFloat64(131, !0),
71
+ e.getFloat64(139, !0),
72
+ e.getFloat64(147, !0)
73
+ ], p = [
74
+ e.getFloat64(155, !0),
75
+ e.getFloat64(163, !0),
76
+ e.getFloat64(171, !0)
77
+ ], f = e.getFloat64(179, !0), d = e.getFloat64(187, !0), m = e.getFloat64(195, !0), w = e.getFloat64(203, !0), b = e.getFloat64(211, !0), C = e.getFloat64(219, !0), F = {
78
+ min: [
79
+ d,
80
+ w,
81
+ C
82
+ ],
83
+ max: [
84
+ f,
85
+ m,
86
+ b
87
+ ]
88
+ };
89
+ if (rt[i] === void 0) throw new Error(`LAS: unsupported point data format ${i}`);
90
+ const E = rt[i];
91
+ if (s < E) throw new Error(`LAS: header point-record length (${s}) smaller than format ${i} baseline (${E})`);
92
+ return {
93
+ versionMajor: o,
94
+ versionMinor: r,
95
+ headerSize: a,
96
+ pointDataOffset: l,
97
+ numberOfVlrs: c,
98
+ pointDataFormatId: i,
99
+ pointRecordLength: s,
100
+ pointCount: g,
101
+ scale: h,
102
+ offset: p,
103
+ bbox: F,
104
+ hasGpsTime: It.has(i),
105
+ hasRgb: At.has(i)
106
+ };
107
+ }
108
+ function G(n, t, e, o = t.pointRecordLength, r = 1) {
109
+ if (n.length < e * o) throw new Error(`LAS: decode expects ${e * o} bytes, got ${n.length}`);
110
+ const a = new DataView(n.buffer, n.byteOffset, n.byteLength), l = new Float32Array(e * 3), c = new Uint16Array(e), i = new Uint8Array(e), s = t.hasRgb ? new Float32Array(e * 3) : void 0, u = dt(t.pointDataFormatId), g = t.pointDataFormatId >= 6 ? 16 : 15;
111
+ let h = 1 / 0, p = 1 / 0, f = 1 / 0, d = -1 / 0, m = -1 / 0, w = -1 / 0;
112
+ for(let b = 0; b < e; b++){
113
+ const C = b * o, F = a.getInt32(C, !0) * t.scale[0] + t.offset[0], E = a.getInt32(C + 4, !0) * t.scale[1] + t.offset[1], x = a.getInt32(C + 8, !0) * t.scale[2] + t.offset[2];
114
+ if (l[b * 3] = F, l[b * 3 + 1] = E, l[b * 3 + 2] = x, F < h && (h = F), F > d && (d = F), E < p && (p = E), E > m && (m = E), x < f && (f = x), x > w && (w = x), c[b] = a.getUint16(C + 12, !0), i[b] = t.pointDataFormatId >= 6 ? a.getUint8(C + g) : a.getUint8(C + g) & 31, s && u >= 0) {
115
+ const L = a.getUint16(C + u, !0), A = a.getUint16(C + u + 2, !0), Z = a.getUint16(C + u + 4, !0);
116
+ s[b * 3] = L * r / 65535, s[b * 3 + 1] = A * r / 65535, s[b * 3 + 2] = Z * r / 65535;
117
+ }
118
+ }
119
+ return {
120
+ positions: l,
121
+ colors: s,
122
+ classifications: i,
123
+ intensities: c,
124
+ pointCount: e,
125
+ bbox: {
126
+ min: [
127
+ h,
128
+ p,
129
+ f
130
+ ],
131
+ max: [
132
+ d,
133
+ m,
134
+ w
135
+ ]
136
+ }
137
+ };
138
+ }
139
+ function ut(n, t, e = 1024) {
140
+ if (!t.hasRgb) return 0;
141
+ const o = t.pointRecordLength, r = Math.min(t.pointCount, Math.floor(n.length / o));
142
+ if (r === 0) return 0;
143
+ const a = new DataView(n.buffer, n.byteOffset, n.byteLength), l = dt(t.pointDataFormatId);
144
+ if (l < 0) return 0;
145
+ const c = Math.max(1, Math.floor(r / Math.min(e, r)));
146
+ let i = 0;
147
+ for(let s = 0; s < r; s += c){
148
+ const u = s * o, g = a.getUint16(u + l, !0), h = a.getUint16(u + l + 2, !0), p = a.getUint16(u + l + 4, !0);
149
+ g > i && (i = g), h > i && (i = h), p > i && (i = p);
150
+ }
151
+ return i;
152
+ }
153
+ function dt(n) {
154
+ switch(n){
155
+ case 2:
156
+ return 20;
157
+ case 3:
158
+ return 28;
159
+ case 5:
160
+ return 28;
161
+ case 7:
162
+ return 30;
163
+ case 8:
164
+ return 30;
165
+ case 10:
166
+ return 30;
167
+ default:
168
+ return -1;
169
+ }
170
+ }
171
+ function Lt(n, t) {
172
+ const e = n.getUint32(t, !0);
173
+ return n.getUint32(t + 4, !0) * 4294967296 + e;
174
+ }
175
+ class Pt {
176
+ constructor(t){
177
+ this.blob = t;
178
+ }
179
+ get size() {
180
+ return this.blob.size;
181
+ }
182
+ async read(t, e) {
183
+ const o = Math.max(0, t), r = Math.min(e, this.blob.size);
184
+ if (r <= o) return new Uint8Array(0);
185
+ const l = await this.blob.slice(o, r).arrayBuffer();
186
+ return new Uint8Array(l);
187
+ }
188
+ }
189
+ const St = 1024, Mt = 4096;
190
+ class Ut {
191
+ bytes;
192
+ header = null;
193
+ cursor = 0;
194
+ rgbScale = 1;
195
+ downsample;
196
+ label;
197
+ constructor(t, e = {}){
198
+ this.bytes = new Pt(t), this.downsample = e.downsample ?? {
199
+ stride: 1
200
+ }, this.label = e.label;
201
+ }
202
+ async open(t) {
203
+ if (this.header) return this.toInfo(this.header);
204
+ z(t);
205
+ const e = await this.bytes.read(0, St);
206
+ z(t);
207
+ const o = ft(e);
208
+ let r = 1;
209
+ if (o.hasRgb) {
210
+ const a = Math.min(Mt * o.pointRecordLength, Math.max(0, this.bytes.size - o.pointDataOffset));
211
+ if (a > 0) {
212
+ const l = await this.bytes.read(o.pointDataOffset, o.pointDataOffset + a);
213
+ z(t);
214
+ const c = ut(l, o);
215
+ r = c > 0 && c <= 255 ? 65535 / 255 : 1;
216
+ }
217
+ }
218
+ return this.header = o, this.rgbScale = r, this.cursor = 0, this.toInfo(o);
219
+ }
220
+ async next(t, e) {
221
+ if (z(e), !Number.isFinite(t) || t <= 0) throw new Error(`LasStreamingSource: maxPoints must be > 0 (got ${t})`);
222
+ if (!this.header) throw new Error("LasStreamingSource: open() must be awaited before next()");
223
+ const o = Math.max(1, this.downsample.stride | 0);
224
+ if (this.cursor >= this.header.pointCount) return null;
225
+ if (o === 1) {
226
+ const p = this.header.pointCount - this.cursor, f = Math.min(t, p), d = this.header.pointDataOffset + this.cursor * this.header.pointRecordLength, m = d + f * this.header.pointRecordLength, w = await this.bytes.read(d, m);
227
+ z(e);
228
+ const b = G(w, this.header, f, this.header.pointRecordLength, this.rgbScale);
229
+ return this.cursor += f, b;
230
+ }
231
+ const r = this.header.pointCount - this.cursor, a = Math.min(t * o, r), l = Math.ceil(a / o), c = this.header.pointDataOffset + this.cursor * this.header.pointRecordLength, i = c + a * this.header.pointRecordLength, s = await this.bytes.read(c, i);
232
+ z(e);
233
+ const u = new Uint8Array(l * this.header.pointRecordLength);
234
+ let g = 0;
235
+ for(let p = 0; p < l; p++){
236
+ const f = p * o * this.header.pointRecordLength;
237
+ u.set(s.subarray(f, f + this.header.pointRecordLength), g), g += this.header.pointRecordLength;
238
+ }
239
+ const h = G(u, this.header, l, this.header.pointRecordLength, this.rgbScale);
240
+ return this.cursor += a, h;
241
+ }
242
+ close() {
243
+ this.header = null, this.cursor = 0;
244
+ }
245
+ toInfo(t) {
246
+ const e = Math.max(1, this.downsample.stride | 0);
247
+ return {
248
+ totalPointCount: e === 1 ? t.pointCount : Math.ceil(t.pointCount / e),
249
+ bbox: t.bbox,
250
+ hasColor: t.hasRgb,
251
+ hasClassification: !0,
252
+ hasIntensity: !0,
253
+ label: this.label
254
+ };
255
+ }
256
+ }
257
+ function z(n) {
258
+ if (n?.aborted) throw new DOMException("Aborted", "AbortError");
259
+ }
260
+ let X = null;
261
+ async function zt() {
262
+ return X || (X = (async ()=>{
263
+ const n = await import("./index-XwKzDuw6.js").then(function(r) {
264
+ return r.i;
265
+ }), t = n.default, o = [
266
+ n.createLazPerf,
267
+ typeof t == "object" && t !== null ? t.createLazPerf : void 0,
268
+ t,
269
+ n
270
+ ].find((r)=>typeof r == "function");
271
+ if (!o) {
272
+ const r = Object.keys(n).join(", ");
273
+ throw new Error(`laz-perf: could not find createLazPerf factory (saw keys: ${r || "<empty>"})`);
274
+ }
275
+ return o();
276
+ })()), X;
277
+ }
278
+ class Ot {
279
+ blob;
280
+ downsample;
281
+ label;
282
+ mod = null;
283
+ laszip = null;
284
+ header = null;
285
+ fileBytes = null;
286
+ filePtr = 0;
287
+ pointPtr = 0;
288
+ pointBuffer = null;
289
+ cursor = 0;
290
+ rgbScale = 1;
291
+ constructor(t, e = {}){
292
+ this.blob = t, this.downsample = e.downsample ?? {
293
+ stride: 1
294
+ }, this.label = e.label;
295
+ }
296
+ async open(t) {
297
+ if (this.header) return this.toInfo(this.header);
298
+ N(t);
299
+ let e, o = 0, r = 0, a;
300
+ try {
301
+ const l = await this.blob.arrayBuffer();
302
+ N(t);
303
+ const c = new Uint8Array(l), i = ft(c);
304
+ e = await zt(), N(t), o = e._malloc(c.byteLength), e.HEAPU8.set(c, o), a = new e.LASZip, a.open(o, c.byteLength);
305
+ const s = a.getPointLength();
306
+ r = e._malloc(s);
307
+ const u = new Uint8Array(s);
308
+ let g = 1;
309
+ if (i.hasRgb) {
310
+ const h = Math.min(4096, i.pointCount), p = new Uint8Array(h * s);
311
+ for(let d = 0; d < h; d++)a.getPoint(r), p.set(e.HEAPU8.subarray(r, r + s), d * s);
312
+ const f = ut(p, i);
313
+ g = f > 0 && f <= 255 ? 65535 / 255 : 1, a.delete(), a = new e.LASZip, a.open(o, c.byteLength);
314
+ }
315
+ return this.fileBytes = c, this.mod = e, this.filePtr = o, this.laszip = a, this.pointPtr = r, this.pointBuffer = u, this.rgbScale = g, this.header = i, this.cursor = 0, this.toInfo(i);
316
+ } catch (l) {
317
+ try {
318
+ a?.delete();
319
+ } catch {}
320
+ if (e && r) try {
321
+ e._free(r);
322
+ } catch {}
323
+ if (e && o) try {
324
+ e._free(o);
325
+ } catch {}
326
+ throw l;
327
+ }
328
+ }
329
+ async next(t, e) {
330
+ if (N(e), !Number.isFinite(t) || t <= 0) throw new Error(`LazStreamingSource: maxPoints must be > 0 (got ${t})`);
331
+ if (!this.header || !this.mod || !this.laszip || !this.pointBuffer) throw new Error("LazStreamingSource: open() must be awaited before next()");
332
+ const o = Math.max(1, this.downsample.stride | 0);
333
+ if (this.cursor >= this.header.pointCount) return null;
334
+ const r = this.pointBuffer.byteLength, a = this.header.pointCount - this.cursor, l = Math.min(o === 1 ? t : t * o, a), c = o === 1 ? l : Math.ceil(l / o), i = new Uint8Array(c * r);
335
+ let s = 0;
336
+ for(let u = 0; u < l; u++)this.laszip.getPoint(this.pointPtr), (o === 1 || u % o === 0) && (i.set(this.mod.HEAPU8.subarray(this.pointPtr, this.pointPtr + r), s * r), s++);
337
+ return this.cursor += l, G(i, this.header, c, r, this.rgbScale);
338
+ }
339
+ close() {
340
+ try {
341
+ this.laszip?.delete();
342
+ } catch {}
343
+ if (this.mod && this.pointPtr) try {
344
+ this.mod._free(this.pointPtr);
345
+ } catch {}
346
+ if (this.mod && this.filePtr) try {
347
+ this.mod._free(this.filePtr);
348
+ } catch {}
349
+ this.laszip = null, this.mod = null, this.header = null, this.fileBytes = null, this.pointBuffer = null, this.filePtr = 0, this.pointPtr = 0, this.cursor = 0;
350
+ }
351
+ toInfo(t) {
352
+ const e = Math.max(1, this.downsample.stride | 0);
353
+ return {
354
+ totalPointCount: e === 1 ? t.pointCount : Math.ceil(t.pointCount / e),
355
+ bbox: t.bbox,
356
+ hasColor: t.hasRgb,
357
+ hasClassification: !0,
358
+ hasIntensity: !0,
359
+ label: this.label
360
+ };
361
+ }
362
+ }
363
+ function N(n) {
364
+ if (n?.aborted) throw new DOMException("Aborted", "AbortError");
365
+ }
366
+ const Dt = {
367
+ char: 1,
368
+ int8: 1,
369
+ uchar: 1,
370
+ uint8: 1,
371
+ short: 2,
372
+ int16: 2,
373
+ ushort: 2,
374
+ uint16: 2,
375
+ int: 4,
376
+ int32: 4,
377
+ uint: 4,
378
+ uint32: 4,
379
+ float: 4,
380
+ float32: 4,
381
+ double: 8,
382
+ float64: 8
383
+ }, ht = new TextDecoder;
384
+ function pt(n) {
385
+ const t = Math.min(65536, n.length), e = ht.decode(n.subarray(0, t));
386
+ if (!e.startsWith("ply")) throw new Error('PLY: missing magic — file does not start with "ply"');
387
+ const o = e.indexOf("end_header");
388
+ if (o < 0) throw new Error("PLY: missing end_header line in first " + t + " bytes");
389
+ const r = e.indexOf(`
390
+ `, o);
391
+ if (r < 0) throw new Error("PLY: end_header line not terminated by newline");
392
+ const a = e.slice(0, r + 1), l = r + 1, c = a.split(`
393
+ `).map((h)=>h.trim()).filter((h)=>h.length > 0);
394
+ let i = null, s = "1.0";
395
+ const u = [];
396
+ let g = null;
397
+ for (const h of c)if (!(h === "ply" || h === "end_header") && !h.startsWith("comment") && !h.startsWith("obj_info")) {
398
+ if (h.startsWith("format ")) {
399
+ const p = h.split(/\s+/), f = p[1];
400
+ if (s = p[2] ?? "1.0", f === "ascii" || f === "binary_little_endian" || f === "binary_big_endian") i = f;
401
+ else throw new Error(`PLY: unsupported format "${f}"`);
402
+ continue;
403
+ }
404
+ if (h.startsWith("element ")) {
405
+ const p = h.split(/\s+/);
406
+ g = {
407
+ name: p[1],
408
+ count: parseInt(p[2], 10),
409
+ properties: [],
410
+ recordSize: 0
411
+ }, u.push(g);
412
+ continue;
413
+ }
414
+ if (h.startsWith("property ")) {
415
+ if (!g) throw new Error(`PLY: property declared before any element: "${h}"`);
416
+ const p = h.split(/\s+/);
417
+ if (p[1] === "list") continue;
418
+ const f = p[1], d = p[2], m = Dt[f];
419
+ if (m === void 0) throw new Error(`PLY: unknown property type "${f}"`);
420
+ g.properties.push({
421
+ name: d,
422
+ type: f,
423
+ size: m,
424
+ offset: g.recordSize
425
+ }), g.recordSize += m;
426
+ continue;
427
+ }
428
+ }
429
+ if (!i) throw new Error("PLY: missing `format` line in header");
430
+ if (!u.some((h)=>h.name === "vertex")) throw new Error("PLY: missing `vertex` element");
431
+ return {
432
+ format: i,
433
+ version: s,
434
+ elements: u,
435
+ bodyOffset: l
436
+ };
437
+ }
438
+ function $t(n) {
439
+ const t = pt(n), e = t.elements.find((d)=>d.name === "vertex");
440
+ if (!e) throw new Error("PLY: no vertex element");
441
+ if (t.elements[0] !== e) throw new Error(`PLY: vertex element must appear first; saw "${t.elements[0]?.name}" first`);
442
+ const o = e.properties.find((d)=>d.name === "x"), r = e.properties.find((d)=>d.name === "y"), a = e.properties.find((d)=>d.name === "z");
443
+ if (!o || !r || !a) throw new Error("PLY: vertex element must define x, y, z properties");
444
+ const l = e.properties.find((d)=>d.name === "red" || d.name === "r"), c = e.properties.find((d)=>d.name === "green" || d.name === "g"), i = e.properties.find((d)=>d.name === "blue" || d.name === "b"), s = !!(l && c && i), u = e.properties.find((d)=>d.name === "intensity" || d.name === "scalar_Intensity"), g = e.count, h = new Float32Array(g * 3), p = s ? new Float32Array(g * 3) : void 0, f = u ? new Uint16Array(g) : void 0;
445
+ return t.format === "ascii" ? Bt(n, t, e, h, p, f) : Rt(n, t, e, h, p, f, t.format === "binary_little_endian"), {
446
+ positions: h,
447
+ colors: p,
448
+ intensities: f,
449
+ pointCount: g,
450
+ bbox: _t(h)
451
+ };
452
+ }
453
+ function Bt(n, t, e, o, r, a) {
454
+ const l = ht.decode(n.subarray(t.bodyOffset)), c = e.properties.findIndex((m)=>m.name === "x"), i = e.properties.findIndex((m)=>m.name === "y"), s = e.properties.findIndex((m)=>m.name === "z"), u = e.properties.findIndex((m)=>m.name === "red" || m.name === "r"), g = e.properties.findIndex((m)=>m.name === "green" || m.name === "g"), h = e.properties.findIndex((m)=>m.name === "blue" || m.name === "b"), p = e.properties.findIndex((m)=>m.name === "intensity" || m.name === "scalar_Intensity");
455
+ let f = 0, d = 0;
456
+ for(; d < e.count && f < l.length;){
457
+ let m = l.indexOf(`
458
+ `, f);
459
+ m < 0 && (m = l.length);
460
+ const w = l.slice(f, m).trim();
461
+ if (f = m + 1, !w) continue;
462
+ const b = w.split(/\s+/);
463
+ o[d * 3] = Number(b[c]), o[d * 3 + 1] = Number(b[i]), o[d * 3 + 2] = Number(b[s]), r && u >= 0 && g >= 0 && h >= 0 && (r[d * 3] = $(Number(b[u]) / 255), r[d * 3 + 1] = $(Number(b[g]) / 255), r[d * 3 + 2] = $(Number(b[h]) / 255)), a && p >= 0 && (a[d] = Math.min(65535, Math.max(0, Number(b[p]) | 0))), d++;
464
+ }
465
+ if (d !== e.count) throw new Error(`PLY ascii: expected ${e.count} vertex lines, got ${d}`);
466
+ }
467
+ function Rt(n, t, e, o, r, a, l) {
468
+ const c = e.recordSize, i = e.count * c;
469
+ if (n.length < t.bodyOffset + i) throw new Error(`PLY binary: expected ${i} body bytes, got ${n.length - t.bodyOffset}`);
470
+ const s = new DataView(n.buffer, n.byteOffset + t.bodyOffset, i), u = e.properties.find((w)=>w.name === "x"), g = e.properties.find((w)=>w.name === "y"), h = e.properties.find((w)=>w.name === "z"), p = r ? e.properties.find((w)=>w.name === "red" || w.name === "r") : void 0, f = r ? e.properties.find((w)=>w.name === "green" || w.name === "g") : void 0, d = r ? e.properties.find((w)=>w.name === "blue" || w.name === "b") : void 0, m = a ? e.properties.find((w)=>w.name === "intensity" || w.name === "scalar_Intensity") : void 0;
471
+ for(let w = 0; w < e.count; w++){
472
+ const b = w * c;
473
+ o[w * 3] = M(s, b + u.offset, u, l), o[w * 3 + 1] = M(s, b + g.offset, g, l), o[w * 3 + 2] = M(s, b + h.offset, h, l), r && p && f && d && (r[w * 3] = $(M(s, b + p.offset, p, l) / 255), r[w * 3 + 1] = $(M(s, b + f.offset, f, l) / 255), r[w * 3 + 2] = $(M(s, b + d.offset, d, l) / 255)), a && m && (a[w] = Math.min(65535, Math.max(0, M(s, b + m.offset, m, l) | 0)));
474
+ }
475
+ }
476
+ function M(n, t, e, o) {
477
+ switch(e.type){
478
+ case "char":
479
+ case "int8":
480
+ return n.getInt8(t);
481
+ case "uchar":
482
+ case "uint8":
483
+ return n.getUint8(t);
484
+ case "short":
485
+ case "int16":
486
+ return n.getInt16(t, o);
487
+ case "ushort":
488
+ case "uint16":
489
+ return n.getUint16(t, o);
490
+ case "int":
491
+ case "int32":
492
+ return n.getInt32(t, o);
493
+ case "uint":
494
+ case "uint32":
495
+ return n.getUint32(t, o);
496
+ case "float":
497
+ case "float32":
498
+ return n.getFloat32(t, o);
499
+ case "double":
500
+ case "float64":
501
+ return n.getFloat64(t, o);
502
+ default:
503
+ throw new Error(`PLY: cannot read scalar of type "${e.type}"`);
504
+ }
505
+ }
506
+ function $(n) {
507
+ return n < 0 ? 0 : n > 1 ? 1 : n;
508
+ }
509
+ function _t(n) {
510
+ let t = 1 / 0, e = 1 / 0, o = 1 / 0, r = -1 / 0, a = -1 / 0, l = -1 / 0;
511
+ for(let c = 0; c < n.length; c += 3){
512
+ const i = n[c], s = n[c + 1], u = n[c + 2];
513
+ i < t && (t = i), i > r && (r = i), s < e && (e = s), s > a && (a = s), u < o && (o = u), u > l && (l = u);
514
+ }
515
+ return {
516
+ min: [
517
+ t,
518
+ e,
519
+ o
520
+ ],
521
+ max: [
522
+ r,
523
+ a,
524
+ l
525
+ ]
526
+ };
527
+ }
528
+ class Tt {
529
+ blob;
530
+ downsample;
531
+ label;
532
+ chunk = null;
533
+ served = !1;
534
+ constructor(t, e = {}){
535
+ this.blob = t, this.downsample = e.downsample ?? {
536
+ stride: 1
537
+ }, this.label = e.label;
538
+ }
539
+ async open(t) {
540
+ V(t);
541
+ const e = await this.blob.arrayBuffer();
542
+ V(t);
543
+ const o = new Uint8Array(e), a = pt(o).elements.find((s)=>s.name === "vertex");
544
+ if (!a) throw new Error("PLY: no vertex element");
545
+ const l = !!a.properties.find((s)=>s.name === "red" || s.name === "r") && !!a.properties.find((s)=>s.name === "green" || s.name === "g") && !!a.properties.find((s)=>s.name === "blue" || s.name === "b"), c = !!a.properties.find((s)=>s.name === "intensity" || s.name === "scalar_Intensity"), i = $t(o);
546
+ return this.chunk = Yt(i, this.downsample.stride), {
547
+ totalPointCount: this.chunk.pointCount,
548
+ bbox: this.chunk.bbox,
549
+ hasColor: l,
550
+ hasClassification: !1,
551
+ hasIntensity: c,
552
+ label: this.label
553
+ };
554
+ }
555
+ async next(t, e) {
556
+ return V(e), !this.chunk || this.served ? null : (this.served = !0, this.chunk);
557
+ }
558
+ close() {
559
+ this.chunk = null, this.served = !1;
560
+ }
561
+ }
562
+ function Yt(n, t) {
563
+ const e = Math.max(1, t | 0);
564
+ if (e === 1) return n;
565
+ const o = Math.ceil(n.pointCount / e), r = new Float32Array(o * 3), a = n.colors ? new Float32Array(o * 3) : void 0, l = n.classifications ? new Uint8Array(o) : void 0, c = n.intensities ? new Uint16Array(o) : void 0;
566
+ let i = 0;
567
+ for(let s = 0; s < n.pointCount; s += e)r[i * 3] = n.positions[s * 3], r[i * 3 + 1] = n.positions[s * 3 + 1], r[i * 3 + 2] = n.positions[s * 3 + 2], a && n.colors && (a[i * 3] = n.colors[s * 3], a[i * 3 + 1] = n.colors[s * 3 + 1], a[i * 3 + 2] = n.colors[s * 3 + 2]), l && n.classifications && (l[i] = n.classifications[s]), c && n.intensities && (c[i] = n.intensities[s]), i++;
568
+ return {
569
+ positions: r,
570
+ colors: a,
571
+ classifications: l,
572
+ intensities: c,
573
+ pointCount: o,
574
+ bbox: n.bbox
575
+ };
576
+ }
577
+ function V(n) {
578
+ if (n?.aborted) throw new DOMException("Aborted", "AbortError");
579
+ }
580
+ function vt(n, t) {
581
+ const e = new Uint8Array(t);
582
+ let o = 0, r = 0;
583
+ const a = n.length;
584
+ for(; o < a;){
585
+ let l = n[o++];
586
+ if (l < 32) {
587
+ const c = l + 1;
588
+ if (o + c > a) throw new Error("LZF: literal run exceeds input bounds");
589
+ if (r + c > t) throw new Error("LZF: literal run exceeds output bounds");
590
+ e.set(n.subarray(o, o + c), r), o += c, r += c;
591
+ } else {
592
+ let c = l >> 5;
593
+ if (c === 7) {
594
+ if (o >= a) throw new Error("LZF: truncated extended length");
595
+ c += n[o++];
596
+ }
597
+ if (c += 2, o >= a) throw new Error("LZF: truncated back-reference offset");
598
+ const i = r - ((l & 31) << 8) - n[o++] - 1;
599
+ if (i < 0) throw new Error("LZF: back-reference points before output start");
600
+ if (r + c > t) throw new Error("LZF: back-reference exceeds output bounds");
601
+ for(let s = 0; s < c; s++)e[r + s] = e[i + s];
602
+ r += c;
603
+ }
604
+ }
605
+ if (r !== t) throw new Error(`LZF: decompressed ${r} bytes, expected ${t}`);
606
+ return e;
607
+ }
608
+ const mt = new TextDecoder;
609
+ function Nt(n) {
610
+ const t = Zt(n);
611
+ let e, o;
612
+ return t.data === "ascii" ? { positions: e, colors: o } = kt(n, t) : t.data === "binary" ? { positions: e, colors: o } = Vt(n, t) : { positions: e, colors: o } = qt(n, t), {
613
+ positions: e,
614
+ colors: o,
615
+ pointCount: t.pointCount,
616
+ bbox: jt(e)
617
+ };
618
+ }
619
+ function Zt(n) {
620
+ const t = Math.min(65536, n.length), e = mt.decode(n.subarray(0, t)), o = e.search(/^DATA\s+(\S+)/m);
621
+ if (o < 0) throw new Error("PCD: missing DATA line in header (scanned first " + t + " bytes)");
622
+ const r = e.slice(0, o), a = e.slice(o).match(/^DATA\s+(\S+)\s*\n/);
623
+ if (!a) throw new Error("PCD: malformed DATA line");
624
+ const l = a[1].toLowerCase();
625
+ if (l !== "ascii" && l !== "binary" && l !== "binary_compressed") throw new Error(`PCD: unsupported DATA kind "${l}"`);
626
+ const c = o + a[0].length, i = new Map;
627
+ for (const E of r.split(`
628
+ `)){
629
+ const x = E.replace(/#.*$/, "").trim();
630
+ if (!x) continue;
631
+ const L = x.split(/\s+/), A = L[0].toUpperCase();
632
+ i.set(A, L.slice(1));
633
+ }
634
+ const s = i.get("FIELDS") ?? [], u = (i.get("SIZE") ?? []).map(Number), g = i.get("TYPE") ?? [], h = (i.get("COUNT") ?? []).map(Number), p = i.get("WIDTH")?.[0], f = i.get("HEIGHT")?.[0], d = i.get("POINTS")?.[0];
635
+ if (s.length === 0) throw new Error("PCD: missing FIELDS");
636
+ if (u.length !== s.length) throw new Error("PCD: SIZE/FIELDS length mismatch");
637
+ if (g.length !== s.length) throw new Error("PCD: TYPE/FIELDS length mismatch");
638
+ const m = [];
639
+ let w = 0;
640
+ for(let E = 0; E < s.length; E++){
641
+ const x = h[E] ?? 1, L = u[E], A = g[E];
642
+ if (A !== "F" && A !== "I" && A !== "U") throw new Error(`PCD: unsupported field TYPE "${A}"`);
643
+ m.push({
644
+ name: s[E],
645
+ size: L,
646
+ type: A,
647
+ count: x,
648
+ offset: w
649
+ }), w += L * x;
650
+ }
651
+ const b = p !== void 0 ? parseInt(p, 10) : 0, C = f !== void 0 ? parseInt(f, 10) : 1, F = d !== void 0 ? parseInt(d, 10) : b * C;
652
+ if (!Number.isFinite(F) || F <= 0) throw new Error("PCD: invalid point count");
653
+ return {
654
+ version: i.get("VERSION")?.[0] ?? "0.7",
655
+ fields: m,
656
+ width: b,
657
+ height: C,
658
+ pointCount: F,
659
+ pointStride: w,
660
+ data: l,
661
+ bodyOffset: c
662
+ };
663
+ }
664
+ function K(n) {
665
+ const t = {};
666
+ for (const e of n.fields){
667
+ const o = e.name.toLowerCase();
668
+ o === "x" ? t.xField = e : o === "y" ? t.yField = e : o === "z" ? t.zField = e : (o === "rgb" || o === "rgba") && (t.rgbField = e);
669
+ }
670
+ if (!t.xField || !t.yField || !t.zField) throw new Error("PCD: x/y/z fields are required");
671
+ return t;
672
+ }
673
+ function kt(n, t) {
674
+ const e = K(t), o = mt.decode(n.subarray(t.bodyOffset)), r = new Float32Array(t.pointCount * 3), a = e.rgbField ? new Float32Array(t.pointCount * 3) : void 0, l = Xt(t, e);
675
+ let c = 0, i = 0, s = 0;
676
+ for(; s < t.pointCount && i < o.length;){
677
+ let u = o.indexOf(`
678
+ `, i);
679
+ u < 0 && (u = o.length);
680
+ const g = o.slice(i, u).trim();
681
+ if (i = u + 1, !g) continue;
682
+ const h = g.split(/\s+/);
683
+ if (r[c * 3] = Number(h[l.xCol]), r[c * 3 + 1] = Number(h[l.yCol]), r[c * 3 + 2] = Number(h[l.zCol]), a && l.rgbCol >= 0) {
684
+ const p = Gt(h[l.rgbCol], e.rgbField);
685
+ a[c * 3] = (p >> 16 & 255) / 255, a[c * 3 + 1] = (p >> 8 & 255) / 255, a[c * 3 + 2] = (p & 255) / 255;
686
+ }
687
+ c++, s++;
688
+ }
689
+ if (s !== t.pointCount) throw new Error(`PCD ascii: expected ${t.pointCount} points, got ${s}`);
690
+ return {
691
+ positions: r,
692
+ colors: a
693
+ };
694
+ }
695
+ function Xt(n, t) {
696
+ let e = 0, o = -1, r = -1, a = -1, l = -1;
697
+ for (const c of n.fields)c === t.xField && (o = e), c === t.yField && (r = e), c === t.zField && (a = e), c === t.rgbField && (l = e), e += c.count;
698
+ return {
699
+ xCol: o,
700
+ yCol: r,
701
+ zCol: a,
702
+ rgbCol: l
703
+ };
704
+ }
705
+ function Vt(n, t) {
706
+ const e = K(t), o = new DataView(n.buffer, n.byteOffset + t.bodyOffset, t.pointCount * t.pointStride), r = new Float32Array(t.pointCount * 3), a = e.rgbField ? new Float32Array(t.pointCount * 3) : void 0;
707
+ for(let l = 0; l < t.pointCount; l++){
708
+ const c = l * t.pointStride;
709
+ if (r[l * 3] = B(o, c + e.xField.offset, e.xField), r[l * 3 + 1] = B(o, c + e.yField.offset, e.yField), r[l * 3 + 2] = B(o, c + e.zField.offset, e.zField), a && e.rgbField) {
710
+ const i = o.getUint32(c + e.rgbField.offset, !0);
711
+ a[l * 3] = (i >> 16 & 255) / 255, a[l * 3 + 1] = (i >> 8 & 255) / 255, a[l * 3 + 2] = (i & 255) / 255;
712
+ }
713
+ }
714
+ return {
715
+ positions: r,
716
+ colors: a
717
+ };
718
+ }
719
+ function qt(n, t) {
720
+ if (n.length < t.bodyOffset + 8) throw new Error("PCD binary_compressed: truncated size header");
721
+ const e = new DataView(n.buffer, n.byteOffset + t.bodyOffset, 8), o = e.getUint32(0, !0), r = e.getUint32(4, !0), a = t.pointCount * t.pointStride;
722
+ if (r !== a) throw new Error(`PCD binary_compressed: declared uncompressed=${r} does not match fields*points=${a}`);
723
+ const l = n.subarray(t.bodyOffset + 8, t.bodyOffset + 8 + o), c = vt(l, r), i = K(t), s = new Map;
724
+ let u = 0;
725
+ for (const b of t.fields)s.set(b, u), u += t.pointCount * b.size * b.count;
726
+ const g = new DataView(c.buffer, c.byteOffset, c.byteLength), h = new Float32Array(t.pointCount * 3), p = i.rgbField ? new Float32Array(t.pointCount * 3) : void 0, f = s.get(i.xField), d = s.get(i.yField), m = s.get(i.zField), w = i.rgbField ? s.get(i.rgbField) : 0;
727
+ for(let b = 0; b < t.pointCount; b++)if (h[b * 3] = B(g, f + b * i.xField.size, i.xField), h[b * 3 + 1] = B(g, d + b * i.yField.size, i.yField), h[b * 3 + 2] = B(g, m + b * i.zField.size, i.zField), p && i.rgbField) {
728
+ const C = g.getUint32(w + b * i.rgbField.size, !0);
729
+ p[b * 3] = (C >> 16 & 255) / 255, p[b * 3 + 1] = (C >> 8 & 255) / 255, p[b * 3 + 2] = (C & 255) / 255;
730
+ }
731
+ return {
732
+ positions: h,
733
+ colors: p
734
+ };
735
+ }
736
+ function B(n, t, e) {
737
+ if (e.type === "F") return e.size === 8 ? n.getFloat64(t, !0) : n.getFloat32(t, !0);
738
+ if (e.type === "U") {
739
+ if (e.size === 1) return n.getUint8(t);
740
+ if (e.size === 2) return n.getUint16(t, !0);
741
+ if (e.size === 4) return n.getUint32(t, !0);
742
+ } else {
743
+ if (e.size === 1) return n.getInt8(t);
744
+ if (e.size === 2) return n.getInt16(t, !0);
745
+ if (e.size === 4) return n.getInt32(t, !0);
746
+ }
747
+ throw new Error(`PCD: unsupported field width ${e.size} for type ${e.type}`);
748
+ }
749
+ const gt = new ArrayBuffer(4), Ht = new Float32Array(gt), Wt = new Uint32Array(gt);
750
+ function Gt(n, t) {
751
+ return t.type === "F" ? (Ht[0] = Number(n), Wt[0]) : Number(n) >>> 0;
752
+ }
753
+ function jt(n) {
754
+ let t = 1 / 0, e = 1 / 0, o = 1 / 0, r = -1 / 0, a = -1 / 0, l = -1 / 0;
755
+ for(let c = 0; c < n.length; c += 3){
756
+ const i = n[c], s = n[c + 1], u = n[c + 2];
757
+ i < t && (t = i), i > r && (r = i), s < e && (e = s), s > a && (a = s), u < o && (o = u), u > l && (l = u);
758
+ }
759
+ return {
760
+ min: [
761
+ t,
762
+ e,
763
+ o
764
+ ],
765
+ max: [
766
+ r,
767
+ a,
768
+ l
769
+ ]
770
+ };
771
+ }
772
+ class Kt {
773
+ blob;
774
+ downsample;
775
+ label;
776
+ chunk = null;
777
+ served = !1;
778
+ constructor(t, e = {}){
779
+ this.blob = t, this.downsample = e.downsample ?? {
780
+ stride: 1
781
+ }, this.label = e.label;
782
+ }
783
+ async open(t) {
784
+ q(t);
785
+ const e = await this.blob.arrayBuffer();
786
+ q(t);
787
+ const o = Nt(new Uint8Array(e));
788
+ return this.chunk = Jt(o, this.downsample.stride), {
789
+ totalPointCount: this.chunk.pointCount,
790
+ bbox: this.chunk.bbox,
791
+ hasColor: !!this.chunk.colors,
792
+ hasClassification: !!this.chunk.classifications,
793
+ hasIntensity: !!this.chunk.intensities,
794
+ label: this.label
795
+ };
796
+ }
797
+ async next(t, e) {
798
+ return q(e), !this.chunk || this.served ? null : (this.served = !0, this.chunk);
799
+ }
800
+ close() {
801
+ this.chunk = null, this.served = !1;
802
+ }
803
+ }
804
+ function Jt(n, t) {
805
+ const e = Math.max(1, t | 0);
806
+ if (e === 1) return n;
807
+ const o = Math.ceil(n.pointCount / e), r = new Float32Array(o * 3), a = n.colors ? new Float32Array(o * 3) : void 0, l = n.classifications ? new Uint8Array(o) : void 0, c = n.intensities ? new Uint16Array(o) : void 0;
808
+ let i = 0;
809
+ for(let s = 0; s < n.pointCount; s += e)r[i * 3] = n.positions[s * 3], r[i * 3 + 1] = n.positions[s * 3 + 1], r[i * 3 + 2] = n.positions[s * 3 + 2], a && n.colors && (a[i * 3] = n.colors[s * 3], a[i * 3 + 1] = n.colors[s * 3 + 1], a[i * 3 + 2] = n.colors[s * 3 + 2]), l && n.classifications && (l[i] = n.classifications[s]), c && n.intensities && (c[i] = n.intensities[s]), i++;
810
+ return {
811
+ positions: r,
812
+ colors: a,
813
+ classifications: l,
814
+ intensities: c,
815
+ pointCount: o,
816
+ bbox: n.bbox
817
+ };
818
+ }
819
+ function q(n) {
820
+ if (n?.aborted) throw new DOMException("Aborted", "AbortError");
821
+ }
822
+ function Qt(n) {
823
+ const t = {
824
+ name: "",
825
+ attrs: new Map,
826
+ children: [],
827
+ text: ""
828
+ }, e = [
829
+ t
830
+ ];
831
+ let o = 0;
832
+ const r = n.length;
833
+ let a = -1;
834
+ const l = (c)=>{
835
+ if (a < 0 || a >= c) {
836
+ a = -1;
837
+ return;
838
+ }
839
+ const i = n.slice(a, c).trim();
840
+ if (i.length > 0) {
841
+ const s = e[e.length - 1];
842
+ s.children.length === 0 && (s.text = s.text + bt(i));
843
+ }
844
+ a = -1;
845
+ };
846
+ for(; o < r;){
847
+ if (n.charCodeAt(o) !== 60) {
848
+ a < 0 && (a = o), o++;
849
+ continue;
850
+ }
851
+ if (l(o), n.startsWith("<?", o)) {
852
+ const m = n.indexOf("?>", o + 2);
853
+ o = m < 0 ? r : m + 2;
854
+ continue;
855
+ }
856
+ if (n.startsWith("<!--", o)) {
857
+ const m = n.indexOf("-->", o + 4);
858
+ o = m < 0 ? r : m + 3;
859
+ continue;
860
+ }
861
+ if (n.startsWith("<![CDATA[", o)) {
862
+ const m = n.indexOf("]]>", o + 9), w = n.slice(o + 9, m < 0 ? r : m), b = e[e.length - 1];
863
+ b.children.length === 0 && (b.text = b.text + w), o = m < 0 ? r : m + 3;
864
+ continue;
865
+ }
866
+ if (n.startsWith("<!", o)) {
867
+ const m = n.indexOf(">", o + 2);
868
+ o = m < 0 ? r : m + 1;
869
+ continue;
870
+ }
871
+ if (n.charCodeAt(o + 1) === 47) {
872
+ const m = n.indexOf(">", o + 2);
873
+ if (m < 0) throw new Error("XML: unterminated closing tag");
874
+ const w = n.slice(o + 2, m).trim(), b = e[e.length - 1];
875
+ if (b.name !== w) throw new Error(`XML: mismatched closing tag </${w}> (expected </${b.name}>)`);
876
+ e.pop(), o = m + 1;
877
+ continue;
878
+ }
879
+ const i = te(n, o + 1);
880
+ if (i < 0) throw new Error("XML: unterminated tag");
881
+ let s = n.slice(o + 1, i).trim(), u = !1;
882
+ s.endsWith("/") && (u = !0, s = s.slice(0, -1).trim());
883
+ const g = s.match(/^([A-Za-z_][\w:.\-]*)/);
884
+ if (!g) {
885
+ o = i + 1;
886
+ continue;
887
+ }
888
+ const h = g[1], p = s.slice(h.length).trim(), f = ee(p), d = {
889
+ name: h,
890
+ attrs: f,
891
+ children: [],
892
+ text: ""
893
+ };
894
+ e.length === 1 && t.name === "" ? (t.name = h, t.attrs = f, u || e.push(t)) : (e[e.length - 1].children.push(d), u || e.push(d)), o = i + 1;
895
+ }
896
+ if (l(r), e.length !== 1) throw new Error(`XML: unclosed tag <${e[e.length - 1].name}>`);
897
+ if (t.name === "") throw new Error("XML: missing root element");
898
+ return t;
899
+ }
900
+ function te(n, t) {
901
+ let e = !1;
902
+ for(let o = t; o < n.length; o++){
903
+ const r = n.charCodeAt(o);
904
+ if (r === 34) e = !e;
905
+ else if (r === 62 && !e) return o;
906
+ }
907
+ return -1;
908
+ }
909
+ const it = /([A-Za-z_][\w:.\-]*)\s*=\s*"([^"]*)"/g;
910
+ function ee(n) {
911
+ const t = new Map;
912
+ if (!n) return t;
913
+ let e;
914
+ for(it.lastIndex = 0; (e = it.exec(n)) !== null;)t.set(e[1], bt(e[2]));
915
+ return t;
916
+ }
917
+ function bt(n) {
918
+ return n.indexOf("&") < 0 ? n : n.replace(/&lt;/g, "<").replace(/&gt;/g, ">").replace(/&quot;/g, '"').replace(/&apos;/g, "'").replace(/&#(\d+);/g, (t, e)=>String.fromCharCode(parseInt(e, 10))).replace(/&#x([0-9a-fA-F]+);/g, (t, e)=>String.fromCharCode(parseInt(e, 16))).replace(/&amp;/g, "&");
919
+ }
920
+ function R(n, t) {
921
+ for (const e of n.children)if (e.name === t) return e;
922
+ return null;
923
+ }
924
+ function ne(n, t) {
925
+ return n.children.filter((e)=>e.name === t);
926
+ }
927
+ function st(n, t) {
928
+ const e = R(n, t);
929
+ if (!e) return null;
930
+ const o = e.text.trim();
931
+ return o.length > 0 ? o : null;
932
+ }
933
+ const at = "ASTM-E57";
934
+ function oe(n) {
935
+ if (n.length < 48) throw new Error("E57: header truncated (need 48 bytes)");
936
+ const t = String.fromCharCode(...n.subarray(0, 8));
937
+ if (t !== at) throw new Error(`E57: bad magic "${t}" (expected "${at}")`);
938
+ const e = new DataView(n.buffer, n.byteOffset, n.byteLength);
939
+ return {
940
+ majorVersion: e.getUint32(8, !0),
941
+ minorVersion: e.getUint32(12, !0),
942
+ fileLogicalSize: O(e, 16),
943
+ xmlLogicalOffset: j(O(e, 24), O(e, 40)),
944
+ xmlLogicalLength: O(e, 32),
945
+ pageSize: O(e, 40)
946
+ };
947
+ }
948
+ function re(n, t) {
949
+ if (t <= 4) throw new Error("E57: pageSize too small");
950
+ const e = t - 4, o = Math.floor(n.length / t), r = n.length - o * t, a = new Uint8Array(o * e + Math.max(0, r - 4));
951
+ let l = 0;
952
+ for(let c = 0; c < o; c++){
953
+ const i = c * t;
954
+ a.set(n.subarray(i, i + e), l), l += e;
955
+ }
956
+ if (r > 4) {
957
+ const c = o * t;
958
+ a.set(n.subarray(c, c + r - 4), l);
959
+ }
960
+ return a;
961
+ }
962
+ function j(n, t) {
963
+ const e = t - 4, o = Math.floor(n / t), r = n - o * t;
964
+ return o * e + r;
965
+ }
966
+ function ie(n, t, e) {
967
+ const o = j(t, e);
968
+ if (o + 32 > n.length) throw new Error(`E57: CompressedVector section header at logical ${o} runs past end of file (length ${n.length})`);
969
+ const r = new DataView(n.buffer, n.byteOffset + o, 32), a = r.getUint8(0);
970
+ if (a !== 1) throw new Error(`E57: expected CompressedVector section (id=1) at physical ${t}, got id=${a}`);
971
+ const l = O(r, 16);
972
+ return j(l, e);
973
+ }
974
+ const se = new TextDecoder;
975
+ function ae(n) {
976
+ const t = Qt(n);
977
+ if (t.name !== "e57Root") throw new Error(`E57: XML root is not <e57Root> (saw <${t.name || "?"}>)`);
978
+ const e = R(t, "data3D");
979
+ if (!e) return [];
980
+ const o = [];
981
+ for (const r of ne(e, "vectorChild")){
982
+ const a = R(r, "points");
983
+ if (!a || a.attrs.get("type") !== "CompressedVector") continue;
984
+ const l = a.attrs.get("fileOffset"), c = a.attrs.get("recordCount");
985
+ if (!l || !c) continue;
986
+ const i = R(a, "prototype");
987
+ if (!i) continue;
988
+ const s = [];
989
+ for (const u of i.children){
990
+ const g = u.attrs.get("type") ?? "";
991
+ g === "Float" ? s.push({
992
+ name: u.name,
993
+ kind: "Float",
994
+ precision: u.attrs.get("precision") === "single" ? "single" : "double"
995
+ }) : g === "ScaledInteger" ? s.push({
996
+ name: u.name,
997
+ kind: "ScaledInteger",
998
+ scale: Number(u.attrs.get("scale") ?? "1"),
999
+ offset: Number(u.attrs.get("offset") ?? "0"),
1000
+ minimum: Number(u.attrs.get("minimum") ?? "0"),
1001
+ maximum: Number(u.attrs.get("maximum") ?? "0")
1002
+ }) : g === "Integer" && s.push({
1003
+ name: u.name,
1004
+ kind: "Integer",
1005
+ minimum: Number(u.attrs.get("minimum") ?? "0"),
1006
+ maximum: Number(u.attrs.get("maximum") ?? "0")
1007
+ });
1008
+ }
1009
+ o.push({
1010
+ guid: st(r, "guid") ?? "",
1011
+ name: st(r, "name") ?? void 0,
1012
+ recordCount: Number(c),
1013
+ binaryFileOffset: Number(l),
1014
+ prototype: s,
1015
+ hasPose: R(r, "pose") !== null
1016
+ });
1017
+ }
1018
+ return o;
1019
+ }
1020
+ function ce(n, t) {
1021
+ const e = U(t.prototype, "cartesianX"), o = U(t.prototype, "cartesianY"), r = U(t.prototype, "cartesianZ");
1022
+ if (!e || !o || !r) throw new Error("E57: prototype missing cartesianX/Y/Z");
1023
+ for (const m of [
1024
+ e,
1025
+ o,
1026
+ r
1027
+ ])if (m.kind !== "Float") throw new Error(`E57: cartesianX/Y/Z encoded as ${m.kind} (only Float supported in this build)`);
1028
+ const a = U(t.prototype, "colorRed"), l = U(t.prototype, "colorGreen"), c = U(t.prototype, "colorBlue"), i = !!(a && l && c), s = U(t.prototype, "intensity");
1029
+ if (s && s.kind === "ScaledInteger") throw new Error("E57: intensity encoded as ScaledInteger (bit-packed integer codec not yet supported)");
1030
+ const u = new Float32Array(t.recordCount * 3), g = i ? new Float32Array(t.recordCount * 3) : void 0, h = s && (s.kind === "Float" || s.kind === "Integer") ? new Uint16Array(t.recordCount) : void 0;
1031
+ let p = t.binaryFileOffset;
1032
+ const f = new DataView(n.buffer, n.byteOffset, n.byteLength);
1033
+ let d = 0;
1034
+ for(; d < t.recordCount && p < n.length;){
1035
+ if (p + 4 > n.length) throw new Error("E57: truncated DataPacket header");
1036
+ const m = f.getUint8(p), w = f.getUint16(p + 2, !0) + 1;
1037
+ if (m !== 1) {
1038
+ p += w;
1039
+ continue;
1040
+ }
1041
+ const b = p + w;
1042
+ if (b > n.length) throw new Error("E57: DataPacket runs past end of logical bytes");
1043
+ const C = f.getUint16(p + 4, !0);
1044
+ if (C !== t.prototype.length) throw new Error(`E57: packet bytestreamCount (${C}) ≠ prototype length (${t.prototype.length})`);
1045
+ const F = [];
1046
+ let E = p + 6;
1047
+ for(let y = 0; y < C; y++)F.push(f.getUint16(E, !0)), E += 2;
1048
+ const x = new Map;
1049
+ let L = E;
1050
+ for(let y = 0; y < C; y++)x.set(t.prototype[y].name, {
1051
+ start: L,
1052
+ length: F[y]
1053
+ }), L += F[y];
1054
+ const A = e.precision === "single" ? 4 : 8, Z = o.precision === "single" ? 4 : 8, yt = r.precision === "single" ? 4 : 8, k = Math.floor(x.get("cartesianX").length / A);
1055
+ if (k !== Math.floor(x.get("cartesianY").length / Z) || k !== Math.floor(x.get("cartesianZ").length / yt)) throw new Error("E57: cartesianX/Y/Z bytestream lengths disagree on point count");
1056
+ const I = Math.min(k, t.recordCount - d), Q = x.get("cartesianX").start, tt = x.get("cartesianY").start, et = x.get("cartesianZ").start;
1057
+ if (e.precision === "single") for(let y = 0; y < I; y++)u[(d + y) * 3] = f.getFloat32(Q + y * 4, !0);
1058
+ else for(let y = 0; y < I; y++)u[(d + y) * 3] = f.getFloat64(Q + y * 8, !0);
1059
+ if (o.precision === "single") for(let y = 0; y < I; y++)u[(d + y) * 3 + 1] = f.getFloat32(tt + y * 4, !0);
1060
+ else for(let y = 0; y < I; y++)u[(d + y) * 3 + 1] = f.getFloat64(tt + y * 8, !0);
1061
+ if (r.precision === "single") for(let y = 0; y < I; y++)u[(d + y) * 3 + 2] = f.getFloat32(et + y * 4, !0);
1062
+ else for(let y = 0; y < I; y++)u[(d + y) * 3 + 2] = f.getFloat64(et + y * 8, !0);
1063
+ if (g && a && l && c && (H(f, x.get("colorRed").start, a, g, d, I, 0), H(f, x.get("colorGreen").start, l, g, d, I, 1), H(f, x.get("colorBlue").start, c, g, d, I, 2)), h && s) {
1064
+ const y = x.get("intensity").start;
1065
+ if (s.kind === "Float") {
1066
+ const P = s.precision === "single" ? 4 : 8;
1067
+ for(let S = 0; S < I; S++){
1068
+ const T = P === 4 ? f.getFloat32(y + S * P, !0) : f.getFloat64(y + S * P, !0);
1069
+ h[d + S] = Math.min(65535, Math.max(0, Math.round(T * 65535)));
1070
+ }
1071
+ } else {
1072
+ const P = s.minimum ?? 0, S = s.maximum ?? 65535, T = S - P, xt = T > 0 ? 1 / T : 1, nt = Math.max(Math.abs(P), Math.abs(S)) > 255 ? 2 : 1, ot = P < 0;
1073
+ for(let Y = 0; Y < I; Y++){
1074
+ const v = y + Y * nt, Ct = ((nt === 2 ? ot ? f.getInt16(v, !0) : f.getUint16(v, !0) : ot ? f.getInt8(v) : f.getUint8(v)) - P) * xt;
1075
+ h[d + Y] = Math.min(65535, Math.max(0, Math.round(Ct * 65535)));
1076
+ }
1077
+ }
1078
+ }
1079
+ d += I, p = b;
1080
+ }
1081
+ return d < t.recordCount ? ct(u.subarray(0, d * 3), g?.subarray(0, d * 3), h?.subarray(0, d), d) : ct(u, g, h, t.recordCount);
1082
+ }
1083
+ function H(n, t, e, o, r, a, l) {
1084
+ if (e.kind === "Float") {
1085
+ const c = e.precision === "single" ? 4 : 8;
1086
+ for(let i = 0; i < a; i++){
1087
+ const s = c === 4 ? n.getFloat32(t + i * c, !0) : n.getFloat64(t + i * c, !0);
1088
+ o[(r + i) * 3 + l] = lt(s);
1089
+ }
1090
+ } else if (e.kind === "Integer") {
1091
+ const c = e.minimum ?? 0, i = e.maximum ?? 255, s = i - c, u = s > 0 ? 1 / s : 1, h = Math.max(Math.abs(c), Math.abs(i)) > 255 ? 2 : 1, p = c < 0;
1092
+ for(let f = 0; f < a; f++){
1093
+ const d = t + f * h, m = h === 2 ? p ? n.getInt16(d, !0) : n.getUint16(d, !0) : p ? n.getInt8(d) : n.getUint8(d);
1094
+ o[(r + f) * 3 + l] = lt((m - c) * u);
1095
+ }
1096
+ } else throw new Error("E57: ScaledInteger color encoding not yet supported");
1097
+ }
1098
+ function ct(n, t, e, o) {
1099
+ return {
1100
+ positions: new Float32Array(n),
1101
+ colors: t ? new Float32Array(t) : void 0,
1102
+ intensities: e ? new Uint16Array(e) : void 0,
1103
+ pointCount: o,
1104
+ bbox: wt(n)
1105
+ };
1106
+ }
1107
+ function U(n, t) {
1108
+ return n.find((e)=>e.name === t);
1109
+ }
1110
+ function O(n, t) {
1111
+ const e = n.getUint32(t, !0);
1112
+ return n.getUint32(t + 4, !0) * 4294967296 + e;
1113
+ }
1114
+ function lt(n) {
1115
+ return n < 0 ? 0 : n > 1 ? 1 : n;
1116
+ }
1117
+ function wt(n) {
1118
+ let t = 1 / 0, e = 1 / 0, o = 1 / 0, r = -1 / 0, a = -1 / 0, l = -1 / 0;
1119
+ for(let c = 0; c < n.length; c += 3){
1120
+ const i = n[c], s = n[c + 1], u = n[c + 2];
1121
+ i < t && (t = i), i > r && (r = i), s < e && (e = s), s > a && (a = s), u < o && (o = u), u > l && (l = u);
1122
+ }
1123
+ return {
1124
+ min: [
1125
+ t,
1126
+ e,
1127
+ o
1128
+ ],
1129
+ max: [
1130
+ r,
1131
+ a,
1132
+ l
1133
+ ]
1134
+ };
1135
+ }
1136
+ function le(n) {
1137
+ const t = oe(n), e = re(n, t.pageSize), o = e.subarray(t.xmlLogicalOffset, t.xmlLogicalOffset + t.xmlLogicalLength), r = se.decode(o), a = ae(r);
1138
+ if (a.length === 0) return null;
1139
+ if (a.length > 1 && a.some((f)=>f.hasPose)) throw new Error(`E57: file contains ${a.length} scans with per-scan poses (registered multi-scan). Multi-scan pose merging is not yet supported — please re-export as a single merged scan.`);
1140
+ const l = a.map((f)=>{
1141
+ const d = ie(e, f.binaryFileOffset, t.pageSize);
1142
+ return ce(e, {
1143
+ ...f,
1144
+ binaryFileOffset: d
1145
+ });
1146
+ });
1147
+ if (l.length === 1) return l[0];
1148
+ let c = 0;
1149
+ for (const f of l)c += f.pointCount;
1150
+ const i = new Float32Array(c * 3), s = l.some((f)=>f.colors), u = l.some((f)=>f.intensities), g = s ? new Float32Array(c * 3) : void 0, h = u ? new Uint16Array(c) : void 0;
1151
+ let p = 0;
1152
+ for (const f of l)i.set(f.positions, p * 3), g && f.colors && g.set(f.colors, p * 3), h && f.intensities && h.set(f.intensities, p), p += f.pointCount;
1153
+ return {
1154
+ positions: i,
1155
+ colors: g,
1156
+ intensities: h,
1157
+ pointCount: c,
1158
+ bbox: wt(i)
1159
+ };
1160
+ }
1161
+ class fe {
1162
+ blob;
1163
+ downsample;
1164
+ label;
1165
+ chunk = null;
1166
+ served = !1;
1167
+ constructor(t, e = {}){
1168
+ this.blob = t, this.downsample = e.downsample ?? {
1169
+ stride: 1
1170
+ }, this.label = e.label;
1171
+ }
1172
+ async open(t) {
1173
+ W(t);
1174
+ const e = await this.blob.arrayBuffer();
1175
+ W(t);
1176
+ const o = le(new Uint8Array(e));
1177
+ if (!o) throw new Error("E57: file contains no Data3D scans");
1178
+ return this.chunk = ue(o, this.downsample.stride), {
1179
+ totalPointCount: this.chunk.pointCount,
1180
+ bbox: this.chunk.bbox,
1181
+ hasColor: !!this.chunk.colors,
1182
+ hasClassification: !1,
1183
+ hasIntensity: !!this.chunk.intensities,
1184
+ label: this.label
1185
+ };
1186
+ }
1187
+ async next(t, e) {
1188
+ return W(e), !this.chunk || this.served ? null : (this.served = !0, this.chunk);
1189
+ }
1190
+ close() {
1191
+ this.chunk = null, this.served = !1;
1192
+ }
1193
+ }
1194
+ function ue(n, t) {
1195
+ const e = Math.max(1, t | 0);
1196
+ if (e === 1) return n;
1197
+ const o = Math.ceil(n.pointCount / e), r = new Float32Array(o * 3), a = n.colors ? new Float32Array(o * 3) : void 0, l = n.intensities ? new Uint16Array(o) : void 0;
1198
+ let c = 0;
1199
+ for(let i = 0; i < n.pointCount; i += e)r[c * 3] = n.positions[i * 3], r[c * 3 + 1] = n.positions[i * 3 + 1], r[c * 3 + 2] = n.positions[i * 3 + 2], a && n.colors && (a[c * 3] = n.colors[i * 3], a[c * 3 + 1] = n.colors[i * 3 + 1], a[c * 3 + 2] = n.colors[i * 3 + 2]), l && n.intensities && (l[c] = n.intensities[i]), c++;
1200
+ return {
1201
+ positions: r,
1202
+ colors: a,
1203
+ intensities: l,
1204
+ pointCount: o,
1205
+ bbox: n.bbox
1206
+ };
1207
+ }
1208
+ function W(n) {
1209
+ if (n?.aborted) throw new DOMException("Aborted", "AbortError");
1210
+ }
1211
+ const _ = new Map;
1212
+ let de = 1;
1213
+ self.onmessage = (n)=>{
1214
+ const t = n.data;
1215
+ switch(t.kind){
1216
+ case "open":
1217
+ he(t);
1218
+ return;
1219
+ case "next":
1220
+ pe(t);
1221
+ return;
1222
+ case "close":
1223
+ me(t.sourceId);
1224
+ return;
1225
+ case "abort":
1226
+ ge(t.sourceId);
1227
+ return;
1228
+ }
1229
+ };
1230
+ async function he(n) {
1231
+ try {
1232
+ const t = be(n.format, n.blob, {
1233
+ label: n.label,
1234
+ downsample: {
1235
+ stride: Math.max(1, n.stride | 0)
1236
+ }
1237
+ }), e = new AbortController, o = await t.open(e.signal), r = de++;
1238
+ _.set(r, {
1239
+ source: t,
1240
+ abort: e
1241
+ }), D({
1242
+ kind: "opened",
1243
+ requestId: n.requestId,
1244
+ sourceId: r,
1245
+ info: o
1246
+ });
1247
+ } catch (t) {
1248
+ D({
1249
+ kind: "error",
1250
+ requestId: n.requestId,
1251
+ message: J(t)
1252
+ });
1253
+ }
1254
+ }
1255
+ async function pe(n) {
1256
+ const t = _.get(n.sourceId);
1257
+ if (!t) {
1258
+ D({
1259
+ kind: "error",
1260
+ requestId: n.requestId,
1261
+ message: `Unknown sourceId ${n.sourceId}`
1262
+ });
1263
+ return;
1264
+ }
1265
+ try {
1266
+ const e = await t.source.next(n.maxPoints, t.abort.signal);
1267
+ if (!e) {
1268
+ D({
1269
+ kind: "chunk",
1270
+ requestId: n.requestId,
1271
+ sourceId: n.sourceId,
1272
+ chunk: null
1273
+ });
1274
+ return;
1275
+ }
1276
+ const { payload: o, transfer: r } = Et(e);
1277
+ D({
1278
+ kind: "chunk",
1279
+ requestId: n.requestId,
1280
+ sourceId: n.sourceId,
1281
+ chunk: o
1282
+ }, r);
1283
+ } catch (e) {
1284
+ D({
1285
+ kind: "error",
1286
+ requestId: n.requestId,
1287
+ message: J(e)
1288
+ });
1289
+ }
1290
+ }
1291
+ function me(n) {
1292
+ const t = _.get(n);
1293
+ if (t) {
1294
+ try {
1295
+ t.abort.abort(), t.source.close();
1296
+ } catch (e) {
1297
+ console.warn("[decode-worker] close failed:", J(e));
1298
+ }
1299
+ _.delete(n);
1300
+ }
1301
+ }
1302
+ function ge(n) {
1303
+ const t = _.get(n);
1304
+ t && t.abort.abort();
1305
+ }
1306
+ function be(n, t, e) {
1307
+ if (n === "las") return new Ut(t, e);
1308
+ if (n === "laz") return new Ot(t, e);
1309
+ if (n === "ply") return new Tt(t, e);
1310
+ if (n === "pcd") return new Kt(t, e);
1311
+ if (n === "e57") return new fe(t, e);
1312
+ throw new Error(`decode-worker: unknown format "${n}"`);
1313
+ }
1314
+ function D(n, t = []) {
1315
+ self.postMessage(n, t);
1316
+ }
1317
+ function J(n) {
1318
+ return n instanceof Error ? n.message : String(n);
1319
+ }
1320
+ })();