@solid-labs/fab-one-widget 0.1.1 → 0.1.3

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