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

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,4137 @@
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 Pt, 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, jt;
12
+ let __tla = (async () => {
13
+ const cn = {
14
+ showDragDrop: true,
15
+ showStartOver: true,
16
+ showInsertMeasurement: true,
17
+ showDebug: true,
18
+ showSpacingToggle: true,
19
+ showAmputationModal: true,
20
+ showNavigation: true,
21
+ showToolbar: true
22
+ }, fn = {
23
+ showDragDrop: false,
24
+ showStartOver: false,
25
+ showInsertMeasurement: false,
26
+ showDebug: false,
27
+ showSpacingToggle: false,
28
+ showAmputationModal: false,
29
+ showNavigation: false,
30
+ showToolbar: false
31
+ }, dn = tn(cn), gt = rn((e, r) => ({
32
+ landmarkPoints: [],
33
+ isAligned: false,
34
+ isCut: false,
35
+ addLandmarkPoint: (n) => e((t) => t.landmarkPoints.length >= 3 ? t : {
36
+ landmarkPoints: [
37
+ ...t.landmarkPoints,
38
+ n
39
+ ]
40
+ }),
41
+ removeLandmarkPoint: (n) => e((t) => ({
42
+ landmarkPoints: t.landmarkPoints.filter((i, a) => a !== n)
43
+ })),
44
+ clearLandmarkPoints: () => e({
45
+ landmarkPoints: [],
46
+ isAligned: false,
47
+ isCut: false
48
+ }),
49
+ updateLandmarkPositions: (n) => e((t) => ({
50
+ landmarkPoints: t.landmarkPoints.map((i, a) => ({
51
+ ...i,
52
+ position: n[a] ?? i.position
53
+ }))
54
+ })),
55
+ setAligned: (n) => e({
56
+ isAligned: n
57
+ }),
58
+ setCut: (n) => e({
59
+ isCut: n
60
+ }),
61
+ isSelectionComplete: () => r().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 r = e.split(`
70
+ `), n = [], t = [];
71
+ let i = false;
72
+ for (const a of r) if (a.startsWith("v ")) {
73
+ const c = a.trim().split(/\s+/);
74
+ if (c.length >= 7) {
75
+ n.push(parseFloat(c[1]), parseFloat(c[2]), parseFloat(c[3]));
76
+ let u = parseFloat(c[4]), s = parseFloat(c[5]), l = parseFloat(c[6]);
77
+ (u > 1 || s > 1 || l > 1) && (u /= 255, s /= 255, l /= 255), t.push(u, s, l), i = true;
78
+ } else c.length >= 4 && (n.push(parseFloat(c[1]), parseFloat(c[2]), parseFloat(c[3])), t.push(0, 0, 0));
79
+ }
80
+ return i ? {
81
+ positions: new Float32Array(n),
82
+ colors: new Float32Array(t)
83
+ } : null;
84
+ }
85
+ function mn(e, r, n, t) {
86
+ const i = e.getAttribute("position"), a = i.count, c = new Float32Array(a * 3), u = r.length / 3;
87
+ let s = 1 / 0, l = 1 / 0, o = 1 / 0, f = -1 / 0, y = -1 / 0, p = -1 / 0;
88
+ for (let b = 0; b < u; b++) {
89
+ const S = r[b * 3] * t, C = r[b * 3 + 1] * t, M = r[b * 3 + 2] * t;
90
+ S < s && (s = S), S > f && (f = S), C < l && (l = C), C > y && (y = C), M < o && (o = M), M > p && (p = M);
91
+ }
92
+ const x = Math.min(128, Math.max(16, Math.round(Math.cbrt(u)))), g = (f - s + 1e-6) / x, w = (y - l + 1e-6) / x, v = (p - o + 1e-6) / x, m = /* @__PURE__ */ new Map();
93
+ for (let b = 0; b < u; b++) {
94
+ const S = Math.min(x - 1, Math.floor((r[b * 3] * t - s) / g)), C = Math.min(x - 1, Math.floor((r[b * 3 + 1] * t - l) / w)), M = Math.min(x - 1, Math.floor((r[b * 3 + 2] * t - o) / v)), P = S * x * x + C * x + M;
95
+ let L = m.get(P);
96
+ L || (L = [], m.set(P, L)), L.push(b);
97
+ }
98
+ for (let b = 0; b < a; b++) {
99
+ const S = i.getX(b), C = i.getY(b), M = i.getZ(b), P = Math.min(x - 1, Math.max(0, Math.floor((S - s) / g))), L = Math.min(x - 1, Math.max(0, Math.floor((C - l) / w))), H = Math.min(x - 1, Math.max(0, Math.floor((M - o) / v)));
100
+ let O = 1 / 0, $ = 0;
101
+ for (let R = 0; R <= x && O > 0; R++) {
102
+ for (let Y = -R; Y <= R; Y++) for (let j = -R; j <= R; j++) for (let ne = -R; ne <= R; ne++) {
103
+ if (R > 0 && Math.abs(Y) < R && Math.abs(j) < R && Math.abs(ne) < R) continue;
104
+ const oe = P + Y, le = L + j, ee = H + ne;
105
+ if (oe < 0 || oe >= x || le < 0 || le >= x || ee < 0 || ee >= x) continue;
106
+ const D = m.get(oe * x * x + le * x + ee);
107
+ if (D) for (const z of D) {
108
+ const F = r[z * 3] * t, V = r[z * 3 + 1] * t, B = r[z * 3 + 2] * t, T = (S - F) ** 2 + (C - V) ** 2 + (M - B) ** 2;
109
+ T < O && (O = T, $ = z);
110
+ }
111
+ }
112
+ if (O < 1 / 0) break;
113
+ }
114
+ c[b * 3] = n[$ * 3], c[b * 3 + 1] = n[$ * 3 + 1], c[b * 3 + 2] = n[$ * 3 + 2];
115
+ }
116
+ e.setAttribute("color", new J.Float32BufferAttribute(c, 3));
117
+ }
118
+ const xn = 30, zt = [
119
+ "#4488ff",
120
+ "#ff4444",
121
+ "#44cc44",
122
+ "#ffaa00",
123
+ "#cc44ff",
124
+ "#44ffcc"
125
+ ];
126
+ function yn(e, r) {
127
+ const n = e.getVertices(), t = e.getFaces(), i = e.getComponentLabels(), a = /* @__PURE__ */ new Map();
128
+ for (let o = 0; o < i.length; o++) {
129
+ const f = i[o];
130
+ a.has(f) || a.set(f, []), a.get(f).push(o);
131
+ }
132
+ const c = [
133
+ ...a.keys()
134
+ ].sort((o, f) => o - f), u = [], s = [], l = [];
135
+ for (const o of c) {
136
+ const f = a.get(o), y = /* @__PURE__ */ new Map(), p = [], x = [];
137
+ for (const m of f) for (let b = 0; b < 3; b++) {
138
+ const S = t[m * 3 + b];
139
+ if (!y.has(S)) {
140
+ const C = p.length / 3;
141
+ p.push(n[S * 3], n[S * 3 + 1], n[S * 3 + 2]), y.set(S, C);
142
+ }
143
+ x.push(y.get(S));
144
+ }
145
+ const g = new J.BufferGeometry();
146
+ g.setAttribute("position", new J.Float32BufferAttribute(p, 3)), g.setIndex(x), g.computeVertexNormals(), u.push(g);
147
+ const v = o === r ? `#${o} inner` : o === 0 ? `#${o} outer` : `#${o} (${f.length} faces)`;
148
+ s.push(v), l.push(zt[o % zt.length]);
149
+ }
150
+ return {
151
+ geometries: u,
152
+ labels: s,
153
+ colors: l,
154
+ innerIdx: r
155
+ };
156
+ }
157
+ async function bn(e, r, n) {
158
+ let t = null;
159
+ try {
160
+ const i = gn(e);
161
+ n == null ? void 0 : n("Loading mesh..."), t = new r.WasmMeshSet(), t.loadObjString(e), n == null ? void 0 : n("Detecting units...");
162
+ const a = t.autoScaleToMm(pn);
163
+ n == null ? void 0 : n("Merging close vertices..."), t.applyMergeCloseVertices(1e-4), n == null ? void 0 : n("Analyzing mesh components...");
164
+ let c = false, u = null;
165
+ if (t.getComponentCount() >= 2) {
166
+ n == null ? void 0 : n("Building component debug info...");
167
+ const y = yn(t, null);
168
+ n == null ? void 0 : n("Extracting inner shell..."), c = t.extractInnerShell(xn), c ? (console.log("Inner shell extracted from double-shell mesh"), y.innerIdx = 1, y.labels[1] = "#1 inner (extracted)", y.labels[0] && (y.labels[0] = "#0 outer (discarded)"), u = y) : (n == null ? void 0 : n("Removing floating artifacts..."), t.splitAndKeepLargest(), u = y);
169
+ } else n == null ? void 0 : n("Removing floating artifacts..."), t.splitAndKeepLargest();
170
+ n == null ? void 0 : n("Closing holes..."), t.applyCloseHoles(30), t.applyMergeCloseVertices(1e-4), n == null ? void 0 : n("Extracting geometry...");
171
+ const l = t.getVertices(), o = t.getFaces();
172
+ if (l.length === 0) return null;
173
+ const f = new J.BufferGeometry();
174
+ if (f.setAttribute("position", new J.Float32BufferAttribute(l, 3)), f.setIndex(Array.from(o)), f.computeVertexNormals(), i) {
175
+ const y = a ? 1e3 : 1;
176
+ mn(f, i.positions, i.colors, y);
177
+ }
178
+ return {
179
+ geometry: f,
180
+ wasScaled: a,
181
+ innerShellExtracted: c,
182
+ componentDebug: u
183
+ };
184
+ } catch (i) {
185
+ return console.error("WASM processing failed:", i), null;
186
+ } finally {
187
+ if (t) try {
188
+ t.free();
189
+ } catch {
190
+ }
191
+ }
192
+ }
193
+ function wn(e) {
194
+ const n = new ln().parse(e);
195
+ let t = null;
196
+ return n.traverse((i) => {
197
+ i.isMesh && !t && (t = i.geometry);
198
+ }), t;
199
+ }
200
+ async function ft(e) {
201
+ const r = await e.arrayBuffer(), i = new an().parse(r).getAttribute("position");
202
+ if (!i || i.count === 0) throw new Error("Empty STL geometry");
203
+ const a = [];
204
+ for (let c = 0; c < i.count; c++) a.push(`v ${i.getX(c)} ${i.getY(c)} ${i.getZ(c)}`);
205
+ for (let c = 0; c < i.count; c += 3) a.push(`f ${c + 1} ${c + 2} ${c + 3}`);
206
+ return a.join(`
207
+ `);
208
+ }
209
+ function Bt(e, r) {
210
+ const n = 1 / r;
211
+ return `${Math.round(e.x * n)}_${Math.round(e.y * n)}_${Math.round(e.z * n)}`;
212
+ }
213
+ function Rt(e, r) {
214
+ if (!e.length) return [];
215
+ const n = [];
216
+ for (const t of e) (n.length === 0 || n[n.length - 1].distanceTo(t) > r) && n.push(t.clone());
217
+ return n.length > 2 && n[0].distanceTo(n[n.length - 1]) > r && n.push(n[0].clone()), n;
218
+ }
219
+ function Ne(e) {
220
+ let r = 0;
221
+ for (let n = 0; n < e.length - 1; n++) r += e[n].distanceTo(e[n + 1]);
222
+ return r;
223
+ }
224
+ function Et(e, r = 1e-3, n = false) {
225
+ if (!e.length) return [];
226
+ const t = /* @__PURE__ */ new Map(), i = (l) => {
227
+ const o = Bt(l, r);
228
+ let f = t.get(o);
229
+ return f || (f = l.clone(), t.set(o, f)), f;
230
+ }, a = e.map((l) => ({
231
+ a: i(l.a),
232
+ b: i(l.b)
233
+ })), c = [];
234
+ for (; a.length; ) {
235
+ const l = a.pop(), o = [
236
+ l.a,
237
+ l.b
238
+ ];
239
+ let f = true;
240
+ for (; f; ) {
241
+ f = false;
242
+ for (let p = a.length - 1; p >= 0; p--) {
243
+ const { a: x, b: g } = a[p];
244
+ if (x.equals(o[o.length - 1])) o.push(g);
245
+ else if (g.equals(o[o.length - 1])) o.push(x);
246
+ else if (x.equals(o[0])) o.unshift(g);
247
+ else if (g.equals(o[0])) o.unshift(x);
248
+ else continue;
249
+ a.splice(p, 1), f = true;
250
+ }
251
+ }
252
+ const y = Rt(o, r);
253
+ y.length > 1 && c.push(y);
254
+ }
255
+ if (!c.length) return [];
256
+ if (c.sort((l, o) => Ne(o) - Ne(l)), !n) return c[0] ?? [];
257
+ const u = Ne(c[0]), s = c.filter((l) => Ne(l) >= u * 0.3);
258
+ return s[s.length - 1] ?? c[0];
259
+ }
260
+ function Ct(e, r, n, t = false) {
261
+ const i = new it(new h(0, 1, 0), -n), a = [], c = new Tt();
262
+ c.setFromBufferAttribute(r.getAttribute("position"));
263
+ const u = {
264
+ linePoints: [],
265
+ lineLength: 0,
266
+ rightmostPoint: new h(0, n, 0)
267
+ };
268
+ if (!i.intersectsBox(c)) return u;
269
+ const s = new ht(), l = new h();
270
+ e.shapecast({
271
+ intersectsBounds: (g) => i.intersectsBox(g),
272
+ intersectsTriangle: (g) => {
273
+ const w = [];
274
+ s.set(g.a, g.b), i.intersectLine(s, l) && w.push(l.clone()), s.set(g.b, g.c), i.intersectLine(s, l) && w.push(l.clone()), s.set(g.c, g.a), i.intersectLine(s, l) && w.push(l.clone()), w.length === 2 && a.push({
275
+ a: w[0],
276
+ b: w[1]
277
+ });
278
+ }
279
+ });
280
+ const o = Et(a, ut, t), f = Ne(o);
281
+ if (o.length < 2) return u;
282
+ let y = -1 / 0, p = new h(0, n, 0);
283
+ for (const g of o) g.x > y && (y = g.x, p = g.clone());
284
+ const x = o.length > 2 && o[0].distanceTo(o[o.length - 1]) < ut * 10;
285
+ return {
286
+ linePoints: o,
287
+ lineLength: f,
288
+ rightmostPoint: p,
289
+ isClosed: x
290
+ };
291
+ }
292
+ function Ze(e, r, n, t = false) {
293
+ const i = Ct(e, r, n, t);
294
+ if (i.isClosed && i.linePoints.length >= 3) return i;
295
+ console.warn(`[slice] y=${n.toFixed(2)} failed (pts=${i.linePoints.length}, closed=${i.isClosed}), retrying...`);
296
+ let a = i;
297
+ for (const c of hn) {
298
+ const u = Ct(e, r, n + c, t);
299
+ if (u.isClosed && u.linePoints.length >= 3) return console.log(`[slice] y=${n.toFixed(2)} recovered with offset ${c > 0 ? "+" : ""}${c}mm (pts=${u.linePoints.length}, len=${u.lineLength.toFixed(1)}mm)`), u;
300
+ u.linePoints.length > a.linePoints.length && (a = u);
301
+ }
302
+ return console.warn(`[slice] y=${n.toFixed(2)} all retries exhausted (pts=${a.linePoints.length}, closed=${a.isClosed})`), a;
303
+ }
304
+ function pt(e, r, n, t) {
305
+ const i = new it().setFromNormalAndCoplanarPoint(t.clone().normalize(), n), a = new Tt();
306
+ if (a.setFromBufferAttribute(r.getAttribute("position")), !i.intersectsBox(a)) return 0;
307
+ const c = [], u = new ht(), s = new h();
308
+ e.shapecast({
309
+ intersectsBounds: (o) => i.intersectsBox(o),
310
+ intersectsTriangle: (o) => {
311
+ const f = [];
312
+ u.set(o.a, o.b), i.intersectLine(u, s) && f.push(s.clone()), u.set(o.b, o.c), i.intersectLine(u, s) && f.push(s.clone()), u.set(o.c, o.a), i.intersectLine(u, s) && f.push(s.clone()), f.length === 2 && c.push({
313
+ a: f[0],
314
+ b: f[1]
315
+ });
316
+ }
317
+ });
318
+ const l = Et(c, ut);
319
+ return Ne(l);
320
+ }
321
+ function ot(e) {
322
+ return new $e(e, {
323
+ maxLeafTris: Ye
324
+ });
325
+ }
326
+ function vt(e, r, n) {
327
+ const t = e instanceof $e ? e : new $e(e, {
328
+ maxLeafTris: Ye
329
+ }), i = new it().setFromNormalAndCoplanarPoint(n.clone().normalize(), r), a = [], c = new ht(), u = new h();
330
+ return t.shapecast({
331
+ intersectsBounds: (s) => i.intersectsBox(s),
332
+ intersectsTriangle: (s) => {
333
+ const l = [];
334
+ c.set(s.a, s.b), i.intersectLine(c, u) && l.push(u.clone()), c.set(s.b, s.c), i.intersectLine(c, u) && l.push(u.clone()), c.set(s.c, s.a), i.intersectLine(c, u) && l.push(u.clone()), l.length === 2 && a.push({
335
+ a: l[0],
336
+ b: l[1]
337
+ });
338
+ }
339
+ }), a;
340
+ }
341
+ function Mt(e, r, n = 1e-3) {
342
+ if (!e.length) return [];
343
+ const t = /* @__PURE__ */ new Map(), i = (l) => {
344
+ const o = Bt(l, n);
345
+ let f = t.get(o);
346
+ return f || (f = l.clone(), t.set(o, f)), f;
347
+ }, a = e.map((l) => ({
348
+ a: i(l.a),
349
+ b: i(l.b)
350
+ })), c = [];
351
+ for (; a.length; ) {
352
+ const l = a.pop(), o = [
353
+ l.a,
354
+ l.b
355
+ ];
356
+ let f = true;
357
+ for (; f; ) {
358
+ f = false;
359
+ for (let p = a.length - 1; p >= 0; p--) {
360
+ const { a: x, b: g } = a[p];
361
+ if (x.equals(o[o.length - 1])) o.push(g);
362
+ else if (g.equals(o[o.length - 1])) o.push(x);
363
+ else if (x.equals(o[0])) o.unshift(g);
364
+ else if (g.equals(o[0])) o.unshift(x);
365
+ else continue;
366
+ a.splice(p, 1), f = true;
367
+ }
368
+ }
369
+ const y = Rt(o, n);
370
+ y.length > 1 && c.push(y);
371
+ }
372
+ if (!c.length) return [];
373
+ let u = [], s = 1 / 0;
374
+ for (const l of c) {
375
+ if (l.length < 3 || !(l[0].distanceTo(l[l.length - 1]) < 2)) continue;
376
+ const f = new h();
377
+ for (const p of l) f.add(p);
378
+ f.divideScalar(l.length);
379
+ const y = f.distanceTo(r);
380
+ y < s && (s = y, u = l);
381
+ }
382
+ if (u.length === 0) for (const l of c) {
383
+ if (l.length < 3) continue;
384
+ const o = new h();
385
+ for (const y of l) o.add(y);
386
+ o.divideScalar(l.length);
387
+ const f = o.distanceTo(r);
388
+ f < s && (s = f, u = l);
389
+ }
390
+ return u;
391
+ }
392
+ function Sn(e) {
393
+ const r = new h();
394
+ for (const n of e) r.add(n);
395
+ return r.divideScalar(e.length);
396
+ }
397
+ function zn(e, r, n) {
398
+ const t = new $e(e, {
399
+ maxLeafTris: Ye
400
+ }), i = new h().subVectors(r, n).normalize(), c = r.distanceTo(n) * 0.05;
401
+ let u = i.clone();
402
+ const s = (v) => {
403
+ const m = [];
404
+ for (let $ = -10; $ <= 0; $++) {
405
+ const R = r.clone().addScaledVector(v, $ * c), Y = vt(t, R, v), j = Mt(Y, R, 1);
406
+ j.length >= 3 && j[0].distanceTo(j[j.length - 1]) < 1 && m.push(Sn(j));
407
+ }
408
+ if (m.length < 3) return null;
409
+ const b = new h();
410
+ for (const $ of m) b.add($);
411
+ b.divideScalar(m.length);
412
+ let S = 0, C = 0, M = 0, P = 0, L = 0, H = 0;
413
+ for (const $ of m) {
414
+ const R = $.x - b.x, Y = $.y - b.y, j = $.z - b.z;
415
+ S += R * R, C += R * Y, M += R * j, P += Y * Y, L += Y * j, H += j * j;
416
+ }
417
+ let O = v.clone();
418
+ for (let $ = 0; $ < 30; $++) {
419
+ const R = S * O.x + C * O.y + M * O.z, Y = C * O.x + P * O.y + L * O.z, j = M * O.x + L * O.y + H * O.z, ne = new h(R, Y, j), oe = ne.length();
420
+ if (oe < 1e-10 || (ne.divideScalar(oe), O.distanceTo(ne) < 1e-8)) break;
421
+ O = ne;
422
+ }
423
+ return O.dot(i) < 0 && O.negate(), O;
424
+ };
425
+ for (let v = 0; v < 3; v++) {
426
+ const m = s(u);
427
+ if (!m) break;
428
+ const b = u.angleTo(m);
429
+ if (u = m, b < 1e-3) break;
430
+ }
431
+ const l = new h();
432
+ Math.abs(u.x) < 0.9 ? l.set(1, 0, 0) : l.set(0, 1, 0), l.crossVectors(u, l).normalize();
433
+ const o = new h().crossVectors(u, l).normalize(), f = (v) => {
434
+ const m = vt(t, r, v), b = Mt(m, r, 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: Ne(b),
442
+ closed: S
443
+ };
444
+ };
445
+ let y = u.clone(), p = 1 / 0;
446
+ for (let v = -3; v <= 3; v += 1) for (let m = -3; m <= 3; m += 1) {
447
+ const b = v * Math.PI / 180, S = m * Math.PI / 180, C = u.clone().applyQuaternion(new Oe().setFromAxisAngle(l, b)).applyQuaternion(new Oe().setFromAxisAngle(o, S)).normalize(), M = f(C);
448
+ M.closed && M.circumference < p && (p = M.circumference, y = C);
449
+ }
450
+ const x = y.clone(), g = new h();
451
+ Math.abs(x.x) < 0.9 ? g.set(1, 0, 0) : g.set(0, 1, 0), g.crossVectors(x, g).normalize();
452
+ const w = new h().crossVectors(x, g).normalize();
453
+ for (let v = -5; v <= 5; v += 1) for (let m = -5; m <= 5; m += 1) {
454
+ const b = v * 0.1 * Math.PI / 180, S = m * 0.1 * Math.PI / 180, C = x.clone().applyQuaternion(new Oe().setFromAxisAngle(g, b)).applyQuaternion(new Oe().setFromAxisAngle(w, S)).normalize(), M = f(C);
455
+ M.closed && M.circumference < p && (p = M.circumference, y = C);
456
+ }
457
+ return p === 1 / 0 && (p = f(u).circumference, y = u), {
458
+ normal: y,
459
+ circumference: p
460
+ };
461
+ }
462
+ function Cn(e, r, n) {
463
+ const t = e.getAttribute("position"), i = e.getIndex();
464
+ if (!i) return {
465
+ isDoubleShell: false,
466
+ sampledFaces: 0,
467
+ opposingPairs: 0,
468
+ confidence: 0
469
+ };
470
+ const a = i.array, c = t.array, u = new h().subVectors(n, r).normalize(), s = n.distanceTo(r), l = Math.min(s * 0.06, 15), o = 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, x = new h();
476
+ let g = 0, w = 0, v = 0;
477
+ for (const S of [
478
+ 0.65,
479
+ 0.78,
480
+ 0.9
481
+ ]) {
482
+ const C = new h().lerpVectors(r, n, S);
483
+ let M = 0, P = 0, L = 0, H = 0;
484
+ for (let Y = 0; Y < a.length; Y += 3) {
485
+ const j = a[Y], ne = a[Y + 1], oe = a[Y + 2], le = (c[j * 3] + c[ne * 3] + c[oe * 3]) / 3, ee = (c[j * 3 + 1] + c[ne * 3 + 1] + c[oe * 3 + 1]) / 3, D = (c[j * 3 + 2] + c[ne * 3 + 2] + c[oe * 3 + 2]) / 3, z = le - C.x, F = ee - C.y, V = D - C.z;
486
+ Math.abs(z * u.x + F * u.y + V * u.z) > l || (M += le, P += ee, L += D, H++);
487
+ }
488
+ if (H < 8) continue;
489
+ const O = new h(M / H, P / H, L / H);
490
+ let $ = 0;
491
+ for (let Y = 0; Y < p; Y++) {
492
+ const j = Y / p * Math.PI * 2, ne = new h().addScaledVector(f, Math.cos(j)).addScaledVector(y, Math.sin(j)), oe = new J.Ray(O, ne);
493
+ let le = 0;
494
+ o.shapecast({
495
+ intersectsBounds: (ee) => oe.intersectsBox(ee),
496
+ intersectsTriangle: (ee) => (oe.intersectTriangle(ee.a, ee.b, ee.c, false, x) && le++, false)
497
+ }), $ += le, w++;
498
+ }
499
+ g += $, $ / p > 1.5 && v++;
500
+ }
501
+ if (w === 0) return {
502
+ isDoubleShell: false,
503
+ sampledFaces: 0,
504
+ opposingPairs: 0,
505
+ confidence: 0
506
+ };
507
+ const m = g / w;
508
+ return {
509
+ isDoubleShell: v >= 2,
510
+ sampledFaces: w,
511
+ opposingPairs: g,
512
+ confidence: m
513
+ };
514
+ }
515
+ function vn(e, r, n, t) {
516
+ const i = new h().subVectors(n, r), a = new h().subVectors(t, r), c = new h().subVectors(e, r), u = i.dot(i), s = i.dot(a), l = i.dot(c), o = a.dot(a), f = a.dot(c), y = 1 / (u * o - s * s), p = (o * l - s * f) * y, x = (u * f - s * l) * y;
517
+ return {
518
+ u: 1 - p - x,
519
+ v: p,
520
+ w: x
521
+ };
522
+ }
523
+ function st(e, r, n, t, i = false) {
524
+ const a = n.clone().normalize(), c = e.getAttribute("position"), u = e.getIndex();
525
+ if (!u) throw new Error("No index buffer");
526
+ const s = new h().subVectors(t, r).dot(a), l = Math.abs(s) < 1e-6 ? 1 : Math.sign(s), o = c.array, f = u.array, y = e.getAttribute("color"), p = y ? y.array : null, x = [], g = [], w = [], v = (D, z, F) => {
527
+ const V = x.length / 3;
528
+ return x.push(D, z, F), V;
529
+ }, m = (D) => new h(o[D * 3], o[D * 3 + 1], o[D * 3 + 2]), b = (D, z) => {
530
+ const F = new h().subVectors(D, r).dot(a), V = new h().subVectors(z, r).dot(a), B = F / (F - V);
531
+ return new h().lerpVectors(D, z, B);
532
+ }, S = /* @__PURE__ */ new Map(), C = /* @__PURE__ */ new Map(), M = /* @__PURE__ */ new Map(), P = (D) => {
533
+ let z = M.get(D);
534
+ return z === void 0 && (z = new h().subVectors(m(D), r).dot(a), M.set(D, z)), z;
535
+ }, L = (D) => {
536
+ if (S.has(D)) return S.get(D);
537
+ const z = m(D), F = v(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 (C.has(F)) return C.get(F);
542
+ const V = b(m(D), m(z)), B = v(V.x, V.y, V.z);
543
+ if (p) {
544
+ const T = P(D), E = P(z), N = T / (T - E);
545
+ g.push(p[D * 3] + N * (p[z * 3] - p[D * 3]), p[D * 3 + 1] + N * (p[z * 3 + 1] - p[D * 3 + 1]), p[D * 3 + 2] + N * (p[z * 3 + 2] - p[D * 3 + 2]));
546
+ }
547
+ return C.set(F, B), B;
548
+ }, O = (D) => {
549
+ const z = P(D);
550
+ return Math.sign(z) === l || 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), N = (B ? 1 : 0) + (T ? 1 : 0) + (E ? 1 : 0);
554
+ if (N !== 0) if (N === 3) w.push(L(z), L(F), L(V));
555
+ else if (N === 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(L(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 = L(q), A = L(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 (i) 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 N = w[T * 3 + E];
574
+ D.has(N) || D.set(N, []), D.get(N).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 = [], N = [
580
+ T
581
+ ];
582
+ for (z.add(T); N.length > 0; ) {
583
+ const X = N.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), N.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 N of T) {
596
+ for (let X = 0; X < 3; X++) {
597
+ const q = w[N * 3 + X], ie = x[q * 3] - t.x, se = x[q * 3 + 1] - t.y, A = x[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(), j = [], 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) || (j.push(x[F * 3], x[F * 3 + 1], x[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(j, 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, r, n) {
616
+ const t = e.getAttribute("position"), i = n - r;
617
+ if (i < 1) return null;
618
+ const a = 30, c = i / a, u = [];
619
+ for (let w = 0; w < a; w++) {
620
+ const v = r + w * c, m = r + (w + 1) * c;
621
+ let b = 0, S = 0, C = 0, M = 0;
622
+ for (let P = 0; P < t.count; P++) {
623
+ const L = t.getY(P);
624
+ L >= v && L < m && (b += t.getX(P), S += L, C += t.getZ(P), M++);
625
+ }
626
+ M > 20 && u.push(new h(b / M, S / M, C / M));
627
+ }
628
+ if (u.length < 5) return null;
629
+ const s = new h();
630
+ for (const w of u) s.add(w);
631
+ s.divideScalar(u.length);
632
+ let l = 0, o = 0, f = 0, y = 0, p = 0, x = 0;
633
+ for (const w of u) {
634
+ const v = w.x - s.x, m = w.y - s.y, b = w.z - s.z;
635
+ l += v * v, o += v * m, f += v * b, y += m * m, p += m * b, x += b * b;
636
+ }
637
+ let g = new h(0.01, 1, 0.01).normalize();
638
+ for (let w = 0; w < 30; w++) {
639
+ const v = l * g.x + o * g.y + f * g.z, m = o * g.x + y * g.y + p * g.z, b = f * g.x + p * g.y + x * g.z, S = new h(v, m, b), C = S.length();
640
+ if (C < 1e-10 || (S.divideScalar(C), g.distanceTo(S) < 1e-8)) break;
641
+ g = S;
642
+ }
643
+ return g.y < 0 && g.negate(), g;
644
+ }
645
+ function Wt(e, r, n, t) {
646
+ const i = e.getIndex(), a = i ? i.count / 3 : 0;
647
+ if (a < 10) return {
648
+ valid: false,
649
+ reason: `Geometry is empty or degenerate (${a} faces)`
650
+ };
651
+ const c = r - n;
652
+ if (c < 4) return {
653
+ valid: false,
654
+ reason: `Height too small (${c.toFixed(1)}mm < 4mm)`
655
+ };
656
+ if (c > 1e3) return {
657
+ valid: false,
658
+ reason: `Height too large (${c.toFixed(1)}mm > 1000mm)`
659
+ };
660
+ const u = new $e(e, {
661
+ maxLeafTris: Ye
662
+ }), s = Ze(u, e, r);
663
+ if (s.lineLength === 0) return {
664
+ valid: false,
665
+ reason: "No circumference at green point \u2014 mesh may be empty at that height"
666
+ };
667
+ const l = r - t;
668
+ if (l <= n) return {
669
+ valid: true,
670
+ reason: ""
671
+ };
672
+ const o = Ze(u, e, l);
673
+ if (s.lineLength > 0 && o.lineLength > 0) {
674
+ const y = s.lineLength / o.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 = r - t * 2;
681
+ if (f > n) {
682
+ const y = Ze(u, e, f);
683
+ if (o.lineLength > 0 && y.lineLength > 0) {
684
+ const p = o.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, r, n, t) {
719
+ const i = new Oe().setFromAxisAngle(n, t);
720
+ return e.applyMatrix4(new kt().makeRotationFromQuaternion(i)), r.map((a) => a.clone().applyQuaternion(i));
721
+ }
722
+ function _t(e, r, n) {
723
+ const t = new Oe().setFromAxisAngle(r, n);
724
+ e.applyMatrix4(new kt().makeRotationFromQuaternion(t));
725
+ }
726
+ function An(e, r, n, t, i, a) {
727
+ const c = n.getAttribute("position"), u = n.getIndex();
728
+ if (!u) return r;
729
+ const l = r[1].y + t * We, o = c.array, f = u.array, y = n.getAttribute("color"), p = y ? y.array : null, x = [], g = [], w = [], v = (A, I, k) => {
730
+ const G = x.length / 3;
731
+ return x.push(A, I, k), G;
732
+ }, m = (A) => [
733
+ o[A * 3],
734
+ o[A * 3 + 1],
735
+ o[A * 3 + 2]
736
+ ], b = (A, I) => {
737
+ const k = (l - A[1]) / (I[1] - A[1]);
738
+ return [
739
+ A[0] + k * (I[0] - A[0]),
740
+ l,
741
+ A[2] + k * (I[2] - A[2])
742
+ ];
743
+ }, S = /* @__PURE__ */ new Map(), C = /* @__PURE__ */ new Map(), M = (A) => {
744
+ if (S.has(A)) return S.get(A);
745
+ const [I, k, G] = m(A), U = v(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
+ }, P = (A, I) => {
748
+ const k = A < I ? `${A}_${I}` : `${I}_${A}`;
749
+ if (C.has(k)) return C.get(k);
750
+ const G = m(A), U = m(I), [re, Le, me] = b(G, U), ae = v(re, Le, me);
751
+ if (p) {
752
+ const xe = (l - G[1]) / (U[1] - G[1]);
753
+ g.push(p[A * 3] + xe * (p[I * 3] - p[A * 3]), p[A * 3 + 1] + xe * (p[I * 3 + 1] - p[A * 3 + 1]), p[A * 3 + 2] + xe * (p[I * 3 + 2] - p[A * 3 + 2]));
754
+ }
755
+ return C.set(k, ae), ae;
756
+ };
757
+ for (let A = 0; A < f.length; A += 3) {
758
+ const I = f[A], k = f[A + 1], G = f[A + 2], U = m(I), re = m(k), Le = m(G), me = U[1] < l, ae = re[1] < l, xe = Le[1] < l, 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), P(pe, we), P(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), je = P(we, pe), Pe = P(he, pe);
767
+ w.push(Ge, je, fe), w.push(fe, je, Pe);
768
+ }
769
+ }
770
+ const L = w.length / 3, H = /* @__PURE__ */ new Map();
771
+ for (let A = 0; A < L; 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 < L; 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 < L; 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 = r[0];
792
+ let j = 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 = x[U * 3] - Y.x, Le = x[U * 3 + 1] - Y.y, me = x[U * 3 + 2] - Y.z, ae = re * re + Le * Le + me * me;
798
+ ae < I && (I = ae);
799
+ }
800
+ if (I < ne) break;
801
+ }
802
+ I < ne && (ne = I, j = A);
803
+ }
804
+ const oe = /* @__PURE__ */ new Map(), le = [], ee = [], D = [];
805
+ let z = 0;
806
+ for (const A of j) for (let I = 0; I < 3; I++) {
807
+ const k = w[A * 3 + I];
808
+ oe.has(k) || (le.push(x[k * 3], x[k * 3 + 1], x[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, i.onStatus("Refining alignment...");
812
+ const V = new h(0, 1, 0);
813
+ let B = [
814
+ ...r
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, Le = U / re, me = [];
823
+ for (let ye = 0; ye < re; ye++) {
824
+ const Te = k + ye * Le, Me = k + (ye + 1) * Le;
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 je = fe.dot(V);
849
+ if (Math.acos(Math.min(1, Math.abs(je))) * 180 / Math.PI < 0.1) break;
850
+ const Pe = new h().crossVectors(fe, V);
851
+ Pe.length() > 1e-4 && (Pe.normalize(), T(Pe, Math.acos(Math.min(1, Math.max(-1, je)))));
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(), i.updateLandmarkPositions(B.map((A) => ({
858
+ x: A.x,
859
+ y: A.y,
860
+ z: A.z
861
+ })));
862
+ const ie = q.boundingBox, se = new h();
863
+ return ie.getSize(se), i.setModelSize(Math.max(se.x, se.y, se.z)), i.setCut(true), i.setAdjustedStartY(null), i.setAdjustedEndY(null), i.setOriginalEndY(B[1].y + 2 * We), B;
864
+ }
865
+ function Fn(e, r, n, t) {
866
+ const i = r.map((x) => new h(x.position.x, x.position.y, x.position.z)), a = i[0], c = i[1];
867
+ t.onStatus("Cutting double shell above green point...");
868
+ const u = c.y + 2 * We, s = new h(c.x, u, c.z), l = e.geometry, o = st(l, s, new h(0, 1, 0), a, true);
869
+ l.dispose(), e.geometry = o, o.computeVertexNormals(), o.computeBoundingBox(), t.onStatus("Setting blue point..."), t.addLandmarkPoint({
870
+ faceIndex: -1,
871
+ vertexIndices: [
872
+ 0,
873
+ 1,
874
+ 2
875
+ ],
876
+ position: {
877
+ x: a.x,
878
+ y: a.y,
879
+ z: a.z
880
+ },
881
+ barycentricCoords: {
882
+ u: 0.33,
883
+ v: 0.33,
884
+ w: 0.34
885
+ }
886
+ }), i.push(a.clone()), t.updateLandmarkPositions(i.map((x) => ({
887
+ x: x.x,
888
+ y: x.y,
889
+ z: x.z
890
+ }))), t.setAligned(true), t.setCut(true), t.setAdjustedStartY(null), t.setAdjustedEndY(null), t.setOriginalEndY(c.y);
891
+ const f = o.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(o, c.y, a.y, n);
894
+ p.valid || console.warn(`Double shell validation warning: ${p.reason}`);
895
+ }
896
+ function In(e, r, n, t) {
897
+ var _a, _b;
898
+ const i = e.geometry.clone(), a = r.map((s) => ({
899
+ ...s
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 s = new h(r[0].position.x, r[0].position.y, r[0].position.z), l = new h(r[1].position.x, r[1].position.y, r[1].position.z);
904
+ t.onStatus("Detecting shell type...");
905
+ const o = Cn(e.geometry, s, l);
906
+ if (console.log(`Shell detection: ${o.isDoubleShell ? "DOUBLE" : "SINGLE"} shell (${o.opposingPairs} inward/${o.sampledFaces} total faces, confidence ${(o.confidence * 100).toFixed(0)}%)`), o.isDoubleShell) {
907
+ (_a = t.setDoubleShell) == null ? void 0 : _a.call(t, true), Fn(e, a, n, t), t.setClippedReferenceGeometry ? (i.computeVertexNormals(), t.setClippedReferenceGeometry(i)) : i.dispose();
908
+ return;
909
+ }
910
+ (_b = t.setDoubleShell) == null ? void 0 : _b.call(t, false);
911
+ }
912
+ let u = "";
913
+ for (let s = 0; s < nt; s++) try {
914
+ s > 0 && (t.onStatus(`Retry ${s}/${nt - 1} \u2014 ${u}`), e.geometry.dispose(), e.geometry = i.clone(), t.removeLandmarkPoint(2), t.setAligned(false), t.setCut(false));
915
+ let l = e.geometry, o = a.map((z) => new h(z.position.x, z.position.y, z.position.z));
916
+ const f = t.setClippedReferenceGeometry ? i.clone() : null;
917
+ let y = 5;
918
+ if (s > 0) {
919
+ const z = Mn[s - 1];
920
+ y = z.cutOffset;
921
+ const F = new h().subVectors(o[1], o[0]).normalize();
922
+ if (z.nudge < 0) o[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), o[1].addScaledVector(E, z.nudge);
926
+ }
927
+ const V = l.getAttribute("position");
928
+ let B = 1 / 0, T = 0;
929
+ for (let E = 0; E < V.count; E++) {
930
+ const N = V.getX(E) - o[1].x, X = V.getY(E) - o[1].y, q = V.getZ(E) - o[1].z, ie = N * N + X * X + q * q;
931
+ ie < B && (B = ie, T = E);
932
+ }
933
+ o[1].set(V.getX(T), V.getY(T), V.getZ(T)), console.log(`Retry ${s}: nudge=${z.nudge}mm angle=${(z.angle * 180 / Math.PI).toFixed(0)}\xB0 cutOffset=${z.cutOffset}" \u2192 green=(${o[1].x.toFixed(1)}, ${o[1].y.toFixed(1)}, ${o[1].z.toFixed(1)})`);
934
+ }
935
+ const p = (z, F) => {
936
+ o = Vt(l, o, z, F), f && _t(f, z, F);
937
+ }, x = o[0], g = o[1], { normal: w } = zn(l, g, x);
938
+ t.onStatus(s > 0 ? `Retry ${s}: Slicing mesh...` : "Slicing mesh at cut plane...");
939
+ const v = new h().subVectors(g, x).normalize(), m = Math.sign(v.dot(w)), b = g.clone().addScaledVector(w, m * y * We), S = st(l, b, w, x);
940
+ l.dispose(), l = S, e.geometry = l, t.onStatus(s > 0 ? `Retry ${s}: Rough alignment...` : "Rough alignment...");
941
+ const C = new h().subVectors(o[1], o[0]).normalize();
942
+ let M = C.dot(c), P = new h().crossVectors(C, c);
943
+ P.length() > 1e-4 && (P.normalize(), p(P, Math.acos(Math.min(1, Math.max(-1, M))))), o[0].y > o[1].y && p(new h(1, 0, 0), Math.PI), l.computeVertexNormals(), t.onStatus(s > 0 ? `Retry ${s}: Translating...` : "Translating to origin...");
944
+ const L = o[0].clone();
945
+ l.translate(-L.x, -L.y, -L.z), f && f.translate(-L.x, -L.y, -L.z), o = o.map((z) => new h(z.x - L.x, z.y - L.y, z.z - L.z)), t.onStatus(s > 0 ? `Retry ${s}: Isolating limb...` : "Isolating limb region...");
946
+ {
947
+ const z = ot(l), F = o[0].y, V = o[1].y, B = new h(0, 1, 0), T = 5;
948
+ l.computeBoundingBox();
949
+ const E = l.boundingBox.max.y, N = [];
950
+ for (let X = F + T; X < E; X += T) {
951
+ const q = pt(z, l, new h(0, X, 0), B);
952
+ q > 0 && N.push({
953
+ y: X,
954
+ circ: q
955
+ });
956
+ }
957
+ if (N.length > 5) {
958
+ const X = V - F, q = F + X * 0.3, ie = F + X * 0.7, se = N.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 N) 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 = N.find((re) => Math.abs(re.y - V) < T);
968
+ if (U && U.circ > I * k) {
969
+ for (let re = N.length - 1; re >= 0; re--) if (!(N[re].y > V + T) && N[re].circ <= I * k) {
970
+ G = N[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(l, new h(0, G, 0), B, o[0]);
978
+ l.dispose(), l = U, e.geometry = l, l.computeVertexNormals(), l.computeBoundingBox();
979
+ } else console.log(`Limb isolation: no anomaly detected (baseline=${I.toFixed(1)}mm)`);
980
+ }
981
+ }
982
+ }
983
+ t.onStatus(s > 0 ? `Retry ${s}: PCA alignment...` : "Iterative PCA alignment...");
984
+ const H = 10, O = 80, $ = o[0].y, R = o[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(l, F, V);
988
+ if (B && (M = B.dot(c), Math.acos(Math.min(1, Math.abs(M))) * 180 / Math.PI > 0.1 && (P = new h().crossVectors(B, c), P.length() > 1e-4))) {
989
+ P.normalize(), p(P, Math.acos(Math.min(1, Math.max(-1, M))));
990
+ const E = o[0].clone();
991
+ l.translate(-E.x, -E.y, -E.z), f && f.translate(-E.x, -E.y, -E.z), o = o.map((N) => new h(N.x - E.x, N.y - E.y, N.z - E.z));
992
+ }
993
+ if (Y -= H, Y <= $) break;
994
+ }
995
+ l.computeVertexNormals(), t.onStatus(s > 0 ? `Retry ${s}: Setting blue point...` : "Setting blue point...");
996
+ const j = new h(o[0].x, o[0].y, o[0].z);
997
+ o.push(j), t.addLandmarkPoint({
998
+ faceIndex: -1,
999
+ vertexIndices: [
1000
+ 0,
1001
+ 1,
1002
+ 2
1003
+ ],
1004
+ position: {
1005
+ x: j.x,
1006
+ y: j.y,
1007
+ z: j.z
1008
+ },
1009
+ barycentricCoords: {
1010
+ u: 0.33,
1011
+ v: 0.33,
1012
+ w: 0.34
1013
+ }
1014
+ }), t.onStatus(s > 0 ? `Retry ${s}: Final PCA...` : "Final PCA refinement...");
1015
+ for (let z = 0; z < 3; z++) {
1016
+ const F = rt(l, 0, o[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 (P = new h().crossVectors(F, c), P.length() > 1e-4) {
1020
+ P.normalize(), p(P, Math.acos(Math.min(1, Math.max(-1, M))));
1021
+ const B = o[0].clone();
1022
+ l.translate(-B.x, -B.y, -B.z), f && f.translate(-B.x, -B.y, -B.z), o = o.map((T) => new h(T.x - B.x, T.y - B.y, T.z - B.z));
1023
+ }
1024
+ }
1025
+ }
1026
+ if (o[1].y < o[0].y) {
1027
+ p(new h(1, 0, 0), Math.PI);
1028
+ const z = o[0].clone();
1029
+ l.translate(-z.x, -z.y, -z.z), f && f.translate(-z.x, -z.y, -z.z), o = o.map((F) => new h(F.x - z.x, F.y - z.y, F.z - z.z));
1030
+ }
1031
+ l.computeVertexNormals(), l.computeBoundingBox(), t.onStatus(s > 0 ? `Retry ${s}: Circumference refinement...` : "Circumference refinement...");
1032
+ {
1033
+ const z = ot(l), F = o[1].y, V = o[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, l, new h(0, re, 0), G);
1044
+ return U;
1045
+ };
1046
+ let N = 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, N = I * T, X = k * T);
1050
+ }
1051
+ const ie = N, 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, N = G, X = U);
1055
+ }
1056
+ const A = Math.sqrt(N * N + X * X);
1057
+ if (A > 0.05 * T) {
1058
+ console.log(`Circumference refinement: rotating ${(-N / T).toFixed(2)}\xB0X ${(-X / T).toFixed(2)}\xB0Z`), Math.abs(N) > 0.01 * T && p(new h(1, 0, 0), -N), Math.abs(X) > 0.01 * T && p(new h(0, 0, 1), -X);
1059
+ const I = o[0].clone();
1060
+ l.translate(-I.x, -I.y, -I.z), f && f.translate(-I.x, -I.y, -I.z), o = o.map((k) => new h(k.x - I.x, k.y - I.y, k.z - I.z)), l.computeVertexNormals();
1061
+ } else console.log(`Circumference refinement: already optimal (${(A / T).toFixed(3)}\xB0)`);
1062
+ }
1063
+ }
1064
+ const ne = o.map((z) => ({
1065
+ x: z.x,
1066
+ y: z.y,
1067
+ z: z.z
1068
+ }));
1069
+ t.updateLandmarkPositions(ne), t.setAligned(true), t.onStatus(s > 0 ? `Retry ${s}: Cutting mesh...` : 'Cutting mesh 2" above green...'), o = An(e, o, l, 5, t, f), t.onStatus("Validating results...");
1070
+ const oe = e.geometry, le = o[1].y, ee = o[0].y, D = Wt(oe, le, ee, n);
1071
+ if (D.valid) {
1072
+ console.log(`Processing succeeded on attempt ${s + 1}`), f && t.setClippedReferenceGeometry && (f.computeVertexNormals(), t.setClippedReferenceGeometry(f));
1073
+ break;
1074
+ }
1075
+ console.warn(`Attempt ${s + 1} failed validation: ${D.reason}`), u = D.reason, f && f.dispose(), s === nt - 1 && (t.setError(`Processing produced unusual results after ${nt} attempts: ${D.reason}`), e.geometry.dispose(), e.geometry = i.clone(), t.removeLandmarkPoint(2), t.setAligned(false), t.setCut(false));
1076
+ } catch (l) {
1077
+ console.error("Processing failed:", l), t.setError(l instanceof Error ? l.message : "Failed to process mesh.");
1078
+ break;
1079
+ }
1080
+ i.dispose();
1081
+ }
1082
+ const Ln = ({ message: e, onDismiss: r }) => 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: r,
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
+ }), Pn = ({ mesh: e, maxPoints: r = 2, meshColor: n = "#c8c8c8", meshOpacity: t = 1 }) => {
1173
+ const { addLandmarkPoint: i, landmarkPoints: a } = gt(), c = Fe((l) => {
1174
+ if (a.length >= r) return;
1175
+ l.stopPropagation();
1176
+ const o = l.intersections[0], f = o == null ? void 0 : o.faceIndex;
1177
+ if (!o || f == null) return;
1178
+ const y = e.geometry, p = y.index;
1179
+ let x;
1180
+ p ? x = [
1181
+ p.getX(f * 3),
1182
+ p.getX(f * 3 + 1),
1183
+ p.getX(f * 3 + 2)
1184
+ ] : x = [
1185
+ f * 3,
1186
+ f * 3 + 1,
1187
+ f * 3 + 2
1188
+ ];
1189
+ const g = y.getAttribute("position"), w = new h().fromBufferAttribute(g, x[0]), v = new h().fromBufferAttribute(g, x[1]), m = new h().fromBufferAttribute(g, x[2]);
1190
+ w.applyMatrix4(e.matrixWorld), v.applyMatrix4(e.matrixWorld), m.applyMatrix4(e.matrixWorld);
1191
+ const b = o.point, S = vn(b, w, v, m), C = {
1192
+ faceIndex: f,
1193
+ vertexIndices: x,
1194
+ position: {
1195
+ x: b.x,
1196
+ y: b.y,
1197
+ z: b.z
1198
+ },
1199
+ barycentricCoords: S
1200
+ };
1201
+ i(C);
1202
+ }, [
1203
+ e,
1204
+ i,
1205
+ a.length,
1206
+ r
1207
+ ]), u = de(() => !!e.geometry.getAttribute("color"), [
1208
+ e
1209
+ ]), s = de(() => new J.MeshStandardMaterial({
1210
+ color: u ? "#ffffff" : n,
1211
+ side: J.DoubleSide,
1212
+ roughness: 0.6,
1213
+ metalness: 0.1,
1214
+ transparent: t < 1,
1215
+ opacity: t,
1216
+ vertexColors: u
1217
+ }), [
1218
+ n,
1219
+ t,
1220
+ u
1221
+ ]);
1222
+ return d("primitive", {
1223
+ object: e,
1224
+ onClick: c,
1225
+ material: s
1226
+ });
1227
+ }, Dn = ({ point: e, index: r, markerSize: n, color: t, label: i }) => {
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
+ n,
1241
+ 16,
1242
+ 16
1243
+ ]
1244
+ }),
1245
+ d("meshBasicMaterial", {
1246
+ color: t
1247
+ }),
1248
+ a && d(Ke, {
1249
+ center: true,
1250
+ style: {
1251
+ pointerEvents: "none"
1252
+ },
1253
+ children: d("div", {
1254
+ style: {
1255
+ padding: "3px 8px",
1256
+ backgroundColor: "rgba(0, 0, 0, 0.75)",
1257
+ borderRadius: 4,
1258
+ color: "#fff",
1259
+ fontSize: 12,
1260
+ fontFamily: "system-ui, sans-serif",
1261
+ whiteSpace: "nowrap",
1262
+ transform: "translateY(-24px)"
1263
+ },
1264
+ children: i
1265
+ })
1266
+ })
1267
+ ]
1268
+ }, r);
1269
+ }, Tn = ({ modelSize: e, labels: r }) => {
1270
+ const { landmarkPoints: n } = gt(), t = e * 0.02, i = [
1271
+ "#ff4444",
1272
+ "#44ff44",
1273
+ "#4444ff"
1274
+ ], c = r ?? [
1275
+ "Origin",
1276
+ "MPT",
1277
+ "Cut Plane"
1278
+ ];
1279
+ return d(He, {
1280
+ children: n.map((u, s) => d(Dn, {
1281
+ point: u,
1282
+ index: s,
1283
+ markerSize: t,
1284
+ color: i[s],
1285
+ label: c[s]
1286
+ }, s))
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, r) => {
1297
+ const n = Math.abs(e - r);
1298
+ return n < 1 ? "#8BC34A" : n < 5 ? "#FFC107" : "#FF5722";
1299
+ }, It = new J.Color("#8BC34A"), Lt = new J.Color("#FFC107"), Bn = new J.Color("#FF5722"), Rn = (e) => {
1300
+ if (e < 1) return It.clone();
1301
+ if (e < 5) {
1302
+ const n = (e - 1) / 4;
1303
+ return It.clone().lerp(Lt, n);
1304
+ }
1305
+ const r = Math.min((e - 5) / 5, 1);
1306
+ return Lt.clone().lerp(Bn, r);
1307
+ }, En = (e, r) => {
1308
+ const n = e.length, t = new Float32Array(n * 2 * 3), i = new Float32Array(n * 2 * 3), a = [];
1309
+ for (let s = 0; s < n; s++) {
1310
+ const l = e[s], o = r[s], f = l.distanceTo(o), y = Rn(f);
1311
+ if (t[s * 6] = l.x, t[s * 6 + 1] = l.y, t[s * 6 + 2] = l.z, i[s * 6] = y.r, i[s * 6 + 1] = y.g, i[s * 6 + 2] = y.b, t[s * 6 + 3] = o.x, t[s * 6 + 4] = o.y, t[s * 6 + 5] = o.z, i[s * 6 + 3] = y.r, i[s * 6 + 4] = y.g, i[s * 6 + 5] = y.b, s < n - 1) {
1312
+ const p = s * 2, x = p + 1, g = (s + 1) * 2, w = g + 1;
1313
+ a.push(p, x, g, x, 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(i, 3)), c.setIndex(a);
1318
+ const u = new J.MeshBasicMaterial({
1319
+ vertexColors: true,
1320
+ transparent: true,
1321
+ opacity: 0.25,
1322
+ side: J.DoubleSide,
1323
+ depthTest: false,
1324
+ depthWrite: false
1325
+ });
1326
+ return new J.Mesh(c, u);
1327
+ }, Wn = ({ bvh: e, geometry: r, yPosition: n, color: t = "#00ff00", labelX: i, onDataChange: a, displayUnit: c = "mm", useInnerSurface: u = false, formValue: s, lineWidth: l = 1.5 }) => {
1328
+ const o = de(() => Ze(e, r, n, u), [
1329
+ e,
1330
+ r,
1331
+ n,
1332
+ u
1333
+ ]), { linePoints: f, lineLength: y } = o, p = de(() => {
1334
+ if (s == null || y <= 0 || f.length < 2) return null;
1335
+ const v = s / y, m = f.reduce((S, C) => S + C.x, 0) / f.length, b = f.reduce((S, C) => S + C.z, 0) / f.length;
1336
+ return f.map((S) => new h(m + (S.x - m) * v, S.y, b + (S.z - b) * v));
1337
+ }, [
1338
+ f,
1339
+ y,
1340
+ s
1341
+ ]), x = de(() => !p || f.length < 2 ? null : En(f, p), [
1342
+ f,
1343
+ p
1344
+ ]);
1345
+ Se(() => () => {
1346
+ x && (x.geometry.dispose(), x.material.dispose());
1347
+ }, [
1348
+ x
1349
+ ]);
1350
+ const g = Ie(null), w = de(() => {
1351
+ const v = new J.BufferGeometry();
1352
+ v.setAttribute("position", new J.Float32BufferAttribute(new Float32Array(6), 3));
1353
+ const m = new J.LineBasicMaterial({
1354
+ color: 6710886,
1355
+ depthTest: false,
1356
+ depthWrite: false,
1357
+ transparent: true
1358
+ });
1359
+ return new J.Line(v, m);
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: n,
1368
+ originalValue: y,
1369
+ modifiedValue: null
1370
+ }));
1371
+ }, [
1372
+ y,
1373
+ n,
1374
+ a
1375
+ ]), Pt(({ camera: v }) => {
1376
+ if (!g.current || f.length < 2) return;
1377
+ const m = new h();
1378
+ v.getWorldDirection(m);
1379
+ const b = new h(m.x, 0, m.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 C = -1 / 0, M = f[0];
1384
+ for (const O of f) {
1385
+ const $ = S.x * O.x + S.z * O.z;
1386
+ $ > C && (C = $, M = O);
1387
+ }
1388
+ const P = i * 0.35, L = new h(M.x + S.x * P, n, M.z + S.z * P);
1389
+ g.current.position.copy(L);
1390
+ const H = w.geometry.getAttribute("position");
1391
+ H.setXYZ(0, M.x, M.y, M.z), H.setXYZ(1, L.x, L.y, L.z), H.needsUpdate = true;
1392
+ }), f.length < 2 ? null : W("group", {
1393
+ children: [
1394
+ d(ge, {
1395
+ points: f,
1396
+ color: t,
1397
+ lineWidth: l,
1398
+ depthTest: false,
1399
+ depthWrite: false,
1400
+ transparent: true
1401
+ }),
1402
+ x && d("primitive", {
1403
+ object: x
1404
+ }),
1405
+ p && s != null && d(ge, {
1406
+ points: p,
1407
+ color: Ft(y, s),
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: s != 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
+ s != null && y > 0 && (() => {
1472
+ const v = y - s, m = v > 0.5 ? "\u25B2" : v < -0.5 ? "\u25BC" : "", b = Ft(y, s);
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
+ m && d("span", {
1485
+ style: {
1486
+ fontSize: 10,
1487
+ color: b,
1488
+ lineHeight: 1
1489
+ },
1490
+ children: m
1491
+ }),
1492
+ W("span", {
1493
+ style: {
1494
+ fontSize: 13,
1495
+ color: b,
1496
+ fontFamily: "monospace",
1497
+ fontWeight: 600
1498
+ },
1499
+ children: [
1500
+ v > 0 ? "+" : "",
1501
+ c === "inch" ? (v / 25.4).toFixed(2) : v.toFixed(1)
1502
+ ]
1503
+ }),
1504
+ 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" ? (s / 25.4).toFixed(2) : s.toFixed(0)
1513
+ ]
1514
+ })
1515
+ ]
1516
+ });
1517
+ })()
1518
+ ]
1519
+ })
1520
+ })
1521
+ })
1522
+ ]
1523
+ });
1524
+ }, Vn = nn(Wn), _n = ({ mesh: e, startY: r, endY: n, spacing: t, modelSize: i, onMeasurementsChange: a, reverseOrder: c = false, displayUnit: u = "mm", useInnerSurface: s = false, formMeasurements: l, originY: o }) => {
1525
+ const f = Ie(/* @__PURE__ */ new Map()), y = e.geometry, p = kn(y), x = de(() => {
1526
+ const m = [];
1527
+ if (c) for (let b = n; b >= r; b -= t) m.push(b);
1528
+ else for (let b = r; b <= n; b += t) m.push(b);
1529
+ return m;
1530
+ }, [
1531
+ r,
1532
+ n,
1533
+ t,
1534
+ c
1535
+ ]);
1536
+ Se(() => {
1537
+ f.current.clear();
1538
+ }, [
1539
+ x
1540
+ ]);
1541
+ const g = [
1542
+ "#5B9BD5"
1543
+ ], w = i * un, v = Fe((m) => {
1544
+ f.current.set(m.yPosition, m);
1545
+ const b = Array.from(f.current.values()).sort((S, C) => c ? C.yPosition - S.yPosition : S.yPosition - C.yPosition);
1546
+ a == null ? void 0 : a(b);
1547
+ }, [
1548
+ a,
1549
+ c
1550
+ ]);
1551
+ return p ? d(He, {
1552
+ children: x.map((m, b) => d(Vn, {
1553
+ bvh: p,
1554
+ geometry: y,
1555
+ yPosition: m,
1556
+ color: o != null && Math.abs(m - o) < t * 0.5 ? "#44ff44" : g[b % g.length],
1557
+ labelX: w,
1558
+ onDataChange: v,
1559
+ displayUnit: u,
1560
+ useInnerSurface: s,
1561
+ formValue: l == null ? void 0 : l[b],
1562
+ lineWidth: o != null && Math.abs(m - o) < t * 0.5 ? 4 : 1.5
1563
+ }, m))
1564
+ }) : null;
1565
+ }, On = ({ mesh: e, greenY: r, modelSize: n, displayUnit: t = "mm" }) => {
1566
+ var _a;
1567
+ const i = e.geometry;
1568
+ i.computeBoundingBox();
1569
+ const a = ((_a = i.boundingBox) == null ? void 0 : _a.min.y) ?? 0, c = r - a, u = n * 0.4, s = n * 0.03, l = Ie(null);
1570
+ Pt(({ camera: v }) => {
1571
+ if (!l.current) return;
1572
+ const m = new h();
1573
+ v.getWorldDirection(m);
1574
+ const b = new h(m.x, 0, m.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
+ l.current.position.set(S.x * u, 0, S.z * u);
1579
+ const C = v.position.x - l.current.position.x, M = v.position.z - l.current.position.z;
1580
+ l.current.rotation.y = Math.atan2(C, M);
1581
+ });
1582
+ const o = new h(0, r, 0), f = new h(0, a, 0), y = new h(0, (r + a) / 2, 0), p = new h(-s, r, 0), x = new h(s, r, 0), g = new h(-s, a, 0), w = new h(s, a, 0);
1583
+ return W("group", {
1584
+ ref: l,
1585
+ children: [
1586
+ d(ge, {
1587
+ points: [
1588
+ o,
1589
+ f
1590
+ ],
1591
+ color: "#888888",
1592
+ lineWidth: 1.5,
1593
+ depthTest: false
1594
+ }),
1595
+ d(ge, {
1596
+ points: [
1597
+ p,
1598
+ x
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: r, isCut: n, mesh: t, viewMode: i, sliceY: a, landmarkCount: c = 0 }) => {
1644
+ const { set: u, size: s, camera: l, invalidate: o } = on(), f = Ie(false), y = Ie(r), p = Ie(n), x = Ie(i), g = Ie(new h()), w = Ie(null), v = Ie(c), m = Fe(() => {
1645
+ if (!t || e <= 0) return;
1646
+ const S = t.geometry;
1647
+ S.computeBoundingBox();
1648
+ const C = S.boundingBox, M = new h();
1649
+ C.getCenter(M);
1650
+ const P = new h();
1651
+ C.getSize(P), g.current.copy(P);
1652
+ const L = s.width / s.height, H = Math.max(P.y, P.x / L) * 1.2, O = H * L, $ = 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
+ s,
1660
+ u
1661
+ ]), b = Fe((S) => {
1662
+ const C = S.position.clone(), M = C.length(), P = Math.atan2(C.x, C.z), L = Math.acos(C.y / M), O = P + 0.02;
1663
+ S.position.set(M * Math.sin(L) * Math.sin(O), M * Math.cos(L), M * Math.sin(L) * Math.cos(O)), S.lookAt(0, 0, 0), S.updateMatrixWorld(true), o();
1664
+ }, [
1665
+ o
1666
+ ]);
1667
+ return Se(() => {
1668
+ if (e > 0 && !f.current && !r) {
1669
+ f.current = true;
1670
+ const S = new J.PerspectiveCamera(50, s.width / s.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
+ s,
1678
+ u,
1679
+ r,
1680
+ b
1681
+ ]), Se(() => {
1682
+ const S = v.current;
1683
+ v.current = c, S === 0 && c === 1 && !r && requestAnimationFrame(() => b(l));
1684
+ }, [
1685
+ c,
1686
+ r,
1687
+ l,
1688
+ b
1689
+ ]), Se(() => {
1690
+ y.current === r && p.current === n || (y.current = r, p.current = n, r && i === "3D" && m());
1691
+ }, [
1692
+ r,
1693
+ n,
1694
+ i,
1695
+ m
1696
+ ]), Se(() => {
1697
+ if (x.current === i) return;
1698
+ const S = x.current;
1699
+ if (x.current = i, !(!r || !t || e <= 0)) if (i === "2D" && a != null) {
1700
+ w.current = l;
1701
+ const C = t.geometry, M = C.getAttribute("position"), P = M.array, L = 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(P[B * 3 + 1] - a) < L) {
1704
+ const T = P[B * 3], E = P[B * 3 + 2];
1705
+ T < H && (H = T), T > O && (O = T), E < $ && ($ = E), E > R && (R = E), Y = true;
1706
+ }
1707
+ if (!Y) {
1708
+ C.computeBoundingBox();
1709
+ const B = C.boundingBox;
1710
+ H = B.min.x, O = B.max.x, $ = B.min.z, R = B.max.z;
1711
+ }
1712
+ const j = (H + O) / 2, ne = ($ + R) / 2, oe = s.width / s.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(j, a + e * 2, ne), V.up.set(0, 0, -1), V.lookAt(j, a, ne), u({
1717
+ camera: V
1718
+ });
1719
+ } else S === "2D" && (w.current ? (u({
1720
+ camera: w.current
1721
+ }), w.current = null) : m());
1722
+ }, [
1723
+ i,
1724
+ a,
1725
+ r,
1726
+ t,
1727
+ e,
1728
+ s,
1729
+ u,
1730
+ l,
1731
+ m
1732
+ ]), Se(() => {
1733
+ if (!r || !l || !l.isOrthographicCamera) return;
1734
+ const S = l;
1735
+ if (i === "2D") {
1736
+ if (!t || a == null) return;
1737
+ const C = t.geometry, M = C.getAttribute("position"), P = M.array, L = 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(P[z * 3 + 1] - a) < L) {
1740
+ const F = P[z * 3], V = P[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
+ C.computeBoundingBox();
1745
+ const z = C.boundingBox;
1746
+ H = z.min.x, O = z.max.x, $ = z.min.z, R = z.max.z;
1747
+ }
1748
+ const j = s.width / s.height, ne = 1.4, oe = (O - H) * ne, le = (R - $) * ne;
1749
+ let ee, D;
1750
+ oe / le > j ? (ee = oe, D = oe / j) : (D = le, ee = le * j), S.left = -ee / 2, S.right = ee / 2, S.top = D / 2, S.bottom = -D / 2;
1751
+ } else {
1752
+ const C = g.current, M = s.width / s.height, P = Math.max(C.y, C.x / M) * 1.2, L = P * M;
1753
+ S.left = -L / 2, S.right = L / 2, S.top = P / 2, S.bottom = -P / 2;
1754
+ }
1755
+ S.updateProjectionMatrix();
1756
+ }, [
1757
+ s.width,
1758
+ s.height,
1759
+ r,
1760
+ l,
1761
+ i,
1762
+ t
1763
+ ]), null;
1764
+ }, jn = ({ mesh: e, isDragging: r }) => {
1765
+ var _a;
1766
+ const n = e.geometry;
1767
+ n.computeBoundingBox();
1768
+ const t = new h();
1769
+ return (_a = n.boundingBox) == null ? void 0 : _a.getCenter(t), d(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: !r,
1777
+ target: [
1778
+ t.x,
1779
+ t.y,
1780
+ t.z
1781
+ ]
1782
+ });
1783
+ }, Nn = ({ wasAutoScaled: e, onDismiss: r }) => 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: r,
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: r }) => 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: r,
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: r, accentColor: n = "rgb(12, 67, 173)" }) => d("div", {
1866
+ style: {
1867
+ backgroundColor: "#fff",
1868
+ borderBottom: "1px solid #e0e0e0",
1869
+ display: "flex",
1870
+ alignItems: "center",
1871
+ padding: "24px 24px",
1872
+ flexShrink: 0
1873
+ },
1874
+ children: e.map((t, i) => {
1875
+ const a = t.number < r, c = t.number === r;
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 ? n : "rgba(0, 0, 0, 0.38)",
1897
+ color: "#fff",
1898
+ display: "flex",
1899
+ alignItems: "center",
1900
+ justifyContent: "center",
1901
+ fontSize: 12,
1902
+ fontFamily: "system-ui, sans-serif",
1903
+ flexShrink: 0
1904
+ },
1905
+ children: a ? "\u2713" : t.number
1906
+ }),
1907
+ d("div", {
1908
+ style: {
1909
+ fontSize: 14,
1910
+ fontWeight: c ? 600 : 400,
1911
+ color: c ? "rgba(0, 0, 0, 0.87)" : "rgba(0, 0, 0, 0.54)",
1912
+ fontFamily: "system-ui, sans-serif",
1913
+ whiteSpace: "nowrap"
1914
+ },
1915
+ children: t.label
1916
+ })
1917
+ ]
1918
+ }),
1919
+ i < e.length - 1 && d("div", {
1920
+ style: {
1921
+ flex: "auto",
1922
+ borderTop: "1px solid #bdbdbd",
1923
+ margin: "0 8px"
1924
+ }
1925
+ })
1926
+ ]
1927
+ }, t.number);
1928
+ })
1929
+ }), Gn = ({ mesh: e, upperY: r, originY: n, modelSize: t, meshColor: i = "#c8c8c8", displayUnit: a = "mm" }) => {
1930
+ const c = e.geometry, u = de(() => new $e(c, {
1931
+ maxLeafTris: Ye
1932
+ }), [
1933
+ c
1934
+ ]), s = de(() => Ze(u, c, n), [
1935
+ u,
1936
+ c,
1937
+ n
1938
+ ]), l = de(() => new it(new h(0, -1, 0), r), [
1939
+ r
1940
+ ]), { mlLine: o, apLine: f, mlWidth: y, apWidth: p } = de(() => {
1941
+ let w = null, v = null, m = 0, b = 0;
1942
+ if (s.linePoints.length >= 2) {
1943
+ let S = s.linePoints[0], C = s.linePoints[0], M = s.linePoints[0], P = s.linePoints[0];
1944
+ for (const L of s.linePoints) L.x < S.x && (S = L), L.x > C.x && (C = L), L.z < M.z && (M = L), L.z > P.z && (P = L);
1945
+ w = [
1946
+ new h(S.x, n, S.z),
1947
+ new h(C.x, n, C.z)
1948
+ ], v = [
1949
+ new h(M.x, n, M.z),
1950
+ new h(P.x, n, P.z)
1951
+ ], m = w[0].distanceTo(w[1]), b = v[0].distanceTo(v[1]);
1952
+ }
1953
+ return {
1954
+ mlLine: w,
1955
+ apLine: v,
1956
+ mlWidth: m,
1957
+ apWidth: b
1958
+ };
1959
+ }, [
1960
+ s,
1961
+ n
1962
+ ]), x = (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: i,
1969
+ side: J.DoubleSide,
1970
+ transparent: true,
1971
+ opacity: 0.15,
1972
+ depthWrite: false,
1973
+ clippingPlanes: [
1974
+ l
1975
+ ]
1976
+ })
1977
+ }),
1978
+ s.linePoints.length >= 2 && d(ge, {
1979
+ points: s.linePoints,
1980
+ color: "#00ff00",
1981
+ lineWidth: 3,
1982
+ depthTest: false,
1983
+ depthWrite: false,
1984
+ transparent: true
1985
+ }),
1986
+ o && W(He, {
1987
+ children: [
1988
+ d(ge, {
1989
+ points: o,
1990
+ color: "#ff8800",
1991
+ lineWidth: 2,
1992
+ depthTest: false,
1993
+ depthWrite: false,
1994
+ transparent: true
1995
+ }),
1996
+ d(Ke, {
1997
+ position: [
1998
+ o[0].x,
1999
+ n,
2000
+ o[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
+ x(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
+ n,
2044
+ f[0].z > f[1].z ? f[0].z : f[1].z
2045
+ ],
2046
+ center: true,
2047
+ style: {
2048
+ pointerEvents: "none"
2049
+ },
2050
+ children: d("div", {
2051
+ style: {
2052
+ whiteSpace: "nowrap",
2053
+ padding: "2px 6px",
2054
+ backgroundColor: "rgba(0,0,0,0.75)",
2055
+ borderRadius: 3
2056
+ },
2057
+ children: W("span", {
2058
+ style: {
2059
+ fontSize: 12,
2060
+ color: "#ff00ff",
2061
+ fontFamily: "monospace"
2062
+ },
2063
+ children: [
2064
+ "AP ",
2065
+ x(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 r = e.getAttribute("position"), n = r.count, t = new h();
2092
+ for (let g = 0; g < n; g++) t.x += r.getX(g), t.y += r.getY(g), t.z += r.getZ(g);
2093
+ t.divideScalar(n);
2094
+ let i = 0, a = 0, c = 0, u = 0, s = 0, l = 0;
2095
+ for (let g = 0; g < n; g++) {
2096
+ const w = r.getX(g) - t.x, v = r.getY(g) - t.y, m = r.getZ(g) - t.z;
2097
+ i += w * w, a += w * v, c += w * m, u += v * v, s += v * m, l += m * m;
2098
+ }
2099
+ i /= n, a /= n, c /= n, u /= n, s /= n, l /= n;
2100
+ const o = [], f = [], y = [
2101
+ [
2102
+ i,
2103
+ a,
2104
+ c
2105
+ ],
2106
+ [
2107
+ a,
2108
+ u,
2109
+ s
2110
+ ],
2111
+ [
2112
+ c,
2113
+ s,
2114
+ l
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(), v = 0;
2119
+ for (let m = 0; m < 100; m++) {
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, C = y[2][0] * w.x + y[2][1] * w.y + y[2][2] * w.z, M = new h(b, S, C);
2121
+ if (v = M.length(), v < 1e-12) break;
2122
+ if (M.divideScalar(v), w.distanceTo(M) < 1e-10) {
2123
+ w = M;
2124
+ break;
2125
+ }
2126
+ w = M;
2127
+ }
2128
+ o.push(w.clone()), f.push(v);
2129
+ for (let m = 0; m < 3; m++) for (let b = 0; b < 3; b++) {
2130
+ const S = [
2131
+ w.x,
2132
+ w.y,
2133
+ w.z
2134
+ ][m], C = [
2135
+ w.x,
2136
+ w.y,
2137
+ w.z
2138
+ ][b];
2139
+ y[m][b] -= v * S * C;
2140
+ }
2141
+ }
2142
+ const p = new h();
2143
+ for (let g = 0; g < n; g++) p.x += r.getX(g), p.y += r.getY(g), p.z += r.getZ(g);
2144
+ p.divideScalar(n);
2145
+ const x = [
2146
+ 0,
2147
+ 0,
2148
+ 0
2149
+ ];
2150
+ for (let g = 0; g < 3; g++) {
2151
+ let w = 1 / 0, v = -1 / 0;
2152
+ const m = o[g];
2153
+ for (let b = 0; b < n; b++) {
2154
+ const S = r.getX(b) - p.x, C = r.getY(b) - p.y, M = r.getZ(b) - p.z, P = S * m.x + C * m.y + M * m.z;
2155
+ P < w && (w = P), P > v && (v = P);
2156
+ }
2157
+ x[g] = (v - w) / 2;
2158
+ }
2159
+ return {
2160
+ axes: o,
2161
+ eigenvalues: f,
2162
+ center: p,
2163
+ halfExtents: x
2164
+ };
2165
+ }
2166
+ function Kn({ pca: e }) {
2167
+ return d("group", {
2168
+ children: e.axes.map((r, n) => {
2169
+ const t = e.center.clone().addScaledVector(r, e.halfExtents[n]), i = e.center.clone().addScaledVector(r, -e.halfExtents[n]);
2170
+ return d(ge, {
2171
+ points: [
2172
+ i,
2173
+ t
2174
+ ],
2175
+ color: Zn[n],
2176
+ lineWidth: 2
2177
+ }, n);
2178
+ })
2179
+ });
2180
+ }
2181
+ function Un({ pca: e }) {
2182
+ const r = de(() => {
2183
+ const { center: n, axes: t, halfExtents: i } = e, a = [];
2184
+ for (let u = -1; u <= 1; u += 2) for (let s = -1; s <= 1; s += 2) for (let l = -1; l <= 1; l += 2) a.push(n.clone().addScaledVector(t[0], u * i[0]).addScaledVector(t[1], s * i[1]).addScaledVector(t[2], l * i[2]));
2185
+ return [
2186
+ [
2187
+ 0,
2188
+ 1
2189
+ ],
2190
+ [
2191
+ 2,
2192
+ 3
2193
+ ],
2194
+ [
2195
+ 4,
2196
+ 5
2197
+ ],
2198
+ [
2199
+ 6,
2200
+ 7
2201
+ ],
2202
+ [
2203
+ 0,
2204
+ 2
2205
+ ],
2206
+ [
2207
+ 1,
2208
+ 3
2209
+ ],
2210
+ [
2211
+ 4,
2212
+ 6
2213
+ ],
2214
+ [
2215
+ 5,
2216
+ 7
2217
+ ],
2218
+ [
2219
+ 0,
2220
+ 4
2221
+ ],
2222
+ [
2223
+ 1,
2224
+ 5
2225
+ ],
2226
+ [
2227
+ 2,
2228
+ 6
2229
+ ],
2230
+ [
2231
+ 3,
2232
+ 7
2233
+ ]
2234
+ ].map(([u, s]) => [
2235
+ a[u],
2236
+ a[s]
2237
+ ]);
2238
+ }, [
2239
+ e
2240
+ ]);
2241
+ return d("group", {
2242
+ children: r.map((n, t) => d(ge, {
2243
+ points: n,
2244
+ color: "#ffaa00",
2245
+ lineWidth: 1,
2246
+ transparent: true,
2247
+ opacity: 0.5
2248
+ }, t))
2249
+ });
2250
+ }
2251
+ function Qn({ redPoint: e, greenPoint: r }) {
2252
+ const n = de(() => new h().subVectors(r, e).normalize(), [
2253
+ e,
2254
+ r
2255
+ ]), t = de(() => {
2256
+ const a = n.dot(new h(0, 1, 0));
2257
+ return Math.acos(Math.min(1, Math.abs(a))) * 180 / Math.PI;
2258
+ }, [
2259
+ n
2260
+ ]), i = t < 1 ? "#44ff44" : t < 5 ? "#ffcc00" : "#ff4444";
2261
+ return W("group", {
2262
+ children: [
2263
+ d(ge, {
2264
+ points: [
2265
+ e,
2266
+ r
2267
+ ],
2268
+ color: i,
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: r,
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: r, greenY: n, modelSize: t }) {
2305
+ const a = t * 0.15, c = de(() => {
2306
+ const u = [];
2307
+ let s = n - 10;
2308
+ const l = new h(0, 1, 0);
2309
+ for (; s > r; ) {
2310
+ const o = Math.min(s, n), f = Math.max(s, n), y = rt(e, o, f);
2311
+ if (y) {
2312
+ const p = y.dot(l), x = Math.acos(Math.min(1, Math.abs(p))) * 180 / Math.PI;
2313
+ u.push({
2314
+ axis: y,
2315
+ regionMin: o,
2316
+ regionMax: f,
2317
+ angleDeg: x
2318
+ });
2319
+ }
2320
+ s -= 10;
2321
+ }
2322
+ return u;
2323
+ }, [
2324
+ e,
2325
+ r,
2326
+ n
2327
+ ]);
2328
+ return d("group", {
2329
+ children: c.map((u, s) => {
2330
+ const l = (u.regionMin + u.regionMax) / 2, o = new h(0, l, 0), f = o.clone().addScaledVector(u.axis, a), y = o.clone().addScaledVector(u.axis, -a), p = s / Math.max(1, c.length - 1), x = 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: x,
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: x,
2349
+ lineWidth: 0.5,
2350
+ transparent: true,
2351
+ opacity: 0.3
2352
+ })
2353
+ ]
2354
+ }, s);
2355
+ })
2356
+ });
2357
+ }
2358
+ function Jn({ geometry: e, redY: r, greenY: n, modelSize: t }) {
2359
+ const i = de(() => {
2360
+ const f = rt(e, r, n);
2361
+ if (!f) return null;
2362
+ const y = f.dot(new h(0, 1, 0)), p = Math.acos(Math.min(1, Math.abs(y))) * 180 / Math.PI;
2363
+ return {
2364
+ axis: f,
2365
+ angleDeg: p
2366
+ };
2367
+ }, [
2368
+ e,
2369
+ r,
2370
+ n
2371
+ ]);
2372
+ if (!i) return null;
2373
+ const a = (r + n) / 2, c = new h(0, a, 0), u = t * 0.4, s = c.clone().addScaledVector(i.axis, u), l = c.clone().addScaledVector(i.axis, -u), o = i.angleDeg < 0.5 ? "#00ffff" : i.angleDeg < 2 ? "#ffcc00" : "#ff6600";
2374
+ return d("group", {
2375
+ children: d(ge, {
2376
+ points: [
2377
+ l,
2378
+ s
2379
+ ],
2380
+ color: o,
2381
+ lineWidth: 3,
2382
+ dashed: true,
2383
+ dashSize: 3,
2384
+ gapSize: 2
2385
+ })
2386
+ });
2387
+ }
2388
+ function eo({ pca: e, modelSize: r }) {
2389
+ const n = e.axes[0], t = r * 0.6, i = e.center.clone().addScaledVector(n, t), a = e.center.clone().addScaledVector(n, -t);
2390
+ return d(ge, {
2391
+ points: [
2392
+ a,
2393
+ i
2394
+ ],
2395
+ color: "#ff8800",
2396
+ lineWidth: 2,
2397
+ dashed: true,
2398
+ dashSize: 3,
2399
+ gapSize: 2
2400
+ });
2401
+ }
2402
+ function to({ geometry: e, redY: r, greenY: n, modelSize: t }) {
2403
+ const i = de(() => {
2404
+ const l = ot(e), o = new h(0, 1, 0), f = 5;
2405
+ e.computeBoundingBox();
2406
+ const y = e.boundingBox.max.y, p = [];
2407
+ for (let C = r + f; C < y; C += f) {
2408
+ const M = pt(l, e, new h(0, C, 0), o);
2409
+ M > 0 && p.push({
2410
+ y: C,
2411
+ circ: M
2412
+ });
2413
+ }
2414
+ if (p.length < 5) return null;
2415
+ const x = n - r, g = r + x * 0.3, w = r + x * 0.7, v = p.filter((C) => C.y >= g && C.y <= w);
2416
+ if (v.length < 3) return null;
2417
+ const m = v.map((C) => C.circ).sort((C, M) => C - M), b = m[Math.floor(m.length / 2)], S = Math.max(...p.map((C) => C.circ));
2418
+ return {
2419
+ circumferences: p,
2420
+ baseline: b,
2421
+ maxCirc: S
2422
+ };
2423
+ }, [
2424
+ e,
2425
+ r,
2426
+ n
2427
+ ]);
2428
+ if (!i) return null;
2429
+ const { circumferences: a, baseline: c, maxCirc: u } = i, s = t * 0.3 / u;
2430
+ return W("group", {
2431
+ children: [
2432
+ a.map(({ y: l, circ: o }, f) => {
2433
+ const y = o / c, p = y > 1.6 ? "#ff4444" : y > 1.3 ? "#ffcc00" : "#22cc66", x = o * s;
2434
+ return d(ge, {
2435
+ points: [
2436
+ new h(-x, l, 0),
2437
+ new h(x, l, 0)
2438
+ ],
2439
+ color: p,
2440
+ lineWidth: 1.5,
2441
+ transparent: true,
2442
+ opacity: 0.6
2443
+ }, f);
2444
+ }),
2445
+ (() => {
2446
+ const l = c * 1.6 * s, o = a[0].y, f = a[a.length - 1].y;
2447
+ return W(He, {
2448
+ children: [
2449
+ d(ge, {
2450
+ points: [
2451
+ new h(-l, o, 0),
2452
+ new h(-l, f, 0)
2453
+ ],
2454
+ color: "#ff4444",
2455
+ lineWidth: 1,
2456
+ dashed: true,
2457
+ dashSize: 3,
2458
+ gapSize: 2,
2459
+ transparent: true,
2460
+ opacity: 0.4
2461
+ }),
2462
+ d(ge, {
2463
+ points: [
2464
+ new h(l, o, 0),
2465
+ new h(l, f, 0)
2466
+ ],
2467
+ color: "#ff4444",
2468
+ lineWidth: 1,
2469
+ dashed: true,
2470
+ dashSize: 3,
2471
+ gapSize: 2,
2472
+ transparent: true,
2473
+ opacity: 0.4
2474
+ })
2475
+ ]
2476
+ });
2477
+ })()
2478
+ ]
2479
+ });
2480
+ }
2481
+ function no({ componentDebug: e }) {
2482
+ return d("group", {
2483
+ children: e.geometries.map((r, n) => {
2484
+ const t = e.colors[n] ?? "#888888", i = n === e.innerIdx;
2485
+ r.computeBoundingBox();
2486
+ const a = new h();
2487
+ return r.boundingBox.getCenter(a), W("group", {
2488
+ children: [
2489
+ d("mesh", {
2490
+ geometry: r,
2491
+ renderOrder: i ? 2 : 1,
2492
+ children: d("meshStandardMaterial", {
2493
+ color: t,
2494
+ transparent: true,
2495
+ opacity: i ? 0.5 : 0.2,
2496
+ side: J.DoubleSide,
2497
+ depthWrite: false,
2498
+ polygonOffset: true,
2499
+ polygonOffsetFactor: 1,
2500
+ polygonOffsetUnits: 1
2501
+ })
2502
+ }),
2503
+ d("mesh", {
2504
+ geometry: r,
2505
+ renderOrder: i ? 2 : 1,
2506
+ children: d("meshBasicMaterial", {
2507
+ color: t,
2508
+ wireframe: true,
2509
+ transparent: true,
2510
+ opacity: i ? 0.4 : 0.15
2511
+ })
2512
+ }),
2513
+ d("group", {
2514
+ position: a,
2515
+ children: d(Ke, {
2516
+ center: true,
2517
+ style: {
2518
+ pointerEvents: "none"
2519
+ },
2520
+ children: d("div", {
2521
+ style: {
2522
+ padding: "2px 8px",
2523
+ backgroundColor: "rgba(0,0,0,0.8)",
2524
+ borderRadius: 4,
2525
+ border: `1px solid ${t}`,
2526
+ whiteSpace: "nowrap"
2527
+ },
2528
+ children: d("span", {
2529
+ style: {
2530
+ fontSize: 11,
2531
+ color: t,
2532
+ fontFamily: "monospace",
2533
+ fontWeight: i ? 700 : 400
2534
+ },
2535
+ children: e.labels[n]
2536
+ })
2537
+ })
2538
+ })
2539
+ })
2540
+ ]
2541
+ }, n);
2542
+ })
2543
+ });
2544
+ }
2545
+ function oo({ mesh: e, layers: r, landmarkPoints: n, componentDebug: t }) {
2546
+ const i = e.geometry, a = de(() => i.getAttribute("position") ? Ot(i) : null, [
2547
+ i
2548
+ ]), c = de(() => !n || n.length < 2 ? null : {
2549
+ red: new h(n[0].position.x, n[0].position.y, n[0].position.z),
2550
+ green: new h(n[1].position.x, n[1].position.y, n[1].position.z)
2551
+ }, [
2552
+ n
2553
+ ]);
2554
+ return W("group", {
2555
+ children: [
2556
+ r.pcaAxes && a && d(Kn, {
2557
+ pca: a
2558
+ }),
2559
+ r.obb && a && d(Un, {
2560
+ pca: a
2561
+ }),
2562
+ r.obbAxis && a && d(eo, {
2563
+ pca: a,
2564
+ modelSize: a.halfExtents[0] ? Math.max(...a.halfExtents) * 2 : 100
2565
+ }),
2566
+ r.shellComponents && t && d(no, {
2567
+ componentDebug: t
2568
+ }),
2569
+ r.circumferenceScan && c && d(to, {
2570
+ geometry: i,
2571
+ redY: c.red.y,
2572
+ greenY: c.green.y,
2573
+ modelSize: (a == null ? void 0 : a.halfExtents[0]) ? Math.max(...a.halfExtents) * 2 : 100
2574
+ }),
2575
+ r.landmarkAxis && c && d(Qn, {
2576
+ redPoint: c.red,
2577
+ greenPoint: c.green
2578
+ }),
2579
+ r.iterativePCA && c && d(qn, {
2580
+ geometry: i,
2581
+ redY: c.red.y,
2582
+ greenY: c.green.y,
2583
+ modelSize: (a == null ? void 0 : a.halfExtents[0]) ? Math.max(...a.halfExtents) * 2 : 100
2584
+ }),
2585
+ r.fullRegionPCA && c && d(Jn, {
2586
+ geometry: i,
2587
+ redY: c.red.y,
2588
+ greenY: c.green.y,
2589
+ modelSize: (a == null ? void 0 : a.halfExtents[0]) ? Math.max(...a.halfExtents) * 2 : 100
2590
+ })
2591
+ ]
2592
+ });
2593
+ }
2594
+ function so({ mesh: e }) {
2595
+ const r = e.geometry, n = de(() => {
2596
+ if (!r.getAttribute("position")) return null;
2597
+ const a = Ot(r), 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
+ r
2605
+ ]);
2606
+ if (!n) return null;
2607
+ const t = n.center.clone().addScaledVector(n.axis, n.halfLen), i = n.center.clone().addScaledVector(n.axis, -n.halfLen);
2608
+ return d(ge, {
2609
+ points: [
2610
+ i,
2611
+ t
2612
+ ],
2613
+ color: "#666",
2614
+ lineWidth: 1,
2615
+ dashed: true,
2616
+ dashSize: 4,
2617
+ gapSize: 3,
2618
+ transparent: true,
2619
+ opacity: 0.4,
2620
+ depthTest: false,
2621
+ renderOrder: 999
2622
+ });
2623
+ }
2624
+ const $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: r }) {
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((n) => 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: n
2718
+ }),
2719
+ $t.filter((t) => t.group === n).map(({ key: t, label: i, 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: () => r(t),
2733
+ style: {
2734
+ accentColor: a,
2735
+ width: 14,
2736
+ height: 14,
2737
+ cursor: "pointer"
2738
+ }
2739
+ }),
2740
+ d("span", {
2741
+ style: {
2742
+ width: 8,
2743
+ height: 8,
2744
+ borderRadius: "50%",
2745
+ backgroundColor: a,
2746
+ opacity: e[t] ? 1 : 0.3,
2747
+ flexShrink: 0
2748
+ }
2749
+ }),
2750
+ d("span", {
2751
+ style: {
2752
+ opacity: e[t] ? 1 : 0.5
2753
+ },
2754
+ children: i
2755
+ })
2756
+ ]
2757
+ }, t))
2758
+ ]
2759
+ }, n))
2760
+ ]
2761
+ });
2762
+ }
2763
+ const lo = ({ config: e, spacingType: r, scanUrl: n, formMeasurements: t, onComplete: i, isDebugUser: a = false, onAnalyticsEvent: c, wasmModule: u }) => {
2764
+ const [s, l] = Q(null), [o, f] = Q(0), [y, p] = Q(false), [x, g] = Q(false), [w, v] = Q(""), [m, b] = Q("3D"), [S, C] = Q(r === "AK" ? 2 : 1), [M, P] = Q(false), [L, H] = Q(null), [O, $] = Q(null), [R, Y] = Q(r ?? null), [j, ne] = Q("mm"), [oe, le] = Q(false), [ee, D] = Q(""), [z, F] = Q(false), [V, B] = Q(false), [T, E] = Q(false), [N, X] = Q(false), [q, ie] = Q(false), [se, A] = Q([]), [I, k] = Q(null), [G, U] = Q(null), [re, Le] = Q(null), [me, ae] = Q(null), [xe, Re] = Q(false), [pe, we] = Q(Xn), [he, Ge] = Q(false), [fe, je] = Q(null), [Pe, ye] = Q("obj"), [Te, Me] = Q(false), [Ae, De] = Q({}), [ze, Ee] = Q(t), [ke, Ue] = Q(true), [mt] = Q("#c8c8c8"), [Nt] = 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: Pe,
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
+ l(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), v("Processing file...");
2821
+ try {
2822
+ let te;
2823
+ if (Z) if (v("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, v) : null;
2840
+ if (ve) e.showAmputationModal && !r ? (H(ve), P(true)) : (Qe(ve.geometry, ve.wasScaled), ve.innerShellExtracted && (X(true), E(true)), ve.componentDebug && $(ve.componentDebug));
2841
+ else {
2842
+ v("Using fallback loader...");
2843
+ const Ce = wn(te);
2844
+ Ce ? e.showAmputationModal && !r ? (H({
2845
+ geometry: Ce,
2846
+ wasScaled: false,
2847
+ innerShellExtracted: false
2848
+ }), P(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), v("");
2854
+ }
2855
+ }, [
2856
+ Xe,
2857
+ e.showAmputationModal,
2858
+ r,
2859
+ Qe
2860
+ ]);
2861
+ Se(() => {
2862
+ if (!n || !Xe) return;
2863
+ (async () => {
2864
+ g(true), v("Downloading scan...");
2865
+ try {
2866
+ const K = await fetch(n);
2867
+ if (!K.ok) throw new Error(`Failed to download scan: ${K.status}`);
2868
+ const Z = new URL(n).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), v("");
2878
+ }
2879
+ })();
2880
+ }, [
2881
+ n,
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), v("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), v("");
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(_), C(_ === "AK" ? 2 : 1), P(false), L && (Qe(L.geometry, L.wasScaled), L.innerShellExtracted && (X(true), E(true)), L.componentDebug && $(L.componentDebug), H(null)), c == null ? void 0 : c("file_loaded", {
2917
+ spacing_type: _,
2918
+ file_format: Pe,
2919
+ is_double_wall: (L == null ? void 0 : L.innerShellExtracted) ?? false
2920
+ });
2921
+ }, [
2922
+ L,
2923
+ Qe,
2924
+ c,
2925
+ Pe
2926
+ ]), Qt = Fe(() => {
2927
+ !s || ce.length < 2 || (le(true), D("Please wait..."), setTimeout(() => {
2928
+ In(s, 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: Le,
2937
+ setAdjustedStartY: k,
2938
+ setAdjustedEndY: U,
2939
+ setError: ae,
2940
+ setDoubleShell: (_) => {
2941
+ E(_), ie(true);
2942
+ },
2943
+ setClippedReferenceGeometry: je,
2944
+ skipDoubleShellDetection: N
2945
+ }), ct.current = false, le(false);
2946
+ }, 50));
2947
+ }, [
2948
+ s,
2949
+ ce,
2950
+ bt,
2951
+ wt,
2952
+ xt,
2953
+ yt,
2954
+ St,
2955
+ at,
2956
+ N
2957
+ ]), qt = Fe(() => {
2958
+ if (!i || !s || 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 = s.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
+ i({
2974
+ spacingType: R,
2975
+ sourceUnit: "mm",
2976
+ fileFormat: Pe,
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: n
2986
+ });
2987
+ }, [
2988
+ i,
2989
+ s,
2990
+ se,
2991
+ R,
2992
+ ce,
2993
+ Pe,
2994
+ T,
2995
+ ze,
2996
+ n
2997
+ ]), Jt = be ? 4 : s ? 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 && !s && !x && 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 && !s && !x && !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
+ s && !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
+ s && !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
+ x && d(At, {
3221
+ message: w || "Processing mesh..."
3222
+ }),
3223
+ oe && d(At, {
3224
+ message: ee
3225
+ }),
3226
+ me && d(Ln, {
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
+ P(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: s ? "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
+ s && m === "3D" && d(Pn, {
3438
+ mesh: s,
3439
+ maxPoints: 2,
3440
+ meshColor: mt,
3441
+ meshOpacity: xe ? 0.3 : Nt
3442
+ }),
3443
+ he && fe && m === "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
+ s && m === "3D" && d(Tn, {
3458
+ modelSize: o,
3459
+ labels: [
3460
+ "Origin",
3461
+ R === "AK" ? "IT/Perineum" : "MPT",
3462
+ "Cut Plane"
3463
+ ]
3464
+ }),
3465
+ d($n, {
3466
+ modelSize: o,
3467
+ isAligned: be,
3468
+ isCut: Gt,
3469
+ mesh: s,
3470
+ viewMode: m,
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 && s && m === "3D" && d(jn, {
3478
+ mesh: s,
3479
+ isDragging: false
3480
+ }),
3481
+ s && be && ce.length >= 3 && (() => {
3482
+ const K = s.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 m === "2D" ? d(Gn, {
3486
+ mesh: s,
3487
+ upperY: te,
3488
+ originY: Z.position.y,
3489
+ modelSize: o,
3490
+ meshColor: mt,
3491
+ displayUnit: j
3492
+ }) : W(He, {
3493
+ children: [
3494
+ d(_n, {
3495
+ mesh: s,
3496
+ startY: Be,
3497
+ endY: te,
3498
+ spacing: at,
3499
+ modelSize: o,
3500
+ onMeasurementsChange: A,
3501
+ reverseOrder: true,
3502
+ displayUnit: j,
3503
+ useInnerSurface: T && !N,
3504
+ formMeasurements: ke ? ze : void 0,
3505
+ originY: Z.position.y
3506
+ }),
3507
+ (!T || N) && d(On, {
3508
+ mesh: s,
3509
+ greenY: Z.position.y,
3510
+ modelSize: o,
3511
+ displayUnit: j
3512
+ })
3513
+ ]
3514
+ });
3515
+ })(),
3516
+ s && be && m === "3D" && d(so, {
3517
+ mesh: s
3518
+ }),
3519
+ s && e.showDebug && xe && m === "3D" && d(oo, {
3520
+ mesh: s,
3521
+ modelSize: o,
3522
+ layers: pe,
3523
+ landmarkPoints: ce,
3524
+ componentDebug: O
3525
+ })
3526
+ ]
3527
+ }),
3528
+ s && (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 && s && m === "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: m === "3D" ? 600 : 400,
3606
+ backgroundColor: m === "3D" ? "rgb(12, 67, 173)" : "#fff",
3607
+ color: m === "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: m === "2D" ? 600 : 400,
3620
+ backgroundColor: m === "2D" ? "rgb(12, 67, 173)" : "#fff",
3621
+ color: m === "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: j === "mm" ? 600 : 400,
3646
+ backgroundColor: j === "mm" ? "rgb(12, 67, 173)" : "#fff",
3647
+ color: j === "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: j === "inch" ? 600 : 400,
3660
+ backgroundColor: j === "inch" ? "rgb(12, 67, 173)" : "#fff",
3661
+ color: j === "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 && m === "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: () => C(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: () => C(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
+ m === "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
+ m === "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
+ s && V && d(Nn, {
3783
+ wasAutoScaled: z,
3784
+ onDismiss: () => B(false)
3785
+ }),
3786
+ s && 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
+ s && !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
+ s && !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
+ jt = function(e) {
4031
+ const r = e === "AK" ? 2 : 1, n = [];
4032
+ for (let t = 2; t >= 1; t -= r) n.push(`${t}_above`);
4033
+ n.push("at_ref");
4034
+ for (let t = r; t <= 9; t += r) n.push(`${t}_below`);
4035
+ return n;
4036
+ };
4037
+ dt = function(e, r) {
4038
+ const n = jt(r), t = {};
4039
+ for (let i = 0; i < Math.min(e.length, n.length); i++) {
4040
+ const a = e[i];
4041
+ a != null && !isNaN(a) && (t[n[i]] = a);
4042
+ }
4043
+ return t;
4044
+ };
4045
+ ao = function(e, r) {
4046
+ if (!e) return;
4047
+ const t = jt(r).map((i) => {
4048
+ const a = e[i];
4049
+ return a ?? void 0;
4050
+ });
4051
+ if (!t.every((i) => i == null)) return t;
4052
+ };
4053
+ bo = ({ request: e, onComplete: r, wasmModule: n }) => {
4054
+ const [t, i] = Q(null), [a, c] = Q(n !== void 0);
4055
+ Se(() => {
4056
+ if (n !== void 0) {
4057
+ c(true);
4058
+ return;
4059
+ }
4060
+ let o = false;
4061
+ return import("./galileo_core_geo-DFVJmkI7.js").then(async (f) => {
4062
+ await f.default(), o || (i(f), c(true));
4063
+ }).catch(() => {
4064
+ o || c(true);
4065
+ }), () => {
4066
+ o = true;
4067
+ };
4068
+ }, [
4069
+ n
4070
+ ]);
4071
+ const u = n !== void 0 ? n : t, s = de(() => ao(e.form_measurements, e.spacing_type), [
4072
+ e.form_measurements,
4073
+ e.spacing_type
4074
+ ]), l = (o) => {
4075
+ const f = o.scanMeasurements.map((w) => +(w.modifiedValue ?? w.originalValue).toFixed(1)), y = dt(f, e.spacing_type);
4076
+ let p, x;
4077
+ if (o.formMeasurements) {
4078
+ p = dt(o.formMeasurements, e.spacing_type);
4079
+ const w = o.scanMeasurements.map((v, m) => {
4080
+ var _a;
4081
+ const b = (_a = o.formMeasurements) == null ? void 0 : _a[m];
4082
+ return b == null || isNaN(b) ? null : +((v.modifiedValue ?? v.originalValue) - b).toFixed(1);
4083
+ });
4084
+ x = dt(w, e.spacing_type);
4085
+ }
4086
+ const g = {
4087
+ spacing_type: e.spacing_type,
4088
+ source_unit: "mm",
4089
+ file_format: o.fileFormat,
4090
+ measurement_source: o.formMeasurements ? "form_provided" : "scan_derived",
4091
+ is_double_wall: o.isDoubleWall,
4092
+ is_unit_converted: false,
4093
+ form_measurements: p,
4094
+ scan_measurements: y,
4095
+ measurement_variance: x,
4096
+ scan_url: e.scan_url,
4097
+ frontal_height: +o.frontalHeight.toFixed(1),
4098
+ transverse_ml: +o.transverseML.toFixed(1),
4099
+ transverse_ap: +o.transverseAP.toFixed(1)
4100
+ };
4101
+ console.log("[GirthManagerWidget] WidgetResponse:", JSON.stringify(g, null, 2)), r == null ? void 0 : r(g);
4102
+ };
4103
+ return a ? d("div", {
4104
+ style: {
4105
+ width: "100%",
4106
+ height: "100%",
4107
+ display: "flex"
4108
+ },
4109
+ children: d(lo, {
4110
+ config: fn,
4111
+ spacingType: e.spacing_type,
4112
+ scanUrl: e.scan_url,
4113
+ formMeasurements: s,
4114
+ onComplete: l,
4115
+ wasmModule: u
4116
+ })
4117
+ }) : d("div", {
4118
+ style: {
4119
+ width: "100%",
4120
+ height: "100%",
4121
+ display: "flex",
4122
+ alignItems: "center",
4123
+ justifyContent: "center"
4124
+ },
4125
+ children: d("span", {
4126
+ children: "Initializing..."
4127
+ })
4128
+ });
4129
+ };
4130
+ })();
4131
+ export {
4132
+ bo as G,
4133
+ __tla,
4134
+ dt as a,
4135
+ ao as c,
4136
+ jt as g
4137
+ };