@solid-labs/fab-one-widget 0.1.12 → 1.0.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.
@@ -1,4823 +0,0 @@
1
- import { jsxs as F, jsx as i, Fragment as Oe } from "react/jsx-runtime";
2
- import { createContext as Zn, Component as Kn, useCallback as re, useMemo as j, useState as E, memo as Un, useEffect as ne, useRef as le, forwardRef as Jn, createElement as en } from "react";
3
- import { useFrame as an, useThree as cn, Canvas as Qn } from "@react-three/fiber";
4
- import { Html as Xe, Line as fe, OrbitControls as dn } from "@react-three/drei";
5
- import * as O from "three";
6
- import { Plane as ut, Vector3 as C, Box3 as fn, Line3 as un, Raycaster as qn } from "three";
7
- import { create as eo } from "zustand";
8
- import { OBJLoader as pn } from "three/examples/jsm/loaders/OBJLoader.js";
9
- import { STLLoader as to } from "three/examples/jsm/loaders/STLLoader.js";
10
- import { MeshBVH as pt } from "three-mesh-bvh";
11
- let mr, ct, ir, Cn;
12
- let __tla = (async () => {
13
- const no = {
14
- showDragDrop: true,
15
- showStartOver: true,
16
- showDebug: true,
17
- showSpacingToggle: true,
18
- showAmputationModal: true,
19
- showNavigation: true,
20
- showToolbar: false,
21
- showSaveButton: true
22
- }, oo = {
23
- showDragDrop: false,
24
- showStartOver: false,
25
- showDebug: false,
26
- showSpacingToggle: false,
27
- showAmputationModal: false,
28
- showNavigation: false,
29
- showToolbar: false,
30
- showSaveButton: false
31
- }, ro = Zn(no), Dt = eo((e, r) => ({
32
- landmarkPoints: [],
33
- isAligned: false,
34
- isCut: false,
35
- addLandmarkPoint: (t) => e((o) => o.landmarkPoints.length >= 3 ? o : {
36
- landmarkPoints: [
37
- ...o.landmarkPoints,
38
- t
39
- ]
40
- }),
41
- removeLandmarkPoint: (t) => e((o) => ({
42
- landmarkPoints: o.landmarkPoints.filter((l, s) => s !== t)
43
- })),
44
- clearLandmarkPoints: () => e({
45
- landmarkPoints: [],
46
- isAligned: false,
47
- isCut: false
48
- }),
49
- updateLandmarkPositions: (t) => e((o) => ({
50
- landmarkPoints: o.landmarkPoints.map((l, s) => ({
51
- ...l,
52
- position: t[s] ?? l.position
53
- }))
54
- })),
55
- setAligned: (t) => e({
56
- isAligned: t
57
- }),
58
- setCut: (t) => e({
59
- isCut: t
60
- }),
61
- isSelectionComplete: () => r().landmarkPoints.length === 3,
62
- reset: () => e({
63
- landmarkPoints: [],
64
- isAligned: false,
65
- isCut: false
66
- })
67
- })), io = 0.45, ht = 3, _t = 1e-3, dt = 25.4, so = [
68
- 0.25,
69
- -0.25,
70
- 0.5,
71
- -0.5
72
- ];
73
- function lo(e) {
74
- var _a;
75
- const r = e.match(/^v\s+\S+\s+\S+\s+\S+(.*)$/m);
76
- if (!r || !((_a = r[1]) == null ? void 0 : _a.trim().includes(" "))) return null;
77
- const t = e.split(`
78
- `), o = [], l = [];
79
- let s = false;
80
- for (const c of t) if (c.startsWith("v ")) {
81
- const a = c.trim().split(/\s+/);
82
- if (a.length >= 7) {
83
- o.push(parseFloat(a[1]), parseFloat(a[2]), parseFloat(a[3]));
84
- let n = parseFloat(a[4]), h = parseFloat(a[5]), d = parseFloat(a[6]);
85
- (n > 1 || h > 1 || d > 1) && (n /= 255, h /= 255, d /= 255), l.push(n, h, d), s = true;
86
- } else a.length >= 4 && (o.push(parseFloat(a[1]), parseFloat(a[2]), parseFloat(a[3])), l.push(0, 0, 0));
87
- }
88
- return s ? {
89
- positions: new Float32Array(o),
90
- colors: new Float32Array(l)
91
- } : null;
92
- }
93
- function ao(e, r, t, o) {
94
- const l = e.getAttribute("position"), s = l.count, c = new Float32Array(s * 3), a = r.length / 3;
95
- let n = 1 / 0, h = 1 / 0, d = 1 / 0, u = -1 / 0, p = -1 / 0, g = -1 / 0;
96
- for (let k = 0; k < a; k++) {
97
- const B = r[k * 3] * o, $ = r[k * 3 + 1] * o, N = r[k * 3 + 2] * o;
98
- B < n && (n = B), B > u && (u = B), $ < h && (h = $), $ > p && (p = $), N < d && (d = N), N > g && (g = N);
99
- }
100
- const M = (n + u) * 0.5, f = (h + p) * 0.5, m = (d + g) * 0.5, x = u - n + 1e-6, S = p - h + 1e-6, I = g - d + 1e-6, P = x * 0.5, L = S * 0.5, b = I * 0.5, z = Math.min(128, Math.max(16, Math.round(Math.cbrt(a)))), y = x / z, D = S / z, w = I / z, A = /* @__PURE__ */ new Map();
101
- for (let k = 0; k < a; k++) {
102
- const B = r[k * 3] * o - M, $ = r[k * 3 + 1] * o - f, N = r[k * 3 + 2] * o - m, U = Math.min(z - 1, Math.max(0, Math.floor((B + P) / y))), be = Math.min(z - 1, Math.max(0, Math.floor(($ + L) / D))), ae = Math.min(z - 1, Math.max(0, Math.floor((N + b) / w))), ue = U * z * z + be * z + ae;
103
- let ie = A.get(ue);
104
- ie || (ie = [], A.set(ue, ie)), ie.push(k);
105
- }
106
- for (let k = 0; k < s; k++) {
107
- const B = l.getX(k), $ = l.getY(k), N = l.getZ(k), U = Math.min(z - 1, Math.max(0, Math.floor((B + P) / y))), be = Math.min(z - 1, Math.max(0, Math.floor(($ + L) / D))), ae = Math.min(z - 1, Math.max(0, Math.floor((N + b) / w)));
108
- let ue = 1 / 0, ie = 0;
109
- for (let J = 0; J <= z && ue > 0; J++) {
110
- for (let Y = -J; Y <= J; Y++) for (let he = -J; he <= J; he++) for (let Z = -J; Z <= J; Z++) {
111
- if (J > 0 && Math.abs(Y) < J && Math.abs(he) < J && Math.abs(Z) < J) continue;
112
- const ge = U + Y, me = be + he, pe = ae + Z;
113
- if (ge < 0 || ge >= z || me < 0 || me >= z || pe < 0 || pe >= z) continue;
114
- const H = A.get(ge * z * z + me * z + pe);
115
- if (H) for (const q of H) {
116
- const xe = r[q * 3] * o - M, Ce = r[q * 3 + 1] * o - f, we = r[q * 3 + 2] * o - m, oe = (B - xe) ** 2 + ($ - Ce) ** 2 + (N - we) ** 2;
117
- oe < ue && (ue = oe, ie = q);
118
- }
119
- }
120
- if (ue < 1 / 0) break;
121
- }
122
- c[k * 3] = t[ie * 3], c[k * 3 + 1] = t[ie * 3 + 1], c[k * 3 + 2] = t[ie * 3 + 2];
123
- }
124
- e.setAttribute("color", new O.Float32BufferAttribute(c, 3));
125
- }
126
- const tn = {
127
- debug: 0,
128
- info: 1,
129
- warn: 2,
130
- error: 3
131
- };
132
- let hn = "warn", gn = null;
133
- const de = {
134
- setLevel(e) {
135
- hn = e;
136
- },
137
- setHandler(e) {
138
- gn = e;
139
- },
140
- debug(e, r, t) {
141
- at("debug", e, r, t);
142
- },
143
- info(e, r, t) {
144
- at("info", e, r, t);
145
- },
146
- warn(e, r, t) {
147
- at("warn", e, r, t);
148
- },
149
- error(e, r, t) {
150
- at("error", e, r, t);
151
- }
152
- };
153
- function at(e, r, t, o) {
154
- if (tn[e] < tn[hn]) return;
155
- const l = `[${r}]`, s = o !== void 0 ? [
156
- l,
157
- t,
158
- o
159
- ] : [
160
- l,
161
- t
162
- ];
163
- switch (e) {
164
- case "debug":
165
- console.debug(...s);
166
- break;
167
- case "info":
168
- console.log(...s);
169
- break;
170
- case "warn":
171
- console.warn(...s);
172
- break;
173
- case "error":
174
- console.error(...s);
175
- break;
176
- }
177
- gn == null ? void 0 : gn(e, r, t, o);
178
- }
179
- function ft(e) {
180
- const r = e.getAttribute("position"), t = new Float32Array(r.array), o = e.getIndex();
181
- if (o) return {
182
- positions: t,
183
- indices: new Uint32Array(o.array)
184
- };
185
- const l = t.length / 3, s = new Uint32Array(l);
186
- for (let c = 0; c < l; c++) s[c] = c;
187
- return {
188
- positions: t,
189
- indices: s
190
- };
191
- }
192
- function mn(e, r) {
193
- const t = new O.BufferGeometry();
194
- return t.setAttribute("position", new O.Float32BufferAttribute(e, 3)), t.setIndex(new O.BufferAttribute(r, 1)), t.computeVertexNormals(), t;
195
- }
196
- async function co(e, r, t) {
197
- try {
198
- const o = lo(e);
199
- t == null ? void 0 : t("Parsing mesh...");
200
- const s = new pn().parse(e);
201
- let c = null;
202
- if (s.traverse((x) => {
203
- x.isMesh && !c && (c = x.geometry);
204
- }), !c) return null;
205
- const { positions: a, indices: n } = ft(c);
206
- if (a.length < 9 || n.length < 3) return de.warn("wasm", `Mesh too small: positions=${a.length} indices=${n.length}`), null;
207
- for (let x = 0; x < Math.min(a.length, 300); x++) if (!isFinite(a[x])) return de.error("wasm", `Invalid position data: NaN/Infinity at index ${x}`), null;
208
- const h = a.length / 3;
209
- for (let x = 0; x < Math.min(n.length, 300); x++) if (n[x] >= h) return de.error("wasm", `Out-of-bounds index: ${n[x]} >= ${h}`), null;
210
- t == null ? void 0 : t("Processing mesh (WASM)...");
211
- const d = r.preprocess_mesh(a, n, 10, 1e-4, 500), u = d.positions(), p = d.indices(), g = d.unit_converted(), M = d.detected_unit(), f = d.log();
212
- if (de.debug("wasm", "preprocess result", f), u.length === 0) return null;
213
- t == null ? void 0 : t("Building geometry...");
214
- const m = mn(u, p);
215
- if (o) {
216
- const x = g ? 1e3 : 1;
217
- ao(m, o.positions, o.colors, x);
218
- }
219
- return {
220
- geometry: m,
221
- wasScaled: g,
222
- unitConverted: g,
223
- detectedUnit: M
224
- };
225
- } catch (o) {
226
- return de.error("wasm", "Processing failed", o), null;
227
- }
228
- }
229
- function fo(e) {
230
- const t = new pn().parse(e);
231
- let o = null;
232
- return t.traverse((l) => {
233
- l.isMesh && !o && (o = l.geometry);
234
- }), o;
235
- }
236
- async function Lt(e) {
237
- const r = await e.arrayBuffer(), l = new to().parse(r).getAttribute("position");
238
- if (!l || l.count === 0) throw new Error("Empty STL geometry");
239
- const s = [];
240
- for (let c = 0; c < l.count; c++) s.push(`v ${l.getX(c)} ${l.getY(c)} ${l.getZ(c)}`);
241
- for (let c = 0; c < l.count; c += 3) s.push(`f ${c + 1} ${c + 2} ${c + 3}`);
242
- return s.join(`
243
- `);
244
- }
245
- function uo(e, r) {
246
- const t = 1 / r;
247
- return `${Math.round(e.x * t)}_${Math.round(e.y * t)}_${Math.round(e.z * t)}`;
248
- }
249
- function po(e, r) {
250
- if (!e.length) return [];
251
- const t = [];
252
- for (const o of e) (t.length === 0 || t[t.length - 1].distanceTo(o) > r) && t.push(o.clone());
253
- return t.length > 2 && t[0].distanceTo(t[t.length - 1]) > r && t.push(t[0].clone()), t;
254
- }
255
- function Ke(e) {
256
- let r = 0;
257
- for (let t = 0; t < e.length - 1; t++) r += e[t].distanceTo(e[t + 1]);
258
- return r;
259
- }
260
- function xn(e, r = 1e-3, t = false) {
261
- if (!e.length) return [];
262
- const o = /* @__PURE__ */ new Map(), l = (u) => {
263
- const p = uo(u, r);
264
- let g = o.get(p);
265
- return g || (g = u.clone(), o.set(p, g)), g;
266
- }, s = e.map((u) => ({
267
- a: l(u.a),
268
- b: l(u.b)
269
- })), c = [];
270
- for (; s.length; ) {
271
- const u = s.pop(), p = [
272
- u.a,
273
- u.b
274
- ];
275
- let g = true;
276
- for (; g; ) {
277
- g = false;
278
- for (let f = s.length - 1; f >= 0; f--) {
279
- const { a: m, b: x } = s[f];
280
- if (m.equals(p[p.length - 1])) p.push(x);
281
- else if (x.equals(p[p.length - 1])) p.push(m);
282
- else if (m.equals(p[0])) p.unshift(x);
283
- else if (x.equals(p[0])) p.unshift(m);
284
- else continue;
285
- s.splice(f, 1), g = true;
286
- }
287
- }
288
- const M = po(p, r);
289
- M.length > 1 && c.push(M);
290
- }
291
- if (!c.length) return [];
292
- if (t) {
293
- c.sort((g, M) => Ke(M) - Ke(g));
294
- const u = Ke(c[0]), p = c.filter((g) => Ke(g) >= u * 0.3);
295
- return p[p.length - 1] ?? c[0];
296
- }
297
- const a = c.filter((u) => u.length >= 3 && u[0].distanceTo(u[u.length - 1]) < r * 10), n = a.length > 0 ? a : c;
298
- if (n.length === 1) return n[0];
299
- let h = n[0], d = 1 / 0;
300
- for (const u of n) {
301
- let p = 0, g = 0;
302
- for (const f of u) p += f.x, g += f.z;
303
- p /= u.length, g /= u.length;
304
- const M = Math.sqrt(p * p + g * g);
305
- M < d && (d = M, h = u);
306
- }
307
- return h;
308
- }
309
- function nn(e, r, t, o = false) {
310
- const l = new ut(new C(0, 1, 0), -t), s = [], c = new fn();
311
- c.setFromBufferAttribute(r.getAttribute("position"));
312
- const a = {
313
- linePoints: [],
314
- lineLength: 0,
315
- rightmostPoint: new C(0, t, 0)
316
- };
317
- if (!l.intersectsBox(c)) return a;
318
- const n = new un(), h = new C();
319
- e.shapecast({
320
- intersectsBounds: (f) => l.intersectsBox(f),
321
- intersectsTriangle: (f) => {
322
- const m = [];
323
- n.set(f.a, f.b), l.intersectLine(n, h) && m.push(h.clone()), n.set(f.b, f.c), l.intersectLine(n, h) && m.push(h.clone()), n.set(f.c, f.a), l.intersectLine(n, h) && m.push(h.clone()), m.length === 2 && s.push({
324
- a: m[0],
325
- b: m[1]
326
- });
327
- }
328
- });
329
- const d = xn(s, _t, o);
330
- if (d.length < 2) return a;
331
- const u = Ke(d);
332
- let p = -1 / 0, g = new C(0, t, 0);
333
- for (const f of d) f.x > p && (p = f.x, g = f.clone());
334
- const M = d.length > 2 && d[0].distanceTo(d[d.length - 1]) < _t * 10;
335
- return {
336
- linePoints: d,
337
- lineLength: u,
338
- rightmostPoint: g,
339
- isClosed: M
340
- };
341
- }
342
- function Ye(e, r, t, o = false) {
343
- const l = nn(e, r, t, o);
344
- if (l.isClosed && l.linePoints.length >= 3) return l;
345
- de.debug("slice", `y=${t.toFixed(2)} failed (pts=${l.linePoints.length}, closed=${l.isClosed}), retrying...`);
346
- let s = l;
347
- for (const c of so) {
348
- const a = nn(e, r, t + c, o);
349
- if (a.isClosed && a.linePoints.length >= 3) return de.debug("slice", `y=${t.toFixed(2)} recovered with offset ${c > 0 ? "+" : ""}${c}mm (pts=${a.linePoints.length}, len=${a.lineLength.toFixed(1)}mm)`), a;
350
- a.linePoints.length > s.linePoints.length && (s = a);
351
- }
352
- return de.warn("slice", `y=${t.toFixed(2)} all retries exhausted (pts=${s.linePoints.length}, closed=${s.isClosed})`), s;
353
- }
354
- function ho(e, r, t, o) {
355
- const l = new ut().setFromNormalAndCoplanarPoint(o.clone().normalize(), t), s = new fn();
356
- if (s.setFromBufferAttribute(r.getAttribute("position")), !l.intersectsBox(s)) return 0;
357
- const c = [], a = new un(), n = new C();
358
- e.shapecast({
359
- intersectsBounds: (d) => l.intersectsBox(d),
360
- intersectsTriangle: (d) => {
361
- const u = [];
362
- a.set(d.a, d.b), l.intersectLine(a, n) && u.push(n.clone()), a.set(d.b, d.c), l.intersectLine(a, n) && u.push(n.clone()), a.set(d.c, d.a), l.intersectLine(a, n) && u.push(n.clone()), u.length === 2 && c.push({
363
- a: u[0],
364
- b: u[1]
365
- });
366
- }
367
- });
368
- const h = xn(c, _t);
369
- return Ke(h);
370
- }
371
- function yn(e) {
372
- return new pt(e, {
373
- maxLeafTris: ht
374
- });
375
- }
376
- function go(e, r, t, o) {
377
- const l = e.getIndex(), s = l ? l.count / 3 : 0;
378
- if (s < 10) return {
379
- valid: false,
380
- reason: `Geometry is empty or degenerate (${s} faces)`
381
- };
382
- const c = r - t;
383
- if (c < 4) return {
384
- valid: false,
385
- reason: `Height too small (${c.toFixed(1)}mm < 4mm)`
386
- };
387
- if (c > 1e3) return {
388
- valid: false,
389
- reason: `Height too large (${c.toFixed(1)}mm > 1000mm)`
390
- };
391
- const a = new pt(e, {
392
- maxLeafTris: ht
393
- }), n = Ye(a, e, r);
394
- if (n.lineLength === 0) return {
395
- valid: false,
396
- reason: "No circumference at green point \u2014 mesh may be empty at that height"
397
- };
398
- const h = r - o;
399
- if (h <= t) return {
400
- valid: true,
401
- reason: ""
402
- };
403
- const d = Ye(a, e, h);
404
- if (n.lineLength > 0 && d.lineLength > 0) {
405
- const p = n.lineLength / d.lineLength;
406
- if (p < 0.5) return {
407
- valid: false,
408
- reason: `First circumference is too small relative to second (ratio ${p.toFixed(2)} < 0.5) \u2014 possible trimmed angle`
409
- };
410
- }
411
- const u = r - o * 2;
412
- if (u > t) {
413
- const p = Ye(a, e, u);
414
- if (d.lineLength > 0 && p.lineLength > 0) {
415
- const g = d.lineLength / p.lineLength;
416
- if (g < 0.5) return {
417
- valid: false,
418
- reason: `Second circumference is too small relative to third (ratio ${g.toFixed(2)} < 0.5) \u2014 possible trimmed angle`
419
- };
420
- }
421
- }
422
- return {
423
- valid: true,
424
- reason: ""
425
- };
426
- }
427
- const Fe = "pipeline";
428
- function mo(e, r, t, o) {
429
- var _a, _b, _c, _d;
430
- const l = e.geometry.clone(), s = r.map((a) => ({
431
- ...a
432
- })), c = o.wasmModule;
433
- try {
434
- let a = e.geometry, n = s.map((H) => new C(H.position.x, H.position.y, H.position.z));
435
- const h = n[0], d = n[1];
436
- if (!c) {
437
- o.onStatus("Aligning mesh (JS fallback)..."), de.warn(Fe, "WASM not available, using JS fallback alignment");
438
- const H = new C(0, 1, 0), q = new C().subVectors(d, h).normalize(), xe = q.dot(H), Ce = new C().crossVectors(q, H);
439
- if (Ce.length() > 1e-4) {
440
- Ce.normalize();
441
- const X = new O.Quaternion().setFromAxisAngle(Ce, Math.acos(Math.min(1, Math.max(-1, xe))));
442
- a.applyMatrix4(new O.Matrix4().makeRotationFromQuaternion(X)), n = n.map((Pe) => Pe.clone().applyQuaternion(X));
443
- }
444
- if (n[0].y > n[1].y) {
445
- const X = new O.Quaternion().setFromAxisAngle(new C(1, 0, 0), Math.PI);
446
- a.applyMatrix4(new O.Matrix4().makeRotationFromQuaternion(X)), n = n.map((Pe) => Pe.clone().applyQuaternion(X));
447
- }
448
- const we = n[0].clone();
449
- a.translate(-we.x, -we.y, -we.z), n = n.map((X) => new C(X.x - we.x, X.y - we.y, X.z - we.z)), a.computeVertexNormals(), a.computeBoundingBox();
450
- const oe = new C(n[0].x, n[0].y, n[0].z);
451
- n.push(oe), o.addLandmarkPoint({
452
- faceIndex: -1,
453
- vertexIndices: [
454
- 0,
455
- 1,
456
- 2
457
- ],
458
- position: {
459
- x: oe.x,
460
- y: oe.y,
461
- z: oe.z
462
- },
463
- barycentricCoords: {
464
- u: 0.33,
465
- v: 0.33,
466
- w: 0.34
467
- }
468
- }), o.updateLandmarkPositions(n.map((X) => ({
469
- x: X.x,
470
- y: X.y,
471
- z: X.z
472
- }))), o.setAligned(true), o.setCut(true), o.setAdjustedStartY(null), o.setAdjustedEndY(null), o.setOriginalEndY(n[1].y + 2 * dt);
473
- const V = new C();
474
- a.computeBoundingBox(), a.boundingBox.getSize(V), o.setModelSize(Math.max(V.x, V.y, V.z)), l.dispose();
475
- return;
476
- }
477
- const { positions: u, indices: p } = ft(a), g = new Float32Array([
478
- h.x,
479
- h.y,
480
- h.z
481
- ]), M = new Float32Array([
482
- d.x,
483
- d.y,
484
- d.z
485
- ]);
486
- o.onStatus("Detecting shell type...");
487
- const f = c.detect_shell(u, p, M, 40), m = f.is_double_shell(), x = f.surface_normal();
488
- de.info(Fe, `Shell: ${m ? "DOUBLE" : "SINGLE"}`, f.details()), (_a = o.setDoubleShell) == null ? void 0 : _a.call(o, m), o.onStatus("Finding cross-section plane...");
489
- const S = new Float32Array([
490
- x[0],
491
- x[1],
492
- x[2]
493
- ]), I = c.find_min_cross_section(u, p, M, S, 10), P = I.plane_normal();
494
- de.info(Fe, "Cross-section found", I.details()), o.onStatus("Aligning mesh...");
495
- const L = new Float32Array([
496
- P[0],
497
- P[1],
498
- P[2]
499
- ]), b = c.align_to_origin(u, g, M, L);
500
- let z = b.positions(), y = b.mpt(), D = b.origin();
501
- const w = b.transform();
502
- de.info(Fe, "Alignment complete", b.details());
503
- const A = [
504
- w[3],
505
- w[4],
506
- w[5],
507
- w[6],
508
- w[7],
509
- w[8],
510
- w[9],
511
- w[10],
512
- w[11]
513
- ], k = new Float32Array([
514
- A[0] * P[0] + A[1] * P[1] + A[2] * P[2],
515
- A[3] * P[0] + A[4] * P[1] + A[5] * P[2],
516
- A[6] * P[0] + A[7] * P[1] + A[8] * P[2]
517
- ]);
518
- o.onStatus("Generating measurement points...");
519
- const B = c.subdivide_origin_to_plane(new Float32Array(D), new Float32Array(y), k);
520
- de.debug(Fe, `Subdivide: ${B.count()} pts, spacing=${B.spacing().toFixed(1)}mm`);
521
- const $ = B.points(), N = B.count(), U = 2, be = 1, ae = [];
522
- for (let H = U; H < N - be; H++) ae.push($[H * 3 + 1]);
523
- o.onStatus("Computing cross-sections...");
524
- let ue = [];
525
- if (ae.length >= 2) {
526
- const q = (m ? c.batch_cross_sections_y_inner.bind(c) : c.batch_cross_sections_y.bind(c))(z, p, new Float32Array(ae), 10);
527
- de.debug(Fe, "Batch (subdivision)", q.details());
528
- const xe = q.all_loop_points(), Ce = q.offsets(), we = q.circumferences();
529
- for (let oe = 0; oe < Ce.length - 1; oe++) {
530
- const V = Ce[oe], X = Ce[oe + 1];
531
- if (X <= V || we[oe] <= 0) continue;
532
- const Pe = (X - V) / 3;
533
- if (Pe < 3) continue;
534
- let Le = 0, Ge = 0, se = 0;
535
- for (let ze = V; ze < X; ze += 3) Le += xe[ze], Ge += xe[ze + 1], se += xe[ze + 2];
536
- ue.push(Le / Pe, Ge / Pe, se / Pe);
537
- }
538
- }
539
- if (ue.length >= 6) {
540
- o.onStatus("Refining alignment...");
541
- const H = c.refine_alignment(new Float32Array(ue), z, new Float32Array(D), new Float32Array(y));
542
- de.info(Fe, "Refinement complete", H.details()), z = H.positions(), y = H.mpt(), D = H.origin();
543
- }
544
- const ie = a.getAttribute("color"), J = mn(z, p);
545
- ie && J.setAttribute("color", ie), a.dispose(), a = J, e.geometry = a, a.computeVertexNormals(), a.computeBoundingBox(), n[0] = new C(D[0], D[1], D[2]), n[1] = new C(y[0], y[1], y[2]), o.onStatus("Setting blue point...");
546
- const Y = new C(n[0].x, n[0].y, n[0].z);
547
- n.push(Y), o.addLandmarkPoint({
548
- faceIndex: -1,
549
- vertexIndices: [
550
- 0,
551
- 1,
552
- 2
553
- ],
554
- position: {
555
- x: Y.x,
556
- y: Y.y,
557
- z: Y.z
558
- },
559
- barycentricCoords: {
560
- u: 0.33,
561
- v: 0.33,
562
- w: 0.34
563
- }
564
- }), o.updateLandmarkPositions(n.map((H) => ({
565
- x: H.x,
566
- y: H.y,
567
- z: H.z
568
- }))), o.setAligned(true);
569
- const he = a.boundingBox, Z = new C();
570
- he.getSize(Z), o.setModelSize(Math.max(Z.x, Z.y, Z.z)), o.setCut(true), o.setAdjustedStartY(null), o.setAdjustedEndY(null), o.setOriginalEndY(n[1].y + 2 * dt), o.onStatus("Computing final measurements...");
571
- {
572
- const H = ft(a), q = n[1].y, xe = n[0].y;
573
- let Ce = 1 / 0, we = -1 / 0;
574
- const oe = H.positions;
575
- for (let se = 1; se < oe.length; se += 3) oe[se] < Ce && (Ce = oe[se]), oe[se] > we && (we = oe[se]);
576
- const V = 25.4, X = [];
577
- X.push(q);
578
- for (let se = 1; se <= 2; se++) {
579
- const ze = q + se * V;
580
- ze < we - 1 && X.push(ze);
581
- }
582
- for (let se = q - V; se > xe; se -= V) X.push(se);
583
- X.sort((se, ze) => se - ze), de.info(Fe, `Horizontal slices: ${X.length} Y planes, range ${(_b = X[0]) == null ? void 0 : _b.toFixed(1)} \u2192 ${(_c = X[X.length - 1]) == null ? void 0 : _c.toFixed(1)} mm`);
584
- const Le = (m ? c.batch_cross_sections_y_inner.bind(c) : c.batch_cross_sections_y.bind(c))(H.positions, H.indices, new Float32Array(X), 10);
585
- de.info(Fe, `Horizontal slices (${m ? "inner" : "outer"}): ${Le.count()}/${X.length} valid`), de.debug(Fe, "Slice details", Le.details());
586
- const Ge = {
587
- yValues: X,
588
- circumferences: Array.from(Le.circumferences()),
589
- allLoopPoints: new Float32Array(Le.all_loop_points()),
590
- offsets: new Uint32Array(Le.offsets()),
591
- mptY: q,
592
- originY: xe
593
- };
594
- (_d = o.setWasmSlices) == null ? void 0 : _d.call(o, Ge);
595
- }
596
- o.onStatus("Validating results...");
597
- const ge = n[1].y, me = n[0].y, pe = go(a, ge, me, t);
598
- pe.valid || de.warn(Fe, `Validation: ${pe.reason}`), o.setClippedReferenceGeometry ? (l.computeVertexNormals(), o.setClippedReferenceGeometry(l)) : l.dispose();
599
- } catch (a) {
600
- de.error(Fe, "Processing failed", a), o.setError(a instanceof Error ? a.message : "Failed to process mesh."), l.dispose();
601
- }
602
- }
603
- class xo extends Kn {
604
- constructor() {
605
- super(...arguments), this.state = {
606
- error: null
607
- }, this.reset = () => {
608
- this.setState({
609
- error: null
610
- });
611
- };
612
- }
613
- static getDerivedStateFromError(r) {
614
- return {
615
- error: r
616
- };
617
- }
618
- componentDidCatch(r, t) {
619
- console.error("[ErrorBoundary] Caught error:", r, t.componentStack);
620
- }
621
- render() {
622
- return this.state.error ? this.props.fallback ? this.props.fallback(this.state.error, this.reset) : F("div", {
623
- style: {
624
- display: "flex",
625
- flexDirection: "column",
626
- alignItems: "center",
627
- justifyContent: "center",
628
- height: "100%",
629
- padding: 32,
630
- textAlign: "center",
631
- fontFamily: "system-ui, sans-serif"
632
- },
633
- children: [
634
- i("div", {
635
- style: {
636
- fontSize: 16,
637
- fontWeight: 600,
638
- color: "#dc3545",
639
- marginBottom: 8
640
- },
641
- children: "Something went wrong"
642
- }),
643
- i("div", {
644
- style: {
645
- fontSize: 13,
646
- color: "#666",
647
- maxWidth: 400,
648
- marginBottom: 16
649
- },
650
- children: this.state.error.message
651
- }),
652
- i("button", {
653
- onClick: this.reset,
654
- style: {
655
- padding: "8px 20px",
656
- borderRadius: 4,
657
- fontSize: 13,
658
- fontWeight: 500,
659
- backgroundColor: "rgb(12, 67, 173)",
660
- border: "none",
661
- color: "#fff",
662
- cursor: "pointer"
663
- },
664
- children: "Try Again"
665
- })
666
- ]
667
- }) : this.props.children;
668
- }
669
- }
670
- const yo = ({ message: e, onDismiss: r }) => F("div", {
671
- style: {
672
- position: "absolute",
673
- top: 16,
674
- right: 16,
675
- padding: "12px 16px",
676
- backgroundColor: "rgba(220, 53, 69, 0.95)",
677
- borderRadius: 8,
678
- color: "#fff",
679
- fontSize: 14,
680
- maxWidth: 300,
681
- zIndex: 100,
682
- display: "flex",
683
- alignItems: "flex-start",
684
- gap: 12
685
- },
686
- children: [
687
- F("div", {
688
- style: {
689
- flex: 1
690
- },
691
- children: [
692
- i("div", {
693
- style: {
694
- fontWeight: "bold",
695
- marginBottom: 4
696
- },
697
- children: "Error"
698
- }),
699
- i("div", {
700
- style: {
701
- fontSize: 12,
702
- opacity: 0.9
703
- },
704
- children: e
705
- })
706
- ]
707
- }),
708
- i("button", {
709
- onClick: r,
710
- style: {
711
- background: "none",
712
- border: "none",
713
- color: "#fff",
714
- cursor: "pointer",
715
- fontSize: 18,
716
- padding: 0,
717
- lineHeight: 1,
718
- opacity: 0.7
719
- },
720
- children: "x"
721
- })
722
- ]
723
- }), on = ({ message: e }) => F("div", {
724
- style: {
725
- position: "absolute",
726
- top: 0,
727
- left: 0,
728
- right: 0,
729
- bottom: 0,
730
- backgroundColor: "rgba(0, 0, 0, 0.7)",
731
- display: "flex",
732
- flexDirection: "column",
733
- alignItems: "center",
734
- justifyContent: "center",
735
- zIndex: 100
736
- },
737
- children: [
738
- i("div", {
739
- style: {
740
- width: 48,
741
- height: 48,
742
- border: "4px solid rgba(255, 255, 255, 0.2)",
743
- borderTopColor: "#4a90d9",
744
- borderRadius: "50%",
745
- animation: "spin 1s linear infinite"
746
- }
747
- }),
748
- e && i("div", {
749
- style: {
750
- marginTop: 16,
751
- color: "#fff",
752
- fontSize: 14
753
- },
754
- children: e
755
- }),
756
- i("style", {
757
- children: "@keyframes spin { to { transform: rotate(360deg); } }"
758
- })
759
- ]
760
- });
761
- function bo(e, r, t, o) {
762
- const l = new C().subVectors(t, r), s = new C().subVectors(o, r), c = new C().subVectors(e, r), a = l.dot(l), n = l.dot(s), h = l.dot(c), d = s.dot(s), u = s.dot(c), p = 1 / (a * d - n * n), g = (d * h - n * u) * p, M = (a * u - n * h) * p;
763
- return {
764
- u: 1 - g - M,
765
- v: g,
766
- w: M
767
- };
768
- }
769
- const wo = ({ mesh: e, maxPoints: r = 2, meshColor: t = "#c8c8c8", meshOpacity: o = 1, frontFaceOnly: l = false, doubleShellTransparency: s = false }) => {
770
- const { addLandmarkPoint: c, landmarkPoints: a } = Dt(), n = re((g) => {
771
- if (a.length >= r) return;
772
- g.stopPropagation();
773
- const M = g.intersections[0], f = M == null ? void 0 : M.faceIndex;
774
- if (!M || f == null) return;
775
- const m = e.geometry, x = m.index;
776
- let S;
777
- x ? S = [
778
- x.getX(f * 3),
779
- x.getX(f * 3 + 1),
780
- x.getX(f * 3 + 2)
781
- ] : S = [
782
- f * 3,
783
- f * 3 + 1,
784
- f * 3 + 2
785
- ];
786
- const I = m.getAttribute("position"), P = new C().fromBufferAttribute(I, S[0]), L = new C().fromBufferAttribute(I, S[1]), b = new C().fromBufferAttribute(I, S[2]);
787
- P.applyMatrix4(e.matrixWorld), L.applyMatrix4(e.matrixWorld), b.applyMatrix4(e.matrixWorld);
788
- const z = M.point, y = bo(z, P, L, b), D = {
789
- faceIndex: f,
790
- vertexIndices: S,
791
- position: {
792
- x: z.x,
793
- y: z.y,
794
- z: z.z
795
- },
796
- barycentricCoords: y
797
- };
798
- c(D);
799
- }, [
800
- e,
801
- c,
802
- a.length,
803
- r
804
- ]), h = j(() => !!e.geometry.getAttribute("color"), [
805
- e
806
- ]), d = s ? Math.min(o, 0.65) : o, u = d < 1, p = j(() => new O.MeshStandardMaterial({
807
- color: h ? "#ffffff" : t,
808
- side: l ? O.FrontSide : O.DoubleSide,
809
- roughness: 0.6,
810
- metalness: 0.1,
811
- transparent: u,
812
- opacity: d,
813
- depthWrite: !s,
814
- vertexColors: h
815
- }), [
816
- t,
817
- d,
818
- u,
819
- h,
820
- l,
821
- s
822
- ]);
823
- return i("primitive", {
824
- object: e,
825
- onClick: n,
826
- material: p,
827
- renderOrder: s ? 0 : void 0
828
- });
829
- }, So = ({ point: e, index: r, markerSize: t, color: o, label: l }) => {
830
- const [s, c] = E(false);
831
- return F("mesh", {
832
- position: [
833
- e.position.x,
834
- e.position.y,
835
- e.position.z
836
- ],
837
- onPointerOver: () => c(true),
838
- onPointerOut: () => c(false),
839
- children: [
840
- i("sphereGeometry", {
841
- args: [
842
- t,
843
- 16,
844
- 16
845
- ]
846
- }),
847
- i("meshBasicMaterial", {
848
- color: o
849
- }),
850
- s && i(Xe, {
851
- center: true,
852
- style: {
853
- pointerEvents: "none"
854
- },
855
- children: i("div", {
856
- style: {
857
- padding: "3px 8px",
858
- backgroundColor: "rgba(0, 0, 0, 0.75)",
859
- borderRadius: 4,
860
- color: "#fff",
861
- fontSize: 12,
862
- fontFamily: "system-ui, sans-serif",
863
- whiteSpace: "nowrap",
864
- transform: "translateY(-24px)"
865
- },
866
- children: l
867
- })
868
- })
869
- ]
870
- }, r);
871
- }, vo = ({ modelSize: e, labels: r }) => {
872
- const { landmarkPoints: t } = Dt(), o = e * 0.02, l = [
873
- "#44ff44",
874
- "#ff4444",
875
- "#4444ff"
876
- ], c = r ?? [
877
- "MPT",
878
- "Origin",
879
- "Cut Plane"
880
- ];
881
- return i(Oe, {
882
- children: t.map((a, n) => i(So, {
883
- point: a,
884
- index: n,
885
- markerSize: o,
886
- color: l[n],
887
- label: c[n]
888
- }, n))
889
- });
890
- };
891
- function bn(e) {
892
- return j(() => e ? new pt(e, {
893
- maxLeafTris: ht
894
- }) : null, [
895
- e
896
- ]);
897
- }
898
- const rn = (e, r) => {
899
- const t = Math.abs(e - r);
900
- return t <= 7 ? "#8BC34A" : t <= 20 ? "#FFC107" : "#FF5722";
901
- }, sn = new O.Color("#8BC34A"), ln = new O.Color("#FFC107"), Co = new O.Color("#FF5722"), Mo = (e) => {
902
- if (e <= 7) return sn.clone();
903
- if (e <= 20) {
904
- const t = (e - 7) / 13;
905
- return sn.clone().lerp(ln, t);
906
- }
907
- const r = Math.min((e - 20) / 20, 1);
908
- return ln.clone().lerp(Co, r);
909
- }, zo = (e, r) => {
910
- const t = e.length, o = new Float32Array(t * 2 * 3), l = new Float32Array(t * 2 * 3), s = [];
911
- for (let n = 0; n < t; n++) {
912
- const h = e[n], d = r[n], u = h.distanceTo(d), p = Mo(u);
913
- if (o[n * 6] = h.x, o[n * 6 + 1] = h.y, o[n * 6 + 2] = h.z, l[n * 6] = p.r, l[n * 6 + 1] = p.g, l[n * 6 + 2] = p.b, o[n * 6 + 3] = d.x, o[n * 6 + 4] = d.y, o[n * 6 + 5] = d.z, l[n * 6 + 3] = p.r, l[n * 6 + 4] = p.g, l[n * 6 + 5] = p.b, n < t - 1) {
914
- const g = n * 2, M = g + 1, f = (n + 1) * 2, m = f + 1;
915
- s.push(g, M, f, M, m, f);
916
- }
917
- }
918
- const c = new O.BufferGeometry();
919
- c.setAttribute("position", new O.Float32BufferAttribute(o, 3)), c.setAttribute("color", new O.Float32BufferAttribute(l, 3)), c.setIndex(s);
920
- const a = new O.MeshBasicMaterial({
921
- vertexColors: true,
922
- transparent: true,
923
- opacity: 0.25,
924
- side: O.DoubleSide,
925
- depthTest: false,
926
- depthWrite: false
927
- });
928
- return new O.Mesh(c, a);
929
- }, Ao = ({ bvh: e, geometry: r, yPosition: t, color: o = "#00ff00", labelX: l, onDataChange: s, displayUnit: c = "mm", useInnerSurface: a = false, formValue: n, lineWidth: h = 1.5, wasmLoopPoints: d, wasmCircumference: u }) => {
930
- const p = j(() => d && u != null ? null : Ye(e, r, t, a), [
931
- e,
932
- r,
933
- t,
934
- a,
935
- d,
936
- u
937
- ]), g = d ?? (p == null ? void 0 : p.linePoints) ?? [], M = u ?? (p == null ? void 0 : p.lineLength) ?? 0, f = j(() => {
938
- if (n == null || M <= 0 || g.length < 2) return null;
939
- const I = n / M, P = g.reduce((b, z) => b + z.x, 0) / g.length, L = g.reduce((b, z) => b + z.z, 0) / g.length;
940
- return g.map((b) => new C(P + (b.x - P) * I, b.y, L + (b.z - L) * I));
941
- }, [
942
- g,
943
- M,
944
- n
945
- ]), m = j(() => !f || g.length < 2 ? null : zo(g, f), [
946
- g,
947
- f
948
- ]);
949
- ne(() => () => {
950
- m && (m.geometry.dispose(), m.material.dispose());
951
- }, [
952
- m
953
- ]);
954
- const x = le(null), S = j(() => {
955
- const I = new O.BufferGeometry();
956
- I.setAttribute("position", new O.Float32BufferAttribute(new Float32Array(6), 3));
957
- const P = new O.LineBasicMaterial({
958
- color: 6710886,
959
- depthTest: false,
960
- depthWrite: false,
961
- transparent: true
962
- });
963
- return new O.Line(I, P);
964
- }, []);
965
- return ne(() => () => {
966
- S.geometry.dispose(), S.material.dispose();
967
- }, [
968
- S
969
- ]), ne(() => {
970
- M > 0 && (s == null ? void 0 : s({
971
- yPosition: t,
972
- originalValue: M,
973
- modifiedValue: null
974
- }));
975
- }, [
976
- M,
977
- t,
978
- s
979
- ]), an(({ camera: I }) => {
980
- if (!x.current || g.length < 2) return;
981
- const P = new C();
982
- I.getWorldDirection(P);
983
- const L = new C(P.x, 0, P.z);
984
- if (L.lengthSq() < 1e-8) return;
985
- L.normalize();
986
- const b = new C().crossVectors(L, new C(0, 1, 0)).normalize();
987
- let z = -1 / 0, y = g[0];
988
- for (const k of g) {
989
- const B = b.x * k.x + b.z * k.z;
990
- B > z && (z = B, y = k);
991
- }
992
- const D = l * 0.35, w = new C(y.x + b.x * D, t, y.z + b.z * D);
993
- x.current.position.copy(w);
994
- const A = S.geometry.getAttribute("position");
995
- A.setXYZ(0, y.x, y.y, y.z), A.setXYZ(1, w.x, w.y, w.z), A.needsUpdate = true;
996
- }), g.length < 2 ? null : F("group", {
997
- renderOrder: 10,
998
- children: [
999
- i(fe, {
1000
- points: g,
1001
- color: o,
1002
- lineWidth: h,
1003
- depthTest: false,
1004
- depthWrite: false,
1005
- transparent: true,
1006
- renderOrder: 10
1007
- }),
1008
- m && i("primitive", {
1009
- object: m,
1010
- renderOrder: 10
1011
- }),
1012
- f && n != null && i(fe, {
1013
- points: f,
1014
- color: rn(M, n),
1015
- lineWidth: 2.5,
1016
- dashed: true,
1017
- dashSize: 2,
1018
- gapSize: 1.5,
1019
- depthTest: false,
1020
- depthWrite: false,
1021
- transparent: true,
1022
- opacity: 0.8,
1023
- renderOrder: 10
1024
- }),
1025
- i("primitive", {
1026
- object: S,
1027
- renderOrder: 10
1028
- }),
1029
- i("group", {
1030
- ref: x,
1031
- children: i(Xe, {
1032
- zIndexRange: [
1033
- 100,
1034
- 0
1035
- ],
1036
- style: {
1037
- pointerEvents: "none",
1038
- transform: "translateY(-50%)"
1039
- },
1040
- children: F("div", {
1041
- style: {
1042
- display: "flex",
1043
- alignItems: "stretch",
1044
- gap: 0,
1045
- marginLeft: 10,
1046
- pointerEvents: "none",
1047
- whiteSpace: "nowrap"
1048
- },
1049
- children: [
1050
- F("div", {
1051
- style: {
1052
- display: "flex",
1053
- alignItems: "center",
1054
- gap: 4,
1055
- padding: "5px 10px",
1056
- backgroundColor: "rgba(0, 0, 0, 0.75)",
1057
- borderRadius: n != null ? "4px 0 0 4px" : 4
1058
- },
1059
- children: [
1060
- i("span", {
1061
- style: {
1062
- fontSize: 14,
1063
- color: "#fff",
1064
- fontFamily: "monospace",
1065
- minWidth: 52,
1066
- textAlign: "right"
1067
- },
1068
- children: c === "inch" ? (M / 25.4).toFixed(2) : M.toFixed(1)
1069
- }),
1070
- i("span", {
1071
- style: {
1072
- fontSize: 11,
1073
- color: "rgba(255,255,255,0.6)",
1074
- fontFamily: "monospace"
1075
- },
1076
- children: c === "inch" ? "in" : "mm"
1077
- })
1078
- ]
1079
- }),
1080
- n != null && M > 0 && (() => {
1081
- const I = M - n, P = I > 0.5 ? "\u25B2" : I < -0.5 ? "\u25BC" : "", L = rn(M, n);
1082
- return F("div", {
1083
- style: {
1084
- display: "flex",
1085
- alignItems: "center",
1086
- gap: 5,
1087
- padding: "5px 10px",
1088
- backgroundColor: "rgba(0, 0, 0, 0.55)",
1089
- borderRadius: "0 4px 4px 0",
1090
- borderLeft: "1px solid rgba(255,255,255,0.12)"
1091
- },
1092
- children: [
1093
- P && i("span", {
1094
- style: {
1095
- fontSize: 10,
1096
- color: L,
1097
- lineHeight: 1
1098
- },
1099
- children: P
1100
- }),
1101
- F("span", {
1102
- style: {
1103
- fontSize: 13,
1104
- color: L,
1105
- fontFamily: "monospace",
1106
- fontWeight: 600
1107
- },
1108
- children: [
1109
- I > 0 ? "+" : "",
1110
- c === "inch" ? (I / 25.4).toFixed(2) : I.toFixed(1)
1111
- ]
1112
- }),
1113
- F("span", {
1114
- style: {
1115
- fontSize: 11,
1116
- color: "rgba(255,255,255,0.4)",
1117
- fontFamily: "monospace"
1118
- },
1119
- children: [
1120
- "form ",
1121
- c === "inch" ? (n / 25.4).toFixed(2) : n.toFixed(0)
1122
- ]
1123
- })
1124
- ]
1125
- });
1126
- })()
1127
- ]
1128
- })
1129
- })
1130
- })
1131
- ]
1132
- });
1133
- }, ko = Un(Ao), Fo = ({ mesh: e, startY: r, endY: t, spacing: o, modelSize: l, onMeasurementsChange: s, reverseOrder: c = false, displayUnit: a = "mm", useInnerSurface: n = false, formMeasurements: h, originY: d, wasmSlices: u }) => {
1134
- const p = le(/* @__PURE__ */ new Map()), g = e.geometry, M = bn(g), f = j(() => {
1135
- if (u) {
1136
- let z = [
1137
- ...u.yValues
1138
- ];
1139
- if (o > 25.4 + 0.1) {
1140
- const y = u.mptY;
1141
- z = z.filter((D) => {
1142
- const w = Math.abs(D - y);
1143
- return w < 0.5 || Math.abs(Math.round(w / o) * o - w) < 0.5;
1144
- });
1145
- }
1146
- return c ? z.sort((y, D) => D - y) : z.sort((y, D) => y - D), z;
1147
- }
1148
- const L = [];
1149
- if (c) for (let b = t; b >= r; b -= o) L.push(b);
1150
- else for (let b = r; b <= t; b += o) L.push(b);
1151
- return L;
1152
- }, [
1153
- r,
1154
- t,
1155
- o,
1156
- c,
1157
- u
1158
- ]), m = j(() => {
1159
- if (!u) return null;
1160
- const L = /* @__PURE__ */ new Map(), { allLoopPoints: b, offsets: z, yValues: y } = u;
1161
- for (let D = 0; D < z.length - 1; D++) {
1162
- const w = z[D], A = z[D + 1];
1163
- if (A <= w) continue;
1164
- const k = [];
1165
- for (let B = w; B < A; B += 3) k.push(new C(b[B], b[B + 1], b[B + 2]));
1166
- k.length >= 3 && L.set(y[D], k);
1167
- }
1168
- return L;
1169
- }, [
1170
- u
1171
- ]), x = j(() => {
1172
- if (!u) return null;
1173
- const L = /* @__PURE__ */ new Map();
1174
- for (let b = 0; b < u.yValues.length; b++) L.set(u.yValues[b], u.circumferences[b]);
1175
- return L;
1176
- }, [
1177
- u
1178
- ]);
1179
- ne(() => {
1180
- p.current.clear();
1181
- }, [
1182
- f
1183
- ]), ne(() => {
1184
- if (!x || !s) return;
1185
- const L = f.filter((b) => (x.get(b) ?? 0) > 0).map((b) => ({
1186
- yPosition: b,
1187
- originalValue: x.get(b) ?? 0,
1188
- modifiedValue: null
1189
- }));
1190
- s(L);
1191
- }, [
1192
- x,
1193
- f,
1194
- s
1195
- ]);
1196
- const S = [
1197
- "#5B9BD5"
1198
- ], I = l * io, P = re((L) => {
1199
- if (x) return;
1200
- p.current.set(L.yPosition, L);
1201
- const b = Array.from(p.current.values()).sort((z, y) => c ? y.yPosition - z.yPosition : z.yPosition - y.yPosition);
1202
- s == null ? void 0 : s(b);
1203
- }, [
1204
- s,
1205
- c,
1206
- x
1207
- ]);
1208
- return M ? i(Oe, {
1209
- children: f.map((L, b) => i(ko, {
1210
- bvh: M,
1211
- geometry: g,
1212
- yPosition: L,
1213
- color: d != null && Math.abs(L - d) < o * 0.5 ? "#44ff44" : S[b % S.length],
1214
- labelX: I,
1215
- onDataChange: P,
1216
- displayUnit: a,
1217
- useInnerSurface: n,
1218
- formValue: h == null ? void 0 : h[b],
1219
- lineWidth: d != null && Math.abs(L - d) < o * 0.5 ? 4 : 1.5,
1220
- wasmLoopPoints: m == null ? void 0 : m.get(L),
1221
- wasmCircumference: x == null ? void 0 : x.get(L)
1222
- }, L))
1223
- }) : null;
1224
- }, Po = ({ mesh: e, greenY: r, modelSize: t, displayUnit: o = "mm", bottomY: l }) => {
1225
- var _a;
1226
- const s = e.geometry;
1227
- s.computeBoundingBox();
1228
- const c = l ?? ((_a = s.boundingBox) == null ? void 0 : _a.min.y) ?? 0, a = r - c, n = t * 0.4, h = t * 0.03, d = le(null);
1229
- an(({ camera: S }) => {
1230
- if (!d.current) return;
1231
- const I = new C();
1232
- S.getWorldDirection(I);
1233
- const P = new C(I.x, 0, I.z);
1234
- if (P.lengthSq() < 1e-8) return;
1235
- P.normalize();
1236
- const L = new C().crossVectors(new C(0, 1, 0), P).normalize();
1237
- d.current.position.set(L.x * n, 0, L.z * n);
1238
- const b = S.position.x - d.current.position.x, z = S.position.z - d.current.position.z;
1239
- d.current.rotation.y = Math.atan2(b, z);
1240
- });
1241
- const u = new C(0, r, 0), p = new C(0, c, 0), g = new C(0, (r + c) / 2, 0), M = new C(-h, r, 0), f = new C(h, r, 0), m = new C(-h, c, 0), x = new C(h, c, 0);
1242
- return F("group", {
1243
- ref: d,
1244
- children: [
1245
- i(fe, {
1246
- points: [
1247
- u,
1248
- p
1249
- ],
1250
- color: "#888888",
1251
- lineWidth: 1.5
1252
- }),
1253
- i(fe, {
1254
- points: [
1255
- M,
1256
- f
1257
- ],
1258
- color: "#888888",
1259
- lineWidth: 1.5
1260
- }),
1261
- i(fe, {
1262
- points: [
1263
- m,
1264
- x
1265
- ],
1266
- color: "#888888",
1267
- lineWidth: 1.5
1268
- }),
1269
- i("mesh", {
1270
- position: g,
1271
- children: i(Xe, {
1272
- center: true,
1273
- style: {
1274
- pointerEvents: "none"
1275
- },
1276
- zIndexRange: [
1277
- 0,
1278
- 0
1279
- ],
1280
- children: F("div", {
1281
- style: {
1282
- padding: "4px 8px",
1283
- backgroundColor: "rgba(0, 0, 0, 0.7)",
1284
- borderRadius: 4,
1285
- color: "#fff",
1286
- fontSize: 16,
1287
- fontFamily: "monospace",
1288
- whiteSpace: "nowrap",
1289
- transform: "rotate(-90deg)",
1290
- transformOrigin: "center center",
1291
- pointerEvents: "none"
1292
- },
1293
- children: [
1294
- o === "inch" ? (a / 25.4).toFixed(2) : a.toFixed(1),
1295
- " ",
1296
- o === "inch" ? "in" : "mm"
1297
- ]
1298
- })
1299
- })
1300
- })
1301
- ]
1302
- });
1303
- }, Lo = ({ modelSize: e, isAligned: r, isCut: t, mesh: o, viewMode: l, sliceY: s, landmarkCount: c = 0, measurementGeometry: a, resetCameraToFrontRef: n }) => {
1304
- const { set: h, size: d, camera: u, invalidate: p } = cn(), g = le(false), M = le(l), f = le(new C()), m = le(null), x = le(c), S = le(r), I = le(t), P = le(a), L = le(0), b = re(() => {
1305
- if (!o || e <= 0) return null;
1306
- const y = a ?? o.geometry;
1307
- y.computeBoundingBox();
1308
- const D = y.boundingBox, w = new C();
1309
- D.getCenter(w);
1310
- const A = new C();
1311
- D.getSize(A), f.current.copy(A);
1312
- const k = d.width / d.height, B = Math.max(A.y, A.x / k) * 1.6, $ = B * k, N = w.y - A.y * 0.05;
1313
- L.current = N;
1314
- const U = new O.OrthographicCamera(-$ / 2, $ / 2, B / 2, -B / 2, 0.1, e * 10);
1315
- return U.position.set(0, N, e * 2), U.lookAt(0, N, 0), U;
1316
- }, [
1317
- o,
1318
- e,
1319
- d,
1320
- a
1321
- ]);
1322
- ne(() => {
1323
- if (n) return n.current = () => {
1324
- const y = b();
1325
- y && (h({
1326
- camera: y
1327
- }), p());
1328
- }, () => {
1329
- n && (n.current = null);
1330
- };
1331
- }, [
1332
- n,
1333
- b,
1334
- h,
1335
- p
1336
- ]);
1337
- const z = re((y) => {
1338
- const D = y.position.clone(), w = D.length(), A = Math.atan2(D.x, D.z), k = Math.acos(D.y / w), $ = A + 0.02;
1339
- y.position.set(w * Math.sin(k) * Math.sin($), w * Math.cos(k), w * Math.sin(k) * Math.cos($)), y.lookAt(0, 0, 0), y.updateMatrixWorld(true), p();
1340
- }, [
1341
- p
1342
- ]);
1343
- return ne(() => {
1344
- if (e > 0 && !g.current && !r) {
1345
- g.current = true;
1346
- const y = new O.PerspectiveCamera(50, d.width / d.height, 0.1, e * 10);
1347
- y.position.set(e * 0.3, e * 0.2, e * 1.5), y.lookAt(0, 0, 0), h({
1348
- camera: y
1349
- }), requestAnimationFrame(() => z(y));
1350
- }
1351
- }, [
1352
- e,
1353
- d,
1354
- h,
1355
- r,
1356
- z
1357
- ]), ne(() => {
1358
- const y = x.current;
1359
- x.current = c, y === 0 && c === 1 && !r && requestAnimationFrame(() => z(u));
1360
- }, [
1361
- c,
1362
- r,
1363
- u,
1364
- z
1365
- ]), ne(() => {
1366
- const y = S.current !== r, D = I.current !== t, w = !P.current && !!a;
1367
- if (S.current = r, I.current = t, P.current = a, !y && !D && !w || !r || l !== "3D") return;
1368
- const A = b();
1369
- A && h({
1370
- camera: A
1371
- });
1372
- }, [
1373
- r,
1374
- t,
1375
- l,
1376
- a,
1377
- b,
1378
- h
1379
- ]), ne(() => {
1380
- if (M.current === l) return;
1381
- const y = M.current;
1382
- if (M.current = l, !(!r || !o || e <= 0)) {
1383
- if (l === "2D" && s != null) {
1384
- m.current = u;
1385
- const D = o.geometry, w = D.getAttribute("position"), A = w.array, k = e * 0.15;
1386
- let B = 1 / 0, $ = -1 / 0, N = 1 / 0, U = -1 / 0, be = false;
1387
- for (let pe = 0; pe < w.count; pe++) if (Math.abs(A[pe * 3 + 1] - s) < k) {
1388
- const H = A[pe * 3], q = A[pe * 3 + 2];
1389
- H < B && (B = H), H > $ && ($ = H), q < N && (N = q), q > U && (U = q), be = true;
1390
- }
1391
- if (!be) {
1392
- D.computeBoundingBox();
1393
- const pe = D.boundingBox;
1394
- B = pe.min.x, $ = pe.max.x, N = pe.min.z, U = pe.max.z;
1395
- }
1396
- const ae = (B + $) / 2, ue = (N + U) / 2, ie = d.width / d.height, J = 1.4, Y = ($ - B) * J, he = (U - N) * J;
1397
- let Z, ge;
1398
- Y / he > ie ? (Z = Y, ge = Y / ie) : (ge = he, Z = he * ie);
1399
- const me = new O.OrthographicCamera(-Z / 2, Z / 2, ge / 2, -ge / 2, 0.1, e * 10);
1400
- me.position.set(ae, s + e * 2, ue), me.up.set(0, 0, -1), me.lookAt(ae, s, ue), h({
1401
- camera: me
1402
- });
1403
- } else if (y === "2D") if (m.current) h({
1404
- camera: m.current
1405
- }), m.current = null;
1406
- else {
1407
- const D = b();
1408
- D && h({
1409
- camera: D
1410
- });
1411
- }
1412
- }
1413
- }, [
1414
- l,
1415
- s,
1416
- r,
1417
- o,
1418
- e,
1419
- d,
1420
- h,
1421
- u,
1422
- b
1423
- ]), ne(() => {
1424
- if (!r || !u || !u.isOrthographicCamera) return;
1425
- const y = u;
1426
- if (l === "2D") {
1427
- if (!o || s == null) return;
1428
- const D = o.geometry, w = D.getAttribute("position"), A = w.array, k = e * 0.15;
1429
- let B = 1 / 0, $ = -1 / 0, N = 1 / 0, U = -1 / 0, be = false;
1430
- for (let Z = 0; Z < w.count; Z++) if (Math.abs(A[Z * 3 + 1] - s) < k) {
1431
- const ge = A[Z * 3], me = A[Z * 3 + 2];
1432
- ge < B && (B = ge), ge > $ && ($ = ge), me < N && (N = me), me > U && (U = me), be = true;
1433
- }
1434
- if (!be) {
1435
- D.computeBoundingBox();
1436
- const Z = D.boundingBox;
1437
- B = Z.min.x, $ = Z.max.x, N = Z.min.z, U = Z.max.z;
1438
- }
1439
- const ae = d.width / d.height, ue = 1.4, ie = ($ - B) * ue, J = (U - N) * ue;
1440
- let Y, he;
1441
- ie / J > ae ? (Y = ie, he = ie / ae) : (he = J, Y = J * ae), y.left = -Y / 2, y.right = Y / 2, y.top = he / 2, y.bottom = -he / 2;
1442
- } else {
1443
- const D = f.current, w = d.width / d.height, A = Math.max(D.y, D.x / w) * 1.6, k = A * w;
1444
- y.left = -k / 2, y.right = k / 2, y.top = A / 2, y.bottom = -A / 2;
1445
- }
1446
- y.updateProjectionMatrix();
1447
- }, [
1448
- d.width,
1449
- d.height,
1450
- r,
1451
- u,
1452
- l,
1453
- o
1454
- ]), null;
1455
- }, Io = ({ mesh: e, isDragging: r }) => {
1456
- var _a;
1457
- const t = e.geometry;
1458
- t.computeBoundingBox();
1459
- const o = new C();
1460
- return (_a = t.boundingBox) == null ? void 0 : _a.getCenter(o), i(dn, {
1461
- enableDamping: false,
1462
- enablePan: false,
1463
- minPolarAngle: Math.PI * 0.15,
1464
- maxPolarAngle: Math.PI * 0.85,
1465
- minZoom: 0.5,
1466
- maxZoom: 3,
1467
- enabled: !r,
1468
- target: [
1469
- o.x,
1470
- o.y,
1471
- o.z
1472
- ]
1473
- });
1474
- }, _o = ({ wasAutoScaled: e, onDismiss: r }) => F("div", {
1475
- style: {
1476
- position: "absolute",
1477
- bottom: 16,
1478
- left: 16,
1479
- zIndex: 10,
1480
- display: "flex",
1481
- alignItems: "flex-start",
1482
- gap: 10,
1483
- padding: "10px 14px",
1484
- maxWidth: 320,
1485
- backgroundColor: e ? "rgba(30, 70, 160, 0.92)" : "rgba(40, 40, 40, 0.88)",
1486
- borderRadius: 8,
1487
- boxShadow: "0 2px 12px rgba(0,0,0,0.15)",
1488
- fontFamily: "system-ui, sans-serif"
1489
- },
1490
- children: [
1491
- i("span", {
1492
- style: {
1493
- fontSize: 13,
1494
- color: "#fff",
1495
- lineHeight: "20px"
1496
- },
1497
- children: e ? "Units detected as meters - converted to mm" : "Units detected as mm"
1498
- }),
1499
- i("button", {
1500
- onClick: r,
1501
- style: {
1502
- background: "none",
1503
- border: "none",
1504
- color: "rgba(255,255,255,0.7)",
1505
- cursor: "pointer",
1506
- fontSize: 16,
1507
- lineHeight: "20px",
1508
- padding: 0,
1509
- marginLeft: "auto",
1510
- flexShrink: 0
1511
- },
1512
- children: "X"
1513
- })
1514
- ]
1515
- }), Do = ({ isDoubleShell: e, onDismiss: r }) => F("div", {
1516
- style: {
1517
- position: "absolute",
1518
- bottom: 68,
1519
- left: 16,
1520
- zIndex: 10,
1521
- display: "flex",
1522
- alignItems: "flex-start",
1523
- gap: 10,
1524
- padding: "10px 14px",
1525
- maxWidth: 320,
1526
- backgroundColor: e ? "rgba(130, 80, 20, 0.92)" : "rgba(40, 40, 40, 0.88)",
1527
- borderRadius: 8,
1528
- boxShadow: "0 2px 12px rgba(0,0,0,0.15)",
1529
- fontFamily: "system-ui, sans-serif"
1530
- },
1531
- children: [
1532
- i("span", {
1533
- style: {
1534
- fontSize: 13,
1535
- color: "#fff",
1536
- lineHeight: "20px"
1537
- },
1538
- children: e ? "Double shell scan detected" : "Single shell scan detected"
1539
- }),
1540
- i("button", {
1541
- onClick: r,
1542
- style: {
1543
- background: "none",
1544
- border: "none",
1545
- color: "rgba(255,255,255,0.7)",
1546
- cursor: "pointer",
1547
- fontSize: 16,
1548
- lineHeight: "20px",
1549
- padding: 0,
1550
- marginLeft: "auto",
1551
- flexShrink: 0
1552
- },
1553
- children: "X"
1554
- })
1555
- ]
1556
- }), Bo = ({ steps: e, currentStep: r, accentColor: t = "rgb(12, 67, 173)" }) => i("div", {
1557
- style: {
1558
- backgroundColor: "#fff",
1559
- borderBottom: "1px solid #e0e0e0",
1560
- display: "flex",
1561
- alignItems: "center",
1562
- padding: "24px 24px",
1563
- flexShrink: 0
1564
- },
1565
- children: e.map((o, l) => {
1566
- const s = o.number < r, c = o.number === r;
1567
- return F("div", {
1568
- style: {
1569
- display: "contents"
1570
- },
1571
- children: [
1572
- F("div", {
1573
- style: {
1574
- display: "flex",
1575
- alignItems: "center",
1576
- gap: 8,
1577
- padding: "0 8px",
1578
- flexShrink: 0,
1579
- cursor: "default"
1580
- },
1581
- children: [
1582
- i("div", {
1583
- style: {
1584
- width: 24,
1585
- height: 24,
1586
- borderRadius: "50%",
1587
- backgroundColor: s || c ? t : "rgba(0, 0, 0, 0.38)",
1588
- color: "#fff",
1589
- display: "flex",
1590
- alignItems: "center",
1591
- justifyContent: "center",
1592
- fontSize: 12,
1593
- fontFamily: "system-ui, sans-serif",
1594
- flexShrink: 0
1595
- },
1596
- children: s ? "\u2713" : o.number
1597
- }),
1598
- i("div", {
1599
- style: {
1600
- fontSize: 14,
1601
- fontWeight: c ? 600 : 400,
1602
- color: c ? "rgba(0, 0, 0, 0.87)" : "rgba(0, 0, 0, 0.54)",
1603
- fontFamily: "system-ui, sans-serif",
1604
- whiteSpace: "nowrap"
1605
- },
1606
- children: o.label
1607
- })
1608
- ]
1609
- }),
1610
- l < e.length - 1 && i("div", {
1611
- style: {
1612
- flex: "auto",
1613
- borderTop: "1px solid #bdbdbd",
1614
- margin: "0 8px"
1615
- }
1616
- })
1617
- ]
1618
- }, o.number);
1619
- })
1620
- }), Ro = ({ mesh: e, upperY: r, originY: t, modelSize: o, meshColor: l = "#c8c8c8", displayUnit: s = "mm" }) => {
1621
- const c = e.geometry, a = j(() => new pt(c, {
1622
- maxLeafTris: ht
1623
- }), [
1624
- c
1625
- ]), n = j(() => Ye(a, c, t), [
1626
- a,
1627
- c,
1628
- t
1629
- ]), h = j(() => new ut(new C(0, -1, 0), r), [
1630
- r
1631
- ]), { mlLine: d, apLine: u, mlWidth: p, apWidth: g } = j(() => {
1632
- let m = null, x = null, S = 0, I = 0;
1633
- if (n.linePoints.length >= 2) {
1634
- let P = n.linePoints[0], L = n.linePoints[0], b = n.linePoints[0], z = n.linePoints[0];
1635
- for (const y of n.linePoints) y.x < P.x && (P = y), y.x > L.x && (L = y), y.z < b.z && (b = y), y.z > z.z && (z = y);
1636
- m = [
1637
- new C(P.x, t, P.z),
1638
- new C(L.x, t, L.z)
1639
- ], x = [
1640
- new C(b.x, t, b.z),
1641
- new C(z.x, t, z.z)
1642
- ], S = m[0].distanceTo(m[1]), I = x[0].distanceTo(x[1]);
1643
- }
1644
- return {
1645
- mlLine: m,
1646
- apLine: x,
1647
- mlWidth: S,
1648
- apWidth: I
1649
- };
1650
- }, [
1651
- n,
1652
- t
1653
- ]), M = (m) => s === "inch" ? (m / 25.4).toFixed(2) : m.toFixed(1), f = s === "inch" ? "in" : "mm";
1654
- return F(Oe, {
1655
- children: [
1656
- i("mesh", {
1657
- geometry: e.geometry,
1658
- children: i("meshStandardMaterial", {
1659
- color: l,
1660
- side: O.DoubleSide,
1661
- transparent: true,
1662
- opacity: 0.15,
1663
- depthWrite: false,
1664
- clippingPlanes: [
1665
- h
1666
- ]
1667
- })
1668
- }),
1669
- n.linePoints.length >= 2 && i(fe, {
1670
- points: n.linePoints,
1671
- color: "#00ff00",
1672
- lineWidth: 3,
1673
- depthTest: false,
1674
- depthWrite: false,
1675
- transparent: true
1676
- }),
1677
- d && F(Oe, {
1678
- children: [
1679
- i(fe, {
1680
- points: d,
1681
- color: "#ff8800",
1682
- lineWidth: 2,
1683
- depthTest: false,
1684
- depthWrite: false,
1685
- transparent: true
1686
- }),
1687
- i(Xe, {
1688
- position: [
1689
- d[0].x,
1690
- t,
1691
- d[0].z - o * 0.02
1692
- ],
1693
- center: true,
1694
- style: {
1695
- pointerEvents: "none"
1696
- },
1697
- children: i("div", {
1698
- style: {
1699
- whiteSpace: "nowrap",
1700
- padding: "2px 6px",
1701
- backgroundColor: "rgba(0,0,0,0.75)",
1702
- borderRadius: 3
1703
- },
1704
- children: F("span", {
1705
- style: {
1706
- fontSize: 12,
1707
- color: "#ff8800",
1708
- fontFamily: "monospace"
1709
- },
1710
- children: [
1711
- "ML ",
1712
- M(p),
1713
- " ",
1714
- f
1715
- ]
1716
- })
1717
- })
1718
- })
1719
- ]
1720
- }),
1721
- u && F(Oe, {
1722
- children: [
1723
- i(fe, {
1724
- points: u,
1725
- color: "#ff00ff",
1726
- lineWidth: 2,
1727
- depthTest: false,
1728
- depthWrite: false,
1729
- transparent: true
1730
- }),
1731
- i(Xe, {
1732
- position: [
1733
- Math.max(u[0].x, u[1].x) + o * 0.02,
1734
- t,
1735
- u[0].z > u[1].z ? u[0].z : u[1].z
1736
- ],
1737
- center: true,
1738
- style: {
1739
- pointerEvents: "none"
1740
- },
1741
- children: i("div", {
1742
- style: {
1743
- whiteSpace: "nowrap",
1744
- padding: "2px 6px",
1745
- backgroundColor: "rgba(0,0,0,0.75)",
1746
- borderRadius: 3
1747
- },
1748
- children: F("span", {
1749
- style: {
1750
- fontSize: 12,
1751
- color: "#ff00ff",
1752
- fontFamily: "monospace"
1753
- },
1754
- children: [
1755
- "AP ",
1756
- M(g),
1757
- " ",
1758
- f
1759
- ]
1760
- })
1761
- })
1762
- })
1763
- ]
1764
- })
1765
- ]
1766
- });
1767
- }, Wo = ({ mesh: e, yPosition: r, onYChange: t, minY: o, maxY: l, modelSize: s, color: c, hoverColor: a, dragColor: n, label: h, onDragStart: d, onDragEnd: u }) => {
1768
- const [p, g] = E(false), [M, f] = E(false), { camera: m, gl: x } = cn(), S = le(0), I = e.geometry, P = bn(I), L = j(() => P ? Ye(P, I, r) : {
1769
- linePoints: [],
1770
- lineLength: 0,
1771
- rightmostPoint: new C()
1772
- }, [
1773
- P,
1774
- I,
1775
- r
1776
- ]), b = re((A, k) => {
1777
- const B = x.domElement.getBoundingClientRect(), $ = (A - B.left) / B.width * 2 - 1, N = -((k - B.top) / B.height) * 2 + 1, U = new qn();
1778
- U.setFromCamera(new O.Vector2($, N), m);
1779
- const be = new ut(new C(0, 0, 1), 0), ae = new C();
1780
- return U.ray.intersectPlane(be, ae), ae ? ae.y : r;
1781
- }, [
1782
- m,
1783
- x,
1784
- r
1785
- ]), z = re((A) => {
1786
- A.stopPropagation(), g(true), x.domElement.style.cursor = "ns-resize", S.current = r - b(A.clientX, A.clientY), A.target.setPointerCapture(A.pointerId), d == null ? void 0 : d();
1787
- }, [
1788
- r,
1789
- x,
1790
- b,
1791
- d
1792
- ]), y = re((A) => {
1793
- if (!p) return;
1794
- let k = b(A.clientX, A.clientY) + S.current;
1795
- k = Math.max(o, Math.min(l, k)), t(k);
1796
- }, [
1797
- p,
1798
- b,
1799
- t,
1800
- o,
1801
- l
1802
- ]), D = re((A) => {
1803
- g(false), x.domElement.style.cursor = "auto", A.target.releasePointerCapture(A.pointerId), u == null ? void 0 : u();
1804
- }, [
1805
- x,
1806
- u
1807
- ]);
1808
- if (L.linePoints.length < 2) return null;
1809
- const w = p ? n : M ? a : c;
1810
- return F("group", {
1811
- renderOrder: 10,
1812
- children: [
1813
- i(fe, {
1814
- points: L.linePoints,
1815
- color: w,
1816
- lineWidth: p ? 6 : M ? 5 : 4,
1817
- depthTest: false,
1818
- depthWrite: false,
1819
- transparent: true,
1820
- renderOrder: 10,
1821
- onPointerDown: z,
1822
- onPointerMove: y,
1823
- onPointerUp: D,
1824
- onPointerEnter: () => {
1825
- f(true), x.domElement.style.cursor = "ns-resize";
1826
- },
1827
- onPointerLeave: () => {
1828
- p || (f(false), x.domElement.style.cursor = "auto");
1829
- }
1830
- }),
1831
- (M || p) && i("mesh", {
1832
- position: [
1833
- L.rightmostPoint.x + s * 0.15,
1834
- r,
1835
- 0
1836
- ],
1837
- children: i(Xe, {
1838
- center: true,
1839
- children: i("div", {
1840
- style: {
1841
- padding: "4px 8px",
1842
- backgroundColor: "rgba(0, 0, 0, 0.8)",
1843
- borderRadius: 4,
1844
- color: w,
1845
- fontSize: 11,
1846
- whiteSpace: "nowrap",
1847
- pointerEvents: "none"
1848
- },
1849
- children: p ? "Dragging..." : h
1850
- })
1851
- })
1852
- })
1853
- ]
1854
- });
1855
- };
1856
- function Eo(e, r) {
1857
- if (e == null) return {};
1858
- var t = {}, o = Object.keys(e), l, s;
1859
- for (s = 0; s < o.length; s++) l = o[s], !(r.indexOf(l) >= 0) && (t[l] = e[l]);
1860
- return t;
1861
- }
1862
- var To = [
1863
- "color"
1864
- ], Oo = Jn(function(e, r) {
1865
- var t = e.color, o = t === void 0 ? "currentColor" : t, l = Eo(e, To);
1866
- return en("svg", Object.assign({
1867
- width: "15",
1868
- height: "15",
1869
- viewBox: "0 0 15 15",
1870
- fill: "none",
1871
- xmlns: "http://www.w3.org/2000/svg"
1872
- }, l, {
1873
- ref: r
1874
- }), en("path", {
1875
- d: "M7.5 2C7.77614 2 8 2.22386 8 2.5L8 11.2929L11.1464 8.14645C11.3417 7.95118 11.6583 7.95118 11.8536 8.14645C12.0488 8.34171 12.0488 8.65829 11.8536 8.85355L7.85355 12.8536C7.75979 12.9473 7.63261 13 7.5 13C7.36739 13 7.24021 12.9473 7.14645 12.8536L3.14645 8.85355C2.95118 8.65829 2.95118 8.34171 3.14645 8.14645C3.34171 7.95118 3.65829 7.95118 3.85355 8.14645L7 11.2929L7 2.5C7 2.22386 7.22386 2 7.5 2Z",
1876
- fill: o,
1877
- fillRule: "evenodd",
1878
- clipRule: "evenodd"
1879
- }));
1880
- });
1881
- const $o = [
1882
- "Scan doesn't load properly",
1883
- "Takes too long",
1884
- "I don't want to",
1885
- "I want a second opinion",
1886
- "I measured from IT"
1887
- ], Ne = {
1888
- padding: "8px 20px",
1889
- borderRadius: 4,
1890
- fontSize: 14,
1891
- fontWeight: 500,
1892
- cursor: "pointer",
1893
- fontFamily: "system-ui, sans-serif",
1894
- letterSpacing: "0.4px",
1895
- lineHeight: "36px"
1896
- }, It = {
1897
- width: "100%",
1898
- padding: "10px 12px",
1899
- fontSize: 15,
1900
- border: "2px solid #ccc",
1901
- borderRadius: 4,
1902
- outline: "none",
1903
- boxSizing: "border-box",
1904
- fontFamily: "system-ui, sans-serif"
1905
- }, Ho = ({ amputationType: e, spacingInches: r, scanMeasurements: t, scanFrontalHeight: o, onSave: l, onSkip: s }) => {
1906
- const c = e === "AK" ? "IT" : "MPT", a = r, n = e === "AK" ? 18 : 9, h = j(() => {
1907
- const w = [];
1908
- for (let A = 2; A >= 1; A -= a) w.push(`${A}\u2033 above ${c}`);
1909
- w.push(`At ${c}`);
1910
- for (let A = a; A <= n; A += a) w.push(`${A}\u2033 below ${c}`);
1911
- return w;
1912
- }, [
1913
- a,
1914
- c,
1915
- n
1916
- ]), [d, u] = E({}), [p, g] = E(""), [M, f] = E(false), [m, x] = E(false), [S, I] = E(null), [P, L] = E(""), b = j(() => {
1917
- const w = p !== "" && !isNaN(parseFloat(p)), A = h.some((k) => {
1918
- const B = d[k];
1919
- return B != null && B !== "" && !isNaN(parseFloat(B));
1920
- });
1921
- return w || A;
1922
- }, [
1923
- d,
1924
- p,
1925
- h
1926
- ]), z = re(() => {
1927
- if (!b) return;
1928
- const w = h.map((k) => {
1929
- const B = d[k];
1930
- return B != null && B !== "" && !isNaN(parseFloat(B)) ? parseFloat(B) : 0;
1931
- }), A = p !== "" && !isNaN(parseFloat(p)) ? parseFloat(p) : 0;
1932
- l({
1933
- circumferences: w,
1934
- frontalHeight: A
1935
- });
1936
- }, [
1937
- b,
1938
- h,
1939
- d,
1940
- p,
1941
- l
1942
- ]), y = re(() => {
1943
- const w = {};
1944
- h.forEach((A, k) => {
1945
- const B = t[k];
1946
- if (B) {
1947
- const $ = B.modifiedValue ?? B.originalValue;
1948
- w[A] = $.toFixed(1);
1949
- }
1950
- }), u(w), o > 0 && g(o.toFixed(1));
1951
- }, [
1952
- h,
1953
- t,
1954
- o
1955
- ]), D = re(() => {
1956
- f(false), x(true);
1957
- }, []);
1958
- if (m) {
1959
- const w = S != null && (S !== "Other" || P.trim() !== ""), A = () => {
1960
- w && s(S === "Other" ? `Other: ${P.trim()}` : S);
1961
- };
1962
- return i("div", {
1963
- style: {
1964
- position: "fixed",
1965
- inset: 0,
1966
- backgroundColor: "rgba(0,0,0,0.5)",
1967
- backdropFilter: "blur(6px)",
1968
- WebkitBackdropFilter: "blur(6px)",
1969
- display: "flex",
1970
- alignItems: "center",
1971
- justifyContent: "center",
1972
- zIndex: 9999,
1973
- fontFamily: "system-ui, sans-serif"
1974
- },
1975
- children: F("div", {
1976
- style: {
1977
- backgroundColor: "#fff",
1978
- borderRadius: 12,
1979
- width: 440,
1980
- boxShadow: "0 24px 38px 3px rgba(0,0,0,0.14)"
1981
- },
1982
- children: [
1983
- F("div", {
1984
- style: {
1985
- padding: "24px 24px 0"
1986
- },
1987
- children: [
1988
- i("div", {
1989
- style: {
1990
- fontSize: 18,
1991
- fontWeight: 600,
1992
- color: "rgba(0,0,0,0.87)",
1993
- marginBottom: 4
1994
- },
1995
- children: "Why are you skipping?"
1996
- }),
1997
- i("div", {
1998
- style: {
1999
- fontSize: 13,
2000
- color: "rgba(0,0,0,0.5)"
2001
- },
2002
- children: "Select a reason to help us improve."
2003
- })
2004
- ]
2005
- }),
2006
- F("div", {
2007
- style: {
2008
- padding: "20px 24px",
2009
- display: "flex",
2010
- flexDirection: "column",
2011
- gap: 2
2012
- },
2013
- children: [
2014
- [
2015
- ...$o,
2016
- "Other"
2017
- ].map((k) => F("label", {
2018
- style: {
2019
- display: "flex",
2020
- alignItems: "center",
2021
- gap: 12,
2022
- padding: "10px 12px",
2023
- borderRadius: 6,
2024
- cursor: "pointer",
2025
- backgroundColor: S === k ? "rgba(12, 67, 173, 0.06)" : "transparent"
2026
- },
2027
- children: [
2028
- i("input", {
2029
- type: "radio",
2030
- name: "skip-reason",
2031
- checked: S === k,
2032
- onChange: () => {
2033
- I(k), k !== "Other" && L("");
2034
- },
2035
- style: {
2036
- accentColor: "rgb(12, 67, 173)",
2037
- width: 16,
2038
- height: 16,
2039
- margin: 0,
2040
- flexShrink: 0
2041
- }
2042
- }),
2043
- i("span", {
2044
- style: {
2045
- fontSize: 14,
2046
- color: "#333"
2047
- },
2048
- children: k
2049
- })
2050
- ]
2051
- }, k)),
2052
- S === "Other" && i("input", {
2053
- autoFocus: true,
2054
- type: "text",
2055
- placeholder: "Please describe...",
2056
- value: P,
2057
- onChange: (k) => L(k.target.value),
2058
- onKeyDown: (k) => {
2059
- k.key === "Enter" && A();
2060
- },
2061
- style: {
2062
- ...It,
2063
- marginTop: 8,
2064
- marginLeft: 40,
2065
- width: "calc(100% - 40px)",
2066
- border: "1px solid #ddd"
2067
- }
2068
- })
2069
- ]
2070
- }),
2071
- F("div", {
2072
- style: {
2073
- display: "flex",
2074
- justifyContent: "flex-end",
2075
- gap: 8,
2076
- padding: "16px 24px",
2077
- borderTop: "1px solid #eee"
2078
- },
2079
- children: [
2080
- i("button", {
2081
- onClick: () => {
2082
- x(false), I(null), L("");
2083
- },
2084
- style: {
2085
- ...Ne,
2086
- backgroundColor: "#fff",
2087
- border: "1px solid #ddd",
2088
- color: "#666"
2089
- },
2090
- children: "Cancel"
2091
- }),
2092
- i("button", {
2093
- onClick: A,
2094
- disabled: !w,
2095
- style: {
2096
- ...Ne,
2097
- backgroundColor: w ? "rgb(12, 67, 173)" : "#e0e0e0",
2098
- border: "none",
2099
- color: w ? "#fff" : "#9e9e9e",
2100
- cursor: w ? "pointer" : "not-allowed"
2101
- },
2102
- children: "Submit"
2103
- })
2104
- ]
2105
- })
2106
- ]
2107
- })
2108
- });
2109
- }
2110
- return M ? i("div", {
2111
- style: {
2112
- position: "fixed",
2113
- inset: 0,
2114
- backgroundColor: "rgba(0,0,0,0.5)",
2115
- backdropFilter: "blur(6px)",
2116
- WebkitBackdropFilter: "blur(6px)",
2117
- display: "flex",
2118
- alignItems: "center",
2119
- justifyContent: "center",
2120
- zIndex: 9999,
2121
- fontFamily: "system-ui, sans-serif"
2122
- },
2123
- children: F("div", {
2124
- style: {
2125
- backgroundColor: "#fff",
2126
- borderRadius: 8,
2127
- width: 440,
2128
- padding: 32,
2129
- boxShadow: "0 24px 38px 3px rgba(0,0,0,0.14)"
2130
- },
2131
- children: [
2132
- i("div", {
2133
- style: {
2134
- fontSize: 20,
2135
- fontWeight: 600,
2136
- color: "rgba(0,0,0,0.87)",
2137
- marginBottom: 8
2138
- },
2139
- children: "Skip Scan Comparison?"
2140
- }),
2141
- i("div", {
2142
- style: {
2143
- fontSize: 14,
2144
- color: "rgba(0,0,0,0.54)",
2145
- marginBottom: 24
2146
- },
2147
- children: "Your measurements will be submitted without comparing to the scan. Are you sure?"
2148
- }),
2149
- F("div", {
2150
- style: {
2151
- display: "flex",
2152
- justifyContent: "flex-end",
2153
- gap: 8
2154
- },
2155
- children: [
2156
- i("button", {
2157
- onClick: () => f(false),
2158
- style: {
2159
- ...Ne,
2160
- backgroundColor: "#fff",
2161
- border: "1px solid #bdbdbd",
2162
- color: "#333"
2163
- },
2164
- children: "Cancel"
2165
- }),
2166
- i("button", {
2167
- onClick: D,
2168
- style: {
2169
- ...Ne,
2170
- backgroundColor: "rgb(12, 67, 173)",
2171
- border: "none",
2172
- color: "#fff"
2173
- },
2174
- children: "Confirm"
2175
- })
2176
- ]
2177
- })
2178
- ]
2179
- })
2180
- }) : F("div", {
2181
- style: {
2182
- position: "fixed",
2183
- inset: 0,
2184
- backgroundColor: "#f5f5f5",
2185
- display: "flex",
2186
- flexDirection: "column",
2187
- zIndex: 9999,
2188
- fontFamily: "system-ui, sans-serif"
2189
- },
2190
- children: [
2191
- i("div", {
2192
- style: {
2193
- padding: "16px 24px 12px",
2194
- backgroundColor: "#fff",
2195
- borderBottom: "1px solid #e0e0e0",
2196
- flexShrink: 0
2197
- },
2198
- children: F("div", {
2199
- style: {
2200
- display: "flex",
2201
- alignItems: "center",
2202
- justifyContent: "space-between",
2203
- flexWrap: "wrap",
2204
- gap: 12
2205
- },
2206
- children: [
2207
- F("div", {
2208
- children: [
2209
- F("div", {
2210
- style: {
2211
- fontSize: 22,
2212
- fontWeight: 600,
2213
- color: "rgba(0,0,0,0.87)"
2214
- },
2215
- children: [
2216
- e,
2217
- " Measurements"
2218
- ]
2219
- }),
2220
- F("div", {
2221
- style: {
2222
- fontSize: 13,
2223
- color: "rgba(0,0,0,0.54)",
2224
- marginTop: 2
2225
- },
2226
- children: [
2227
- "Enter circumference and length measurements (mm). ",
2228
- a,
2229
- "\u2033",
2230
- " spacing."
2231
- ]
2232
- })
2233
- ]
2234
- }),
2235
- i("button", {
2236
- onClick: y,
2237
- style: {
2238
- ...Ne,
2239
- backgroundColor: "#fff",
2240
- border: "2px solid rgb(12, 67, 173)",
2241
- color: "rgb(12, 67, 173)",
2242
- fontWeight: 600,
2243
- padding: "6px 16px",
2244
- fontSize: 13
2245
- },
2246
- children: F("span", {
2247
- style: {
2248
- marginRight: 8,
2249
- display: "flex",
2250
- alignItems: "center",
2251
- gap: 4
2252
- },
2253
- children: [
2254
- i(Oo, {
2255
- style: {
2256
- width: 16,
2257
- height: 16
2258
- }
2259
- }),
2260
- "Pull Measurements from Scan"
2261
- ]
2262
- })
2263
- })
2264
- ]
2265
- })
2266
- }),
2267
- F("div", {
2268
- style: {
2269
- flex: 1,
2270
- minHeight: 0,
2271
- overflow: "auto",
2272
- padding: "20px 24px",
2273
- WebkitOverflowScrolling: "touch"
2274
- },
2275
- children: [
2276
- i("div", {
2277
- style: {
2278
- fontSize: 15,
2279
- fontWeight: 600,
2280
- color: "rgba(0,0,0,0.87)",
2281
- marginBottom: 12
2282
- },
2283
- children: "Circumferences"
2284
- }),
2285
- i("div", {
2286
- style: {
2287
- display: "grid",
2288
- gridTemplateColumns: "repeat(auto-fill, minmax(180px, 1fr))",
2289
- gap: "12px 20px",
2290
- marginBottom: 28
2291
- },
2292
- children: h.map((w, A) => F("div", {
2293
- children: [
2294
- F("label", {
2295
- style: {
2296
- display: "block",
2297
- fontSize: 12,
2298
- fontWeight: 500,
2299
- color: "rgb(12, 67, 173)",
2300
- marginBottom: 4
2301
- },
2302
- children: [
2303
- w,
2304
- " (mm) ",
2305
- i("span", {
2306
- style: {
2307
- color: "#d32f2f"
2308
- },
2309
- children: "*"
2310
- })
2311
- ]
2312
- }),
2313
- i("input", {
2314
- type: "number",
2315
- step: "0.1",
2316
- value: d[w] ?? "",
2317
- onChange: (k) => u((B) => ({
2318
- ...B,
2319
- [w]: k.target.value
2320
- })),
2321
- style: {
2322
- ...It,
2323
- padding: "8px 10px",
2324
- fontSize: 14,
2325
- borderColor: d[w] ? "rgb(12, 67, 173)" : "#ccc"
2326
- },
2327
- placeholder: "0.0"
2328
- })
2329
- ]
2330
- }, A))
2331
- }),
2332
- i("div", {
2333
- style: {
2334
- fontSize: 15,
2335
- fontWeight: 600,
2336
- color: "rgba(0,0,0,0.87)",
2337
- marginBottom: 12
2338
- },
2339
- children: "Lengths"
2340
- }),
2341
- i("div", {
2342
- style: {
2343
- display: "grid",
2344
- gridTemplateColumns: "repeat(auto-fill, minmax(180px, 1fr))",
2345
- gap: "12px 20px"
2346
- },
2347
- children: F("div", {
2348
- children: [
2349
- F("label", {
2350
- style: {
2351
- display: "block",
2352
- fontSize: 12,
2353
- fontWeight: 500,
2354
- color: "rgb(12, 67, 173)",
2355
- marginBottom: 4
2356
- },
2357
- children: [
2358
- "Frontal Height (mm) ",
2359
- i("span", {
2360
- style: {
2361
- color: "#d32f2f"
2362
- },
2363
- children: "*"
2364
- })
2365
- ]
2366
- }),
2367
- i("input", {
2368
- type: "number",
2369
- step: "0.1",
2370
- value: p,
2371
- onChange: (w) => g(w.target.value),
2372
- style: {
2373
- ...It,
2374
- padding: "8px 10px",
2375
- fontSize: 14,
2376
- borderColor: p ? "rgb(12, 67, 173)" : "#ccc"
2377
- },
2378
- placeholder: "0.0"
2379
- })
2380
- ]
2381
- })
2382
- })
2383
- ]
2384
- }),
2385
- F("div", {
2386
- style: {
2387
- padding: "12px 24px",
2388
- backgroundColor: "#fff",
2389
- borderTop: "1px solid #e0e0e0",
2390
- display: "flex",
2391
- alignItems: "center",
2392
- justifyContent: "flex-end",
2393
- gap: 8,
2394
- flexShrink: 0,
2395
- flexWrap: "wrap"
2396
- },
2397
- children: [
2398
- i("button", {
2399
- onClick: () => f(true),
2400
- style: {
2401
- ...Ne,
2402
- backgroundColor: "#fff",
2403
- border: "1px solid #bdbdbd",
2404
- color: "#666",
2405
- padding: "6px 16px",
2406
- fontSize: 13
2407
- },
2408
- children: "Have Galileo Check My Measurements"
2409
- }),
2410
- i("button", {
2411
- onClick: z,
2412
- disabled: !b,
2413
- style: {
2414
- ...Ne,
2415
- backgroundColor: b ? "rgb(12, 67, 173)" : "#e0e0e0",
2416
- border: "none",
2417
- color: b ? "#fff" : "#9e9e9e",
2418
- cursor: b ? "pointer" : "not-allowed",
2419
- padding: "6px 16px",
2420
- fontSize: 13
2421
- },
2422
- children: "Save Measurements"
2423
- })
2424
- ]
2425
- })
2426
- ]
2427
- });
2428
- };
2429
- function wn(e, r, t) {
2430
- const o = e.getAttribute("position"), l = t - r;
2431
- if (l < 1) return null;
2432
- const s = 30, c = l / s, a = [];
2433
- for (let m = 0; m < s; m++) {
2434
- const x = r + m * c, S = r + (m + 1) * c;
2435
- let I = 0, P = 0, L = 0, b = 0;
2436
- for (let z = 0; z < o.count; z++) {
2437
- const y = o.getY(z);
2438
- y >= x && y < S && (I += o.getX(z), P += y, L += o.getZ(z), b++);
2439
- }
2440
- b > 20 && a.push(new C(I / b, P / b, L / b));
2441
- }
2442
- if (a.length < 5) return null;
2443
- const n = new C();
2444
- for (const m of a) n.add(m);
2445
- n.divideScalar(a.length);
2446
- let h = 0, d = 0, u = 0, p = 0, g = 0, M = 0;
2447
- for (const m of a) {
2448
- const x = m.x - n.x, S = m.y - n.y, I = m.z - n.z;
2449
- h += x * x, d += x * S, u += x * I, p += S * S, g += S * I, M += I * I;
2450
- }
2451
- let f = new C(0.01, 1, 0.01).normalize();
2452
- for (let m = 0; m < 30; m++) {
2453
- const x = h * f.x + d * f.y + u * f.z, S = d * f.x + p * f.y + g * f.z, I = u * f.x + g * f.y + M * f.z, P = new C(x, S, I), L = P.length();
2454
- if (L < 1e-10 || (P.divideScalar(L), f.distanceTo(P) < 1e-8)) break;
2455
- f = P;
2456
- }
2457
- return f.y < 0 && f.negate(), f;
2458
- }
2459
- const Vo = {
2460
- pcaAxes: true,
2461
- obb: true,
2462
- obbAxis: true,
2463
- shellComponents: true,
2464
- ambientOcclusion: true,
2465
- circumferenceScan: false,
2466
- landmarkAxis: true,
2467
- iterativePCA: false,
2468
- fullRegionPCA: true
2469
- }, jo = [
2470
- "#ff4444",
2471
- "#44cc44",
2472
- "#4488ff"
2473
- ];
2474
- function Sn(e) {
2475
- const r = e.getAttribute("position"), t = r.count, o = new C();
2476
- for (let f = 0; f < t; f++) o.x += r.getX(f), o.y += r.getY(f), o.z += r.getZ(f);
2477
- o.divideScalar(t);
2478
- let l = 0, s = 0, c = 0, a = 0, n = 0, h = 0;
2479
- for (let f = 0; f < t; f++) {
2480
- const m = r.getX(f) - o.x, x = r.getY(f) - o.y, S = r.getZ(f) - o.z;
2481
- l += m * m, s += m * x, c += m * S, a += x * x, n += x * S, h += S * S;
2482
- }
2483
- l /= t, s /= t, c /= t, a /= t, n /= t, h /= t;
2484
- const d = [], u = [], p = [
2485
- [
2486
- l,
2487
- s,
2488
- c
2489
- ],
2490
- [
2491
- s,
2492
- a,
2493
- n
2494
- ],
2495
- [
2496
- c,
2497
- n,
2498
- h
2499
- ]
2500
- ];
2501
- for (let f = 0; f < 3; f++) {
2502
- let m = new C(1 + f * 0.1, 1 - f * 0.1, 0.5 + f * 0.3).normalize(), x = 0;
2503
- for (let S = 0; S < 100; S++) {
2504
- const I = p[0][0] * m.x + p[0][1] * m.y + p[0][2] * m.z, P = p[1][0] * m.x + p[1][1] * m.y + p[1][2] * m.z, L = p[2][0] * m.x + p[2][1] * m.y + p[2][2] * m.z, b = new C(I, P, L);
2505
- if (x = b.length(), x < 1e-12) break;
2506
- if (b.divideScalar(x), m.distanceTo(b) < 1e-10) {
2507
- m = b;
2508
- break;
2509
- }
2510
- m = b;
2511
- }
2512
- d.push(m.clone()), u.push(x);
2513
- for (let S = 0; S < 3; S++) for (let I = 0; I < 3; I++) {
2514
- const P = [
2515
- m.x,
2516
- m.y,
2517
- m.z
2518
- ][S], L = [
2519
- m.x,
2520
- m.y,
2521
- m.z
2522
- ][I];
2523
- p[S][I] -= x * P * L;
2524
- }
2525
- }
2526
- const g = new C();
2527
- for (let f = 0; f < t; f++) g.x += r.getX(f), g.y += r.getY(f), g.z += r.getZ(f);
2528
- g.divideScalar(t);
2529
- const M = [
2530
- 0,
2531
- 0,
2532
- 0
2533
- ];
2534
- for (let f = 0; f < 3; f++) {
2535
- let m = 1 / 0, x = -1 / 0;
2536
- const S = d[f];
2537
- for (let I = 0; I < t; I++) {
2538
- const P = r.getX(I) - g.x, L = r.getY(I) - g.y, b = r.getZ(I) - g.z, z = P * S.x + L * S.y + b * S.z;
2539
- z < m && (m = z), z > x && (x = z);
2540
- }
2541
- M[f] = (x - m) / 2;
2542
- }
2543
- return {
2544
- axes: d,
2545
- eigenvalues: u,
2546
- center: g,
2547
- halfExtents: M
2548
- };
2549
- }
2550
- function No({ pca: e }) {
2551
- return i("group", {
2552
- children: e.axes.map((r, t) => {
2553
- const o = e.center.clone().addScaledVector(r, e.halfExtents[t]), l = e.center.clone().addScaledVector(r, -e.halfExtents[t]);
2554
- return i(fe, {
2555
- points: [
2556
- l,
2557
- o
2558
- ],
2559
- color: jo[t],
2560
- lineWidth: 2
2561
- }, t);
2562
- })
2563
- });
2564
- }
2565
- function Yo({ pca: e }) {
2566
- const r = j(() => {
2567
- const { center: t, axes: o, halfExtents: l } = e, s = [];
2568
- for (let a = -1; a <= 1; a += 2) for (let n = -1; n <= 1; n += 2) for (let h = -1; h <= 1; h += 2) s.push(t.clone().addScaledVector(o[0], a * l[0]).addScaledVector(o[1], n * l[1]).addScaledVector(o[2], h * l[2]));
2569
- return [
2570
- [
2571
- 0,
2572
- 1
2573
- ],
2574
- [
2575
- 2,
2576
- 3
2577
- ],
2578
- [
2579
- 4,
2580
- 5
2581
- ],
2582
- [
2583
- 6,
2584
- 7
2585
- ],
2586
- [
2587
- 0,
2588
- 2
2589
- ],
2590
- [
2591
- 1,
2592
- 3
2593
- ],
2594
- [
2595
- 4,
2596
- 6
2597
- ],
2598
- [
2599
- 5,
2600
- 7
2601
- ],
2602
- [
2603
- 0,
2604
- 4
2605
- ],
2606
- [
2607
- 1,
2608
- 5
2609
- ],
2610
- [
2611
- 2,
2612
- 6
2613
- ],
2614
- [
2615
- 3,
2616
- 7
2617
- ]
2618
- ].map(([a, n]) => [
2619
- s[a],
2620
- s[n]
2621
- ]);
2622
- }, [
2623
- e
2624
- ]);
2625
- return i("group", {
2626
- children: r.map((t, o) => i(fe, {
2627
- points: t,
2628
- color: "#ffaa00",
2629
- lineWidth: 1,
2630
- transparent: true,
2631
- opacity: 0.5
2632
- }, o))
2633
- });
2634
- }
2635
- function Xo({ redPoint: e, greenPoint: r }) {
2636
- const t = j(() => new C().subVectors(r, e).normalize(), [
2637
- e,
2638
- r
2639
- ]), o = j(() => {
2640
- const s = t.dot(new C(0, 1, 0));
2641
- return Math.acos(Math.min(1, Math.abs(s))) * 180 / Math.PI;
2642
- }, [
2643
- t
2644
- ]), l = o < 1 ? "#44ff44" : o < 5 ? "#ffcc00" : "#ff4444";
2645
- return F("group", {
2646
- children: [
2647
- i(fe, {
2648
- points: [
2649
- e,
2650
- r
2651
- ],
2652
- color: l,
2653
- lineWidth: 3
2654
- }),
2655
- F("mesh", {
2656
- position: e,
2657
- children: [
2658
- i("sphereGeometry", {
2659
- args: [
2660
- 1.5,
2661
- 8,
2662
- 8
2663
- ]
2664
- }),
2665
- i("meshBasicMaterial", {
2666
- color: "#ff4444"
2667
- })
2668
- ]
2669
- }),
2670
- F("mesh", {
2671
- position: r,
2672
- children: [
2673
- i("sphereGeometry", {
2674
- args: [
2675
- 1.5,
2676
- 8,
2677
- 8
2678
- ]
2679
- }),
2680
- i("meshBasicMaterial", {
2681
- color: "#44ff44"
2682
- })
2683
- ]
2684
- })
2685
- ]
2686
- });
2687
- }
2688
- function Go({ geometry: e, redY: r, greenY: t, modelSize: o }) {
2689
- const s = o * 0.15, c = j(() => {
2690
- const a = [];
2691
- let n = t - 10;
2692
- const h = new C(0, 1, 0);
2693
- for (; n > r; ) {
2694
- const d = Math.min(n, t), u = Math.max(n, t), p = wn(e, d, u);
2695
- if (p) {
2696
- const g = p.dot(h), M = Math.acos(Math.min(1, Math.abs(g))) * 180 / Math.PI;
2697
- a.push({
2698
- axis: p,
2699
- regionMin: d,
2700
- regionMax: u,
2701
- angleDeg: M
2702
- });
2703
- }
2704
- n -= 10;
2705
- }
2706
- return a;
2707
- }, [
2708
- e,
2709
- r,
2710
- t
2711
- ]);
2712
- return i("group", {
2713
- children: c.map((a, n) => {
2714
- const h = (a.regionMin + a.regionMax) / 2, d = new C(0, h, 0), u = d.clone().addScaledVector(a.axis, s), p = d.clone().addScaledVector(a.axis, -s), g = n / Math.max(1, c.length - 1), M = a.angleDeg < 0.5 ? `hsl(${120 - g * 120}, 80%, 60%)` : `hsl(${40 - a.angleDeg * 2}, 90%, 55%)`;
2715
- return F("group", {
2716
- children: [
2717
- i(fe, {
2718
- points: [
2719
- p,
2720
- u
2721
- ],
2722
- color: M,
2723
- lineWidth: 1.5,
2724
- transparent: true,
2725
- opacity: 0.7
2726
- }),
2727
- i(fe, {
2728
- points: [
2729
- new C(-s * 0.3, a.regionMin, 0),
2730
- new C(s * 0.3, a.regionMin, 0)
2731
- ],
2732
- color: M,
2733
- lineWidth: 0.5,
2734
- transparent: true,
2735
- opacity: 0.3
2736
- })
2737
- ]
2738
- }, n);
2739
- })
2740
- });
2741
- }
2742
- function Zo({ geometry: e, redY: r, greenY: t, modelSize: o }) {
2743
- const l = j(() => {
2744
- const u = wn(e, r, t);
2745
- if (!u) return null;
2746
- const p = u.dot(new C(0, 1, 0)), g = Math.acos(Math.min(1, Math.abs(p))) * 180 / Math.PI;
2747
- return {
2748
- axis: u,
2749
- angleDeg: g
2750
- };
2751
- }, [
2752
- e,
2753
- r,
2754
- t
2755
- ]);
2756
- if (!l) return null;
2757
- const s = (r + t) / 2, c = new C(0, s, 0), a = o * 0.4, n = c.clone().addScaledVector(l.axis, a), h = c.clone().addScaledVector(l.axis, -a), d = l.angleDeg < 0.5 ? "#00ffff" : l.angleDeg < 2 ? "#ffcc00" : "#ff6600";
2758
- return i("group", {
2759
- children: i(fe, {
2760
- points: [
2761
- h,
2762
- n
2763
- ],
2764
- color: d,
2765
- lineWidth: 3,
2766
- dashed: true,
2767
- dashSize: 3,
2768
- gapSize: 2
2769
- })
2770
- });
2771
- }
2772
- function Ko({ pca: e, modelSize: r }) {
2773
- const t = e.axes[0], o = r * 0.6, l = e.center.clone().addScaledVector(t, o), s = e.center.clone().addScaledVector(t, -o);
2774
- return i(fe, {
2775
- points: [
2776
- s,
2777
- l
2778
- ],
2779
- color: "#ff8800",
2780
- lineWidth: 2,
2781
- dashed: true,
2782
- dashSize: 3,
2783
- gapSize: 2
2784
- });
2785
- }
2786
- function Uo({ geometry: e, redY: r, greenY: t, modelSize: o, measurementGeometry: l }) {
2787
- const s = j(() => {
2788
- const d = l ?? e, u = yn(d), p = new C(0, 1, 0), g = 5, f = t + 3 * 25.4, m = [];
2789
- for (let y = r + g; y < f; y += g) {
2790
- const D = ho(u, d, new C(0, y, 0), p);
2791
- D > 0 && m.push({
2792
- y,
2793
- circ: D
2794
- });
2795
- }
2796
- if (m.length < 5) return null;
2797
- const x = t - r, S = r + x * 0.3, I = r + x * 0.7, P = m.filter((y) => y.y >= S && y.y <= I);
2798
- if (P.length < 3) return null;
2799
- const L = P.map((y) => y.circ).sort((y, D) => y - D), b = L[Math.floor(L.length / 2)], z = Math.max(...m.map((y) => y.circ));
2800
- return {
2801
- circumferences: m,
2802
- baseline: b,
2803
- maxCirc: z
2804
- };
2805
- }, [
2806
- e,
2807
- r,
2808
- t
2809
- ]);
2810
- if (!s) return null;
2811
- const { circumferences: c, baseline: a, maxCirc: n } = s, h = o * 0.3 / n;
2812
- return F("group", {
2813
- children: [
2814
- c.map(({ y: d, circ: u }, p) => {
2815
- const g = u / a, M = g > 1.6 ? "#ff4444" : g > 1.3 ? "#ffcc00" : "#22cc66", f = u * h;
2816
- return i(fe, {
2817
- points: [
2818
- new C(-f, d, 0),
2819
- new C(f, d, 0)
2820
- ],
2821
- color: M,
2822
- lineWidth: 1.5,
2823
- transparent: true,
2824
- opacity: 0.6
2825
- }, p);
2826
- }),
2827
- (() => {
2828
- const d = a * 1.6 * h, u = c[0].y, p = c[c.length - 1].y;
2829
- return F(Oe, {
2830
- children: [
2831
- i(fe, {
2832
- points: [
2833
- new C(-d, u, 0),
2834
- new C(-d, p, 0)
2835
- ],
2836
- color: "#ff4444",
2837
- lineWidth: 1,
2838
- dashed: true,
2839
- dashSize: 3,
2840
- gapSize: 2,
2841
- transparent: true,
2842
- opacity: 0.4
2843
- }),
2844
- i(fe, {
2845
- points: [
2846
- new C(d, u, 0),
2847
- new C(d, p, 0)
2848
- ],
2849
- color: "#ff4444",
2850
- lineWidth: 1,
2851
- dashed: true,
2852
- dashSize: 3,
2853
- gapSize: 2,
2854
- transparent: true,
2855
- opacity: 0.4
2856
- })
2857
- ]
2858
- });
2859
- })()
2860
- ]
2861
- });
2862
- }
2863
- function Jo({ componentDebug: e }) {
2864
- return i("group", {
2865
- children: e.geometries.map((r, t) => {
2866
- const o = e.colors[t] ?? "#888888", l = t === e.innerIdx;
2867
- r.computeBoundingBox();
2868
- const s = new C();
2869
- return r.boundingBox.getCenter(s), F("group", {
2870
- children: [
2871
- i("mesh", {
2872
- geometry: r,
2873
- renderOrder: l ? 2 : 1,
2874
- children: i("meshStandardMaterial", {
2875
- color: o,
2876
- transparent: true,
2877
- opacity: l ? 0.5 : 0.2,
2878
- side: O.DoubleSide,
2879
- depthWrite: false,
2880
- polygonOffset: true,
2881
- polygonOffsetFactor: 1,
2882
- polygonOffsetUnits: 1
2883
- })
2884
- }),
2885
- i("mesh", {
2886
- geometry: r,
2887
- renderOrder: l ? 2 : 1,
2888
- children: i("meshBasicMaterial", {
2889
- color: o,
2890
- wireframe: true,
2891
- transparent: true,
2892
- opacity: l ? 0.4 : 0.15
2893
- })
2894
- }),
2895
- i("group", {
2896
- position: s,
2897
- children: i(Xe, {
2898
- center: true,
2899
- style: {
2900
- pointerEvents: "none"
2901
- },
2902
- children: i("div", {
2903
- style: {
2904
- padding: "2px 8px",
2905
- backgroundColor: "rgba(0,0,0,0.8)",
2906
- borderRadius: 4,
2907
- border: `1px solid ${o}`,
2908
- whiteSpace: "nowrap"
2909
- },
2910
- children: i("span", {
2911
- style: {
2912
- fontSize: 11,
2913
- color: o,
2914
- fontFamily: "monospace",
2915
- fontWeight: l ? 700 : 400
2916
- },
2917
- children: e.labels[t]
2918
- })
2919
- })
2920
- })
2921
- })
2922
- ]
2923
- }, t);
2924
- })
2925
- });
2926
- }
2927
- function Qo({ geometry: e, aoData: r }) {
2928
- const t = j(() => {
2929
- const o = e.toNonIndexed(), l = o.getAttribute("position"), s = r.length, c = l.count, a = new Float32Array(c * 3);
2930
- for (let n = 0; n < s && n * 3 + 2 < c; n++) {
2931
- const h = r[n], d = h, u = h < 0.5 ? 0.8 - h * 1.2 : 0.2 * (1 - h), p = 1 - h;
2932
- for (let g = 0; g < 3; g++) {
2933
- const M = (n * 3 + g) * 3;
2934
- a[M] = d, a[M + 1] = u, a[M + 2] = p;
2935
- }
2936
- }
2937
- return o.setAttribute("color", new O.Float32BufferAttribute(a, 3)), o;
2938
- }, [
2939
- e,
2940
- r
2941
- ]);
2942
- return j(() => () => t.dispose(), [
2943
- t
2944
- ]), i("mesh", {
2945
- geometry: t,
2946
- renderOrder: 3,
2947
- children: i("meshBasicMaterial", {
2948
- vertexColors: true,
2949
- transparent: true,
2950
- opacity: 0.85,
2951
- side: O.DoubleSide,
2952
- depthWrite: false
2953
- })
2954
- });
2955
- }
2956
- function qo({ mesh: e, layers: r, landmarkPoints: t, componentDebug: o, aoData: l, aoGeometry: s, measurementGeometry: c }) {
2957
- const a = e.geometry, n = j(() => a.getAttribute("position") ? Sn(a) : null, [
2958
- a
2959
- ]), h = j(() => !t || t.length < 2 ? null : {
2960
- red: new C(t[1].position.x, t[1].position.y, t[1].position.z),
2961
- green: new C(t[0].position.x, t[0].position.y, t[0].position.z)
2962
- }, [
2963
- t
2964
- ]);
2965
- return F("group", {
2966
- children: [
2967
- r.pcaAxes && n && i(No, {
2968
- pca: n
2969
- }),
2970
- r.obb && n && i(Yo, {
2971
- pca: n
2972
- }),
2973
- r.obbAxis && n && i(Ko, {
2974
- pca: n,
2975
- modelSize: n.halfExtents[0] ? Math.max(...n.halfExtents) * 2 : 100
2976
- }),
2977
- r.shellComponents && o && i(Jo, {
2978
- componentDebug: o
2979
- }),
2980
- r.ambientOcclusion && l && l.length > 0 && i(Qo, {
2981
- geometry: s ?? a,
2982
- aoData: l
2983
- }),
2984
- r.circumferenceScan && h && i(Uo, {
2985
- geometry: a,
2986
- redY: h.red.y,
2987
- greenY: h.green.y,
2988
- modelSize: (n == null ? void 0 : n.halfExtents[0]) ? Math.max(...n.halfExtents) * 2 : 100,
2989
- measurementGeometry: c
2990
- }),
2991
- c && i("mesh", {
2992
- geometry: c,
2993
- renderOrder: 5,
2994
- children: i("meshBasicMaterial", {
2995
- color: "#00ccff",
2996
- wireframe: true,
2997
- transparent: true,
2998
- opacity: 0.15,
2999
- depthWrite: false
3000
- })
3001
- }),
3002
- r.landmarkAxis && h && i(Xo, {
3003
- redPoint: h.red,
3004
- greenPoint: h.green
3005
- }),
3006
- r.iterativePCA && h && i(Go, {
3007
- geometry: a,
3008
- redY: h.red.y,
3009
- greenY: h.green.y,
3010
- modelSize: (n == null ? void 0 : n.halfExtents[0]) ? Math.max(...n.halfExtents) * 2 : 100
3011
- }),
3012
- r.fullRegionPCA && h && i(Zo, {
3013
- geometry: a,
3014
- redY: h.red.y,
3015
- greenY: h.green.y,
3016
- modelSize: (n == null ? void 0 : n.halfExtents[0]) ? Math.max(...n.halfExtents) * 2 : 100
3017
- })
3018
- ]
3019
- });
3020
- }
3021
- function er({ mesh: e }) {
3022
- const r = e.geometry, t = j(() => {
3023
- if (!r.getAttribute("position")) return null;
3024
- const s = Sn(r), c = s.axes[0], a = s.halfExtents[0] * 1.3;
3025
- return {
3026
- axis: c,
3027
- center: s.center,
3028
- halfLen: a
3029
- };
3030
- }, [
3031
- r
3032
- ]);
3033
- if (!t) return null;
3034
- const o = t.center.clone().addScaledVector(t.axis, t.halfLen), l = t.center.clone().addScaledVector(t.axis, -t.halfLen);
3035
- return i(fe, {
3036
- points: [
3037
- l,
3038
- o
3039
- ],
3040
- color: "#666",
3041
- lineWidth: 1,
3042
- dashed: true,
3043
- dashSize: 4,
3044
- gapSize: 3,
3045
- transparent: true,
3046
- opacity: 0.4,
3047
- depthTest: false,
3048
- renderOrder: 999
3049
- });
3050
- }
3051
- const vn = [
3052
- {
3053
- key: "pcaAxes",
3054
- label: "PCA Axes (full mesh)",
3055
- color: "#ff4444",
3056
- group: "Geometry"
3057
- },
3058
- {
3059
- key: "obb",
3060
- label: "OBB Wireframe",
3061
- color: "#ffaa00",
3062
- group: "Geometry"
3063
- },
3064
- {
3065
- key: "obbAxis",
3066
- label: "OBB Primary Axis",
3067
- color: "#ff8800",
3068
- group: "Geometry"
3069
- },
3070
- {
3071
- key: "shellComponents",
3072
- label: "Shell Components",
3073
- color: "#4488ff",
3074
- group: "Shell Detection"
3075
- },
3076
- {
3077
- key: "ambientOcclusion",
3078
- label: "Ambient Occlusion (inner faces)",
3079
- color: "#ff6644",
3080
- group: "Shell Detection"
3081
- },
3082
- {
3083
- key: "circumferenceScan",
3084
- label: "Circumference Scan (step 4.5)",
3085
- color: "#22cc66",
3086
- group: "Isolation",
3087
- hideWhenDoubleShell: true
3088
- },
3089
- {
3090
- key: "landmarkAxis",
3091
- label: "Landmark Axis (rough align)",
3092
- color: "#44ff44",
3093
- group: "Alignment"
3094
- },
3095
- {
3096
- key: "iterativePCA",
3097
- label: "Iterative PCA (step 5)",
3098
- color: "#cc66ff",
3099
- group: "Alignment"
3100
- },
3101
- {
3102
- key: "fullRegionPCA",
3103
- label: "Full Region PCA (step 7)",
3104
- color: "#00ffff",
3105
- group: "Alignment"
3106
- }
3107
- ], tr = [
3108
- ...new Set(vn.map((e) => e.group))
3109
- ];
3110
- function nr({ layers: e, onToggleLayer: r, isDoubleShell: t }) {
3111
- return F("div", {
3112
- style: {
3113
- position: "absolute",
3114
- top: 16,
3115
- left: 16,
3116
- zIndex: 20,
3117
- backgroundColor: "rgba(7, 6, 17, 0.9)",
3118
- border: "1px solid rgba(255,255,255,0.1)",
3119
- borderRadius: 6,
3120
- padding: "10px 12px",
3121
- fontFamily: "system-ui, sans-serif",
3122
- fontSize: 12,
3123
- color: "#ccc",
3124
- minWidth: 180,
3125
- backdropFilter: "blur(8px)"
3126
- },
3127
- children: [
3128
- i("div", {
3129
- style: {
3130
- fontSize: 10,
3131
- fontWeight: 600,
3132
- textTransform: "uppercase",
3133
- letterSpacing: "0.5px",
3134
- color: "#888",
3135
- marginBottom: 8
3136
- },
3137
- children: "Debug Layers"
3138
- }),
3139
- tr.map((o) => {
3140
- const l = vn.filter((s) => s.group === o && !(s.hideWhenDoubleShell && t));
3141
- return l.length === 0 ? null : F("div", {
3142
- children: [
3143
- i("div", {
3144
- style: {
3145
- fontSize: 9,
3146
- fontWeight: 600,
3147
- textTransform: "uppercase",
3148
- letterSpacing: "0.5px",
3149
- color: "#555",
3150
- marginTop: 6,
3151
- marginBottom: 4
3152
- },
3153
- children: o
3154
- }),
3155
- l.map(({ key: s, label: c, color: a }) => F("label", {
3156
- style: {
3157
- display: "flex",
3158
- alignItems: "center",
3159
- gap: 8,
3160
- padding: "3px 0",
3161
- cursor: "pointer",
3162
- userSelect: "none"
3163
- },
3164
- children: [
3165
- i("input", {
3166
- type: "checkbox",
3167
- checked: e[s],
3168
- onChange: () => r(s),
3169
- style: {
3170
- accentColor: a,
3171
- width: 14,
3172
- height: 14,
3173
- cursor: "pointer"
3174
- }
3175
- }),
3176
- i("span", {
3177
- style: {
3178
- width: 8,
3179
- height: 8,
3180
- borderRadius: "50%",
3181
- backgroundColor: a,
3182
- opacity: e[s] ? 1 : 0.3,
3183
- flexShrink: 0
3184
- }
3185
- }),
3186
- i("span", {
3187
- style: {
3188
- opacity: e[s] ? 1 : 0.5
3189
- },
3190
- children: c
3191
- })
3192
- ]
3193
- }, s))
3194
- ]
3195
- }, o);
3196
- })
3197
- ]
3198
- });
3199
- }
3200
- const or = ({ config: e, spacingType: r, scanUrl: t, formMeasurements: o, onComplete: l, isDebugUser: s = false, onAnalyticsEvent: c, wasmModule: a }) => {
3201
- const [n, h] = E(null), [d, u] = E(0), [p, g] = E(false), [M, f] = E(false), [m, x] = E(""), [S, I] = E("3D"), [P, L] = E(r === "AK" ? 2 : 1), [b, z] = E(false), [y, D] = E(null), [w, A] = E(r ?? null), [k, B] = E("mm"), [$, N] = E(false), [U, be] = E(""), [ae, ue] = E(false), [ie, J] = E(false), [Y, he] = E(false), [Z, ge] = E(false), [me, pe] = E(null), [H, q] = E(null), [xe, Ce] = E(null), [we, oe] = E(false), [V, X] = E([]), [Pe, Le] = E(null), [Ge, se] = E(null), [ze, Bt] = E(null), [gt, Mn] = E(null), [zn, Rt] = E(false), [Wt, An] = E(null), [mt, _e] = E(null), [Re, kn] = E(false), [Et, Fn] = E(Vo), [$e, Tt] = E("obj"), [Ae, xt] = E(o), [nt, Ot] = E(true), [$t, yt] = E(false), [Ht, Pn] = E(false), [Ie, ot] = E(false), [bt, Ln] = E(null), [Vt] = E("#c8c8c8"), [In] = E(1), [Ze, _n] = E(false), [wt, jt] = E([]), rt = le(null), He = le(null), St = le(false), Dn = le(null), vt = le(null), Ct = le(null), Ue = re(async () => {
3202
- if (Ct.current) try {
3203
- const v = (await import("./html2canvas.esm-Dmi1NfiH.js")).default, _ = Ct.current, W = 2, R = async (K = false) => {
3204
- const te = await v(_, {
3205
- backgroundColor: null,
3206
- useCORS: true,
3207
- scale: W,
3208
- ignoreElements: (et) => {
3209
- var _a, _b;
3210
- return ((_a = et.style) == null ? void 0 : _a.zIndex) === "10" || ((_b = et.hasAttribute) == null ? void 0 : _b.call(et, "data-finalizing-overlay"));
3211
- }
3212
- }), Q = _.getBoundingClientRect(), ke = Q.width, We = Q.height;
3213
- let ve, Me, ye, Te;
3214
- if (K) {
3215
- const De = te.getContext("2d").getImageData(0, 0, te.width, te.height).data;
3216
- let Be = te.width, Ee = te.height, tt = 0, lt = 0;
3217
- for (let Ve = 0; Ve < te.height; Ve++) for (let je = 0; je < te.width; je++) {
3218
- const Gn = (Ve * te.width + je) * 4;
3219
- De[Gn + 3] > 20 && (je < Be && (Be = je), je > tt && (tt = je), Ve < Ee && (Ee = Ve), Ve > lt && (lt = Ve));
3220
- }
3221
- tt <= Be && (Be = 0, Ee = 0, tt = te.width, lt = te.height), ve = Be / W, Me = Ee / W, ye = tt / W, Te = lt / W;
3222
- } else {
3223
- const et = _.querySelectorAll("[style*='pointer-events: none']");
3224
- ve = 1 / 0, Me = 1 / 0, ye = -1 / 0, Te = -1 / 0, et.forEach((Pt) => {
3225
- const De = Pt.getBoundingClientRect();
3226
- if (De.width === 0 || De.height === 0) return;
3227
- const Be = De.left - Q.left, Ee = De.top - Q.top;
3228
- Be < ve && (ve = Be), Ee < Me && (Me = Ee), Be + De.width > ye && (ye = Be + De.width), Ee + De.height > Te && (Te = Ee + De.height);
3229
- }), ve === 1 / 0 && (ve = 0, Me = 0, ye = ke, Te = We);
3230
- }
3231
- const Qt = Math.max(ke, We) * 0.03, qt = Math.max(ke, We) * 0.06;
3232
- ve = Math.max(0, ve - Qt), Me = Math.max(0, Me - qt), ye = Math.min(ke, ye + Qt), Te = Math.min(We, Te + qt);
3233
- const kt = (ye - ve) * W, Ft = (Te - Me) * W, Yn = Math.max(0, ve * W), Xn = Math.max(0, Me * W), st = document.createElement("canvas");
3234
- return st.width = Math.round(kt), st.height = Math.round(Ft), st.getContext("2d").drawImage(te, Math.round(Yn), Math.round(Xn), Math.round(kt), Math.round(Ft), 0, 0, Math.round(kt), Math.round(Ft)), st.toDataURL("image/png");
3235
- };
3236
- vt.current && vt.current(), await new Promise((K) => setTimeout(K, 100)), await new Promise((K) => requestAnimationFrame(() => requestAnimationFrame(K)));
3237
- const ce = await R();
3238
- I("2D"), await new Promise((K) => setTimeout(K, 200)), await new Promise((K) => requestAnimationFrame(() => requestAnimationFrame(K)));
3239
- const G = await R(true);
3240
- return I("3D"), {
3241
- frontal_view_png: ce,
3242
- side_view_png: G
3243
- };
3244
- } catch {
3245
- return;
3246
- }
3247
- }, []), Se = re((v) => {
3248
- const _ = /* @__PURE__ */ new Date(), W = `${String(_.getHours()).padStart(2, "0")}:${String(_.getMinutes()).padStart(2, "0")}:${String(_.getSeconds()).padStart(2, "0")}.${String(_.getMilliseconds()).padStart(3, "0")}`;
3249
- jt((R) => [
3250
- ...R.slice(-200),
3251
- `[${W}] ${v}`
3252
- ]);
3253
- }, []), { landmarkPoints: T, clearLandmarkPoints: Bn, addLandmarkPoint: Nt, removeLandmarkPoint: Yt, updateLandmarkPositions: Xt, setAligned: Gt, isAligned: ee, setCut: Zt, isCut: Mt, reset: Kt } = Dt();
3254
- ne(() => {
3255
- Kt();
3256
- }, [
3257
- Kt
3258
- ]);
3259
- const it = P * dt;
3260
- ne(() => {
3261
- if (!s || T.length === 0) return;
3262
- const v = T[T.length - 1];
3263
- Se(`LANDMARK[${T.length - 1}]: placed at (${v.position.x.toFixed(1)}, ${v.position.y.toFixed(1)}, ${v.position.z.toFixed(1)}) face=${v.faceIndex}`);
3264
- }, [
3265
- T.length,
3266
- s,
3267
- Se
3268
- ]), ne(() => {
3269
- s && ee && Se("STATE: mesh aligned");
3270
- }, [
3271
- ee,
3272
- s,
3273
- Se
3274
- ]), ne(() => {
3275
- s && Mt && Se("STATE: mesh cut");
3276
- }, [
3277
- Mt,
3278
- s,
3279
- Se
3280
- ]), ne(() => {
3281
- rt.current && (rt.current.scrollTop = rt.current.scrollHeight);
3282
- }, [
3283
- wt
3284
- ]);
3285
- const Ut = j(() => xe ? new O.Mesh(xe) : null, [
3286
- xe
3287
- ]);
3288
- ne(() => {
3289
- o && xt(o);
3290
- }, [
3291
- o
3292
- ]), ne(() => {
3293
- o || xt(void 0);
3294
- }, [
3295
- P
3296
- ]);
3297
- const zt = le(false);
3298
- ne(() => {
3299
- if (!ee || V.length === 0 || zt.current || !c) return;
3300
- zt.current = true;
3301
- const v = T.length >= 3 ? Math.abs(T[2].position.y - T[0].position.y) : null;
3302
- c("dimensions_calculated", {
3303
- spacing_type: w,
3304
- source_unit: "mm",
3305
- file_format: $e,
3306
- measurement_source: "scan_derived",
3307
- is_double_wall: Y,
3308
- is_unit_converted: false,
3309
- form_measurements: (Ae == null ? void 0 : Ae.filter((_) => _ != null)) ?? null,
3310
- scan_measurements: V.map((_) => +(_.modifiedValue ?? _.originalValue).toFixed(1)),
3311
- measurement_variance: Ae ? V.map((_, W) => {
3312
- const R = Ae[W];
3313
- return R == null ? null : +((_.modifiedValue ?? _.originalValue) - R).toFixed(1);
3314
- }) : null,
3315
- frontal_height: v !== null ? +v.toFixed(1) : null
3316
- });
3317
- }, [
3318
- ee,
3319
- V
3320
- ]), ne(() => {
3321
- a !== void 0 && (He.current = a), _n(true);
3322
- }, [
3323
- a
3324
- ]);
3325
- const Je = re((v, _) => {
3326
- v.computeBoundingBox();
3327
- const W = v.boundingBox, R = new C();
3328
- W.getCenter(R), v.translate(-R.x, -R.y, -R.z), v.computeBoundingBox();
3329
- const ce = v.boundingBox, G = new C();
3330
- ce.getSize(G), u(Math.max(G.x, G.y, G.z));
3331
- const K = new O.Mesh(v, new O.MeshStandardMaterial({
3332
- color: 8947848,
3333
- side: O.DoubleSide
3334
- }));
3335
- h(K), ue(_), J(true), ge(false), St.current = false;
3336
- }, []), Qe = re(async (v, _) => {
3337
- _e(null);
3338
- const W = _.toLowerCase(), R = W.endsWith(".stl");
3339
- if (!W.endsWith(".obj") && !R) {
3340
- _e("Unsupported file format. Please use OBJ or STL.");
3341
- return;
3342
- }
3343
- Tt(R ? "stl" : "obj"), f(true), x("Processing file..."), Se(`FILE_LOAD: ${_} (${R ? "STL" : "OBJ"})`);
3344
- try {
3345
- let G;
3346
- if (R) if (x("Converting STL..."), v instanceof ArrayBuffer) {
3347
- const Q = new Blob([
3348
- v
3349
- ]), ke = new File([
3350
- Q
3351
- ], _);
3352
- G = await Lt(ke);
3353
- } else {
3354
- const Q = new Blob([
3355
- v
3356
- ]), ke = new File([
3357
- Q
3358
- ], _);
3359
- G = await Lt(ke);
3360
- }
3361
- else G = typeof v == "string" ? v : new TextDecoder().decode(v);
3362
- const K = performance.now(), te = He.current ? await co(G, He.current, (Q) => {
3363
- x(Q), Se(`PREPROCESS: ${Q}`);
3364
- }) : null;
3365
- if (te) Se(`PREPROCESS: done in ${(performance.now() - K).toFixed(0)}ms \u2014 unit=${te.detectedUnit}, scaled=${te.wasScaled}`), e.showAmputationModal && !r ? (D(te), z(true)) : Je(te.geometry, te.wasScaled);
3366
- else {
3367
- x("Using fallback loader...");
3368
- const Q = fo(G);
3369
- Q ? e.showAmputationModal && !r ? (D({
3370
- geometry: Q,
3371
- wasScaled: false
3372
- }), z(true)) : Je(Q, false) : _e("Failed to parse the mesh.");
3373
- }
3374
- } catch (G) {
3375
- _e(G instanceof Error ? G.message : "Failed to process the mesh file.");
3376
- } finally {
3377
- f(false), x("");
3378
- }
3379
- }, [
3380
- Ze,
3381
- e.showAmputationModal,
3382
- r,
3383
- Je
3384
- ]);
3385
- ne(() => {
3386
- if (!t || !Ze) return;
3387
- (async () => {
3388
- f(true), x("Loading scan...");
3389
- try {
3390
- const _ = await fetch(t);
3391
- if (!_.ok) throw new Error(`Failed to download scan: ${_.status}`);
3392
- const R = new URL(t).pathname.split("/").pop() || "scan.obj";
3393
- if (R.toLowerCase().endsWith(".stl")) {
3394
- const G = await _.arrayBuffer();
3395
- await Qe(G, R);
3396
- } else {
3397
- const G = await _.text();
3398
- await Qe(G, R);
3399
- }
3400
- } catch (_) {
3401
- _e(_ instanceof Error ? _.message : "Failed to load scan from URL."), f(false), x("");
3402
- }
3403
- })();
3404
- }, [
3405
- t,
3406
- Ze
3407
- ]);
3408
- const Rn = re((v) => {
3409
- v.preventDefault(), g(true);
3410
- }, []), Wn = re((v) => {
3411
- v.preventDefault(), g(false);
3412
- }, []), En = re(async (v) => {
3413
- if (v.preventDefault(), g(false), !Ze) {
3414
- _e("WASM module is still loading. Please wait.");
3415
- return;
3416
- }
3417
- const _ = v.dataTransfer.files[0];
3418
- if (!_) return;
3419
- const W = _.name.toLowerCase();
3420
- if (!W.endsWith(".obj") && !W.endsWith(".stl")) {
3421
- _e("Please drop an OBJ or STL file.");
3422
- return;
3423
- }
3424
- if (W.endsWith(".stl")) {
3425
- Tt("stl"), f(true), x("Converting STL...");
3426
- try {
3427
- const R = await Lt(_);
3428
- await Qe(R, _.name.replace(/\.stl$/i, ".obj"));
3429
- } catch (R) {
3430
- _e(R instanceof Error ? R.message : "Failed to process STL file."), f(false), x("");
3431
- }
3432
- } else {
3433
- const R = await _.text();
3434
- await Qe(R, _.name);
3435
- }
3436
- }, [
3437
- Ze,
3438
- Qe
3439
- ]), Tn = re((v) => {
3440
- A(v), L(v === "AK" ? 2 : 1), z(false), y && (Je(y.geometry, y.wasScaled), D(null)), c == null ? void 0 : c("file_loaded", {
3441
- spacing_type: v,
3442
- file_format: $e,
3443
- is_double_wall: false
3444
- });
3445
- }, [
3446
- y,
3447
- Je,
3448
- c,
3449
- $e
3450
- ]);
3451
- ne(() => {
3452
- if (!n || T.length !== 1 || !He.current || St.current) return;
3453
- St.current = true;
3454
- const v = T[0], _ = He.current, W = n.geometry, { positions: R, indices: ce } = ft(W), G = new Float32Array([
3455
- v.position.x,
3456
- v.position.y,
3457
- v.position.z
3458
- ]), K = _.detect_shell(R, ce, G, 40), te = K.details(), Q = K.is_double_shell();
3459
- Se(`SHELL_DETECT: ${Q ? "DOUBLE" : "SINGLE"} \u2014 ${te}`), Q && (he(true), oe(true), Se(`SHELL_DETECT: double shell, thickness=${K.thickness().toFixed(1)}mm`));
3460
- }, [
3461
- n,
3462
- T,
3463
- Se
3464
- ]);
3465
- const On = re(() => {
3466
- if (!n || T.length < 2) return;
3467
- N(true), be("Please wait..."), Se("PIPELINE: starting processing pipeline...");
3468
- const v = performance.now();
3469
- setTimeout(() => {
3470
- const _ = [
3471
- T[1],
3472
- T[0],
3473
- ...T.slice(2)
3474
- ];
3475
- mo(n, _, dt, {
3476
- onStatus: (W) => {
3477
- be(W), Se(`PIPELINE: ${W}`);
3478
- },
3479
- addLandmarkPoint: Nt,
3480
- removeLandmarkPoint: Yt,
3481
- updateLandmarkPositions: (W) => {
3482
- const R = [
3483
- W[1],
3484
- W[0],
3485
- ...W.slice(2)
3486
- ];
3487
- Xt(R);
3488
- },
3489
- setAligned: Gt,
3490
- setCut: Zt,
3491
- setModelSize: u,
3492
- setOriginalEndY: Mn,
3493
- setAdjustedStartY: se,
3494
- setAdjustedEndY: Bt,
3495
- setError: _e,
3496
- setDoubleShell: (W) => {
3497
- he(W), oe(true);
3498
- },
3499
- setAoData: (W, R) => {
3500
- pe(W), q(R ?? null);
3501
- },
3502
- setInnerShellExtracted: ge,
3503
- setMeasurementGeometry: Ce,
3504
- setWasmSlices: Le,
3505
- wasmModule: He.current ?? void 0
3506
- }), Se(`PIPELINE: completed in ${(performance.now() - v).toFixed(0)}ms`), zt.current = false, N(false);
3507
- }, 50);
3508
- }, [
3509
- n,
3510
- T,
3511
- Xt,
3512
- Gt,
3513
- Nt,
3514
- Yt,
3515
- Zt,
3516
- Z
3517
- ]), Jt = le(false);
3518
- ne(() => {
3519
- ee && V.length > 0 && !Jt.current && (Jt.current = true, yt(true));
3520
- }, [
3521
- ee,
3522
- V.length
3523
- ]);
3524
- const qe = j(() => {
3525
- var _a;
3526
- if (!n || T.length < 3) return 0;
3527
- if (Y) return Math.abs(T[0].position.y - T[2].position.y);
3528
- const v = n.geometry;
3529
- v.computeBoundingBox();
3530
- const _ = ((_a = v.boundingBox) == null ? void 0 : _a.min.y) ?? 0;
3531
- return Math.abs(T[0].position.y - _);
3532
- }, [
3533
- n,
3534
- T,
3535
- Y
3536
- ]), $n = re((v) => {
3537
- Ln(v), xt(v.circumferences), yt(false), Ot(true), Pn(true);
3538
- }, []), Hn = re(async (v) => {
3539
- if (!(!l || !n || !w)) {
3540
- yt(false), ot(true);
3541
- try {
3542
- const _ = await Promise.race([
3543
- Ue(),
3544
- new Promise((W) => setTimeout(() => W(void 0), 8e3))
3545
- ]);
3546
- l({
3547
- spacingType: w,
3548
- sourceUnit: "mm",
3549
- fileFormat: $e,
3550
- measurementSource: "form_provided",
3551
- isDoubleWall: Y,
3552
- isUnitConverted: false,
3553
- formMeasurements: Ae,
3554
- scanMeasurements: V,
3555
- frontalHeight: qe,
3556
- transverseML: 0,
3557
- transverseAP: 0,
3558
- scanUrl: t,
3559
- decision: "skip",
3560
- skipReason: v,
3561
- screenshots: _
3562
- });
3563
- } finally {
3564
- ot(false);
3565
- }
3566
- }
3567
- }, [
3568
- l,
3569
- n,
3570
- w,
3571
- $e,
3572
- Y,
3573
- Ae,
3574
- V,
3575
- qe,
3576
- t,
3577
- Ue
3578
- ]), At = re(async (v) => {
3579
- if (!(!l || !n || V.length === 0 || !w)) {
3580
- ot(true);
3581
- try {
3582
- let _ = 0, W = 0;
3583
- if (T.length >= 2) {
3584
- const ce = n.geometry, K = T[0].position.y;
3585
- try {
3586
- const te = yn(ce), Q = Ye(te, ce, K);
3587
- if (Q.linePoints.length >= 2) {
3588
- let ke = Q.linePoints[0], We = Q.linePoints[0], ve = Q.linePoints[0], Me = Q.linePoints[0];
3589
- for (const ye of Q.linePoints) ye.x < ke.x && (ke = ye), ye.x > We.x && (We = ye), ye.z < ve.z && (ve = ye), ye.z > Me.z && (Me = ye);
3590
- _ = new C(ke.x, K, ke.z).distanceTo(new C(We.x, K, We.z)), W = new C(ve.x, K, ve.z).distanceTo(new C(Me.x, K, Me.z));
3591
- }
3592
- } catch {
3593
- }
3594
- }
3595
- const R = await Promise.race([
3596
- Ue(),
3597
- new Promise((ce) => setTimeout(() => ce(void 0), 8e3))
3598
- ]);
3599
- l({
3600
- spacingType: w,
3601
- sourceUnit: "mm",
3602
- fileFormat: $e,
3603
- measurementSource: v === "use_form_measurements" ? "form_provided" : "scan_derived",
3604
- isDoubleWall: Y,
3605
- isUnitConverted: false,
3606
- formMeasurements: Ae,
3607
- scanMeasurements: V,
3608
- frontalHeight: (bt == null ? void 0 : bt.frontalHeight) ?? qe,
3609
- transverseML: _,
3610
- transverseAP: W,
3611
- scanUrl: t,
3612
- decision: v,
3613
- userEnteredMeasurements: bt ?? void 0,
3614
- screenshots: R
3615
- });
3616
- } finally {
3617
- ot(false);
3618
- }
3619
- }
3620
- }, [
3621
- l,
3622
- n,
3623
- V,
3624
- w,
3625
- T,
3626
- $e,
3627
- Y,
3628
- Ae,
3629
- t,
3630
- bt,
3631
- qe,
3632
- Ue
3633
- ]), Vn = j(() => {
3634
- if (!Ae || V.length === 0) return false;
3635
- const v = Math.min(Ae.length, V.length);
3636
- if (v === 0) return false;
3637
- for (let _ = 0; _ < v; _++) {
3638
- const W = Ae[_], R = V[_];
3639
- if (!R || W == null || W === 0) continue;
3640
- const ce = R.modifiedValue ?? R.originalValue;
3641
- if (Math.abs(ce - W) > 7) return false;
3642
- }
3643
- return true;
3644
- }, [
3645
- Ae,
3646
- V
3647
- ]), jn = Ht ? 5 : ee && $t || ee ? 4 : n ? T.length === 0 ? 2 : 3 : 1, Nn = [
3648
- {
3649
- label: "Load File",
3650
- number: 1
3651
- },
3652
- {
3653
- label: w === "AK" ? "Set IT" : "Set MPT",
3654
- number: 2
3655
- },
3656
- {
3657
- label: "Set Origin",
3658
- number: 3
3659
- },
3660
- {
3661
- label: "Measurements",
3662
- number: 4
3663
- },
3664
- {
3665
- label: "Review",
3666
- number: 5
3667
- }
3668
- ];
3669
- return F(ro.Provider, {
3670
- value: e,
3671
- children: [
3672
- F("div", {
3673
- style: {
3674
- flex: 1,
3675
- display: "flex",
3676
- flexDirection: "column",
3677
- backgroundColor: "#F9F9FA",
3678
- minWidth: 0,
3679
- position: "relative",
3680
- height: "100%"
3681
- },
3682
- children: [
3683
- e.showToolbar && i("div", {
3684
- style: {
3685
- height: 83,
3686
- backgroundColor: "#9e9e9e",
3687
- flexShrink: 0,
3688
- position: "relative",
3689
- overflow: "hidden"
3690
- },
3691
- children: i("div", {
3692
- style: {
3693
- position: "absolute",
3694
- inset: 0,
3695
- opacity: 0.1,
3696
- backgroundImage: "repeating-linear-gradient(45deg, transparent, transparent 10px, #fff 10px, #fff 12px)",
3697
- pointerEvents: "none"
3698
- }
3699
- })
3700
- }),
3701
- i(Bo, {
3702
- steps: Nn,
3703
- currentStep: jn
3704
- }),
3705
- F("div", {
3706
- style: {
3707
- flex: 1,
3708
- display: "flex",
3709
- flexDirection: "column",
3710
- minHeight: 0
3711
- },
3712
- children: [
3713
- F("div", {
3714
- ref: Ct,
3715
- style: {
3716
- flex: 1,
3717
- position: "relative",
3718
- minHeight: 0,
3719
- overflow: "hidden"
3720
- },
3721
- onDragOver: e.showDragDrop ? Rn : void 0,
3722
- onDragLeave: e.showDragDrop ? Wn : void 0,
3723
- onDrop: e.showDragDrop ? En : void 0,
3724
- children: [
3725
- e.showDragDrop && !n && !M && i("div", {
3726
- style: {
3727
- position: "absolute",
3728
- inset: 16,
3729
- border: "3px dashed #ccc",
3730
- borderRadius: 4,
3731
- display: "flex",
3732
- alignItems: "center",
3733
- justifyContent: "center",
3734
- pointerEvents: "none"
3735
- },
3736
- children: Ze ? i("div", {
3737
- style: {
3738
- fontSize: 18,
3739
- color: "#aaa",
3740
- fontWeight: 400,
3741
- fontFamily: "system-ui, sans-serif"
3742
- },
3743
- children: "Drag & Drop Files Here"
3744
- }) : F("div", {
3745
- style: {
3746
- textAlign: "center"
3747
- },
3748
- children: [
3749
- i("div", {
3750
- style: {
3751
- width: 32,
3752
- height: 32,
3753
- border: "3px solid rgba(0,0,0,0.1)",
3754
- borderTopColor: "#4a90d9",
3755
- borderRadius: "50%",
3756
- animation: "spin 1s linear infinite",
3757
- margin: "0 auto 12px"
3758
- }
3759
- }),
3760
- i("div", {
3761
- style: {
3762
- fontSize: 16,
3763
- color: "#999",
3764
- fontFamily: "system-ui, sans-serif"
3765
- },
3766
- children: "Loading WASM module..."
3767
- }),
3768
- i("style", {
3769
- children: "@keyframes spin { to { transform: rotate(360deg); } }"
3770
- })
3771
- ]
3772
- })
3773
- }),
3774
- !e.showDragDrop && !n && !M && !mt && i("div", {
3775
- style: {
3776
- position: "absolute",
3777
- inset: 0,
3778
- display: "flex",
3779
- alignItems: "center",
3780
- justifyContent: "center"
3781
- },
3782
- children: F("div", {
3783
- style: {
3784
- textAlign: "center"
3785
- },
3786
- children: [
3787
- i("div", {
3788
- style: {
3789
- width: 32,
3790
- height: 32,
3791
- border: "3px solid rgba(0,0,0,0.1)",
3792
- borderTopColor: "#4a90d9",
3793
- borderRadius: "50%",
3794
- animation: "spin 1s linear infinite",
3795
- margin: "0 auto 12px"
3796
- }
3797
- }),
3798
- i("div", {
3799
- style: {
3800
- fontSize: 16,
3801
- color: "#999",
3802
- fontFamily: "system-ui, sans-serif"
3803
- },
3804
- children: "Loading scan..."
3805
- }),
3806
- i("style", {
3807
- children: "@keyframes spin { to { transform: rotate(360deg); } }"
3808
- })
3809
- ]
3810
- })
3811
- }),
3812
- n && !ee && T.length === 0 && F("div", {
3813
- style: {
3814
- position: "absolute",
3815
- top: 16,
3816
- left: "50%",
3817
- transform: "translateX(-50%)",
3818
- display: "flex",
3819
- alignItems: "center",
3820
- gap: 8,
3821
- padding: "8px 16px",
3822
- backgroundColor: "rgba(0, 0, 0, 0.6)",
3823
- borderRadius: 8,
3824
- color: "#fff",
3825
- fontSize: 13,
3826
- pointerEvents: "none",
3827
- zIndex: 5,
3828
- fontFamily: "system-ui, sans-serif"
3829
- },
3830
- children: [
3831
- i("div", {
3832
- style: {
3833
- width: 10,
3834
- height: 10,
3835
- borderRadius: "50%",
3836
- backgroundColor: "#44ff44",
3837
- flexShrink: 0
3838
- }
3839
- }),
3840
- "Click mesh to set ",
3841
- w === "AK" ? "IT" : "MPT"
3842
- ]
3843
- }),
3844
- n && !ee && T.length === 1 && F("div", {
3845
- style: {
3846
- position: "absolute",
3847
- top: 16,
3848
- left: "50%",
3849
- transform: "translateX(-50%)",
3850
- display: "flex",
3851
- alignItems: "center",
3852
- gap: 8,
3853
- padding: "8px 16px",
3854
- backgroundColor: "rgba(0, 0, 0, 0.6)",
3855
- borderRadius: 8,
3856
- color: "#fff",
3857
- fontSize: 13,
3858
- pointerEvents: "none",
3859
- zIndex: 5,
3860
- fontFamily: "system-ui, sans-serif"
3861
- },
3862
- children: [
3863
- i("div", {
3864
- style: {
3865
- width: 10,
3866
- height: 10,
3867
- borderRadius: "50%",
3868
- backgroundColor: "#ff4444",
3869
- flexShrink: 0
3870
- }
3871
- }),
3872
- "Click mesh to set Origin"
3873
- ]
3874
- }),
3875
- M && i(on, {
3876
- message: m || "Processing mesh..."
3877
- }),
3878
- $ && i(on, {
3879
- message: U
3880
- }),
3881
- mt && i(yo, {
3882
- message: mt,
3883
- onDismiss: () => _e(null)
3884
- }),
3885
- e.showAmputationModal && b && i("div", {
3886
- style: {
3887
- position: "absolute",
3888
- inset: 0,
3889
- backgroundColor: "rgba(0,0,0,0.32)",
3890
- backdropFilter: "blur(6px)",
3891
- WebkitBackdropFilter: "blur(6px)",
3892
- display: "flex",
3893
- alignItems: "center",
3894
- justifyContent: "center",
3895
- zIndex: 20
3896
- },
3897
- children: F("div", {
3898
- style: {
3899
- backgroundColor: "#fff",
3900
- borderRadius: 4,
3901
- width: 560,
3902
- boxShadow: "0 11px 15px -7px rgba(0,0,0,0.2), 0 24px 38px 3px rgba(0,0,0,0.14), 0 9px 46px 8px rgba(0,0,0,0.12)",
3903
- fontFamily: "system-ui, sans-serif"
3904
- },
3905
- children: [
3906
- F("div", {
3907
- style: {
3908
- padding: "24px 24px 20px"
3909
- },
3910
- children: [
3911
- i("div", {
3912
- style: {
3913
- fontSize: 20,
3914
- fontWeight: 500,
3915
- color: "rgba(0,0,0,0.87)",
3916
- marginBottom: 8
3917
- },
3918
- children: "Select Spacing Type"
3919
- }),
3920
- i("div", {
3921
- style: {
3922
- fontSize: 14,
3923
- color: "rgba(0,0,0,0.54)",
3924
- marginBottom: 24
3925
- },
3926
- children: "Choose the measurement spacing for this scan"
3927
- }),
3928
- i("div", {
3929
- style: {
3930
- display: "flex",
3931
- gap: 16
3932
- },
3933
- children: [
3934
- "AK",
3935
- "BK"
3936
- ].map((v) => F("label", {
3937
- onClick: () => A(v),
3938
- style: {
3939
- flex: 1,
3940
- display: "flex",
3941
- flexDirection: "column",
3942
- padding: "20px 24px",
3943
- border: "2px solid",
3944
- borderRadius: 4,
3945
- cursor: "pointer",
3946
- borderColor: w === v ? "rgb(12, 67, 173)" : "#e0e0e0",
3947
- backgroundColor: w === v ? "rgba(12, 67, 173, 0.04)" : "#fff",
3948
- transition: "border-color 0.15s, background-color 0.15s"
3949
- },
3950
- children: [
3951
- i("input", {
3952
- type: "radio",
3953
- name: "ampType",
3954
- checked: w === v,
3955
- onChange: () => A(v),
3956
- style: {
3957
- accentColor: "rgb(12, 67, 173)",
3958
- marginBottom: 12,
3959
- width: 18,
3960
- height: 18
3961
- }
3962
- }),
3963
- i("span", {
3964
- style: {
3965
- fontSize: 18,
3966
- fontWeight: 600,
3967
- color: "rgba(0,0,0,0.87)",
3968
- marginBottom: 4
3969
- },
3970
- children: v
3971
- }),
3972
- F("span", {
3973
- style: {
3974
- fontSize: 13,
3975
- color: "rgba(0,0,0,0.54)"
3976
- },
3977
- children: [
3978
- v === "AK" ? "2" : "1",
3979
- "-inch measurement spacing"
3980
- ]
3981
- })
3982
- ]
3983
- }, v))
3984
- })
3985
- ]
3986
- }),
3987
- F("div", {
3988
- style: {
3989
- display: "flex",
3990
- justifyContent: "flex-end",
3991
- gap: 8,
3992
- padding: "12px 24px 20px",
3993
- borderTop: "1px solid #e0e0e0"
3994
- },
3995
- children: [
3996
- i("button", {
3997
- onClick: () => {
3998
- z(false), D(null);
3999
- },
4000
- style: {
4001
- padding: "6px 16px",
4002
- borderRadius: 4,
4003
- fontSize: 14,
4004
- fontWeight: 500,
4005
- backgroundColor: "#fff",
4006
- border: "1px solid #bdbdbd",
4007
- color: "rgba(0,0,0,0.87)",
4008
- cursor: "pointer",
4009
- fontFamily: "system-ui, sans-serif",
4010
- lineHeight: "36px",
4011
- letterSpacing: "0.4px"
4012
- },
4013
- children: "Cancel"
4014
- }),
4015
- i("button", {
4016
- onClick: () => w && Tn(w),
4017
- disabled: !w,
4018
- style: {
4019
- padding: "6px 16px",
4020
- borderRadius: 4,
4021
- fontSize: 14,
4022
- fontWeight: 500,
4023
- backgroundColor: w ? "rgb(12, 67, 173)" : "#e0e0e0",
4024
- border: "none",
4025
- color: w ? "#fff" : "#9e9e9e",
4026
- cursor: w ? "pointer" : "not-allowed",
4027
- fontFamily: "system-ui, sans-serif",
4028
- lineHeight: "36px",
4029
- letterSpacing: "0.4px"
4030
- },
4031
- children: "Next \xBB"
4032
- })
4033
- ]
4034
- })
4035
- ]
4036
- })
4037
- }),
4038
- e.showDragDrop && p && i("div", {
4039
- style: {
4040
- position: "absolute",
4041
- inset: 0,
4042
- backgroundColor: "rgba(12, 67, 173, 0.1)",
4043
- border: "2px dashed rgb(12, 67, 173)",
4044
- pointerEvents: "none",
4045
- zIndex: 10
4046
- }
4047
- }),
4048
- i(xo, {
4049
- children: F(Qn, {
4050
- camera: {
4051
- position: [
4052
- 0,
4053
- 0,
4054
- 5
4055
- ]
4056
- },
4057
- style: {
4058
- display: n ? "block" : "none",
4059
- backgroundColor: Re ? "#070611" : void 0
4060
- },
4061
- gl: {
4062
- localClippingEnabled: true,
4063
- preserveDrawingBuffer: true
4064
- },
4065
- scene: {
4066
- background: Re ? new O.Color("#070611") : null
4067
- },
4068
- children: [
4069
- i("ambientLight", {
4070
- intensity: 0.4
4071
- }),
4072
- i("directionalLight", {
4073
- position: [
4074
- 10,
4075
- 10,
4076
- 5
4077
- ],
4078
- intensity: 1.2
4079
- }),
4080
- i("directionalLight", {
4081
- position: [
4082
- -5,
4083
- 5,
4084
- -5
4085
- ],
4086
- intensity: 0.4
4087
- }),
4088
- i("directionalLight", {
4089
- position: [
4090
- 0,
4091
- -10,
4092
- 0
4093
- ],
4094
- intensity: 0.2
4095
- }),
4096
- n && S === "3D" && i(wo, {
4097
- mesh: n,
4098
- maxPoints: 2,
4099
- meshColor: Vt,
4100
- meshOpacity: Re ? 0.3 : In,
4101
- frontFaceOnly: Z,
4102
- doubleShellTransparency: Y && ee
4103
- }),
4104
- n && S === "3D" && i(vo, {
4105
- modelSize: d,
4106
- labels: [
4107
- w === "AK" ? "IT" : "MPT",
4108
- "Origin",
4109
- "Cut Plane"
4110
- ]
4111
- }),
4112
- i(Lo, {
4113
- modelSize: d,
4114
- isAligned: ee,
4115
- isCut: Mt,
4116
- mesh: n,
4117
- viewMode: S,
4118
- sliceY: ee && T.length >= 2 ? ze ?? gt ?? T[0].position.y : void 0,
4119
- landmarkCount: T.length,
4120
- measurementGeometry: xe,
4121
- resetCameraToFrontRef: vt
4122
- }),
4123
- !ee && i(dn, {
4124
- enableDamping: false
4125
- }),
4126
- ee && V.length > 0 && n && S === "3D" && i(Io, {
4127
- mesh: n,
4128
- isDragging: zn
4129
- }),
4130
- n && ee && T.length >= 3 && (() => {
4131
- const _ = n.geometry.getIndex();
4132
- if (!_ || _.count < 30) return null;
4133
- const W = T[2], R = T[0], ce = Ge ?? W.position.y, G = ze ?? gt ?? R.position.y;
4134
- return S === "2D" ? i(Ro, {
4135
- mesh: Ut ?? n,
4136
- upperY: G,
4137
- originY: R.position.y,
4138
- modelSize: d,
4139
- meshColor: Vt,
4140
- displayUnit: k
4141
- }) : F(Oe, {
4142
- children: [
4143
- i(Fo, {
4144
- mesh: Ut ?? n,
4145
- startY: ce,
4146
- endY: G,
4147
- spacing: it,
4148
- modelSize: d,
4149
- onMeasurementsChange: X,
4150
- reverseOrder: true,
4151
- displayUnit: k,
4152
- useInnerSurface: Y && !Z,
4153
- formMeasurements: nt ? Ae : void 0,
4154
- originY: Wt ?? R.position.y,
4155
- wasmSlices: Pe
4156
- }),
4157
- i(Po, {
4158
- mesh: n,
4159
- greenY: R.position.y,
4160
- modelSize: d,
4161
- displayUnit: k,
4162
- bottomY: Y ? W.position.y : void 0
4163
- }),
4164
- i(Wo, {
4165
- mesh: n,
4166
- yPosition: Wt ?? R.position.y,
4167
- onYChange: (K) => {
4168
- An(K), Le(null);
4169
- const te = K - R.position.y;
4170
- Bt((gt ?? R.position.y + it * 2) + te);
4171
- },
4172
- minY: R.position.y - it,
4173
- maxY: R.position.y + it,
4174
- modelSize: d,
4175
- color: "#44ff44",
4176
- hoverColor: "#88ff88",
4177
- dragColor: "#ffffff",
4178
- label: w === "AK" ? "IT" : "MPT",
4179
- onDragStart: () => Rt(true),
4180
- onDragEnd: () => Rt(false)
4181
- })
4182
- ]
4183
- });
4184
- })(),
4185
- n && ee && S === "3D" && Re && i(er, {
4186
- mesh: n
4187
- }),
4188
- n && e.showDebug && Re && S === "3D" && i(qo, {
4189
- mesh: n,
4190
- modelSize: d,
4191
- layers: Et,
4192
- landmarkPoints: T,
4193
- componentDebug: null,
4194
- aoData: me,
4195
- aoGeometry: H,
4196
- measurementGeometry: xe
4197
- }),
4198
- i(rr, {
4199
- screenshotFnRef: Dn,
4200
- mesh: n,
4201
- modelSize: d,
4202
- measurementGeometry: xe
4203
- })
4204
- ]
4205
- })
4206
- }),
4207
- n && F("div", {
4208
- style: {
4209
- position: "absolute",
4210
- top: 16,
4211
- left: 16,
4212
- zIndex: 10,
4213
- display: "flex",
4214
- gap: 8
4215
- },
4216
- children: [
4217
- e.showStartOver && i("button", {
4218
- onClick: () => window.location.reload(),
4219
- style: {
4220
- padding: "6px 16px",
4221
- borderRadius: 4,
4222
- fontSize: 13,
4223
- fontWeight: 500,
4224
- backgroundColor: "#fff",
4225
- border: "1px solid #bdbdbd",
4226
- color: "#333",
4227
- cursor: "pointer",
4228
- fontFamily: "system-ui, sans-serif",
4229
- letterSpacing: "0.4px",
4230
- boxShadow: "0 2px 8px rgba(0,0,0,0.1)"
4231
- },
4232
- children: "Start Over"
4233
- }),
4234
- !ee && T.length >= 1 && i("button", {
4235
- onClick: Bn,
4236
- style: {
4237
- padding: "6px 16px",
4238
- borderRadius: 4,
4239
- fontSize: 13,
4240
- fontWeight: 500,
4241
- backgroundColor: "#fff",
4242
- border: "1px solid #bdbdbd",
4243
- color: "#333",
4244
- cursor: "pointer",
4245
- fontFamily: "system-ui, sans-serif",
4246
- letterSpacing: "0.4px",
4247
- boxShadow: "0 2px 8px rgba(0,0,0,0.1)"
4248
- },
4249
- children: "Reset Points"
4250
- })
4251
- ]
4252
- }),
4253
- e.showDebug && Re && n && S === "3D" && i(nr, {
4254
- layers: Et,
4255
- onToggleLayer: (v) => Fn((_) => ({
4256
- ..._,
4257
- [v]: !_[v]
4258
- })),
4259
- isDoubleShell: Y
4260
- }),
4261
- ee && V.length > 0 && F("div", {
4262
- style: {
4263
- position: "absolute",
4264
- top: 16,
4265
- right: 16,
4266
- display: "flex",
4267
- gap: 8,
4268
- zIndex: 10
4269
- },
4270
- children: [
4271
- F("div", {
4272
- style: {
4273
- display: "flex",
4274
- borderRadius: 6,
4275
- overflow: "hidden",
4276
- border: "1px solid #ccc",
4277
- boxShadow: "0 2px 8px rgba(0,0,0,0.1)"
4278
- },
4279
- children: [
4280
- i("button", {
4281
- onClick: () => I("3D"),
4282
- style: {
4283
- padding: "6px 14px",
4284
- fontSize: 13,
4285
- fontWeight: S === "3D" ? 600 : 400,
4286
- backgroundColor: S === "3D" ? "rgb(12, 67, 173)" : "#fff",
4287
- color: S === "3D" ? "#fff" : "#666",
4288
- border: "none",
4289
- cursor: "pointer",
4290
- fontFamily: "system-ui, sans-serif"
4291
- },
4292
- children: "Orbital"
4293
- }),
4294
- i("button", {
4295
- onClick: () => I("2D"),
4296
- style: {
4297
- padding: "6px 14px",
4298
- fontSize: 13,
4299
- fontWeight: S === "2D" ? 600 : 400,
4300
- backgroundColor: S === "2D" ? "rgb(12, 67, 173)" : "#fff",
4301
- color: S === "2D" ? "#fff" : "#666",
4302
- border: "none",
4303
- borderLeft: "1px solid #ccc",
4304
- cursor: "pointer",
4305
- fontFamily: "system-ui, sans-serif"
4306
- },
4307
- children: "Transverse"
4308
- })
4309
- ]
4310
- }),
4311
- F("div", {
4312
- style: {
4313
- display: "flex",
4314
- borderRadius: 6,
4315
- overflow: "hidden",
4316
- border: "1px solid #ccc",
4317
- boxShadow: "0 2px 8px rgba(0,0,0,0.1)"
4318
- },
4319
- children: [
4320
- i("button", {
4321
- onClick: () => B("mm"),
4322
- style: {
4323
- padding: "6px 14px",
4324
- fontSize: 13,
4325
- fontWeight: k === "mm" ? 600 : 400,
4326
- backgroundColor: k === "mm" ? "rgb(12, 67, 173)" : "#fff",
4327
- color: k === "mm" ? "#fff" : "#666",
4328
- border: "none",
4329
- cursor: "pointer",
4330
- fontFamily: "system-ui, sans-serif"
4331
- },
4332
- children: "mm"
4333
- }),
4334
- i("button", {
4335
- onClick: () => B("inch"),
4336
- style: {
4337
- padding: "6px 14px",
4338
- fontSize: 13,
4339
- fontWeight: k === "inch" ? 600 : 400,
4340
- backgroundColor: k === "inch" ? "rgb(12, 67, 173)" : "#fff",
4341
- color: k === "inch" ? "#fff" : "#666",
4342
- border: "none",
4343
- borderLeft: "1px solid #ccc",
4344
- cursor: "pointer",
4345
- fontFamily: "system-ui, sans-serif"
4346
- },
4347
- children: "in"
4348
- })
4349
- ]
4350
- }),
4351
- e.showSpacingToggle && S === "3D" && F("div", {
4352
- style: {
4353
- display: "flex",
4354
- borderRadius: 6,
4355
- overflow: "hidden",
4356
- border: "1px solid #ccc",
4357
- boxShadow: "0 2px 8px rgba(0,0,0,0.1)"
4358
- },
4359
- children: [
4360
- i("button", {
4361
- onClick: () => L(1),
4362
- style: {
4363
- padding: "6px 14px",
4364
- fontSize: 13,
4365
- fontWeight: P === 1 ? 600 : 400,
4366
- backgroundColor: P === 1 ? "rgb(12, 67, 173)" : "#fff",
4367
- color: P === 1 ? "#fff" : "#666",
4368
- border: "none",
4369
- cursor: "pointer",
4370
- fontFamily: "system-ui, sans-serif"
4371
- },
4372
- children: '1"'
4373
- }),
4374
- i("button", {
4375
- onClick: () => L(2),
4376
- style: {
4377
- padding: "6px 14px",
4378
- fontSize: 13,
4379
- fontWeight: P === 2 ? 600 : 400,
4380
- backgroundColor: P === 2 ? "rgb(12, 67, 173)" : "#fff",
4381
- color: P === 2 ? "#fff" : "#666",
4382
- border: "none",
4383
- borderLeft: "1px solid #ccc",
4384
- cursor: "pointer",
4385
- fontFamily: "system-ui, sans-serif"
4386
- },
4387
- children: '2"'
4388
- })
4389
- ]
4390
- }),
4391
- S === "3D" && Ae && i("div", {
4392
- style: {
4393
- display: "flex",
4394
- borderRadius: 6,
4395
- overflow: "hidden",
4396
- border: "1px solid #ccc",
4397
- boxShadow: "0 2px 8px rgba(0,0,0,0.1)"
4398
- },
4399
- children: i("button", {
4400
- onClick: () => Ot((v) => !v),
4401
- style: {
4402
- padding: "6px 14px",
4403
- fontSize: 13,
4404
- fontWeight: nt ? 600 : 400,
4405
- backgroundColor: nt ? "rgb(12, 67, 173)" : "#fff",
4406
- color: nt ? "#fff" : "#666",
4407
- border: "none",
4408
- cursor: "pointer",
4409
- fontFamily: "system-ui, sans-serif"
4410
- },
4411
- children: "Measurement Overlay"
4412
- })
4413
- }),
4414
- e.showSaveButton && i("div", {
4415
- style: {
4416
- display: "flex",
4417
- borderRadius: 6,
4418
- overflow: "hidden",
4419
- border: "1px solid #ccc",
4420
- boxShadow: "0 2px 8px rgba(0,0,0,0.1)"
4421
- },
4422
- children: i("button", {
4423
- onClick: async () => {
4424
- const v = await Ue();
4425
- if (!v) return;
4426
- const _ = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10), W = (R, ce) => {
4427
- const G = document.createElement("a");
4428
- G.href = R, G.download = ce, G.click();
4429
- };
4430
- W(v.frontal_view_png, `measurements_front_${_}.png`), await new Promise((R) => setTimeout(R, 300)), W(v.side_view_png, `measurements_transverse_${_}.png`);
4431
- },
4432
- style: {
4433
- padding: "6px 14px",
4434
- fontSize: 13,
4435
- fontWeight: 400,
4436
- backgroundColor: "#fff",
4437
- color: "#666",
4438
- border: "none",
4439
- cursor: "pointer",
4440
- fontFamily: "system-ui, sans-serif"
4441
- },
4442
- children: "Save"
4443
- })
4444
- }),
4445
- e.showDebug && s && i("div", {
4446
- style: {
4447
- display: "flex",
4448
- borderRadius: 6,
4449
- overflow: "hidden",
4450
- border: "1px solid #ccc",
4451
- boxShadow: "0 2px 8px rgba(0,0,0,0.1)"
4452
- },
4453
- children: i("button", {
4454
- onClick: () => kn((v) => !v),
4455
- style: {
4456
- padding: "6px 14px",
4457
- fontSize: 13,
4458
- fontWeight: Re ? 600 : 400,
4459
- backgroundColor: Re ? "#e65100" : "#fff",
4460
- color: Re ? "#fff" : "#666",
4461
- border: "none",
4462
- cursor: "pointer",
4463
- fontFamily: "system-ui, sans-serif"
4464
- },
4465
- children: "Debug"
4466
- })
4467
- })
4468
- ]
4469
- }),
4470
- n && ie && i(_o, {
4471
- wasAutoScaled: ae,
4472
- onDismiss: () => J(false)
4473
- }),
4474
- n && we && ee && i(Do, {
4475
- isDoubleShell: Y,
4476
- onDismiss: () => oe(false)
4477
- })
4478
- ]
4479
- }),
4480
- Ie && F("div", {
4481
- "data-finalizing-overlay": true,
4482
- style: {
4483
- position: "absolute",
4484
- inset: 0,
4485
- backgroundColor: "#fff",
4486
- display: "flex",
4487
- flexDirection: "column",
4488
- alignItems: "center",
4489
- justifyContent: "center",
4490
- zIndex: 50
4491
- },
4492
- children: [
4493
- i("div", {
4494
- style: {
4495
- width: 32,
4496
- height: 32,
4497
- border: "3px solid #e0e0e0",
4498
- borderTopColor: "rgb(12, 67, 173)",
4499
- borderRadius: "50%",
4500
- animation: "gm-spin 0.8s linear infinite"
4501
- }
4502
- }),
4503
- i("p", {
4504
- style: {
4505
- marginTop: 12,
4506
- fontSize: 14,
4507
- color: "#555",
4508
- fontFamily: "system-ui, sans-serif"
4509
- },
4510
- children: "Generating screenshots and preparing data\u2026"
4511
- }),
4512
- i("style", {
4513
- children: "@keyframes gm-spin { to { transform: rotate(360deg) } }"
4514
- })
4515
- ]
4516
- }),
4517
- F("div", {
4518
- style: {
4519
- padding: "12px 24px",
4520
- backgroundColor: "#fff",
4521
- borderTop: "1px solid #e0e0e0",
4522
- display: "flex",
4523
- alignItems: "center",
4524
- justifyContent: "flex-end",
4525
- gap: 8,
4526
- flexShrink: 0
4527
- },
4528
- children: [
4529
- n && !ee && T.length >= 2 && i("button", {
4530
- onClick: On,
4531
- style: {
4532
- padding: "6px 16px",
4533
- borderRadius: 4,
4534
- fontSize: 14,
4535
- fontWeight: 500,
4536
- backgroundColor: "rgb(12, 67, 173)",
4537
- border: "none",
4538
- color: "#fff",
4539
- cursor: "pointer",
4540
- fontFamily: "system-ui, sans-serif",
4541
- letterSpacing: "0.4px",
4542
- lineHeight: "36px"
4543
- },
4544
- children: "Next \xBB"
4545
- }),
4546
- ee && Ht && (Vn ? i("button", {
4547
- disabled: Ie,
4548
- onClick: () => At("continue"),
4549
- style: {
4550
- padding: "6px 16px",
4551
- borderRadius: 4,
4552
- fontSize: 14,
4553
- fontWeight: 500,
4554
- backgroundColor: Ie ? "#9e9e9e" : "rgb(12, 67, 173)",
4555
- border: "none",
4556
- color: "#fff",
4557
- cursor: Ie ? "not-allowed" : "pointer",
4558
- fontFamily: "system-ui, sans-serif",
4559
- letterSpacing: "0.4px",
4560
- lineHeight: "36px"
4561
- },
4562
- children: "Continue"
4563
- }) : F(Oe, {
4564
- children: [
4565
- i("button", {
4566
- disabled: Ie,
4567
- onClick: () => At("use_form_measurements"),
4568
- style: {
4569
- padding: "6px 16px",
4570
- borderRadius: 4,
4571
- fontSize: 14,
4572
- fontWeight: 500,
4573
- backgroundColor: Ie ? "#9e9e9e" : "rgb(12, 67, 173)",
4574
- border: "none",
4575
- color: "#fff",
4576
- cursor: Ie ? "not-allowed" : "pointer",
4577
- fontFamily: "system-ui, sans-serif",
4578
- letterSpacing: "0.4px",
4579
- lineHeight: "36px"
4580
- },
4581
- children: "Set to Measurements"
4582
- }),
4583
- i("button", {
4584
- disabled: Ie,
4585
- onClick: () => At("use_scan"),
4586
- style: {
4587
- padding: "6px 16px",
4588
- borderRadius: 4,
4589
- fontSize: 14,
4590
- fontWeight: 500,
4591
- backgroundColor: Ie ? "#e0e0e0" : "#fff",
4592
- border: "1px solid #bdbdbd",
4593
- color: Ie ? "#999" : "#333",
4594
- cursor: Ie ? "not-allowed" : "pointer",
4595
- fontFamily: "system-ui, sans-serif",
4596
- letterSpacing: "0.4px",
4597
- lineHeight: "36px"
4598
- },
4599
- children: "Go With Scan"
4600
- })
4601
- ]
4602
- }))
4603
- ]
4604
- })
4605
- ]
4606
- }),
4607
- s && wt.length > 0 && F("div", {
4608
- style: {
4609
- height: 120,
4610
- flexShrink: 0,
4611
- background: "#0d1117",
4612
- borderTop: "1px solid #30363d",
4613
- fontFamily: "'SF Mono', 'Cascadia Code', 'Fira Code', Consolas, monospace",
4614
- fontSize: 11,
4615
- color: "#c9d1d9",
4616
- display: "flex",
4617
- flexDirection: "column"
4618
- },
4619
- children: [
4620
- F("div", {
4621
- style: {
4622
- display: "flex",
4623
- alignItems: "center",
4624
- justifyContent: "space-between",
4625
- padding: "3px 10px",
4626
- background: "#161b22",
4627
- borderBottom: "1px solid #21262d",
4628
- flexShrink: 0
4629
- },
4630
- children: [
4631
- i("span", {
4632
- style: {
4633
- color: "#58a6ff",
4634
- fontSize: 10,
4635
- fontWeight: 600,
4636
- letterSpacing: 0.5
4637
- },
4638
- children: "GALILEO DEBUG"
4639
- }),
4640
- F("div", {
4641
- style: {
4642
- display: "flex",
4643
- gap: 8,
4644
- alignItems: "center"
4645
- },
4646
- children: [
4647
- F("span", {
4648
- style: {
4649
- color: "#484f58",
4650
- fontSize: 9
4651
- },
4652
- children: [
4653
- "WASM ",
4654
- He.current ? "v2" : "N/A",
4655
- " | ",
4656
- T.length,
4657
- " pts | ",
4658
- ee ? "aligned" : "unaligned",
4659
- " | ",
4660
- V.length,
4661
- " slices"
4662
- ]
4663
- }),
4664
- i("button", {
4665
- onClick: () => jt([]),
4666
- style: {
4667
- background: "none",
4668
- border: "1px solid #30363d",
4669
- borderRadius: 3,
4670
- color: "#484f58",
4671
- fontSize: 9,
4672
- cursor: "pointer",
4673
- padding: "1px 6px"
4674
- },
4675
- children: "clear"
4676
- })
4677
- ]
4678
- })
4679
- ]
4680
- }),
4681
- i("div", {
4682
- ref: rt,
4683
- style: {
4684
- flex: 1,
4685
- overflowY: "auto",
4686
- padding: "4px 10px",
4687
- lineHeight: 1.6
4688
- },
4689
- children: wt.map((v, _) => {
4690
- const W = v.includes("ERROR") || v.includes("failed"), R = v.includes("warning") || v.includes("WARN"), ce = v.includes("PIPELINE:"), G = v.includes("STATE:");
4691
- return i("div", {
4692
- style: {
4693
- color: W ? "#f85149" : R ? "#d29922" : ce ? "#58a6ff" : G ? "#3fb950" : "#8b949e",
4694
- whiteSpace: "pre"
4695
- },
4696
- children: v
4697
- }, _);
4698
- })
4699
- })
4700
- ]
4701
- })
4702
- ]
4703
- }),
4704
- ee && $t && w && i(Ho, {
4705
- amputationType: w,
4706
- spacingInches: P,
4707
- scanMeasurements: V,
4708
- scanFrontalHeight: qe,
4709
- onSave: $n,
4710
- onSkip: Hn
4711
- })
4712
- ]
4713
- });
4714
- };
4715
- function rr({ screenshotFnRef: e }) {
4716
- return ne(() => {
4717
- e.current = null;
4718
- }, [
4719
- e
4720
- ]), null;
4721
- }
4722
- Cn = function(e) {
4723
- const r = e === "AK" ? 2 : 1, t = [];
4724
- for (let o = 2; o >= 1; o -= r) t.push(`${o}_above`);
4725
- t.push("at_ref");
4726
- for (let o = r; o <= 9; o += r) t.push(`${o}_below`);
4727
- if (e === "BK") for (const o of [
4728
- 10,
4729
- 11,
4730
- 12
4731
- ]) t.push(`${o}_below`);
4732
- else for (const o of [
4733
- 10,
4734
- 12,
4735
- 14,
4736
- 16,
4737
- 18
4738
- ]) t.push(`${o}_below`);
4739
- return t;
4740
- };
4741
- ct = function(e, r) {
4742
- const t = Cn(r), o = {};
4743
- for (let l = 0; l < Math.min(e.length, t.length); l++) {
4744
- const s = e[l];
4745
- s != null && !isNaN(s) && (o[t[l]] = s);
4746
- }
4747
- return o;
4748
- };
4749
- ir = function(e, r) {
4750
- if (!e) return;
4751
- const o = Cn(r).map((l) => {
4752
- const s = e[l];
4753
- return s ?? void 0;
4754
- });
4755
- if (!o.every((l) => l == null)) return o;
4756
- };
4757
- mr = ({ request: e, onComplete: r, wasmModule: t }) => {
4758
- const o = j(() => ir(e.form_measurements, e.spacing_type), [
4759
- e.form_measurements,
4760
- e.spacing_type
4761
- ]), l = (s) => {
4762
- var _a, _b;
4763
- const c = s.scanMeasurements.map((f) => +(f.modifiedValue ?? f.originalValue).toFixed(1)), a = ct(c, e.spacing_type);
4764
- let n, h;
4765
- if (s.formMeasurements) {
4766
- n = ct(s.formMeasurements, e.spacing_type);
4767
- const f = s.scanMeasurements.map((m, x) => {
4768
- var _a2;
4769
- const S = (_a2 = s.formMeasurements) == null ? void 0 : _a2[x];
4770
- return S == null || isNaN(S) ? null : +((m.modifiedValue ?? m.originalValue) - S).toFixed(1);
4771
- });
4772
- h = ct(f, e.spacing_type);
4773
- }
4774
- const d = s.userEnteredMeasurements ? ct(s.userEnteredMeasurements.circumferences, e.spacing_type) : void 0, u = s.decision === "use_scan" || s.decision === "continue", p = u ? a : d ?? n ?? a, g = u ? +s.frontalHeight.toFixed(1) : +(((_a = s.userEnteredMeasurements) == null ? void 0 : _a.frontalHeight) ?? s.frontalHeight).toFixed(1), M = {
4775
- spacing_type: e.spacing_type,
4776
- source_unit: "mm",
4777
- file_format: s.fileFormat,
4778
- measurement_source: s.formMeasurements ? "form_provided" : "scan_derived",
4779
- is_double_wall: s.isDoubleWall,
4780
- is_unit_converted: false,
4781
- form_measurements: n,
4782
- scan_measurements: a,
4783
- measurement_variance: h,
4784
- scan_url: e.scan_url,
4785
- frontal_height: +s.frontalHeight.toFixed(1),
4786
- transverse_ml: +s.transverseML.toFixed(1),
4787
- transverse_ap: +s.transverseAP.toFixed(1),
4788
- decision: s.decision,
4789
- skip_reason: s.skipReason,
4790
- user_measurements: d,
4791
- user_frontal_height: (_b = s.userEnteredMeasurements) == null ? void 0 : _b.frontalHeight,
4792
- final_measurements: p,
4793
- final_frontal_height: g,
4794
- final_transverse_ml: +s.transverseML.toFixed(1),
4795
- final_transverse_ap: +s.transverseAP.toFixed(1),
4796
- screenshots: s.screenshots
4797
- };
4798
- r == null ? void 0 : r(M);
4799
- };
4800
- return i("div", {
4801
- style: {
4802
- width: "100%",
4803
- height: "100%",
4804
- display: "flex"
4805
- },
4806
- children: i(or, {
4807
- config: oo,
4808
- spacingType: e.spacing_type,
4809
- scanUrl: e.scan_url,
4810
- formMeasurements: o,
4811
- onComplete: l,
4812
- wasmModule: t
4813
- })
4814
- });
4815
- };
4816
- })();
4817
- export {
4818
- mr as G,
4819
- __tla,
4820
- ct as a,
4821
- ir as c,
4822
- Cn as g
4823
- };