@solid-labs/fab-one-widget 0.1.4 → 0.1.5

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.
@@ -0,0 +1,4122 @@
1
+ import { jsxs as W, 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 Se, useRef as Ie } from "react";
3
+ import { useFrame as Lt, useThree as on, Canvas as sn } from "@react-three/fiber";
4
+ import { Html as Ke, Line as ge, OrbitControls as Dt } from "@react-three/drei";
5
+ import * as J from "three";
6
+ import { Plane as it, Vector3 as h, Box3 as Tt, Line3 as ht, Quaternion as Oe, Matrix4 as kt } 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, dt, ao, Nt;
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), gt = rn((e, s) => ({
32
+ landmarkPoints: [],
33
+ isAligned: false,
34
+ isCut: false,
35
+ addLandmarkPoint: (o) => e((t) => t.landmarkPoints.length >= 3 ? t : {
36
+ landmarkPoints: [
37
+ ...t.landmarkPoints,
38
+ o
39
+ ]
40
+ }),
41
+ removeLandmarkPoint: (o) => e((t) => ({
42
+ landmarkPoints: t.landmarkPoints.filter((l, a) => a !== o)
43
+ })),
44
+ clearLandmarkPoints: () => e({
45
+ landmarkPoints: [],
46
+ isAligned: false,
47
+ isCut: false
48
+ }),
49
+ updateLandmarkPositions: (o) => e((t) => ({
50
+ landmarkPoints: t.landmarkPoints.map((l, a) => ({
51
+ ...l,
52
+ position: o[a] ?? l.position
53
+ }))
54
+ })),
55
+ setAligned: (o) => e({
56
+ isAligned: o
57
+ }),
58
+ setCut: (o) => e({
59
+ isCut: o
60
+ }),
61
+ isSelectionComplete: () => s().landmarkPoints.length === 3
62
+ })), un = 0.45, Ye = 3, ut = 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
+ `), o = [], t = [];
71
+ let l = false;
72
+ for (const a of s) if (a.startsWith("v ")) {
73
+ const c = a.trim().split(/\s+/);
74
+ if (c.length >= 7) {
75
+ o.push(parseFloat(c[1]), parseFloat(c[2]), parseFloat(c[3]));
76
+ let u = parseFloat(c[4]), n = parseFloat(c[5]), i = parseFloat(c[6]);
77
+ (u > 1 || n > 1 || i > 1) && (u /= 255, n /= 255, i /= 255), t.push(u, n, i), l = true;
78
+ } else c.length >= 4 && (o.push(parseFloat(c[1]), parseFloat(c[2]), parseFloat(c[3])), t.push(0, 0, 0));
79
+ }
80
+ return l ? {
81
+ positions: new Float32Array(o),
82
+ colors: new Float32Array(t)
83
+ } : null;
84
+ }
85
+ function mn(e, s, o, t) {
86
+ const l = e.getAttribute("position"), a = l.count, c = new Float32Array(a * 3), u = s.length / 3;
87
+ let n = 1 / 0, i = 1 / 0, r = 1 / 0, f = -1 / 0, y = -1 / 0, p = -1 / 0;
88
+ for (let b = 0; b < u; b++) {
89
+ const S = s[b * 3] * t, v = s[b * 3 + 1] * t, M = s[b * 3 + 2] * t;
90
+ S < n && (n = S), S > f && (f = S), v < i && (i = v), v > y && (y = v), 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 - n + 1e-6) / m, w = (y - i + 1e-6) / m, C = (p - r + 1e-6) / m, x = /* @__PURE__ */ new Map();
93
+ for (let b = 0; b < u; b++) {
94
+ const S = Math.min(m - 1, Math.floor((s[b * 3] * t - n) / g)), v = Math.min(m - 1, Math.floor((s[b * 3 + 1] * t - i) / w)), M = Math.min(m - 1, Math.floor((s[b * 3 + 2] * t - r) / C)), L = S * m * m + v * 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 S = l.getX(b), v = l.getY(b), M = l.getZ(b), L = Math.min(m - 1, Math.max(0, Math.floor((S - n) / g))), P = Math.min(m - 1, Math.max(0, Math.floor((v - i) / w))), H = Math.min(m - 1, Math.max(0, Math.floor((M - r) / C)));
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 z of D) {
108
+ const F = s[z * 3] * t, V = s[z * 3 + 1] * t, B = s[z * 3 + 2] * t, T = (S - F) ** 2 + (v - V) ** 2 + (M - B) ** 2;
109
+ T < O && (O = T, $ = z);
110
+ }
111
+ }
112
+ if (O < 1 / 0) break;
113
+ }
114
+ c[b * 3] = o[$ * 3], c[b * 3 + 1] = o[$ * 3 + 1], c[b * 3 + 2] = o[$ * 3 + 2];
115
+ }
116
+ e.setAttribute("color", new J.Float32BufferAttribute(c, 3));
117
+ }
118
+ const xn = 30, zt = [
119
+ "#4488ff",
120
+ "#ff4444",
121
+ "#44cc44",
122
+ "#ffaa00",
123
+ "#cc44ff",
124
+ "#44ffcc"
125
+ ];
126
+ function yn(e, s) {
127
+ const o = e.getVertices(), t = e.getFaces(), l = e.getComponentLabels(), a = /* @__PURE__ */ new Map();
128
+ for (let r = 0; r < l.length; r++) {
129
+ const f = l[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 = [], n = [], i = [];
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 S = t[x * 3 + b];
139
+ if (!y.has(S)) {
140
+ const v = p.length / 3;
141
+ p.push(o[S * 3], o[S * 3 + 1], o[S * 3 + 2]), y.set(S, v);
142
+ }
143
+ m.push(y.get(S));
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 C = r === s ? `#${r} inner` : r === 0 ? `#${r} outer` : `#${r} (${f.length} faces)`;
148
+ n.push(C), i.push(zt[r % zt.length]);
149
+ }
150
+ return {
151
+ geometries: u,
152
+ labels: n,
153
+ colors: i,
154
+ innerIdx: s
155
+ };
156
+ }
157
+ async function bn(e, s, o) {
158
+ let t = null;
159
+ try {
160
+ const l = gn(e);
161
+ o == null ? void 0 : o("Loading mesh..."), t = new s.WasmMeshSet(), t.loadObjString(e), o == null ? void 0 : o("Detecting units...");
162
+ const a = t.autoScaleToMm(pn);
163
+ o == null ? void 0 : o("Merging close vertices..."), t.applyMergeCloseVertices(1e-4), o == null ? void 0 : o("Analyzing mesh components...");
164
+ let c = false, u = null;
165
+ if (t.getComponentCount() >= 2) {
166
+ o == null ? void 0 : o("Building component debug info...");
167
+ const y = yn(t, null);
168
+ o == null ? void 0 : o("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) : (o == null ? void 0 : o("Removing floating artifacts..."), t.splitAndKeepLargest(), u = y);
169
+ } else o == null ? void 0 : o("Removing floating artifacts..."), t.splitAndKeepLargest();
170
+ o == null ? void 0 : o("Closing holes..."), t.applyCloseHoles(30), t.applyMergeCloseVertices(1e-4), o == null ? void 0 : o("Extracting geometry...");
171
+ const i = t.getVertices(), r = t.getFaces();
172
+ if (i.length === 0) return null;
173
+ const f = new J.BufferGeometry();
174
+ if (f.setAttribute("position", new J.Float32BufferAttribute(i, 3)), f.setIndex(Array.from(r)), f.computeVertexNormals(), l) {
175
+ const y = a ? 1e3 : 1;
176
+ mn(f, l.positions, l.colors, y);
177
+ }
178
+ return {
179
+ geometry: f,
180
+ wasScaled: a,
181
+ innerShellExtracted: c,
182
+ componentDebug: u
183
+ };
184
+ } catch (l) {
185
+ return console.error("WASM processing failed:", l), null;
186
+ } finally {
187
+ if (t) try {
188
+ t.free();
189
+ } catch {
190
+ }
191
+ }
192
+ }
193
+ function wn(e) {
194
+ const o = new ln().parse(e);
195
+ let t = null;
196
+ return o.traverse((l) => {
197
+ l.isMesh && !t && (t = l.geometry);
198
+ }), t;
199
+ }
200
+ async function ft(e) {
201
+ const s = await e.arrayBuffer(), l = new an().parse(s).getAttribute("position");
202
+ if (!l || l.count === 0) throw new Error("Empty STL geometry");
203
+ const a = [];
204
+ for (let c = 0; c < l.count; c++) a.push(`v ${l.getX(c)} ${l.getY(c)} ${l.getZ(c)}`);
205
+ for (let c = 0; c < l.count; c += 3) a.push(`f ${c + 1} ${c + 2} ${c + 3}`);
206
+ return a.join(`
207
+ `);
208
+ }
209
+ function Bt(e, s) {
210
+ const o = 1 / s;
211
+ return `${Math.round(e.x * o)}_${Math.round(e.y * o)}_${Math.round(e.z * o)}`;
212
+ }
213
+ function Rt(e, s) {
214
+ if (!e.length) return [];
215
+ const o = [];
216
+ for (const t of e) (o.length === 0 || o[o.length - 1].distanceTo(t) > s) && o.push(t.clone());
217
+ return o.length > 2 && o[0].distanceTo(o[o.length - 1]) > s && o.push(o[0].clone()), o;
218
+ }
219
+ function je(e) {
220
+ let s = 0;
221
+ for (let o = 0; o < e.length - 1; o++) s += e[o].distanceTo(e[o + 1]);
222
+ return s;
223
+ }
224
+ function Et(e, s = 1e-3, o = false) {
225
+ if (!e.length) return [];
226
+ const t = /* @__PURE__ */ new Map(), l = (i) => {
227
+ const r = Bt(i, s);
228
+ let f = t.get(r);
229
+ return f || (f = i.clone(), t.set(r, f)), f;
230
+ }, a = e.map((i) => ({
231
+ a: l(i.a),
232
+ b: l(i.b)
233
+ })), c = [];
234
+ for (; a.length; ) {
235
+ const i = a.pop(), r = [
236
+ i.a,
237
+ i.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 = Rt(r, s);
253
+ y.length > 1 && c.push(y);
254
+ }
255
+ if (!c.length) return [];
256
+ if (c.sort((i, r) => je(r) - je(i)), !o) return c[0] ?? [];
257
+ const u = je(c[0]), n = c.filter((i) => je(i) >= u * 0.3);
258
+ return n[n.length - 1] ?? c[0];
259
+ }
260
+ function Ct(e, s, o, t = false) {
261
+ const l = new it(new h(0, 1, 0), -o), a = [], c = new Tt();
262
+ c.setFromBufferAttribute(s.getAttribute("position"));
263
+ const u = {
264
+ linePoints: [],
265
+ lineLength: 0,
266
+ rightmostPoint: new h(0, o, 0)
267
+ };
268
+ if (!l.intersectsBox(c)) return u;
269
+ const n = new ht(), i = new h();
270
+ e.shapecast({
271
+ intersectsBounds: (g) => l.intersectsBox(g),
272
+ intersectsTriangle: (g) => {
273
+ const w = [];
274
+ n.set(g.a, g.b), l.intersectLine(n, i) && w.push(i.clone()), n.set(g.b, g.c), l.intersectLine(n, i) && w.push(i.clone()), n.set(g.c, g.a), l.intersectLine(n, i) && w.push(i.clone()), w.length === 2 && a.push({
275
+ a: w[0],
276
+ b: w[1]
277
+ });
278
+ }
279
+ });
280
+ const r = Et(a, ut, t), f = je(r);
281
+ if (r.length < 2) return u;
282
+ let y = -1 / 0, p = new h(0, o, 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]) < ut * 10;
285
+ return {
286
+ linePoints: r,
287
+ lineLength: f,
288
+ rightmostPoint: p,
289
+ isClosed: m
290
+ };
291
+ }
292
+ function Ze(e, s, o, t = false) {
293
+ const l = Ct(e, s, o, t);
294
+ if (l.isClosed && l.linePoints.length >= 3) return l;
295
+ console.warn(`[slice] y=${o.toFixed(2)} failed (pts=${l.linePoints.length}, closed=${l.isClosed}), retrying...`);
296
+ let a = l;
297
+ for (const c of hn) {
298
+ const u = Ct(e, s, o + c, t);
299
+ if (u.isClosed && u.linePoints.length >= 3) return console.log(`[slice] y=${o.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=${o.toFixed(2)} all retries exhausted (pts=${a.linePoints.length}, closed=${a.isClosed})`), a;
303
+ }
304
+ function pt(e, s, o, t) {
305
+ const l = new it().setFromNormalAndCoplanarPoint(t.clone().normalize(), o), a = new Tt();
306
+ if (a.setFromBufferAttribute(s.getAttribute("position")), !l.intersectsBox(a)) return 0;
307
+ const c = [], u = new ht(), n = new h();
308
+ e.shapecast({
309
+ intersectsBounds: (r) => l.intersectsBox(r),
310
+ intersectsTriangle: (r) => {
311
+ const f = [];
312
+ u.set(r.a, r.b), l.intersectLine(u, n) && f.push(n.clone()), u.set(r.b, r.c), l.intersectLine(u, n) && f.push(n.clone()), u.set(r.c, r.a), l.intersectLine(u, n) && f.push(n.clone()), f.length === 2 && c.push({
313
+ a: f[0],
314
+ b: f[1]
315
+ });
316
+ }
317
+ });
318
+ const i = Et(c, ut);
319
+ return je(i);
320
+ }
321
+ function ot(e) {
322
+ return new $e(e, {
323
+ maxLeafTris: Ye
324
+ });
325
+ }
326
+ function vt(e, s, o) {
327
+ const t = e instanceof $e ? e : new $e(e, {
328
+ maxLeafTris: Ye
329
+ }), l = new it().setFromNormalAndCoplanarPoint(o.clone().normalize(), s), a = [], c = new ht(), u = new h();
330
+ return t.shapecast({
331
+ intersectsBounds: (n) => l.intersectsBox(n),
332
+ intersectsTriangle: (n) => {
333
+ const i = [];
334
+ c.set(n.a, n.b), l.intersectLine(c, u) && i.push(u.clone()), c.set(n.b, n.c), l.intersectLine(c, u) && i.push(u.clone()), c.set(n.c, n.a), l.intersectLine(c, u) && i.push(u.clone()), i.length === 2 && a.push({
335
+ a: i[0],
336
+ b: i[1]
337
+ });
338
+ }
339
+ }), a;
340
+ }
341
+ function Mt(e, s, o = 1e-3) {
342
+ if (!e.length) return [];
343
+ const t = /* @__PURE__ */ new Map(), l = (i) => {
344
+ const r = Bt(i, o);
345
+ let f = t.get(r);
346
+ return f || (f = i.clone(), t.set(r, f)), f;
347
+ }, a = e.map((i) => ({
348
+ a: l(i.a),
349
+ b: l(i.b)
350
+ })), c = [];
351
+ for (; a.length; ) {
352
+ const i = a.pop(), r = [
353
+ i.a,
354
+ i.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 = Rt(r, o);
370
+ y.length > 1 && c.push(y);
371
+ }
372
+ if (!c.length) return [];
373
+ let u = [], n = 1 / 0;
374
+ for (const i of c) {
375
+ if (i.length < 3 || !(i[0].distanceTo(i[i.length - 1]) < 2)) continue;
376
+ const f = new h();
377
+ for (const p of i) f.add(p);
378
+ f.divideScalar(i.length);
379
+ const y = f.distanceTo(s);
380
+ y < n && (n = y, u = i);
381
+ }
382
+ if (u.length === 0) for (const i of c) {
383
+ if (i.length < 3) continue;
384
+ const r = new h();
385
+ for (const y of i) r.add(y);
386
+ r.divideScalar(i.length);
387
+ const f = r.distanceTo(s);
388
+ f < n && (n = f, u = i);
389
+ }
390
+ return u;
391
+ }
392
+ function Sn(e) {
393
+ const s = new h();
394
+ for (const o of e) s.add(o);
395
+ return s.divideScalar(e.length);
396
+ }
397
+ function zn(e, s, o) {
398
+ const t = new $e(e, {
399
+ maxLeafTris: Ye
400
+ }), l = new h().subVectors(s, o).normalize(), c = s.distanceTo(o) * 0.05;
401
+ let u = l.clone();
402
+ const n = (C) => {
403
+ const x = [];
404
+ for (let $ = -10; $ <= 0; $++) {
405
+ const R = s.clone().addScaledVector(C, $ * c), Y = vt(t, R, C), N = Mt(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 S = 0, v = 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
+ S += R * R, v += R * Y, M += R * N, L += Y * Y, P += Y * N, H += N * N;
416
+ }
417
+ let O = C.clone();
418
+ for (let $ = 0; $ < 30; $++) {
419
+ const R = S * O.x + v * O.y + M * O.z, Y = v * 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(l) < 0 && O.negate(), O;
424
+ };
425
+ for (let C = 0; C < 3; C++) {
426
+ const x = n(u);
427
+ if (!x) break;
428
+ const b = u.angleTo(x);
429
+ if (u = x, b < 1e-3) break;
430
+ }
431
+ const i = new h();
432
+ Math.abs(u.x) < 0.9 ? i.set(1, 0, 0) : i.set(0, 1, 0), i.crossVectors(u, i).normalize();
433
+ const r = new h().crossVectors(u, i).normalize(), f = (C) => {
434
+ const x = vt(t, s, C), b = Mt(x, s, 1);
435
+ if (b.length < 3) return {
436
+ circumference: 1 / 0,
437
+ closed: false
438
+ };
439
+ const S = b[0].distanceTo(b[b.length - 1]) < 1;
440
+ return {
441
+ circumference: je(b),
442
+ closed: S
443
+ };
444
+ };
445
+ let y = u.clone(), p = 1 / 0;
446
+ for (let C = -3; C <= 3; C += 1) for (let x = -3; x <= 3; x += 1) {
447
+ const b = C * Math.PI / 180, S = x * Math.PI / 180, v = u.clone().applyQuaternion(new Oe().setFromAxisAngle(i, b)).applyQuaternion(new Oe().setFromAxisAngle(r, S)).normalize(), M = f(v);
448
+ M.closed && M.circumference < p && (p = M.circumference, y = v);
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 w = new h().crossVectors(m, g).normalize();
453
+ for (let C = -5; C <= 5; C += 1) for (let x = -5; x <= 5; x += 1) {
454
+ const b = C * 0.1 * Math.PI / 180, S = x * 0.1 * Math.PI / 180, v = m.clone().applyQuaternion(new Oe().setFromAxisAngle(g, b)).applyQuaternion(new Oe().setFromAxisAngle(w, S)).normalize(), M = f(v);
455
+ M.closed && M.circumference < p && (p = M.circumference, y = v);
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, o) {
463
+ const t = e.getAttribute("position"), l = e.getIndex();
464
+ if (!l) return {
465
+ isDoubleShell: false,
466
+ sampledFaces: 0,
467
+ opposingPairs: 0,
468
+ confidence: 0
469
+ };
470
+ const a = l.array, c = t.array, u = new h().subVectors(o, s).normalize(), n = o.distanceTo(s), i = Math.min(n * 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, w = 0, C = 0;
477
+ for (const S of [
478
+ 0.65,
479
+ 0.78,
480
+ 0.9
481
+ ]) {
482
+ const v = new h().lerpVectors(s, o, S);
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, z = le - v.x, F = ee - v.y, V = D - v.z;
486
+ Math.abs(z * u.x + F * u.y + V * u.z) > i || (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, w++;
498
+ }
499
+ g += $, $ / p > 1.5 && C++;
500
+ }
501
+ if (w === 0) return {
502
+ isDoubleShell: false,
503
+ sampledFaces: 0,
504
+ opposingPairs: 0,
505
+ confidence: 0
506
+ };
507
+ const x = g / w;
508
+ return {
509
+ isDoubleShell: C >= 2,
510
+ sampledFaces: w,
511
+ opposingPairs: g,
512
+ confidence: x
513
+ };
514
+ }
515
+ function vn(e, s, o, t) {
516
+ const l = new h().subVectors(o, s), a = new h().subVectors(t, s), c = new h().subVectors(e, s), u = l.dot(l), n = l.dot(a), i = l.dot(c), r = a.dot(a), f = a.dot(c), y = 1 / (u * r - n * n), p = (r * i - n * f) * y, m = (u * f - n * i) * y;
517
+ return {
518
+ u: 1 - p - m,
519
+ v: p,
520
+ w: m
521
+ };
522
+ }
523
+ function st(e, s, o, t, l = false) {
524
+ const a = o.clone().normalize(), c = e.getAttribute("position"), u = e.getIndex();
525
+ if (!u) throw new Error("No index buffer");
526
+ const n = new h().subVectors(t, s).dot(a), i = Math.abs(n) < 1e-6 ? 1 : Math.sign(n), r = c.array, f = u.array, y = e.getAttribute("color"), p = y ? y.array : null, m = [], g = [], w = [], C = (D, z, F) => {
527
+ const V = m.length / 3;
528
+ return m.push(D, z, F), V;
529
+ }, x = (D) => new h(r[D * 3], r[D * 3 + 1], r[D * 3 + 2]), b = (D, z) => {
530
+ const F = new h().subVectors(D, s).dot(a), V = new h().subVectors(z, s).dot(a), B = F / (F - V);
531
+ return new h().lerpVectors(D, z, B);
532
+ }, S = /* @__PURE__ */ new Map(), v = /* @__PURE__ */ new Map(), M = /* @__PURE__ */ new Map(), L = (D) => {
533
+ let z = M.get(D);
534
+ return z === void 0 && (z = new h().subVectors(x(D), s).dot(a), M.set(D, z)), z;
535
+ }, P = (D) => {
536
+ if (S.has(D)) return S.get(D);
537
+ const z = x(D), F = C(z.x, z.y, z.z);
538
+ return p && g.push(p[D * 3], p[D * 3 + 1], p[D * 3 + 2]), S.set(D, F), F;
539
+ }, H = (D, z) => {
540
+ const F = D < z ? `${D}_${z}` : `${z}_${D}`;
541
+ if (v.has(F)) return v.get(F);
542
+ const V = b(x(D), x(z)), B = C(V.x, V.y, V.z);
543
+ if (p) {
544
+ const T = L(D), E = L(z), j = T / (T - E);
545
+ g.push(p[D * 3] + j * (p[z * 3] - p[D * 3]), p[D * 3 + 1] + j * (p[z * 3 + 1] - p[D * 3 + 1]), p[D * 3 + 2] + j * (p[z * 3 + 2] - p[D * 3 + 2]));
546
+ }
547
+ return v.set(F, B), B;
548
+ }, O = (D) => {
549
+ const z = L(D);
550
+ return Math.sign(z) === i || Math.abs(z) < 1e-6;
551
+ };
552
+ for (let D = 0; D < f.length; D += 3) {
553
+ const z = f[D], F = f[D + 1], V = f[D + 2], B = O(z), T = O(F), E = O(V), j = (B ? 1 : 0) + (T ? 1 : 0) + (E ? 1 : 0);
554
+ if (j !== 0) if (j === 3) w.push(P(z), P(F), P(V));
555
+ else if (j === 1) {
556
+ let X, Q, ie;
557
+ B ? (X = z, Q = F, ie = V) : T ? (X = F, Q = V, ie = z) : (X = V, Q = z, ie = F), w.push(P(X), H(X, Q), H(X, ie));
558
+ } else {
559
+ let X, Q, ie;
560
+ B ? T ? (X = V, Q = z, ie = F) : (X = F, Q = V, ie = z) : (X = z, Q = F, ie = V);
561
+ const se = P(Q), A = P(ie), I = H(Q, X), k = H(ie, X);
562
+ w.push(se, I, A), w.push(A, I, k);
563
+ }
564
+ }
565
+ const $ = w.length / 3;
566
+ let R;
567
+ if (l) R = Array.from({
568
+ length: $
569
+ }, (D, z) => z);
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 = w[T * 3 + E];
574
+ D.has(j) || D.set(j, []), D.get(j).push(T);
575
+ }
576
+ const z = /* @__PURE__ */ new Set(), F = [];
577
+ for (let T = 0; T < $; T++) {
578
+ if (z.has(T)) continue;
579
+ const E = [], j = [
580
+ T
581
+ ];
582
+ for (z.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 = w[X * 3 + Q];
587
+ for (const se of D.get(ie)) z.has(se) || (z.add(se), j.push(se));
588
+ }
589
+ }
590
+ F.push(E);
591
+ }
592
+ let V = 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 = w[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, V = T);
603
+ }
604
+ R = V;
605
+ }
606
+ const Y = /* @__PURE__ */ new Map(), N = [], ne = [], oe = [];
607
+ let le = 0;
608
+ for (const D of R) for (let z = 0; z < 3; z++) {
609
+ const F = w[D * 3 + z];
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 rt(e, s, o) {
616
+ const t = e.getAttribute("position"), l = o - s;
617
+ if (l < 1) return null;
618
+ const a = 30, c = l / a, u = [];
619
+ for (let w = 0; w < a; w++) {
620
+ const C = s + w * c, x = s + (w + 1) * c;
621
+ let b = 0, S = 0, v = 0, M = 0;
622
+ for (let L = 0; L < t.count; L++) {
623
+ const P = t.getY(L);
624
+ P >= C && P < x && (b += t.getX(L), S += P, v += t.getZ(L), M++);
625
+ }
626
+ M > 20 && u.push(new h(b / M, S / M, v / M));
627
+ }
628
+ if (u.length < 5) return null;
629
+ const n = new h();
630
+ for (const w of u) n.add(w);
631
+ n.divideScalar(u.length);
632
+ let i = 0, r = 0, f = 0, y = 0, p = 0, m = 0;
633
+ for (const w of u) {
634
+ const C = w.x - n.x, x = w.y - n.y, b = w.z - n.z;
635
+ i += C * C, r += C * x, f += C * 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 w = 0; w < 30; w++) {
639
+ const C = i * 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, S = new h(C, x, b), v = S.length();
640
+ if (v < 1e-10 || (S.divideScalar(v), g.distanceTo(S) < 1e-8)) break;
641
+ g = S;
642
+ }
643
+ return g.y < 0 && g.negate(), g;
644
+ }
645
+ function Wt(e, s, o, t) {
646
+ const l = e.getIndex(), a = l ? l.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 - o;
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
+ }), n = Ze(u, e, s);
663
+ if (n.lineLength === 0) return {
664
+ valid: false,
665
+ reason: "No circumference at green point \u2014 mesh may be empty at that height"
666
+ };
667
+ const i = s - t;
668
+ if (i <= o) return {
669
+ valid: true,
670
+ reason: ""
671
+ };
672
+ const r = Ze(u, e, i);
673
+ if (n.lineLength > 0 && r.lineLength > 0) {
674
+ const y = n.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 > o) {
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
+ ], nt = 5;
718
+ function Vt(e, s, o, t) {
719
+ const l = new Oe().setFromAxisAngle(o, t);
720
+ return e.applyMatrix4(new kt().makeRotationFromQuaternion(l)), s.map((a) => a.clone().applyQuaternion(l));
721
+ }
722
+ function _t(e, s, o) {
723
+ const t = new Oe().setFromAxisAngle(s, o);
724
+ e.applyMatrix4(new kt().makeRotationFromQuaternion(t));
725
+ }
726
+ function An(e, s, o, t, l, a) {
727
+ const c = o.getAttribute("position"), u = o.getIndex();
728
+ if (!u) return s;
729
+ const i = s[1].y + t * We, r = c.array, f = u.array, y = o.getAttribute("color"), p = y ? y.array : null, m = [], g = [], w = [], C = (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 = (i - A[1]) / (I[1] - A[1]);
738
+ return [
739
+ A[0] + k * (I[0] - A[0]),
740
+ i,
741
+ A[2] + k * (I[2] - A[2])
742
+ ];
743
+ }, S = /* @__PURE__ */ new Map(), v = /* @__PURE__ */ new Map(), M = (A) => {
744
+ if (S.has(A)) return S.get(A);
745
+ const [I, k, G] = x(A), U = C(I, k, G);
746
+ return p && g.push(p[A * 3], p[A * 3 + 1], p[A * 3 + 2]), S.set(A, U), U;
747
+ }, L = (A, I) => {
748
+ const k = A < I ? `${A}_${I}` : `${I}_${A}`;
749
+ if (v.has(k)) return v.get(k);
750
+ const G = x(A), U = x(I), [re, Pe, me] = b(G, U), ae = C(re, Pe, me);
751
+ if (p) {
752
+ const xe = (i - 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 v.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] < i, ae = re[1] < i, xe = Pe[1] < i, Re = (me ? 1 : 0) + (ae ? 1 : 0) + (xe ? 1 : 0);
759
+ if (Re !== 0) if (Re === 3) w.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), w.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
+ w.push(Ge, Ne, fe), w.push(fe, Ne, Le);
768
+ }
769
+ }
770
+ const P = w.length / 3, H = /* @__PURE__ */ new Map();
771
+ for (let A = 0; A < P; A++) for (let I = 0; I < 3; I++) {
772
+ const k = w[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 = w[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 z = 0;
806
+ for (const A of N) for (let I = 0; I < 3; I++) {
807
+ const k = w[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, z++)), 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, l.onStatus("Refining alignment...");
812
+ const V = new h(0, 1, 0);
813
+ let B = [
814
+ ...s
815
+ ];
816
+ const T = (A, I) => {
817
+ B = Vt(F, B, A, I), a && _t(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, ze = 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, ze += I.getZ(ke), Ee++);
829
+ }
830
+ Ee > 20 && me.push(new h(Ae / Ee, De / Ee, ze / 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), ze = De.length();
844
+ if (ze < 1e-10 || (De.divideScalar(ze), fe.distanceTo(De) < 1e-8)) break;
845
+ fe = De;
846
+ }
847
+ fe.y < 0 && fe.negate();
848
+ const Ne = fe.dot(V);
849
+ if (Math.acos(Math.min(1, Math.abs(Ne))) * 180 / Math.PI < 0.1) break;
850
+ const Le = new h().crossVectors(fe, V);
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 = st(F, new h(0, X, 0), new h(0, 1, 0), B[0]);
857
+ e.geometry.dispose(), e.geometry = Q, Q.computeVertexNormals(), Q.computeBoundingBox(), l.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), l.setModelSize(Math.max(se.x, se.y, se.z)), l.setCut(true), l.setAdjustedStartY(null), l.setAdjustedEndY(null), l.setOriginalEndY(B[1].y + 2 * We), B;
864
+ }
865
+ function Fn(e, s, o, t) {
866
+ const l = s.map((m) => new h(m.position.x, m.position.y, m.position.z)), a = l[0], c = l[1];
867
+ t.onStatus("Cutting double shell above green point...");
868
+ const u = c.y + 2 * We, n = new h(c.x, u, c.z), i = e.geometry, r = st(i, n, new h(0, 1, 0), a, true);
869
+ i.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
+ }), l.push(a.clone()), t.updateLandmarkPositions(l.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 = Wt(r, c.y, a.y, o);
894
+ p.valid || console.warn(`Double shell validation warning: ${p.reason}`);
895
+ }
896
+ function In(e, s, o, t) {
897
+ var _a, _b;
898
+ const l = e.geometry.clone(), a = s.map((n) => ({
899
+ ...n
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 n = new h(s[0].position.x, s[0].position.y, s[0].position.z), i = 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, n, i);
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, o, t), t.setClippedReferenceGeometry ? (l.computeVertexNormals(), t.setClippedReferenceGeometry(l)) : l.dispose();
908
+ return;
909
+ }
910
+ (_b = t.setDoubleShell) == null ? void 0 : _b.call(t, false);
911
+ }
912
+ let u = "";
913
+ for (let n = 0; n < nt; n++) try {
914
+ n > 0 && (t.onStatus(`Retry ${n}/${nt - 1} \u2014 ${u}`), e.geometry.dispose(), e.geometry = l.clone(), t.removeLandmarkPoint(2), t.setAligned(false), t.setCut(false));
915
+ let i = e.geometry, r = a.map((z) => new h(z.position.x, z.position.y, z.position.z));
916
+ const f = t.setClippedReferenceGeometry ? l.clone() : null;
917
+ let y = 5;
918
+ if (n > 0) {
919
+ const z = Mn[n - 1];
920
+ y = z.cutOffset;
921
+ const F = new h().subVectors(r[1], r[0]).normalize();
922
+ if (z.nudge < 0) r[1].addScaledVector(F, z.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, z.angle), r[1].addScaledVector(E, z.nudge);
926
+ }
927
+ const V = i.getAttribute("position");
928
+ let B = 1 / 0, T = 0;
929
+ for (let E = 0; E < V.count; E++) {
930
+ const j = V.getX(E) - r[1].x, X = V.getY(E) - r[1].y, Q = V.getZ(E) - r[1].z, ie = j * j + X * X + Q * Q;
931
+ ie < B && (B = ie, T = E);
932
+ }
933
+ r[1].set(V.getX(T), V.getY(T), V.getZ(T)), console.log(`Retry ${n}: nudge=${z.nudge}mm angle=${(z.angle * 180 / Math.PI).toFixed(0)}\xB0 cutOffset=${z.cutOffset}" \u2192 green=(${r[1].x.toFixed(1)}, ${r[1].y.toFixed(1)}, ${r[1].z.toFixed(1)})`);
934
+ }
935
+ const p = (z, F) => {
936
+ r = Vt(i, r, z, F), f && _t(f, z, F);
937
+ }, m = r[0], g = r[1], { normal: w } = zn(i, g, m);
938
+ t.onStatus(n > 0 ? `Retry ${n}: Slicing mesh...` : "Slicing mesh at cut plane...");
939
+ const C = new h().subVectors(g, m).normalize(), x = Math.sign(C.dot(w)), b = g.clone().addScaledVector(w, x * y * We), S = st(i, b, w, m);
940
+ i.dispose(), i = S, e.geometry = i, t.onStatus(n > 0 ? `Retry ${n}: Rough alignment...` : "Rough alignment...");
941
+ const v = new h().subVectors(r[1], r[0]).normalize();
942
+ let M = v.dot(c), L = new h().crossVectors(v, 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), i.computeVertexNormals(), t.onStatus(n > 0 ? `Retry ${n}: Translating...` : "Translating to origin...");
944
+ const P = r[0].clone();
945
+ i.translate(-P.x, -P.y, -P.z), f && f.translate(-P.x, -P.y, -P.z), r = r.map((z) => new h(z.x - P.x, z.y - P.y, z.z - P.z)), t.onStatus(n > 0 ? `Retry ${n}: Isolating limb...` : "Isolating limb region...");
946
+ {
947
+ const z = ot(i), F = r[0].y, V = r[1].y, B = new h(0, 1, 0), T = 5;
948
+ i.computeBoundingBox();
949
+ const E = i.boundingBox.max.y, j = [];
950
+ for (let X = F + T; X < E; X += T) {
951
+ const Q = pt(z, i, 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 = V - 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 < V - 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 - V) < T);
968
+ if (U && U.circ > I * k) {
969
+ for (let re = j.length - 1; re >= 0; re--) if (!(j[re].y > V + 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 = st(i, new h(0, G, 0), B, r[0]);
978
+ i.dispose(), i = U, e.geometry = i, i.computeVertexNormals(), i.computeBoundingBox();
979
+ } else console.log(`Limb isolation: no anomaly detected (baseline=${I.toFixed(1)}mm)`);
980
+ }
981
+ }
982
+ }
983
+ t.onStatus(n > 0 ? `Retry ${n}: 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 z = 0; z < O; z++) {
987
+ const F = Math.min(Y, R), V = Math.max(Y, R), B = rt(i, F, V);
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
+ i.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
+ i.computeVertexNormals(), t.onStatus(n > 0 ? `Retry ${n}: 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(n > 0 ? `Retry ${n}: Final PCA...` : "Final PCA refinement...");
1015
+ for (let z = 0; z < 3; z++) {
1016
+ const F = rt(i, 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
+ i.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 z = r[0].clone();
1029
+ i.translate(-z.x, -z.y, -z.z), f && f.translate(-z.x, -z.y, -z.z), r = r.map((F) => new h(F.x - z.x, F.y - z.y, F.z - z.z));
1030
+ }
1031
+ i.computeVertexNormals(), i.computeBoundingBox(), t.onStatus(n > 0 ? `Retry ${n}: Circumference refinement...` : "Circumference refinement...");
1032
+ {
1033
+ const z = ot(i), F = r[1].y, V = r[0].y, B = [
1034
+ F - We,
1035
+ F - 2 * We,
1036
+ F - 3 * We
1037
+ ].filter((T) => T > V + 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 += pt(z, i, 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
+ i.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)), i.computeVertexNormals();
1061
+ } else console.log(`Circumference refinement: already optimal (${(A / T).toFixed(3)}\xB0)`);
1062
+ }
1063
+ }
1064
+ const ne = r.map((z) => ({
1065
+ x: z.x,
1066
+ y: z.y,
1067
+ z: z.z
1068
+ }));
1069
+ t.updateLandmarkPositions(ne), t.setAligned(true), t.onStatus(n > 0 ? `Retry ${n}: Cutting mesh...` : 'Cutting mesh 2" above green...'), r = An(e, r, i, 5, t, f), t.onStatus("Validating results...");
1070
+ const oe = e.geometry, le = r[1].y, ee = r[0].y, D = Wt(oe, le, ee, o);
1071
+ if (D.valid) {
1072
+ console.log(`Processing succeeded on attempt ${n + 1}`), f && t.setClippedReferenceGeometry && (f.computeVertexNormals(), t.setClippedReferenceGeometry(f));
1073
+ break;
1074
+ }
1075
+ console.warn(`Attempt ${n + 1} failed validation: ${D.reason}`), u = D.reason, f && f.dispose(), n === nt - 1 && (t.setError(`Processing produced unusual results after ${nt} attempts: ${D.reason}`), e.geometry.dispose(), e.geometry = l.clone(), t.removeLandmarkPoint(2), t.setAligned(false), t.setCut(false));
1076
+ } catch (i) {
1077
+ console.error("Processing failed:", i), t.setError(i instanceof Error ? i.message : "Failed to process mesh.");
1078
+ break;
1079
+ }
1080
+ l.dispose();
1081
+ }
1082
+ const Pn = ({ message: e, onDismiss: s }) => W("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
+ W("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
+ }), At = ({ message: e }) => W("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: o = "#c8c8c8", meshOpacity: t = 1 }) => {
1173
+ const { addLandmarkPoint: l, landmarkPoints: a } = gt(), c = Fe((i) => {
1174
+ if (a.length >= s) return;
1175
+ i.stopPropagation();
1176
+ const r = i.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"), w = new h().fromBufferAttribute(g, m[0]), C = new h().fromBufferAttribute(g, m[1]), x = new h().fromBufferAttribute(g, m[2]);
1190
+ w.applyMatrix4(e.matrixWorld), C.applyMatrix4(e.matrixWorld), x.applyMatrix4(e.matrixWorld);
1191
+ const b = r.point, S = vn(b, w, C, x), v = {
1192
+ faceIndex: f,
1193
+ vertexIndices: m,
1194
+ position: {
1195
+ x: b.x,
1196
+ y: b.y,
1197
+ z: b.z
1198
+ },
1199
+ barycentricCoords: S
1200
+ };
1201
+ l(v);
1202
+ }, [
1203
+ e,
1204
+ l,
1205
+ a.length,
1206
+ s
1207
+ ]), u = de(() => !!e.geometry.getAttribute("color"), [
1208
+ e
1209
+ ]), n = de(() => new J.MeshStandardMaterial({
1210
+ color: u ? "#ffffff" : o,
1211
+ side: J.DoubleSide,
1212
+ roughness: 0.6,
1213
+ metalness: 0.1,
1214
+ transparent: t < 1,
1215
+ opacity: t,
1216
+ vertexColors: u
1217
+ }), [
1218
+ o,
1219
+ t,
1220
+ u
1221
+ ]);
1222
+ return d("primitive", {
1223
+ object: e,
1224
+ onClick: c,
1225
+ material: n
1226
+ });
1227
+ }, Dn = ({ point: e, index: s, markerSize: o, color: t, label: l }) => {
1228
+ const [a, c] = q(false);
1229
+ return W("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
+ o,
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: l
1265
+ })
1266
+ })
1267
+ ]
1268
+ }, s);
1269
+ }, Tn = ({ modelSize: e, labels: s }) => {
1270
+ const { landmarkPoints: o } = gt(), t = e * 0.02, l = [
1271
+ "#ff4444",
1272
+ "#44ff44",
1273
+ "#4444ff"
1274
+ ], c = s ?? [
1275
+ "Origin",
1276
+ "MPT",
1277
+ "Cut Plane"
1278
+ ];
1279
+ return d(He, {
1280
+ children: o.map((u, n) => d(Dn, {
1281
+ point: u,
1282
+ index: n,
1283
+ markerSize: t,
1284
+ color: l[n],
1285
+ label: c[n]
1286
+ }, n))
1287
+ });
1288
+ };
1289
+ function kn(e) {
1290
+ return de(() => e ? new $e(e, {
1291
+ maxLeafTris: Ye
1292
+ }) : null, [
1293
+ e
1294
+ ]);
1295
+ }
1296
+ const Ft = (e, s) => {
1297
+ const o = Math.abs(e - s);
1298
+ return o < 1 ? "#8BC34A" : o < 5 ? "#FFC107" : "#FF5722";
1299
+ }, It = new J.Color("#8BC34A"), Pt = new J.Color("#FFC107"), Bn = new J.Color("#FF5722"), Rn = (e) => {
1300
+ if (e < 1) return It.clone();
1301
+ if (e < 5) {
1302
+ const o = (e - 1) / 4;
1303
+ return It.clone().lerp(Pt, o);
1304
+ }
1305
+ const s = Math.min((e - 5) / 5, 1);
1306
+ return Pt.clone().lerp(Bn, s);
1307
+ }, En = (e, s) => {
1308
+ const o = e.length, t = new Float32Array(o * 2 * 3), l = new Float32Array(o * 2 * 3), a = [];
1309
+ for (let n = 0; n < o; n++) {
1310
+ const i = e[n], r = s[n], f = i.distanceTo(r), y = Rn(f);
1311
+ if (t[n * 6] = i.x, t[n * 6 + 1] = i.y, t[n * 6 + 2] = i.z, l[n * 6] = y.r, l[n * 6 + 1] = y.g, l[n * 6 + 2] = y.b, t[n * 6 + 3] = r.x, t[n * 6 + 4] = r.y, t[n * 6 + 5] = r.z, l[n * 6 + 3] = y.r, l[n * 6 + 4] = y.g, l[n * 6 + 5] = y.b, n < o - 1) {
1312
+ const p = n * 2, m = p + 1, g = (n + 1) * 2, w = g + 1;
1313
+ a.push(p, m, g, m, w, g);
1314
+ }
1315
+ }
1316
+ const c = new J.BufferGeometry();
1317
+ c.setAttribute("position", new J.Float32BufferAttribute(t, 3)), c.setAttribute("color", new J.Float32BufferAttribute(l, 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: o, color: t = "#00ff00", labelX: l, onDataChange: a, displayUnit: c = "mm", useInnerSurface: u = false, formValue: n, lineWidth: i = 1.5 }) => {
1328
+ const r = de(() => Ze(e, s, o, u), [
1329
+ e,
1330
+ s,
1331
+ o,
1332
+ u
1333
+ ]), { linePoints: f, lineLength: y } = r, p = de(() => {
1334
+ if (n == null || y <= 0 || f.length < 2) return null;
1335
+ const C = n / y, x = f.reduce((S, v) => S + v.x, 0) / f.length, b = f.reduce((S, v) => S + v.z, 0) / f.length;
1336
+ return f.map((S) => new h(x + (S.x - x) * C, S.y, b + (S.z - b) * C));
1337
+ }, [
1338
+ f,
1339
+ y,
1340
+ n
1341
+ ]), m = de(() => !p || f.length < 2 ? null : En(f, p), [
1342
+ f,
1343
+ p
1344
+ ]);
1345
+ Se(() => () => {
1346
+ m && (m.geometry.dispose(), m.material.dispose());
1347
+ }, [
1348
+ m
1349
+ ]);
1350
+ const g = Ie(null), w = de(() => {
1351
+ const C = new J.BufferGeometry();
1352
+ C.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(C, x);
1360
+ }, []);
1361
+ return Se(() => () => {
1362
+ w.geometry.dispose(), w.material.dispose();
1363
+ }, [
1364
+ w
1365
+ ]), Se(() => {
1366
+ y > 0 && (a == null ? void 0 : a({
1367
+ yPosition: o,
1368
+ originalValue: y,
1369
+ modifiedValue: null
1370
+ }));
1371
+ }, [
1372
+ y,
1373
+ o,
1374
+ a
1375
+ ]), Lt(({ camera: C }) => {
1376
+ if (!g.current || f.length < 2) return;
1377
+ const x = new h();
1378
+ C.getWorldDirection(x);
1379
+ const b = new h(x.x, 0, x.z);
1380
+ if (b.lengthSq() < 1e-8) return;
1381
+ b.normalize();
1382
+ const S = new h().crossVectors(b, new h(0, 1, 0)).normalize();
1383
+ let v = -1 / 0, M = f[0];
1384
+ for (const O of f) {
1385
+ const $ = S.x * O.x + S.z * O.z;
1386
+ $ > v && (v = $, M = O);
1387
+ }
1388
+ const L = l * 0.35, P = new h(M.x + S.x * L, o, M.z + S.z * L);
1389
+ g.current.position.copy(P);
1390
+ const H = w.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 : W("group", {
1393
+ children: [
1394
+ d(ge, {
1395
+ points: f,
1396
+ color: t,
1397
+ lineWidth: i,
1398
+ depthTest: false,
1399
+ depthWrite: false,
1400
+ transparent: true
1401
+ }),
1402
+ m && d("primitive", {
1403
+ object: m
1404
+ }),
1405
+ p && n != null && d(ge, {
1406
+ points: p,
1407
+ color: Ft(y, n),
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: w
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: W("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
+ W("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: n != 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
+ n != null && y > 0 && (() => {
1472
+ const C = y - n, x = C > 0.5 ? "\u25B2" : C < -0.5 ? "\u25BC" : "", b = Ft(y, n);
1473
+ return W("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
+ W("span", {
1493
+ style: {
1494
+ fontSize: 13,
1495
+ color: b,
1496
+ fontFamily: "monospace",
1497
+ fontWeight: 600
1498
+ },
1499
+ children: [
1500
+ C > 0 ? "+" : "",
1501
+ c === "inch" ? (C / 25.4).toFixed(2) : C.toFixed(1)
1502
+ ]
1503
+ }),
1504
+ W("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" ? (n / 25.4).toFixed(2) : n.toFixed(0)
1513
+ ]
1514
+ })
1515
+ ]
1516
+ });
1517
+ })()
1518
+ ]
1519
+ })
1520
+ })
1521
+ })
1522
+ ]
1523
+ });
1524
+ }, Vn = nn(Wn), _n = ({ mesh: e, startY: s, endY: o, spacing: t, modelSize: l, onMeasurementsChange: a, reverseOrder: c = false, displayUnit: u = "mm", useInnerSurface: n = false, formMeasurements: i, 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 = o; b >= s; b -= t) x.push(b);
1528
+ else for (let b = s; b <= o; b += t) x.push(b);
1529
+ return x;
1530
+ }, [
1531
+ s,
1532
+ o,
1533
+ t,
1534
+ c
1535
+ ]);
1536
+ Se(() => {
1537
+ f.current.clear();
1538
+ }, [
1539
+ m
1540
+ ]);
1541
+ const g = [
1542
+ "#5B9BD5"
1543
+ ], w = l * un, C = Fe((x) => {
1544
+ f.current.set(x.yPosition, x);
1545
+ const b = Array.from(f.current.values()).sort((S, v) => c ? v.yPosition - S.yPosition : S.yPosition - v.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: w,
1558
+ onDataChange: C,
1559
+ displayUnit: u,
1560
+ useInnerSurface: n,
1561
+ formValue: i == null ? void 0 : i[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: o, displayUnit: t = "mm" }) => {
1566
+ var _a;
1567
+ const l = e.geometry;
1568
+ l.computeBoundingBox();
1569
+ const a = ((_a = l.boundingBox) == null ? void 0 : _a.min.y) ?? 0, c = s - a, u = o * 0.4, n = o * 0.03, i = Ie(null);
1570
+ Lt(({ camera: C }) => {
1571
+ if (!i.current) return;
1572
+ const x = new h();
1573
+ C.getWorldDirection(x);
1574
+ const b = new h(x.x, 0, x.z);
1575
+ if (b.lengthSq() < 1e-8) return;
1576
+ b.normalize();
1577
+ const S = new h().crossVectors(new h(0, 1, 0), b).normalize();
1578
+ i.current.position.set(S.x * u, 0, S.z * u);
1579
+ const v = C.position.x - i.current.position.x, M = C.position.z - i.current.position.z;
1580
+ i.current.rotation.y = Math.atan2(v, 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(-n, s, 0), m = new h(n, s, 0), g = new h(-n, a, 0), w = new h(n, a, 0);
1583
+ return W("group", {
1584
+ ref: i,
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
+ w
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: W("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: o, mesh: t, viewMode: l, sliceY: a, landmarkCount: c = 0 }) => {
1644
+ const { set: u, size: n, camera: i, invalidate: r } = on(), f = Ie(false), y = Ie(s), p = Ie(o), m = Ie(l), g = Ie(new h()), w = Ie(null), C = Ie(c), x = Fe(() => {
1645
+ if (!t || e <= 0) return;
1646
+ const S = t.geometry;
1647
+ S.computeBoundingBox();
1648
+ const v = S.boundingBox, M = new h();
1649
+ v.getCenter(M);
1650
+ const L = new h();
1651
+ v.getSize(L), g.current.copy(L);
1652
+ const P = n.width / n.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
+ n,
1660
+ u
1661
+ ]), b = Fe((S) => {
1662
+ const v = S.position.clone(), M = v.length(), L = Math.atan2(v.x, v.z), P = Math.acos(v.y / M), O = L + 0.02;
1663
+ S.position.set(M * Math.sin(P) * Math.sin(O), M * Math.cos(P), M * Math.sin(P) * Math.cos(O)), S.lookAt(0, 0, 0), S.updateMatrixWorld(true), r();
1664
+ }, [
1665
+ r
1666
+ ]);
1667
+ return Se(() => {
1668
+ if (e > 0 && !f.current && !s) {
1669
+ f.current = true;
1670
+ const S = new J.PerspectiveCamera(50, n.width / n.height, 0.1, e * 10);
1671
+ S.position.set(e * 0.3, e * 0.2, e * 1.5), S.lookAt(0, 0, 0), u({
1672
+ camera: S
1673
+ }), requestAnimationFrame(() => b(S));
1674
+ }
1675
+ }, [
1676
+ e,
1677
+ n,
1678
+ u,
1679
+ s,
1680
+ b
1681
+ ]), Se(() => {
1682
+ const S = C.current;
1683
+ C.current = c, S === 0 && c === 1 && !s && requestAnimationFrame(() => b(i));
1684
+ }, [
1685
+ c,
1686
+ s,
1687
+ i,
1688
+ b
1689
+ ]), Se(() => {
1690
+ y.current === s && p.current === o || (y.current = s, p.current = o, s && l === "3D" && x());
1691
+ }, [
1692
+ s,
1693
+ o,
1694
+ l,
1695
+ x
1696
+ ]), Se(() => {
1697
+ if (m.current === l) return;
1698
+ const S = m.current;
1699
+ if (m.current = l, !(!s || !t || e <= 0)) if (l === "2D" && a != null) {
1700
+ w.current = i;
1701
+ const v = t.geometry, M = v.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
+ v.computeBoundingBox();
1709
+ const B = v.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 = n.width / n.height, le = 1.4, ee = (O - H) * le, D = (R - $) * le;
1713
+ let z, F;
1714
+ ee / D > oe ? (z = ee, F = ee / oe) : (F = D, z = D * oe);
1715
+ const V = new J.OrthographicCamera(-z / 2, z / 2, F / 2, -F / 2, 0.1, e * 10);
1716
+ V.position.set(N, a + e * 2, ne), V.up.set(0, 0, -1), V.lookAt(N, a, ne), u({
1717
+ camera: V
1718
+ });
1719
+ } else S === "2D" && (w.current ? (u({
1720
+ camera: w.current
1721
+ }), w.current = null) : x());
1722
+ }, [
1723
+ l,
1724
+ a,
1725
+ s,
1726
+ t,
1727
+ e,
1728
+ n,
1729
+ u,
1730
+ i,
1731
+ x
1732
+ ]), Se(() => {
1733
+ if (!s || !i || !i.isOrthographicCamera) return;
1734
+ const S = i;
1735
+ if (l === "2D") {
1736
+ if (!t || a == null) return;
1737
+ const v = t.geometry, M = v.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 z = 0; z < M.count; z++) if (Math.abs(L[z * 3 + 1] - a) < P) {
1740
+ const F = L[z * 3], V = L[z * 3 + 2];
1741
+ F < H && (H = F), F > O && (O = F), V < $ && ($ = V), V > R && (R = V), Y = true;
1742
+ }
1743
+ if (!Y) {
1744
+ v.computeBoundingBox();
1745
+ const z = v.boundingBox;
1746
+ H = z.min.x, O = z.max.x, $ = z.min.z, R = z.max.z;
1747
+ }
1748
+ const N = n.width / n.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), S.left = -ee / 2, S.right = ee / 2, S.top = D / 2, S.bottom = -D / 2;
1751
+ } else {
1752
+ const v = g.current, M = n.width / n.height, L = Math.max(v.y, v.x / M) * 1.2, P = L * M;
1753
+ S.left = -P / 2, S.right = P / 2, S.top = L / 2, S.bottom = -L / 2;
1754
+ }
1755
+ S.updateProjectionMatrix();
1756
+ }, [
1757
+ n.width,
1758
+ n.height,
1759
+ s,
1760
+ i,
1761
+ l,
1762
+ t
1763
+ ]), null;
1764
+ }, Nn = ({ mesh: e, isDragging: s }) => {
1765
+ var _a;
1766
+ const o = e.geometry;
1767
+ o.computeBoundingBox();
1768
+ const t = new h();
1769
+ return (_a = o.boundingBox) == null ? void 0 : _a.getCenter(t), d(Dt, {
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 }) => W("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 }) => W("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: o = "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, l) => {
1875
+ const a = t.number < s, c = t.number === s;
1876
+ return W("div", {
1877
+ style: {
1878
+ display: "contents"
1879
+ },
1880
+ children: [
1881
+ W("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 ? o : "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
+ l < 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: o, modelSize: t, meshColor: l = "#c8c8c8", displayUnit: a = "mm" }) => {
1930
+ const c = e.geometry, u = de(() => new $e(c, {
1931
+ maxLeafTris: Ye
1932
+ }), [
1933
+ c
1934
+ ]), n = de(() => Ze(u, c, o), [
1935
+ u,
1936
+ c,
1937
+ o
1938
+ ]), i = de(() => new it(new h(0, -1, 0), s), [
1939
+ s
1940
+ ]), { mlLine: r, apLine: f, mlWidth: y, apWidth: p } = de(() => {
1941
+ let w = null, C = null, x = 0, b = 0;
1942
+ if (n.linePoints.length >= 2) {
1943
+ let S = n.linePoints[0], v = n.linePoints[0], M = n.linePoints[0], L = n.linePoints[0];
1944
+ for (const P of n.linePoints) P.x < S.x && (S = P), P.x > v.x && (v = P), P.z < M.z && (M = P), P.z > L.z && (L = P);
1945
+ w = [
1946
+ new h(S.x, o, S.z),
1947
+ new h(v.x, o, v.z)
1948
+ ], C = [
1949
+ new h(M.x, o, M.z),
1950
+ new h(L.x, o, L.z)
1951
+ ], x = w[0].distanceTo(w[1]), b = C[0].distanceTo(C[1]);
1952
+ }
1953
+ return {
1954
+ mlLine: w,
1955
+ apLine: C,
1956
+ mlWidth: x,
1957
+ apWidth: b
1958
+ };
1959
+ }, [
1960
+ n,
1961
+ o
1962
+ ]), m = (w) => a === "inch" ? (w / 25.4).toFixed(2) : w.toFixed(1), g = a === "inch" ? "in" : "mm";
1963
+ return W(He, {
1964
+ children: [
1965
+ d("mesh", {
1966
+ geometry: e.geometry,
1967
+ children: d("meshStandardMaterial", {
1968
+ color: l,
1969
+ side: J.DoubleSide,
1970
+ transparent: true,
1971
+ opacity: 0.15,
1972
+ depthWrite: false,
1973
+ clippingPlanes: [
1974
+ i
1975
+ ]
1976
+ })
1977
+ }),
1978
+ n.linePoints.length >= 2 && d(ge, {
1979
+ points: n.linePoints,
1980
+ color: "#00ff00",
1981
+ lineWidth: 3,
1982
+ depthTest: false,
1983
+ depthWrite: false,
1984
+ transparent: true
1985
+ }),
1986
+ r && W(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
+ o,
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: W("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 && W(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
+ o,
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: W("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 Ot(e) {
2091
+ const s = e.getAttribute("position"), o = s.count, t = new h();
2092
+ for (let g = 0; g < o; g++) t.x += s.getX(g), t.y += s.getY(g), t.z += s.getZ(g);
2093
+ t.divideScalar(o);
2094
+ let l = 0, a = 0, c = 0, u = 0, n = 0, i = 0;
2095
+ for (let g = 0; g < o; g++) {
2096
+ const w = s.getX(g) - t.x, C = s.getY(g) - t.y, x = s.getZ(g) - t.z;
2097
+ l += w * w, a += w * C, c += w * x, u += C * C, n += C * x, i += x * x;
2098
+ }
2099
+ l /= o, a /= o, c /= o, u /= o, n /= o, i /= o;
2100
+ const r = [], f = [], y = [
2101
+ [
2102
+ l,
2103
+ a,
2104
+ c
2105
+ ],
2106
+ [
2107
+ a,
2108
+ u,
2109
+ n
2110
+ ],
2111
+ [
2112
+ c,
2113
+ n,
2114
+ i
2115
+ ]
2116
+ ];
2117
+ for (let g = 0; g < 3; g++) {
2118
+ let w = new h(1 + g * 0.1, 1 - g * 0.1, 0.5 + g * 0.3).normalize(), C = 0;
2119
+ for (let x = 0; x < 100; x++) {
2120
+ const b = y[0][0] * w.x + y[0][1] * w.y + y[0][2] * w.z, S = y[1][0] * w.x + y[1][1] * w.y + y[1][2] * w.z, v = y[2][0] * w.x + y[2][1] * w.y + y[2][2] * w.z, M = new h(b, S, v);
2121
+ if (C = M.length(), C < 1e-12) break;
2122
+ if (M.divideScalar(C), w.distanceTo(M) < 1e-10) {
2123
+ w = M;
2124
+ break;
2125
+ }
2126
+ w = M;
2127
+ }
2128
+ r.push(w.clone()), f.push(C);
2129
+ for (let x = 0; x < 3; x++) for (let b = 0; b < 3; b++) {
2130
+ const S = [
2131
+ w.x,
2132
+ w.y,
2133
+ w.z
2134
+ ][x], v = [
2135
+ w.x,
2136
+ w.y,
2137
+ w.z
2138
+ ][b];
2139
+ y[x][b] -= C * S * v;
2140
+ }
2141
+ }
2142
+ const p = new h();
2143
+ for (let g = 0; g < o; g++) p.x += s.getX(g), p.y += s.getY(g), p.z += s.getZ(g);
2144
+ p.divideScalar(o);
2145
+ const m = [
2146
+ 0,
2147
+ 0,
2148
+ 0
2149
+ ];
2150
+ for (let g = 0; g < 3; g++) {
2151
+ let w = 1 / 0, C = -1 / 0;
2152
+ const x = r[g];
2153
+ for (let b = 0; b < o; b++) {
2154
+ const S = s.getX(b) - p.x, v = s.getY(b) - p.y, M = s.getZ(b) - p.z, L = S * x.x + v * x.y + M * x.z;
2155
+ L < w && (w = L), L > C && (C = L);
2156
+ }
2157
+ m[g] = (C - w) / 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, o) => {
2169
+ const t = e.center.clone().addScaledVector(s, e.halfExtents[o]), l = e.center.clone().addScaledVector(s, -e.halfExtents[o]);
2170
+ return d(ge, {
2171
+ points: [
2172
+ l,
2173
+ t
2174
+ ],
2175
+ color: Zn[o],
2176
+ lineWidth: 2
2177
+ }, o);
2178
+ })
2179
+ });
2180
+ }
2181
+ function Un({ pca: e }) {
2182
+ const s = de(() => {
2183
+ const { center: o, axes: t, halfExtents: l } = e, a = [];
2184
+ for (let u = -1; u <= 1; u += 2) for (let n = -1; n <= 1; n += 2) for (let i = -1; i <= 1; i += 2) a.push(o.clone().addScaledVector(t[0], u * l[0]).addScaledVector(t[1], n * l[1]).addScaledVector(t[2], i * l[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, n]) => [
2235
+ a[u],
2236
+ a[n]
2237
+ ]);
2238
+ }, [
2239
+ e
2240
+ ]);
2241
+ return d("group", {
2242
+ children: s.map((o, t) => d(ge, {
2243
+ points: o,
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 o = de(() => new h().subVectors(s, e).normalize(), [
2253
+ e,
2254
+ s
2255
+ ]), t = de(() => {
2256
+ const a = o.dot(new h(0, 1, 0));
2257
+ return Math.acos(Math.min(1, Math.abs(a))) * 180 / Math.PI;
2258
+ }, [
2259
+ o
2260
+ ]), l = t < 1 ? "#44ff44" : t < 5 ? "#ffcc00" : "#ff4444";
2261
+ return W("group", {
2262
+ children: [
2263
+ d(ge, {
2264
+ points: [
2265
+ e,
2266
+ s
2267
+ ],
2268
+ color: l,
2269
+ lineWidth: 3
2270
+ }),
2271
+ W("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
+ W("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: o, modelSize: t }) {
2305
+ const a = t * 0.15, c = de(() => {
2306
+ const u = [];
2307
+ let n = o - 10;
2308
+ const i = new h(0, 1, 0);
2309
+ for (; n > s; ) {
2310
+ const r = Math.min(n, o), f = Math.max(n, o), y = rt(e, r, f);
2311
+ if (y) {
2312
+ const p = y.dot(i), 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
+ n -= 10;
2321
+ }
2322
+ return u;
2323
+ }, [
2324
+ e,
2325
+ s,
2326
+ o
2327
+ ]);
2328
+ return d("group", {
2329
+ children: c.map((u, n) => {
2330
+ const i = (u.regionMin + u.regionMax) / 2, r = new h(0, i, 0), f = r.clone().addScaledVector(u.axis, a), y = r.clone().addScaledVector(u.axis, -a), p = n / 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 W("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
+ }, n);
2355
+ })
2356
+ });
2357
+ }
2358
+ function Jn({ geometry: e, redY: s, greenY: o, modelSize: t }) {
2359
+ const l = de(() => {
2360
+ const f = rt(e, s, o);
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
+ o
2371
+ ]);
2372
+ if (!l) return null;
2373
+ const a = (s + o) / 2, c = new h(0, a, 0), u = t * 0.4, n = c.clone().addScaledVector(l.axis, u), i = c.clone().addScaledVector(l.axis, -u), r = l.angleDeg < 0.5 ? "#00ffff" : l.angleDeg < 2 ? "#ffcc00" : "#ff6600";
2374
+ return d("group", {
2375
+ children: d(ge, {
2376
+ points: [
2377
+ i,
2378
+ n
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 o = e.axes[0], t = s * 0.6, l = e.center.clone().addScaledVector(o, t), a = e.center.clone().addScaledVector(o, -t);
2390
+ return d(ge, {
2391
+ points: [
2392
+ a,
2393
+ l
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: o, modelSize: t }) {
2403
+ const l = de(() => {
2404
+ const i = ot(e), r = new h(0, 1, 0), f = 5;
2405
+ e.computeBoundingBox();
2406
+ const y = e.boundingBox.max.y, p = [];
2407
+ for (let v = s + f; v < y; v += f) {
2408
+ const M = pt(i, e, new h(0, v, 0), r);
2409
+ M > 0 && p.push({
2410
+ y: v,
2411
+ circ: M
2412
+ });
2413
+ }
2414
+ if (p.length < 5) return null;
2415
+ const m = o - s, g = s + m * 0.3, w = s + m * 0.7, C = p.filter((v) => v.y >= g && v.y <= w);
2416
+ if (C.length < 3) return null;
2417
+ const x = C.map((v) => v.circ).sort((v, M) => v - M), b = x[Math.floor(x.length / 2)], S = Math.max(...p.map((v) => v.circ));
2418
+ return {
2419
+ circumferences: p,
2420
+ baseline: b,
2421
+ maxCirc: S
2422
+ };
2423
+ }, [
2424
+ e,
2425
+ s,
2426
+ o
2427
+ ]);
2428
+ if (!l) return null;
2429
+ const { circumferences: a, baseline: c, maxCirc: u } = l, n = t * 0.3 / u;
2430
+ return W("group", {
2431
+ children: [
2432
+ a.map(({ y: i, circ: r }, f) => {
2433
+ const y = r / c, p = y > 1.6 ? "#ff4444" : y > 1.3 ? "#ffcc00" : "#22cc66", m = r * n;
2434
+ return d(ge, {
2435
+ points: [
2436
+ new h(-m, i, 0),
2437
+ new h(m, i, 0)
2438
+ ],
2439
+ color: p,
2440
+ lineWidth: 1.5,
2441
+ transparent: true,
2442
+ opacity: 0.6
2443
+ }, f);
2444
+ }),
2445
+ (() => {
2446
+ const i = c * 1.6 * n, r = a[0].y, f = a[a.length - 1].y;
2447
+ return W(He, {
2448
+ children: [
2449
+ d(ge, {
2450
+ points: [
2451
+ new h(-i, r, 0),
2452
+ new h(-i, 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(i, r, 0),
2465
+ new h(i, 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, o) => {
2484
+ const t = e.colors[o] ?? "#888888", l = o === e.innerIdx;
2485
+ s.computeBoundingBox();
2486
+ const a = new h();
2487
+ return s.boundingBox.getCenter(a), W("group", {
2488
+ children: [
2489
+ d("mesh", {
2490
+ geometry: s,
2491
+ renderOrder: l ? 2 : 1,
2492
+ children: d("meshStandardMaterial", {
2493
+ color: t,
2494
+ transparent: true,
2495
+ opacity: l ? 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: l ? 2 : 1,
2506
+ children: d("meshBasicMaterial", {
2507
+ color: t,
2508
+ wireframe: true,
2509
+ transparent: true,
2510
+ opacity: l ? 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: l ? 700 : 400
2534
+ },
2535
+ children: e.labels[o]
2536
+ })
2537
+ })
2538
+ })
2539
+ })
2540
+ ]
2541
+ }, o);
2542
+ })
2543
+ });
2544
+ }
2545
+ function oo({ mesh: e, layers: s, landmarkPoints: o, componentDebug: t }) {
2546
+ const l = e.geometry, a = de(() => l.getAttribute("position") ? Ot(l) : null, [
2547
+ l
2548
+ ]), c = de(() => !o || o.length < 2 ? null : {
2549
+ red: new h(o[0].position.x, o[0].position.y, o[0].position.z),
2550
+ green: new h(o[1].position.x, o[1].position.y, o[1].position.z)
2551
+ }, [
2552
+ o
2553
+ ]);
2554
+ return W("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: l,
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: l,
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: l,
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, o = de(() => {
2596
+ if (!s.getAttribute("position")) return null;
2597
+ const a = Ot(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 (!o) return null;
2607
+ const t = o.center.clone().addScaledVector(o.axis, o.halfLen), l = o.center.clone().addScaledVector(o.axis, -o.halfLen);
2608
+ return d(ge, {
2609
+ points: [
2610
+ l,
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 $t = [
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($t.map((e) => e.group))
2675
+ ];
2676
+ function io({ layers: e, onToggleLayer: s }) {
2677
+ return W("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((o) => W("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: o
2718
+ }),
2719
+ $t.filter((t) => t.group === o).map(({ key: t, label: l, color: a }) => W("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: l
2755
+ })
2756
+ ]
2757
+ }, t))
2758
+ ]
2759
+ }, o))
2760
+ ]
2761
+ });
2762
+ }
2763
+ const lo = ({ config: e, spacingType: s, scanUrl: o, formMeasurements: t, onComplete: l, isDebugUser: a = false, onAnalyticsEvent: c, wasmModule: u }) => {
2764
+ const [n, i] = q(null), [r, f] = q(0), [y, p] = q(false), [m, g] = q(false), [w, C] = q(""), [x, b] = q("3D"), [S, v] = 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(""), [z, F] = q(false), [V, 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({}), [ze, Ee] = q(t), [ke, Ue] = q(true), [mt] = q("#c8c8c8"), [jt] = q(1), [Xe, Ht] = q(false), lt = Ie(null), { landmarkPoints: ce, clearLandmarkPoints: Yt, addLandmarkPoint: xt, removeLandmarkPoint: yt, updateLandmarkPositions: bt, setAligned: wt, isAligned: be, setCut: St, isCut: Gt } = gt(), at = S * We;
2765
+ Se(() => {
2766
+ t && Ee(t);
2767
+ }, [
2768
+ t
2769
+ ]), Se(() => {
2770
+ t || (Ee(void 0), De({}));
2771
+ }, [
2772
+ S
2773
+ ]);
2774
+ const ct = Ie(false);
2775
+ Se(() => {
2776
+ if (!be || se.length === 0 || ct.current || !c) return;
2777
+ ct.current = true;
2778
+ const _ = 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: (ze == null ? void 0 : ze.filter((K) => K != null)) ?? null,
2787
+ scan_measurements: se.map((K) => +(K.modifiedValue ?? K.originalValue).toFixed(1)),
2788
+ measurement_variance: ze ? se.map((K, ue) => {
2789
+ const Z = ze[ue];
2790
+ return Z == null ? null : +((K.modifiedValue ?? K.originalValue) - Z).toFixed(1);
2791
+ }) : null,
2792
+ frontal_height: _ !== null ? +_.toFixed(1) : null
2793
+ });
2794
+ }, [
2795
+ be,
2796
+ se
2797
+ ]), Se(() => {
2798
+ u !== void 0 && (lt.current = u), Ht(true);
2799
+ }, [
2800
+ u
2801
+ ]);
2802
+ const Qe = Fe((_, K) => {
2803
+ _.computeBoundingBox();
2804
+ const ue = _.boundingBox, Z = new h();
2805
+ ue.getCenter(Z), _.translate(-Z.x, -Z.y, -Z.z), _.computeBoundingBox();
2806
+ const Be = _.boundingBox, te = new h();
2807
+ Be.getSize(te), f(Math.max(te.x, te.y, te.z));
2808
+ const ve = new J.Mesh(_, new J.MeshStandardMaterial({
2809
+ color: 8947848,
2810
+ side: J.DoubleSide
2811
+ }));
2812
+ i(ve), F(K), B(true);
2813
+ }, []), qe = Fe(async (_, K) => {
2814
+ ae(null);
2815
+ const ue = K.toLowerCase(), Z = ue.endsWith(".stl");
2816
+ if (!ue.endsWith(".obj") && !Z) {
2817
+ ae("Unsupported file format. Please use OBJ or STL.");
2818
+ return;
2819
+ }
2820
+ ye(Z ? "stl" : "obj"), g(true), C("Processing file...");
2821
+ try {
2822
+ let te;
2823
+ if (Z) if (C("Converting STL..."), _ instanceof ArrayBuffer) {
2824
+ const Ce = new Blob([
2825
+ _
2826
+ ]), Ve = new File([
2827
+ Ce
2828
+ ], K);
2829
+ te = await ft(Ve);
2830
+ } else {
2831
+ const Ce = new Blob([
2832
+ _
2833
+ ]), Ve = new File([
2834
+ Ce
2835
+ ], K);
2836
+ te = await ft(Ve);
2837
+ }
2838
+ else te = typeof _ == "string" ? _ : new TextDecoder().decode(_);
2839
+ const ve = lt.current ? await bn(te, lt.current, C) : null;
2840
+ if (ve) e.showAmputationModal && !s ? (H(ve), L(true)) : (Qe(ve.geometry, ve.wasScaled), ve.innerShellExtracted && (X(true), E(true)), ve.componentDebug && $(ve.componentDebug));
2841
+ else {
2842
+ C("Using fallback loader...");
2843
+ const Ce = wn(te);
2844
+ Ce ? e.showAmputationModal && !s ? (H({
2845
+ geometry: Ce,
2846
+ wasScaled: false,
2847
+ innerShellExtracted: false
2848
+ }), L(true)) : Qe(Ce, false) : ae("Failed to parse the mesh.");
2849
+ }
2850
+ } catch (te) {
2851
+ ae(te instanceof Error ? te.message : "Failed to process the mesh file.");
2852
+ } finally {
2853
+ g(false), C("");
2854
+ }
2855
+ }, [
2856
+ Xe,
2857
+ e.showAmputationModal,
2858
+ s,
2859
+ Qe
2860
+ ]);
2861
+ Se(() => {
2862
+ if (!o || !Xe) return;
2863
+ (async () => {
2864
+ g(true), C("Downloading scan...");
2865
+ try {
2866
+ const K = await fetch(o);
2867
+ if (!K.ok) throw new Error(`Failed to download scan: ${K.status}`);
2868
+ const Z = new URL(o).pathname.split("/").pop() || "scan.obj";
2869
+ if (Z.toLowerCase().endsWith(".stl")) {
2870
+ const te = await K.arrayBuffer();
2871
+ await qe(te, Z);
2872
+ } else {
2873
+ const te = await K.text();
2874
+ await qe(te, Z);
2875
+ }
2876
+ } catch (K) {
2877
+ ae(K instanceof Error ? K.message : "Failed to load scan from URL."), g(false), C("");
2878
+ }
2879
+ })();
2880
+ }, [
2881
+ o,
2882
+ Xe
2883
+ ]);
2884
+ const Xt = Fe((_) => {
2885
+ _.preventDefault(), p(true);
2886
+ }, []), Zt = Fe((_) => {
2887
+ _.preventDefault(), p(false);
2888
+ }, []), Kt = Fe(async (_) => {
2889
+ if (_.preventDefault(), p(false), !Xe) {
2890
+ ae("WASM module is still loading. Please wait.");
2891
+ return;
2892
+ }
2893
+ const K = _.dataTransfer.files[0];
2894
+ if (!K) return;
2895
+ const ue = K.name.toLowerCase();
2896
+ if (!ue.endsWith(".obj") && !ue.endsWith(".stl")) {
2897
+ ae("Please drop an OBJ or STL file.");
2898
+ return;
2899
+ }
2900
+ if (ue.endsWith(".stl")) {
2901
+ ye("stl"), g(true), C("Converting STL...");
2902
+ try {
2903
+ const Z = await ft(K);
2904
+ await qe(Z, K.name);
2905
+ } catch (Z) {
2906
+ ae(Z instanceof Error ? Z.message : "Failed to process STL file."), g(false), C("");
2907
+ }
2908
+ } else {
2909
+ const Z = await K.text();
2910
+ await qe(Z, K.name);
2911
+ }
2912
+ }, [
2913
+ Xe,
2914
+ qe
2915
+ ]), Ut = Fe((_) => {
2916
+ Y(_), v(_ === "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", {
2917
+ spacing_type: _,
2918
+ file_format: Le,
2919
+ is_double_wall: (P == null ? void 0 : P.innerShellExtracted) ?? false
2920
+ });
2921
+ }, [
2922
+ P,
2923
+ Qe,
2924
+ c,
2925
+ Le
2926
+ ]), Qt = Fe(() => {
2927
+ !n || ce.length < 2 || (le(true), D("Please wait..."), setTimeout(() => {
2928
+ In(n, ce, at, {
2929
+ onStatus: D,
2930
+ addLandmarkPoint: xt,
2931
+ removeLandmarkPoint: yt,
2932
+ updateLandmarkPositions: bt,
2933
+ setAligned: wt,
2934
+ setCut: St,
2935
+ setModelSize: f,
2936
+ setOriginalEndY: Pe,
2937
+ setAdjustedStartY: k,
2938
+ setAdjustedEndY: U,
2939
+ setError: ae,
2940
+ setDoubleShell: (_) => {
2941
+ E(_), ie(true);
2942
+ },
2943
+ setClippedReferenceGeometry: Ne,
2944
+ skipDoubleShellDetection: j
2945
+ }), ct.current = false, le(false);
2946
+ }, 50));
2947
+ }, [
2948
+ n,
2949
+ ce,
2950
+ bt,
2951
+ wt,
2952
+ xt,
2953
+ yt,
2954
+ St,
2955
+ at,
2956
+ j
2957
+ ]), qt = Fe(() => {
2958
+ if (!l || !n || se.length === 0 || !R) return;
2959
+ let _ = 0, K = 0;
2960
+ const ue = ce.length >= 3 ? Math.abs(ce[2].position.y - ce[1].position.y) : 0;
2961
+ if (ce.length >= 2) {
2962
+ const Z = n.geometry, te = ce[1].position.y;
2963
+ try {
2964
+ const ve = ot(Z), Ce = Ze(ve, Z, te);
2965
+ if (Ce.linePoints.length >= 2) {
2966
+ let Ve = Ce.linePoints[0], Je = Ce.linePoints[0], et = Ce.linePoints[0], tt = Ce.linePoints[0];
2967
+ for (const _e of Ce.linePoints) _e.x < Ve.x && (Ve = _e), _e.x > Je.x && (Je = _e), _e.z < et.z && (et = _e), _e.z > tt.z && (tt = _e);
2968
+ _ = new h(Ve.x, te, Ve.z).distanceTo(new h(Je.x, te, Je.z)), K = new h(et.x, te, et.z).distanceTo(new h(tt.x, te, tt.z));
2969
+ }
2970
+ } catch {
2971
+ }
2972
+ }
2973
+ l({
2974
+ spacingType: R,
2975
+ sourceUnit: "mm",
2976
+ fileFormat: Le,
2977
+ measurementSource: ze ? "form_provided" : "scan_derived",
2978
+ isDoubleWall: T,
2979
+ isUnitConverted: false,
2980
+ formMeasurements: ze,
2981
+ scanMeasurements: se,
2982
+ frontalHeight: ue,
2983
+ transverseML: _,
2984
+ transverseAP: K,
2985
+ scanUrl: o
2986
+ });
2987
+ }, [
2988
+ l,
2989
+ n,
2990
+ se,
2991
+ R,
2992
+ ce,
2993
+ Le,
2994
+ T,
2995
+ ze,
2996
+ o
2997
+ ]), Jt = be ? 4 : n ? ce.length === 0 ? 2 : 3 : 1, en = [
2998
+ {
2999
+ label: "Load File",
3000
+ number: 1
3001
+ },
3002
+ {
3003
+ label: "Set Origin",
3004
+ number: 2
3005
+ },
3006
+ {
3007
+ label: R === "AK" ? "Set IT/Perineum" : "Set MPT",
3008
+ number: 3
3009
+ },
3010
+ {
3011
+ label: "Results",
3012
+ number: 4
3013
+ }
3014
+ ];
3015
+ return W(dn.Provider, {
3016
+ value: e,
3017
+ children: [
3018
+ W("div", {
3019
+ style: {
3020
+ flex: 1,
3021
+ display: "flex",
3022
+ flexDirection: "column",
3023
+ backgroundColor: "#F9F9FA",
3024
+ minWidth: 0,
3025
+ position: "relative",
3026
+ height: "100%"
3027
+ },
3028
+ children: [
3029
+ e.showToolbar && d("div", {
3030
+ style: {
3031
+ height: 83,
3032
+ backgroundColor: "#9e9e9e",
3033
+ flexShrink: 0,
3034
+ position: "relative",
3035
+ overflow: "hidden"
3036
+ },
3037
+ children: d("div", {
3038
+ style: {
3039
+ position: "absolute",
3040
+ inset: 0,
3041
+ opacity: 0.1,
3042
+ backgroundImage: "repeating-linear-gradient(45deg, transparent, transparent 10px, #fff 10px, #fff 12px)",
3043
+ pointerEvents: "none"
3044
+ }
3045
+ })
3046
+ }),
3047
+ d(Yn, {
3048
+ steps: en,
3049
+ currentStep: Jt
3050
+ }),
3051
+ W("div", {
3052
+ style: {
3053
+ flex: 1,
3054
+ display: "flex",
3055
+ flexDirection: "column",
3056
+ minHeight: 0
3057
+ },
3058
+ children: [
3059
+ W("div", {
3060
+ style: {
3061
+ flex: 1,
3062
+ position: "relative",
3063
+ minHeight: 0,
3064
+ overflow: "hidden"
3065
+ },
3066
+ onDragOver: e.showDragDrop ? Xt : void 0,
3067
+ onDragLeave: e.showDragDrop ? Zt : void 0,
3068
+ onDrop: e.showDragDrop ? Kt : void 0,
3069
+ children: [
3070
+ e.showDragDrop && !n && !m && d("div", {
3071
+ style: {
3072
+ position: "absolute",
3073
+ inset: 16,
3074
+ border: "3px dashed #ccc",
3075
+ borderRadius: 4,
3076
+ display: "flex",
3077
+ alignItems: "center",
3078
+ justifyContent: "center",
3079
+ pointerEvents: "none"
3080
+ },
3081
+ children: Xe ? d("div", {
3082
+ style: {
3083
+ fontSize: 18,
3084
+ color: "#aaa",
3085
+ fontWeight: 400,
3086
+ fontFamily: "system-ui, sans-serif"
3087
+ },
3088
+ children: "Drag & Drop Files Here"
3089
+ }) : W("div", {
3090
+ style: {
3091
+ textAlign: "center"
3092
+ },
3093
+ children: [
3094
+ d("div", {
3095
+ style: {
3096
+ width: 32,
3097
+ height: 32,
3098
+ border: "3px solid rgba(0,0,0,0.1)",
3099
+ borderTopColor: "#4a90d9",
3100
+ borderRadius: "50%",
3101
+ animation: "spin 1s linear infinite",
3102
+ margin: "0 auto 12px"
3103
+ }
3104
+ }),
3105
+ d("div", {
3106
+ style: {
3107
+ fontSize: 16,
3108
+ color: "#999",
3109
+ fontFamily: "system-ui, sans-serif"
3110
+ },
3111
+ children: "Loading WASM module..."
3112
+ }),
3113
+ d("style", {
3114
+ children: "@keyframes spin { to { transform: rotate(360deg); } }"
3115
+ })
3116
+ ]
3117
+ })
3118
+ }),
3119
+ !e.showDragDrop && !n && !m && !me && d("div", {
3120
+ style: {
3121
+ position: "absolute",
3122
+ inset: 0,
3123
+ display: "flex",
3124
+ alignItems: "center",
3125
+ justifyContent: "center"
3126
+ },
3127
+ children: W("div", {
3128
+ style: {
3129
+ textAlign: "center"
3130
+ },
3131
+ children: [
3132
+ d("div", {
3133
+ style: {
3134
+ width: 32,
3135
+ height: 32,
3136
+ border: "3px solid rgba(0,0,0,0.1)",
3137
+ borderTopColor: "#4a90d9",
3138
+ borderRadius: "50%",
3139
+ animation: "spin 1s linear infinite",
3140
+ margin: "0 auto 12px"
3141
+ }
3142
+ }),
3143
+ d("div", {
3144
+ style: {
3145
+ fontSize: 16,
3146
+ color: "#999",
3147
+ fontFamily: "system-ui, sans-serif"
3148
+ },
3149
+ children: "Loading scan..."
3150
+ }),
3151
+ d("style", {
3152
+ children: "@keyframes spin { to { transform: rotate(360deg); } }"
3153
+ })
3154
+ ]
3155
+ })
3156
+ }),
3157
+ n && !be && ce.length === 0 && W("div", {
3158
+ style: {
3159
+ position: "absolute",
3160
+ top: 16,
3161
+ left: "50%",
3162
+ transform: "translateX(-50%)",
3163
+ display: "flex",
3164
+ alignItems: "center",
3165
+ gap: 8,
3166
+ padding: "8px 16px",
3167
+ backgroundColor: "rgba(0, 0, 0, 0.6)",
3168
+ borderRadius: 8,
3169
+ color: "#fff",
3170
+ fontSize: 13,
3171
+ pointerEvents: "none",
3172
+ zIndex: 5,
3173
+ fontFamily: "system-ui, sans-serif"
3174
+ },
3175
+ children: [
3176
+ d("div", {
3177
+ style: {
3178
+ width: 10,
3179
+ height: 10,
3180
+ borderRadius: "50%",
3181
+ backgroundColor: "#ff4444",
3182
+ flexShrink: 0
3183
+ }
3184
+ }),
3185
+ "Click mesh to set Origin"
3186
+ ]
3187
+ }),
3188
+ n && !be && ce.length === 1 && W("div", {
3189
+ style: {
3190
+ position: "absolute",
3191
+ top: 16,
3192
+ left: "50%",
3193
+ transform: "translateX(-50%)",
3194
+ display: "flex",
3195
+ alignItems: "center",
3196
+ gap: 8,
3197
+ padding: "8px 16px",
3198
+ backgroundColor: "rgba(0, 0, 0, 0.6)",
3199
+ borderRadius: 8,
3200
+ color: "#fff",
3201
+ fontSize: 13,
3202
+ pointerEvents: "none",
3203
+ zIndex: 5,
3204
+ fontFamily: "system-ui, sans-serif"
3205
+ },
3206
+ children: [
3207
+ d("div", {
3208
+ style: {
3209
+ width: 10,
3210
+ height: 10,
3211
+ borderRadius: "50%",
3212
+ backgroundColor: "#44ff44",
3213
+ flexShrink: 0
3214
+ }
3215
+ }),
3216
+ "Click mesh to set ",
3217
+ R === "AK" ? "IT/Perineum" : "MPT"
3218
+ ]
3219
+ }),
3220
+ m && d(At, {
3221
+ message: w || "Processing mesh..."
3222
+ }),
3223
+ oe && d(At, {
3224
+ message: ee
3225
+ }),
3226
+ me && d(Pn, {
3227
+ message: me,
3228
+ onDismiss: () => ae(null)
3229
+ }),
3230
+ e.showAmputationModal && M && d("div", {
3231
+ style: {
3232
+ position: "absolute",
3233
+ inset: 0,
3234
+ backgroundColor: "rgba(0,0,0,0.32)",
3235
+ display: "flex",
3236
+ alignItems: "center",
3237
+ justifyContent: "center",
3238
+ zIndex: 20
3239
+ },
3240
+ children: W("div", {
3241
+ style: {
3242
+ backgroundColor: "#fff",
3243
+ borderRadius: 4,
3244
+ width: 560,
3245
+ 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)",
3246
+ fontFamily: "system-ui, sans-serif"
3247
+ },
3248
+ children: [
3249
+ W("div", {
3250
+ style: {
3251
+ padding: "24px 24px 20px"
3252
+ },
3253
+ children: [
3254
+ d("div", {
3255
+ style: {
3256
+ fontSize: 20,
3257
+ fontWeight: 500,
3258
+ color: "rgba(0,0,0,0.87)",
3259
+ marginBottom: 8
3260
+ },
3261
+ children: "Select Spacing Type"
3262
+ }),
3263
+ d("div", {
3264
+ style: {
3265
+ fontSize: 14,
3266
+ color: "rgba(0,0,0,0.54)",
3267
+ marginBottom: 24
3268
+ },
3269
+ children: "Choose the measurement spacing for this scan"
3270
+ }),
3271
+ d("div", {
3272
+ style: {
3273
+ display: "flex",
3274
+ gap: 16
3275
+ },
3276
+ children: [
3277
+ "AK",
3278
+ "BK"
3279
+ ].map((_) => W("label", {
3280
+ onClick: () => Y(_),
3281
+ style: {
3282
+ flex: 1,
3283
+ display: "flex",
3284
+ flexDirection: "column",
3285
+ padding: "20px 24px",
3286
+ border: "2px solid",
3287
+ borderRadius: 4,
3288
+ cursor: "pointer",
3289
+ borderColor: R === _ ? "rgb(12, 67, 173)" : "#e0e0e0",
3290
+ backgroundColor: R === _ ? "rgba(12, 67, 173, 0.04)" : "#fff",
3291
+ transition: "border-color 0.15s, background-color 0.15s"
3292
+ },
3293
+ children: [
3294
+ d("input", {
3295
+ type: "radio",
3296
+ name: "ampType",
3297
+ checked: R === _,
3298
+ onChange: () => Y(_),
3299
+ style: {
3300
+ accentColor: "rgb(12, 67, 173)",
3301
+ marginBottom: 12,
3302
+ width: 18,
3303
+ height: 18
3304
+ }
3305
+ }),
3306
+ d("span", {
3307
+ style: {
3308
+ fontSize: 18,
3309
+ fontWeight: 600,
3310
+ color: "rgba(0,0,0,0.87)",
3311
+ marginBottom: 4
3312
+ },
3313
+ children: _
3314
+ }),
3315
+ W("span", {
3316
+ style: {
3317
+ fontSize: 13,
3318
+ color: "rgba(0,0,0,0.54)"
3319
+ },
3320
+ children: [
3321
+ _ === "AK" ? "2" : "1",
3322
+ "-inch measurement spacing"
3323
+ ]
3324
+ })
3325
+ ]
3326
+ }, _))
3327
+ })
3328
+ ]
3329
+ }),
3330
+ W("div", {
3331
+ style: {
3332
+ display: "flex",
3333
+ justifyContent: "flex-end",
3334
+ gap: 8,
3335
+ padding: "12px 24px 20px",
3336
+ borderTop: "1px solid #e0e0e0"
3337
+ },
3338
+ children: [
3339
+ d("button", {
3340
+ onClick: () => {
3341
+ L(false), H(null);
3342
+ },
3343
+ style: {
3344
+ padding: "6px 16px",
3345
+ borderRadius: 4,
3346
+ fontSize: 14,
3347
+ fontWeight: 500,
3348
+ backgroundColor: "#fff",
3349
+ border: "1px solid #bdbdbd",
3350
+ color: "rgba(0,0,0,0.87)",
3351
+ cursor: "pointer",
3352
+ fontFamily: "system-ui, sans-serif",
3353
+ lineHeight: "36px",
3354
+ letterSpacing: "0.4px"
3355
+ },
3356
+ children: "Cancel"
3357
+ }),
3358
+ d("button", {
3359
+ onClick: () => R && Ut(R),
3360
+ disabled: !R,
3361
+ style: {
3362
+ padding: "6px 16px",
3363
+ borderRadius: 4,
3364
+ fontSize: 14,
3365
+ fontWeight: 500,
3366
+ backgroundColor: R ? "rgb(12, 67, 173)" : "#e0e0e0",
3367
+ border: "none",
3368
+ color: R ? "#fff" : "#9e9e9e",
3369
+ cursor: R ? "pointer" : "not-allowed",
3370
+ fontFamily: "system-ui, sans-serif",
3371
+ lineHeight: "36px",
3372
+ letterSpacing: "0.4px"
3373
+ },
3374
+ children: "Next \xBB"
3375
+ })
3376
+ ]
3377
+ })
3378
+ ]
3379
+ })
3380
+ }),
3381
+ e.showDragDrop && y && d("div", {
3382
+ style: {
3383
+ position: "absolute",
3384
+ inset: 0,
3385
+ backgroundColor: "rgba(12, 67, 173, 0.1)",
3386
+ border: "2px dashed rgb(12, 67, 173)",
3387
+ pointerEvents: "none",
3388
+ zIndex: 10
3389
+ }
3390
+ }),
3391
+ W(sn, {
3392
+ camera: {
3393
+ position: [
3394
+ 0,
3395
+ 0,
3396
+ 5
3397
+ ]
3398
+ },
3399
+ style: {
3400
+ display: n ? "block" : "none",
3401
+ backgroundColor: xe ? "#070611" : void 0
3402
+ },
3403
+ gl: {
3404
+ localClippingEnabled: true
3405
+ },
3406
+ scene: {
3407
+ background: xe ? new J.Color("#070611") : null
3408
+ },
3409
+ children: [
3410
+ d("ambientLight", {
3411
+ intensity: 0.4
3412
+ }),
3413
+ d("directionalLight", {
3414
+ position: [
3415
+ 10,
3416
+ 10,
3417
+ 5
3418
+ ],
3419
+ intensity: 1.2
3420
+ }),
3421
+ d("directionalLight", {
3422
+ position: [
3423
+ -5,
3424
+ 5,
3425
+ -5
3426
+ ],
3427
+ intensity: 0.4
3428
+ }),
3429
+ d("directionalLight", {
3430
+ position: [
3431
+ 0,
3432
+ -10,
3433
+ 0
3434
+ ],
3435
+ intensity: 0.2
3436
+ }),
3437
+ n && x === "3D" && d(Ln, {
3438
+ mesh: n,
3439
+ maxPoints: 2,
3440
+ meshColor: mt,
3441
+ meshOpacity: xe ? 0.3 : jt
3442
+ }),
3443
+ he && fe && x === "3D" && d("mesh", {
3444
+ geometry: fe,
3445
+ renderOrder: 1,
3446
+ children: d("meshStandardMaterial", {
3447
+ color: "#c8c8c8",
3448
+ transparent: true,
3449
+ opacity: 0.35,
3450
+ side: J.DoubleSide,
3451
+ depthWrite: false,
3452
+ polygonOffset: true,
3453
+ polygonOffsetFactor: 1,
3454
+ polygonOffsetUnits: 1
3455
+ })
3456
+ }),
3457
+ n && x === "3D" && d(Tn, {
3458
+ modelSize: r,
3459
+ labels: [
3460
+ "Origin",
3461
+ R === "AK" ? "IT/Perineum" : "MPT",
3462
+ "Cut Plane"
3463
+ ]
3464
+ }),
3465
+ d($n, {
3466
+ modelSize: r,
3467
+ isAligned: be,
3468
+ isCut: Gt,
3469
+ mesh: n,
3470
+ viewMode: x,
3471
+ sliceY: be && ce.length >= 2 ? G ?? re ?? ce[1].position.y : void 0,
3472
+ landmarkCount: ce.length
3473
+ }),
3474
+ !be && d(Dt, {
3475
+ enableDamping: false
3476
+ }),
3477
+ be && se.length > 0 && n && x === "3D" && d(Nn, {
3478
+ mesh: n,
3479
+ isDragging: false
3480
+ }),
3481
+ n && be && ce.length >= 3 && (() => {
3482
+ const K = n.geometry.getIndex();
3483
+ if (!K || K.count < 30) return null;
3484
+ const ue = ce[2], Z = ce[1], Be = I ?? ue.position.y, te = G ?? re ?? Z.position.y;
3485
+ return x === "2D" ? d(Gn, {
3486
+ mesh: n,
3487
+ upperY: te,
3488
+ originY: Z.position.y,
3489
+ modelSize: r,
3490
+ meshColor: mt,
3491
+ displayUnit: N
3492
+ }) : W(He, {
3493
+ children: [
3494
+ d(_n, {
3495
+ mesh: n,
3496
+ startY: Be,
3497
+ endY: te,
3498
+ spacing: at,
3499
+ modelSize: r,
3500
+ onMeasurementsChange: A,
3501
+ reverseOrder: true,
3502
+ displayUnit: N,
3503
+ useInnerSurface: T && !j,
3504
+ formMeasurements: ke ? ze : void 0,
3505
+ originY: Z.position.y
3506
+ }),
3507
+ (!T || j) && d(On, {
3508
+ mesh: n,
3509
+ greenY: Z.position.y,
3510
+ modelSize: r,
3511
+ displayUnit: N
3512
+ })
3513
+ ]
3514
+ });
3515
+ })(),
3516
+ n && be && x === "3D" && d(so, {
3517
+ mesh: n
3518
+ }),
3519
+ n && e.showDebug && xe && x === "3D" && d(oo, {
3520
+ mesh: n,
3521
+ modelSize: r,
3522
+ layers: pe,
3523
+ landmarkPoints: ce,
3524
+ componentDebug: O
3525
+ })
3526
+ ]
3527
+ }),
3528
+ n && (e.showStartOver || e.showInsertMeasurement) && W("div", {
3529
+ style: {
3530
+ position: "absolute",
3531
+ top: 16,
3532
+ left: 16,
3533
+ zIndex: 10,
3534
+ display: "flex",
3535
+ gap: 8
3536
+ },
3537
+ children: [
3538
+ e.showStartOver && d("button", {
3539
+ onClick: () => window.location.reload(),
3540
+ style: {
3541
+ padding: "6px 16px",
3542
+ borderRadius: 4,
3543
+ fontSize: 13,
3544
+ fontWeight: 500,
3545
+ backgroundColor: "#fff",
3546
+ border: "1px solid #bdbdbd",
3547
+ color: "#333",
3548
+ cursor: "pointer",
3549
+ fontFamily: "system-ui, sans-serif",
3550
+ letterSpacing: "0.4px",
3551
+ boxShadow: "0 2px 8px rgba(0,0,0,0.1)"
3552
+ },
3553
+ children: "Start Over"
3554
+ }),
3555
+ e.showInsertMeasurement && d("button", {
3556
+ onClick: () => Me(true),
3557
+ style: {
3558
+ padding: "6px 16px",
3559
+ borderRadius: 4,
3560
+ fontSize: 13,
3561
+ fontWeight: 500,
3562
+ backgroundColor: "rgb(12, 67, 173)",
3563
+ border: "none",
3564
+ color: "#fff",
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: "Insert Measurement"
3571
+ })
3572
+ ]
3573
+ }),
3574
+ e.showDebug && xe && n && x === "3D" && d(io, {
3575
+ layers: pe,
3576
+ onToggleLayer: (_) => we((K) => ({
3577
+ ...K,
3578
+ [_]: !K[_]
3579
+ }))
3580
+ }),
3581
+ be && se.length > 0 && W("div", {
3582
+ style: {
3583
+ position: "absolute",
3584
+ top: 16,
3585
+ right: 16,
3586
+ display: "flex",
3587
+ gap: 8,
3588
+ zIndex: 10
3589
+ },
3590
+ children: [
3591
+ W("div", {
3592
+ style: {
3593
+ display: "flex",
3594
+ borderRadius: 6,
3595
+ overflow: "hidden",
3596
+ border: "1px solid #ccc",
3597
+ boxShadow: "0 2px 8px rgba(0,0,0,0.1)"
3598
+ },
3599
+ children: [
3600
+ d("button", {
3601
+ onClick: () => b("3D"),
3602
+ style: {
3603
+ padding: "6px 14px",
3604
+ fontSize: 13,
3605
+ fontWeight: x === "3D" ? 600 : 400,
3606
+ backgroundColor: x === "3D" ? "rgb(12, 67, 173)" : "#fff",
3607
+ color: x === "3D" ? "#fff" : "#666",
3608
+ border: "none",
3609
+ cursor: "pointer",
3610
+ fontFamily: "system-ui, sans-serif"
3611
+ },
3612
+ children: "Frontal"
3613
+ }),
3614
+ d("button", {
3615
+ onClick: () => b("2D"),
3616
+ style: {
3617
+ padding: "6px 14px",
3618
+ fontSize: 13,
3619
+ fontWeight: x === "2D" ? 600 : 400,
3620
+ backgroundColor: x === "2D" ? "rgb(12, 67, 173)" : "#fff",
3621
+ color: x === "2D" ? "#fff" : "#666",
3622
+ border: "none",
3623
+ borderLeft: "1px solid #ccc",
3624
+ cursor: "pointer",
3625
+ fontFamily: "system-ui, sans-serif"
3626
+ },
3627
+ children: "Transverse"
3628
+ })
3629
+ ]
3630
+ }),
3631
+ W("div", {
3632
+ style: {
3633
+ display: "flex",
3634
+ borderRadius: 6,
3635
+ overflow: "hidden",
3636
+ border: "1px solid #ccc",
3637
+ boxShadow: "0 2px 8px rgba(0,0,0,0.1)"
3638
+ },
3639
+ children: [
3640
+ d("button", {
3641
+ onClick: () => ne("mm"),
3642
+ style: {
3643
+ padding: "6px 14px",
3644
+ fontSize: 13,
3645
+ fontWeight: N === "mm" ? 600 : 400,
3646
+ backgroundColor: N === "mm" ? "rgb(12, 67, 173)" : "#fff",
3647
+ color: N === "mm" ? "#fff" : "#666",
3648
+ border: "none",
3649
+ cursor: "pointer",
3650
+ fontFamily: "system-ui, sans-serif"
3651
+ },
3652
+ children: "mm"
3653
+ }),
3654
+ d("button", {
3655
+ onClick: () => ne("inch"),
3656
+ style: {
3657
+ padding: "6px 14px",
3658
+ fontSize: 13,
3659
+ fontWeight: N === "inch" ? 600 : 400,
3660
+ backgroundColor: N === "inch" ? "rgb(12, 67, 173)" : "#fff",
3661
+ color: N === "inch" ? "#fff" : "#666",
3662
+ border: "none",
3663
+ borderLeft: "1px solid #ccc",
3664
+ cursor: "pointer",
3665
+ fontFamily: "system-ui, sans-serif"
3666
+ },
3667
+ children: "in"
3668
+ })
3669
+ ]
3670
+ }),
3671
+ e.showSpacingToggle && x === "3D" && W("div", {
3672
+ style: {
3673
+ display: "flex",
3674
+ borderRadius: 6,
3675
+ overflow: "hidden",
3676
+ border: "1px solid #ccc",
3677
+ boxShadow: "0 2px 8px rgba(0,0,0,0.1)"
3678
+ },
3679
+ children: [
3680
+ d("button", {
3681
+ onClick: () => v(1),
3682
+ style: {
3683
+ padding: "6px 14px",
3684
+ fontSize: 13,
3685
+ fontWeight: S === 1 ? 600 : 400,
3686
+ backgroundColor: S === 1 ? "rgb(12, 67, 173)" : "#fff",
3687
+ color: S === 1 ? "#fff" : "#666",
3688
+ border: "none",
3689
+ cursor: "pointer",
3690
+ fontFamily: "system-ui, sans-serif"
3691
+ },
3692
+ children: '1"'
3693
+ }),
3694
+ d("button", {
3695
+ onClick: () => v(2),
3696
+ style: {
3697
+ padding: "6px 14px",
3698
+ fontSize: 13,
3699
+ fontWeight: S === 2 ? 600 : 400,
3700
+ backgroundColor: S === 2 ? "rgb(12, 67, 173)" : "#fff",
3701
+ color: S === 2 ? "#fff" : "#666",
3702
+ border: "none",
3703
+ borderLeft: "1px solid #ccc",
3704
+ cursor: "pointer",
3705
+ fontFamily: "system-ui, sans-serif"
3706
+ },
3707
+ children: '2"'
3708
+ })
3709
+ ]
3710
+ }),
3711
+ x === "3D" && fe && d("div", {
3712
+ style: {
3713
+ display: "flex",
3714
+ borderRadius: 6,
3715
+ overflow: "hidden",
3716
+ border: "1px solid #ccc",
3717
+ boxShadow: "0 2px 8px rgba(0,0,0,0.1)"
3718
+ },
3719
+ children: d("button", {
3720
+ onClick: () => Ge((_) => !_),
3721
+ style: {
3722
+ padding: "6px 14px",
3723
+ fontSize: 13,
3724
+ fontWeight: he ? 600 : 400,
3725
+ backgroundColor: he ? "rgb(12, 67, 173)" : "#fff",
3726
+ color: he ? "#fff" : "#666",
3727
+ border: "none",
3728
+ cursor: "pointer",
3729
+ fontFamily: "system-ui, sans-serif"
3730
+ },
3731
+ children: "Show Full Scan"
3732
+ })
3733
+ }),
3734
+ x === "3D" && ze && d("div", {
3735
+ style: {
3736
+ display: "flex",
3737
+ borderRadius: 6,
3738
+ overflow: "hidden",
3739
+ border: "1px solid #ccc",
3740
+ boxShadow: "0 2px 8px rgba(0,0,0,0.1)"
3741
+ },
3742
+ children: d("button", {
3743
+ onClick: () => Ue((_) => !_),
3744
+ style: {
3745
+ padding: "6px 14px",
3746
+ fontSize: 13,
3747
+ fontWeight: ke ? 600 : 400,
3748
+ backgroundColor: ke ? "rgb(12, 67, 173)" : "#fff",
3749
+ color: ke ? "#fff" : "#666",
3750
+ border: "none",
3751
+ cursor: "pointer",
3752
+ fontFamily: "system-ui, sans-serif"
3753
+ },
3754
+ children: "Form Overlay"
3755
+ })
3756
+ }),
3757
+ e.showDebug && a && d("div", {
3758
+ style: {
3759
+ display: "flex",
3760
+ borderRadius: 6,
3761
+ overflow: "hidden",
3762
+ border: "1px solid #ccc",
3763
+ boxShadow: "0 2px 8px rgba(0,0,0,0.1)"
3764
+ },
3765
+ children: d("button", {
3766
+ onClick: () => Re((_) => !_),
3767
+ style: {
3768
+ padding: "6px 14px",
3769
+ fontSize: 13,
3770
+ fontWeight: xe ? 600 : 400,
3771
+ backgroundColor: xe ? "#e65100" : "#fff",
3772
+ color: xe ? "#fff" : "#666",
3773
+ border: "none",
3774
+ cursor: "pointer",
3775
+ fontFamily: "system-ui, sans-serif"
3776
+ },
3777
+ children: "Debug"
3778
+ })
3779
+ })
3780
+ ]
3781
+ }),
3782
+ n && V && d(jn, {
3783
+ wasAutoScaled: z,
3784
+ onDismiss: () => B(false)
3785
+ }),
3786
+ n && Q && be && d(Hn, {
3787
+ isDoubleShell: T,
3788
+ onDismiss: () => ie(false)
3789
+ })
3790
+ ]
3791
+ }),
3792
+ W("div", {
3793
+ style: {
3794
+ padding: "12px 24px",
3795
+ backgroundColor: "#fff",
3796
+ borderTop: "1px solid #e0e0e0",
3797
+ display: "flex",
3798
+ alignItems: "center",
3799
+ justifyContent: "flex-end",
3800
+ gap: 8,
3801
+ flexShrink: 0
3802
+ },
3803
+ children: [
3804
+ n && !be && ce.length >= 2 && d("button", {
3805
+ onClick: Qt,
3806
+ style: {
3807
+ padding: "6px 16px",
3808
+ borderRadius: 4,
3809
+ fontSize: 14,
3810
+ fontWeight: 500,
3811
+ backgroundColor: "rgb(12, 67, 173)",
3812
+ border: "none",
3813
+ color: "#fff",
3814
+ cursor: "pointer",
3815
+ fontFamily: "system-ui, sans-serif",
3816
+ letterSpacing: "0.4px",
3817
+ lineHeight: "36px"
3818
+ },
3819
+ children: "Next \xBB"
3820
+ }),
3821
+ n && !be && ce.length >= 1 && d("button", {
3822
+ onClick: Yt,
3823
+ style: {
3824
+ padding: "6px 16px",
3825
+ borderRadius: 4,
3826
+ fontSize: 14,
3827
+ fontWeight: 500,
3828
+ backgroundColor: "#fff",
3829
+ border: "1px solid #bdbdbd",
3830
+ color: "#333",
3831
+ cursor: "pointer",
3832
+ fontFamily: "system-ui, sans-serif",
3833
+ letterSpacing: "0.4px",
3834
+ lineHeight: "36px"
3835
+ },
3836
+ children: "Reset Points"
3837
+ }),
3838
+ be && d("button", {
3839
+ onClick: qt,
3840
+ disabled: se.length === 0,
3841
+ style: {
3842
+ padding: "6px 16px",
3843
+ borderRadius: 4,
3844
+ fontSize: 14,
3845
+ fontWeight: 500,
3846
+ backgroundColor: se.length > 0 ? "rgb(12, 67, 173)" : "#e0e0e0",
3847
+ border: "none",
3848
+ color: se.length > 0 ? "#fff" : "#9e9e9e",
3849
+ cursor: se.length > 0 ? "pointer" : "not-allowed",
3850
+ fontFamily: "system-ui, sans-serif",
3851
+ letterSpacing: "0.4px",
3852
+ lineHeight: "36px"
3853
+ },
3854
+ children: "Continue to Next Step"
3855
+ })
3856
+ ]
3857
+ })
3858
+ ]
3859
+ })
3860
+ ]
3861
+ }),
3862
+ e.showInsertMeasurement && Te && (() => {
3863
+ const _ = R === "AK" ? "IT/Perineum" : "MPT", K = S, ue = [];
3864
+ for (let Z = 2; Z >= 1; Z -= K) ue.push(`${Z}\u2033 above ${_}`);
3865
+ ue.push(`At ${_}`);
3866
+ for (let Z = K; Z <= 9; Z += K) ue.push(`${Z}\u2033 below ${_}`);
3867
+ return d("div", {
3868
+ style: {
3869
+ position: "fixed",
3870
+ inset: 0,
3871
+ backgroundColor: "rgba(0,0,0,0.32)",
3872
+ display: "flex",
3873
+ alignItems: "center",
3874
+ justifyContent: "flex-start",
3875
+ paddingLeft: 40,
3876
+ zIndex: 9999
3877
+ },
3878
+ children: W("div", {
3879
+ style: {
3880
+ backgroundColor: "#fff",
3881
+ borderRadius: 4,
3882
+ width: 620,
3883
+ maxHeight: "80vh",
3884
+ display: "flex",
3885
+ flexDirection: "column",
3886
+ 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)",
3887
+ fontFamily: "system-ui, sans-serif"
3888
+ },
3889
+ children: [
3890
+ W("div", {
3891
+ style: {
3892
+ padding: "24px 24px 0"
3893
+ },
3894
+ children: [
3895
+ W("div", {
3896
+ style: {
3897
+ fontSize: 20,
3898
+ fontWeight: 500,
3899
+ color: "rgba(0,0,0,0.87)",
3900
+ marginBottom: 4
3901
+ },
3902
+ children: [
3903
+ R,
3904
+ " Circumferences"
3905
+ ]
3906
+ }),
3907
+ W("div", {
3908
+ style: {
3909
+ fontSize: 13,
3910
+ color: "rgba(0,0,0,0.54)",
3911
+ marginBottom: 20
3912
+ },
3913
+ children: [
3914
+ "Enter form measurements (mm). ",
3915
+ K,
3916
+ "\u2033",
3917
+ " spacing."
3918
+ ]
3919
+ })
3920
+ ]
3921
+ }),
3922
+ d("div", {
3923
+ style: {
3924
+ padding: "0 24px",
3925
+ overflowY: "auto",
3926
+ flex: 1
3927
+ },
3928
+ children: d("div", {
3929
+ style: {
3930
+ display: "grid",
3931
+ gridTemplateColumns: "1fr 1fr",
3932
+ gap: "16px 24px"
3933
+ },
3934
+ children: ue.map((Z, Be) => W("div", {
3935
+ children: [
3936
+ W("label", {
3937
+ style: {
3938
+ display: "block",
3939
+ fontSize: 13,
3940
+ fontWeight: 500,
3941
+ color: "rgb(12, 67, 173)",
3942
+ marginBottom: 6
3943
+ },
3944
+ children: [
3945
+ Z,
3946
+ " (mm):"
3947
+ ]
3948
+ }),
3949
+ d("input", {
3950
+ type: "number",
3951
+ step: "0.1",
3952
+ value: Ae[Z] ?? "",
3953
+ onChange: (te) => De((ve) => ({
3954
+ ...ve,
3955
+ [Z]: te.target.value
3956
+ })),
3957
+ style: {
3958
+ width: "100%",
3959
+ padding: "10px 12px",
3960
+ fontSize: 15,
3961
+ border: "2px solid rgb(12, 67, 173)",
3962
+ borderRadius: 4,
3963
+ outline: "none",
3964
+ boxSizing: "border-box",
3965
+ fontFamily: "system-ui, sans-serif"
3966
+ }
3967
+ })
3968
+ ]
3969
+ }, Be))
3970
+ })
3971
+ }),
3972
+ W("div", {
3973
+ style: {
3974
+ display: "flex",
3975
+ justifyContent: "flex-end",
3976
+ gap: 8,
3977
+ padding: "16px 24px",
3978
+ borderTop: "1px solid #e0e0e0",
3979
+ marginTop: 16
3980
+ },
3981
+ children: [
3982
+ d("button", {
3983
+ onClick: () => {
3984
+ Me(false), De({});
3985
+ },
3986
+ style: {
3987
+ padding: "6px 16px",
3988
+ borderRadius: 4,
3989
+ fontSize: 14,
3990
+ fontWeight: 500,
3991
+ backgroundColor: "#fff",
3992
+ border: "1px solid #bdbdbd",
3993
+ color: "rgba(0,0,0,0.87)",
3994
+ cursor: "pointer",
3995
+ fontFamily: "system-ui, sans-serif",
3996
+ lineHeight: "36px",
3997
+ letterSpacing: "0.4px"
3998
+ },
3999
+ children: "Cancel"
4000
+ }),
4001
+ d("button", {
4002
+ onClick: () => {
4003
+ const Z = ue.map((te) => parseFloat(Ae[te] || "")), Be = Z.filter((te) => !isNaN(te));
4004
+ Ee(Be.length > 0 ? Z.map((te) => isNaN(te) ? void 0 : te) : void 0), Me(false);
4005
+ },
4006
+ style: {
4007
+ padding: "6px 16px",
4008
+ borderRadius: 4,
4009
+ fontSize: 14,
4010
+ fontWeight: 500,
4011
+ backgroundColor: "rgb(12, 67, 173)",
4012
+ border: "none",
4013
+ color: "#fff",
4014
+ cursor: "pointer",
4015
+ fontFamily: "system-ui, sans-serif",
4016
+ lineHeight: "36px",
4017
+ letterSpacing: "0.4px"
4018
+ },
4019
+ children: "Save"
4020
+ })
4021
+ ]
4022
+ })
4023
+ ]
4024
+ })
4025
+ });
4026
+ })()
4027
+ ]
4028
+ });
4029
+ };
4030
+ Nt = function(e) {
4031
+ const s = e === "AK" ? 2 : 1, o = [];
4032
+ for (let t = 2; t >= 1; t -= s) o.push(`${t}_above`);
4033
+ o.push("at_ref");
4034
+ for (let t = s; t <= 9; t += s) o.push(`${t}_below`);
4035
+ return o;
4036
+ };
4037
+ dt = function(e, s) {
4038
+ const o = Nt(s), t = {};
4039
+ for (let l = 0; l < Math.min(e.length, o.length); l++) {
4040
+ const a = e[l];
4041
+ a != null && !isNaN(a) && (t[o[l]] = a);
4042
+ }
4043
+ return t;
4044
+ };
4045
+ ao = function(e, s) {
4046
+ if (!e) return;
4047
+ const t = Nt(s).map((l) => {
4048
+ const a = e[l];
4049
+ return a ?? void 0;
4050
+ });
4051
+ if (!t.every((l) => l == null)) return t;
4052
+ };
4053
+ bo = ({ request: e, onComplete: s, wasmModule: o }) => {
4054
+ const [t, l] = q(null);
4055
+ Se(() => {
4056
+ if (o !== void 0) return;
4057
+ let n = false;
4058
+ return import("./galileo_core_geo-DFVJmkI7.js").then(async (i) => {
4059
+ await i.default(), n || l(i);
4060
+ }).catch(() => {
4061
+ }), () => {
4062
+ n = true;
4063
+ };
4064
+ }, [
4065
+ o
4066
+ ]);
4067
+ const a = o !== void 0 ? o : t, c = de(() => ao(e.form_measurements, e.spacing_type), [
4068
+ e.form_measurements,
4069
+ e.spacing_type
4070
+ ]), u = (n) => {
4071
+ const i = n.scanMeasurements.map((m) => +(m.modifiedValue ?? m.originalValue).toFixed(1)), r = dt(i, e.spacing_type);
4072
+ let f, y;
4073
+ if (n.formMeasurements) {
4074
+ f = dt(n.formMeasurements, e.spacing_type);
4075
+ const m = n.scanMeasurements.map((g, w) => {
4076
+ var _a;
4077
+ const C = (_a = n.formMeasurements) == null ? void 0 : _a[w];
4078
+ return C == null || isNaN(C) ? null : +((g.modifiedValue ?? g.originalValue) - C).toFixed(1);
4079
+ });
4080
+ y = dt(m, e.spacing_type);
4081
+ }
4082
+ const p = {
4083
+ spacing_type: e.spacing_type,
4084
+ source_unit: "mm",
4085
+ file_format: n.fileFormat,
4086
+ measurement_source: n.formMeasurements ? "form_provided" : "scan_derived",
4087
+ is_double_wall: n.isDoubleWall,
4088
+ is_unit_converted: false,
4089
+ form_measurements: f,
4090
+ scan_measurements: r,
4091
+ measurement_variance: y,
4092
+ scan_url: e.scan_url,
4093
+ frontal_height: +n.frontalHeight.toFixed(1),
4094
+ transverse_ml: +n.transverseML.toFixed(1),
4095
+ transverse_ap: +n.transverseAP.toFixed(1)
4096
+ };
4097
+ console.log("[GirthManagerWidget] WidgetResponse:", JSON.stringify(p, null, 2)), s == null ? void 0 : s(p);
4098
+ };
4099
+ return d("div", {
4100
+ style: {
4101
+ width: "100%",
4102
+ height: "100%",
4103
+ display: "flex"
4104
+ },
4105
+ children: d(lo, {
4106
+ config: fn,
4107
+ spacingType: e.spacing_type,
4108
+ scanUrl: e.scan_url,
4109
+ formMeasurements: c,
4110
+ onComplete: u,
4111
+ wasmModule: a
4112
+ })
4113
+ });
4114
+ };
4115
+ })();
4116
+ export {
4117
+ bo as G,
4118
+ __tla,
4119
+ dt as a,
4120
+ ao as c,
4121
+ Nt as g
4122
+ };