@solid-labs/fab-one-widget 0.1.6 → 0.1.7

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