@solid-labs/fab-one-widget 0.1.6 → 0.1.8
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.
- package/dist/GirthManagerWidget-C5L2H3Y2.js +4786 -0
- package/dist/GirthManagerWidget-C5L2H3Y2.js.map +1 -0
- package/dist/geo_wasm.d.ts +529 -0
- package/dist/geo_wasm.js +1686 -0
- package/dist/geo_wasm_bg.wasm +0 -0
- package/dist/girth-manager-ui/src/GirthManagerCore.d.ts +11 -5
- package/dist/girth-manager-ui/src/components/CameraFit.d.ts +5 -1
- package/dist/girth-manager-ui/src/components/CircumferenceMeasurements.d.ts +4 -1
- package/dist/girth-manager-ui/src/components/CircumferenceSlice.d.ts +6 -1
- package/dist/girth-manager-ui/src/components/ClickableMesh.d.ts +5 -1
- package/dist/girth-manager-ui/src/components/DebugOverlays.d.ts +14 -2
- package/dist/girth-manager-ui/src/components/DebugPanel.d.ts +2 -1
- package/dist/girth-manager-ui/src/components/ErrorBoundary.d.ts +16 -0
- package/dist/girth-manager-ui/src/components/MeasurementInputForm.d.ts +14 -0
- package/dist/girth-manager-ui/src/components/VerticalDimension.d.ts +3 -1
- package/dist/girth-manager-ui/src/config.d.ts +2 -2
- package/dist/girth-manager-ui/src/index.d.ts +10 -6
- package/dist/girth-manager-ui/src/processing/logger.d.ts +13 -0
- package/dist/girth-manager-ui/src/processing/mesh-ops.d.ts +0 -22
- package/dist/girth-manager-ui/src/processing/pipeline.d.ts +34 -6
- package/dist/girth-manager-ui/src/processing/types.d.ts +112 -12
- package/dist/girth-manager-ui/src/processing/vertex-colors.d.ts +6 -1
- package/dist/girth-manager-ui/src/processing/wasm-loader.d.ts +16 -16
- package/dist/girth-manager-web-widget/src/GirthManagerWidget.d.ts +3 -5
- package/dist/girth-manager-web-widget/src/index.d.ts +1 -1
- package/dist/girth-manager-web-widget/src/types.d.ts +57 -0
- package/dist/girth-manager-web-widget/src/web-component.d.ts +2 -2
- package/dist/html2canvas.esm-Dmi1NfiH.js +4871 -0
- package/dist/html2canvas.esm-Dmi1NfiH.js.map +1 -0
- package/dist/index.js +1 -1
- package/dist/web-component.js +2 -2
- package/dist/web-component.js.map +1 -1
- package/package.json +16 -11
- package/dist/GirthManagerWidget-Ci-QU3Wh.js +0 -4137
- package/dist/GirthManagerWidget-Ci-QU3Wh.js.map +0 -1
- package/dist/galileo_core_geo-DFVJmkI7.js +0 -298
- package/dist/galileo_core_geo-DFVJmkI7.js.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"GirthManagerWidget-Ci-QU3Wh.js","sources":["../../girth-manager-ui/src/config.ts","../../girth-manager-ui/src/store.ts","../../girth-manager-ui/src/processing/constants.ts","../../girth-manager-ui/src/processing/vertex-colors.ts","../../girth-manager-ui/src/processing/wasm-loader.ts","../../girth-manager-ui/src/processing/stl-convert.ts","../../girth-manager-ui/src/processing/slice.ts","../../girth-manager-ui/src/processing/cut-plane.ts","../../girth-manager-ui/src/processing/mesh-ops.ts","../../girth-manager-ui/src/processing/alignment.ts","../../girth-manager-ui/src/processing/validation.ts","../../girth-manager-ui/src/processing/pipeline.ts","../../girth-manager-ui/src/components/ErrorDisplay.tsx","../../girth-manager-ui/src/components/LoadingSpinner.tsx","../../girth-manager-ui/src/components/ClickableMesh.tsx","../../girth-manager-ui/src/components/LandmarkMarkers.tsx","../../girth-manager-ui/src/hooks/useCachedBVH.ts","../../girth-manager-ui/src/components/CircumferenceSlice.tsx","../../girth-manager-ui/src/components/CircumferenceMeasurements.tsx","../../girth-manager-ui/src/components/VerticalDimension.tsx","../../girth-manager-ui/src/components/CameraFit.tsx","../../girth-manager-ui/src/components/AlignedOrbitControls.tsx","../../girth-manager-ui/src/components/ScaleNotice.tsx","../../girth-manager-ui/src/components/ShellNotice.tsx","../../girth-manager-ui/src/components/Stepper.tsx","../../girth-manager-ui/src/components/TransverseView.tsx","../../girth-manager-ui/src/components/DebugOverlays.tsx","../../girth-manager-ui/src/components/DebugPanel.tsx","../../girth-manager-ui/src/GirthManagerCore.tsx","../src/types.ts","../src/GirthManagerWidget.tsx"],"sourcesContent":["import { createContext, useContext } from \"react\"\n\n/**\n * Configuration that controls which UI features are visible\n * in GirthManagerCore. The internal app enables all features;\n * the external widget disables chrome, debug, drag-drop, etc.\n */\nexport interface GirthManagerConfig {\n /** Show drag-and-drop file upload zone */\n showDragDrop: boolean\n /** Show \"Start Over\" button */\n showStartOver: boolean\n /** Show \"Insert Measurement\" button and modal */\n showInsertMeasurement: boolean\n /** Allow debug mode toggle (requires isDebugUser) */\n showDebug: boolean\n /** Show 1\"/2\" measurement spacing toggle */\n showSpacingToggle: boolean\n /** Show AK/BK amputation type selection modal */\n showAmputationModal: boolean\n /** Show left navigation sidebar */\n showNavigation: boolean\n /** Show top toolbar ribbon */\n showToolbar: boolean\n}\n\n/** Default config for the internal application (all features enabled) */\nexport const INTERNAL_CONFIG: GirthManagerConfig = {\n showDragDrop: true,\n showStartOver: true,\n showInsertMeasurement: true,\n showDebug: true,\n showSpacingToggle: true,\n showAmputationModal: true,\n showNavigation: true,\n showToolbar: true,\n}\n\n/** Config for the external widget (minimal UI) */\nexport const WIDGET_CONFIG: GirthManagerConfig = {\n showDragDrop: false,\n showStartOver: false,\n showInsertMeasurement: false,\n showDebug: false,\n showSpacingToggle: false,\n showAmputationModal: false,\n showNavigation: false,\n showToolbar: false,\n}\n\nexport const GirthManagerConfigContext = createContext<GirthManagerConfig>(INTERNAL_CONFIG)\n\nexport function useGirthManagerConfig(): GirthManagerConfig {\n return useContext(GirthManagerConfigContext)\n}\n","import { create } from \"zustand\"\nimport type { LandmarkPoint } from \"./processing/types\"\n\ninterface MeasurementStore {\n landmarkPoints: LandmarkPoint[]\n isAligned: boolean\n isCut: boolean\n addLandmarkPoint: (point: LandmarkPoint) => void\n removeLandmarkPoint: (index: number) => void\n clearLandmarkPoints: () => void\n updateLandmarkPositions: (positions: { x: number; y: number; z: number }[]) => void\n setAligned: (aligned: boolean) => void\n setCut: (cut: boolean) => void\n isSelectionComplete: () => boolean\n}\n\nexport const useMeasurementStore = create<MeasurementStore>((set, get) => ({\n landmarkPoints: [],\n isAligned: false,\n isCut: false,\n\n addLandmarkPoint: (point) =>\n set((state) => {\n if (state.landmarkPoints.length >= 3) return state\n return { landmarkPoints: [...state.landmarkPoints, point] }\n }),\n\n removeLandmarkPoint: (index) =>\n set((state) => ({\n landmarkPoints: state.landmarkPoints.filter((_, i) => i !== index),\n })),\n\n clearLandmarkPoints: () => set({ landmarkPoints: [], isAligned: false, isCut: false }),\n\n updateLandmarkPositions: (positions) =>\n set((state) => ({\n landmarkPoints: state.landmarkPoints.map((point, i) => ({\n ...point,\n position: positions[i] ?? point.position,\n })),\n })),\n\n setAligned: (aligned) => set({ isAligned: aligned }),\n setCut: (cut) => set({ isCut: cut }),\n isSelectionComplete: () => get().landmarkPoints.length === 3,\n}))\n","export const LABEL_X_OFFSET_RATIO = 0.45\nexport const BVH_MAX_LEAF_TRIS = 3\nexport const WELD_EPSILON = 1e-3\nexport const MM_PER_INCH = 25.4\nexport const ABOVE_POINT_OFFSET_INCHES = 2\nexport const AUTO_SCALE_VOLUME_THRESHOLD = 5\nexport const RETRY_OFFSETS = [0.25, -0.25, 0.5, -0.5]\n","import * as THREE from \"three\"\n\n/** Parse vertex positions and colors from OBJ text. Returns null if no vertex colors found. */\nexport function parseObjVertexColors(objText: string): { positions: Float32Array; colors: Float32Array } | null {\n const lines = objText.split(\"\\n\")\n const positions: number[] = []\n const colors: number[] = []\n let hasColors = false\n\n for (const line of lines) {\n if (line.startsWith(\"v \")) {\n const parts = line.trim().split(/\\s+/)\n if (parts.length >= 7) {\n positions.push(parseFloat(parts[1]), parseFloat(parts[2]), parseFloat(parts[3]))\n let r = parseFloat(parts[4]), g = parseFloat(parts[5]), b = parseFloat(parts[6])\n if (r > 1 || g > 1 || b > 1) { r /= 255; g /= 255; b /= 255 }\n colors.push(r, g, b)\n hasColors = true\n } else if (parts.length >= 4) {\n positions.push(parseFloat(parts[1]), parseFloat(parts[2]), parseFloat(parts[3]))\n colors.push(0, 0, 0)\n }\n }\n }\n\n if (!hasColors) return null\n return { positions: new Float32Array(positions), colors: new Float32Array(colors) }\n}\n\n/** Transfer vertex colors from original OBJ data to processed geometry via nearest-vertex matching with spatial grid. */\nexport function transferVertexColors(\n geometry: THREE.BufferGeometry,\n origPositions: Float32Array,\n origColors: Float32Array,\n scaleFactor: number\n): void {\n const posAttr = geometry.getAttribute(\"position\")\n const vertCount = posAttr.count\n const outColors = new Float32Array(vertCount * 3)\n const origVertCount = origPositions.length / 3\n\n let minX = Infinity, minY = Infinity, minZ = Infinity\n let maxX = -Infinity, maxY = -Infinity, maxZ = -Infinity\n for (let j = 0; j < origVertCount; j++) {\n const ox = origPositions[j * 3] * scaleFactor, oy = origPositions[j * 3 + 1] * scaleFactor, oz = origPositions[j * 3 + 2] * scaleFactor\n if (ox < minX) minX = ox; if (ox > maxX) maxX = ox\n if (oy < minY) minY = oy; if (oy > maxY) maxY = oy\n if (oz < minZ) minZ = oz; if (oz > maxZ) maxZ = oz\n }\n const gridRes = Math.min(128, Math.max(16, Math.round(Math.cbrt(origVertCount))))\n const cellSizeX = (maxX - minX + 1e-6) / gridRes\n const cellSizeY = (maxY - minY + 1e-6) / gridRes\n const cellSizeZ = (maxZ - minZ + 1e-6) / gridRes\n const grid = new Map<number, number[]>()\n\n for (let j = 0; j < origVertCount; j++) {\n const gx = Math.min(gridRes - 1, Math.floor((origPositions[j * 3] * scaleFactor - minX) / cellSizeX))\n const gy = Math.min(gridRes - 1, Math.floor((origPositions[j * 3 + 1] * scaleFactor - minY) / cellSizeY))\n const gz = Math.min(gridRes - 1, Math.floor((origPositions[j * 3 + 2] * scaleFactor - minZ) / cellSizeZ))\n const key = gx * gridRes * gridRes + gy * gridRes + gz\n let cell = grid.get(key)\n if (!cell) { cell = []; grid.set(key, cell) }\n cell.push(j)\n }\n\n for (let i = 0; i < vertCount; i++) {\n const x = posAttr.getX(i), y = posAttr.getY(i), z = posAttr.getZ(i)\n const gx = Math.min(gridRes - 1, Math.max(0, Math.floor((x - minX) / cellSizeX)))\n const gy = Math.min(gridRes - 1, Math.max(0, Math.floor((y - minY) / cellSizeY)))\n const gz = Math.min(gridRes - 1, Math.max(0, Math.floor((z - minZ) / cellSizeZ)))\n let bestDist = Infinity, bestIdx = 0\n\n for (let r = 0; r <= gridRes && bestDist > 0; r++) {\n for (let dx = -r; dx <= r; dx++) {\n for (let dy = -r; dy <= r; dy++) {\n for (let dz = -r; dz <= r; dz++) {\n if (r > 0 && Math.abs(dx) < r && Math.abs(dy) < r && Math.abs(dz) < r) continue\n const nx = gx + dx, ny = gy + dy, nz = gz + dz\n if (nx < 0 || nx >= gridRes || ny < 0 || ny >= gridRes || nz < 0 || nz >= gridRes) continue\n const cell = grid.get(nx * gridRes * gridRes + ny * gridRes + nz)\n if (!cell) continue\n for (const j of cell) {\n const ox = origPositions[j * 3] * scaleFactor\n const oy = origPositions[j * 3 + 1] * scaleFactor\n const oz = origPositions[j * 3 + 2] * scaleFactor\n const dist = (x - ox) ** 2 + (y - oy) ** 2 + (z - oz) ** 2\n if (dist < bestDist) { bestDist = dist; bestIdx = j }\n }\n }\n }\n }\n if (bestDist < Infinity) break\n }\n outColors[i * 3] = origColors[bestIdx * 3]\n outColors[i * 3 + 1] = origColors[bestIdx * 3 + 1]\n outColors[i * 3 + 2] = origColors[bestIdx * 3 + 2]\n }\n\n geometry.setAttribute(\"color\", new THREE.Float32BufferAttribute(outColors, 3))\n}\n","import * as THREE from \"three\"\nimport { OBJLoader } from \"three/examples/jsm/loaders/OBJLoader.js\"\nimport type { WasmMeshSetType } from \"./types\"\nimport { AUTO_SCALE_VOLUME_THRESHOLD } from \"./constants\"\nimport { parseObjVertexColors, transferVertexColors } from \"./vertex-colors\"\n\n/** Max wall thickness in mm for double-shell socket meshes */\nconst MAX_WALL_THICKNESS_MM = 30\n\n/** Colors assigned to each component in debug visualization */\nconst COMPONENT_COLORS = [\n \"#4488ff\", // 0 = largest (outer shell) — blue\n \"#ff4444\", // 1 = second largest (inner shell) — red\n \"#44cc44\", // 2 = third (floor/platform) — green\n \"#ffaa00\", // 3 — orange\n \"#cc44ff\", // 4 — purple\n \"#44ffcc\", // 5 — teal\n]\n\n/** Per-component debug geometry */\nexport interface ComponentDebugInfo {\n geometries: THREE.BufferGeometry[]\n labels: string[]\n colors: string[]\n innerIdx: number | null\n}\n\nexport interface WasmProcessResult {\n geometry: THREE.BufferGeometry\n wasScaled: boolean\n /** True if a double-shell was detected and the inner shell was extracted */\n innerShellExtracted: boolean\n /** Debug: per-component colored geometries (only populated when componentCount >= 2) */\n componentDebug: ComponentDebugInfo | null\n}\n\n/** Build per-component debug geometries from WASM mesh state */\nfunction buildComponentDebugGeometries(\n meshSet: WasmMeshSetType,\n innerIdx: number | null\n): ComponentDebugInfo {\n const vertices = meshSet.getVertices()\n const faces = meshSet.getFaces()\n const labels = meshSet.getComponentLabels()\n\n // Group faces by component\n const componentFaces = new Map<number, number[]>()\n for (let i = 0; i < labels.length; i++) {\n const comp = labels[i]\n if (!componentFaces.has(comp)) componentFaces.set(comp, [])\n componentFaces.get(comp)!.push(i)\n }\n\n const sortedKeys = [...componentFaces.keys()].sort((a, b) => a - b)\n const geometries: THREE.BufferGeometry[] = []\n const geoLabels: string[] = []\n const colors: string[] = []\n\n for (const compIdx of sortedKeys) {\n const faceIndices = componentFaces.get(compIdx)!\n // Build geometry for this component\n const usedVerts = new Map<number, number>()\n const positions: number[] = []\n const indices: number[] = []\n\n for (const fi of faceIndices) {\n for (let j = 0; j < 3; j++) {\n const vi = faces[fi * 3 + j]\n if (!usedVerts.has(vi)) {\n const newIdx = positions.length / 3\n positions.push(vertices[vi * 3], vertices[vi * 3 + 1], vertices[vi * 3 + 2])\n usedVerts.set(vi, newIdx)\n }\n indices.push(usedVerts.get(vi)!)\n }\n }\n\n const geo = new THREE.BufferGeometry()\n geo.setAttribute(\"position\", new THREE.Float32BufferAttribute(positions, 3))\n geo.setIndex(indices)\n geo.computeVertexNormals()\n geometries.push(geo)\n\n // Label\n const isInner = compIdx === innerIdx\n const label = isInner ? `#${compIdx} inner` :\n compIdx === 0 ? `#${compIdx} outer` :\n `#${compIdx} (${faceIndices.length} faces)`\n geoLabels.push(label)\n colors.push(COMPONENT_COLORS[compIdx % COMPONENT_COLORS.length])\n }\n\n return { geometries, labels: geoLabels, colors, innerIdx }\n}\n\n/** Process OBJ string through WASM pipeline (merge, clean, close holes, scale) */\nexport async function processWithWasm(\n objContents: string,\n wasmModule: { WasmMeshSet: new () => WasmMeshSetType },\n onStatus?: (message: string) => void\n): Promise<WasmProcessResult | null> {\n let meshSet: WasmMeshSetType | null = null\n try {\n const objColors = parseObjVertexColors(objContents)\n\n onStatus?.(\"Loading mesh...\")\n meshSet = new wasmModule.WasmMeshSet()\n meshSet.loadObjString(objContents)\n onStatus?.(\"Detecting units...\")\n const wasScaled = meshSet.autoScaleToMm(AUTO_SCALE_VOLUME_THRESHOLD)\n onStatus?.(\"Merging close vertices...\")\n meshSet.applyMergeCloseVertices(0.0001)\n\n // Check for double-shell: if multiple components exist, try to extract inner shell.\n // This must happen BEFORE splitAndKeepLargest, which would discard the inner shell.\n onStatus?.(\"Analyzing mesh components...\")\n let innerShellExtracted = false\n let componentDebug: ComponentDebugInfo | null = null\n const componentCount = meshSet.getComponentCount()\n if (componentCount >= 2) {\n // Capture debug geometries BEFORE extraction (shows all components)\n onStatus?.(\"Building component debug info...\")\n // We need to figure out which component will be \"inner\" before extracting.\n // The labels are sorted by size descending, so after extractInnerShell the\n // inner component is the smaller of the overlapping pair.\n // Build debug geo from current state (all components present).\n const preExtractDebug = buildComponentDebugGeometries(meshSet, null)\n\n onStatus?.(\"Extracting inner shell...\")\n innerShellExtracted = meshSet.extractInnerShell(MAX_WALL_THICKNESS_MM)\n if (innerShellExtracted) {\n console.log(\"Inner shell extracted from double-shell mesh\")\n // Mark the inner component in debug info — it's component #1 (second largest)\n // since extractInnerShell keeps the smaller of the overlapping pair\n preExtractDebug.innerIdx = 1\n preExtractDebug.labels[1] = `#1 inner (extracted)`\n if (preExtractDebug.labels[0]) preExtractDebug.labels[0] = `#0 outer (discarded)`\n componentDebug = preExtractDebug\n } else {\n // No overlapping shell pair found — keep largest (normal single-shell behavior)\n onStatus?.(\"Removing floating artifacts...\")\n meshSet.splitAndKeepLargest()\n componentDebug = preExtractDebug\n }\n } else {\n // Single component — could still be a connected double-shell,\n // which will be handled by the existing pipeline detection\n onStatus?.(\"Removing floating artifacts...\")\n meshSet.splitAndKeepLargest()\n }\n\n onStatus?.(\"Closing holes...\")\n meshSet.applyCloseHoles(30)\n meshSet.applyMergeCloseVertices(0.0001)\n onStatus?.(\"Extracting geometry...\")\n const vertices = meshSet.getVertices()\n const faces = meshSet.getFaces()\n if (vertices.length === 0) return null\n const geometry = new THREE.BufferGeometry()\n geometry.setAttribute(\"position\", new THREE.Float32BufferAttribute(vertices, 3))\n geometry.setIndex(Array.from(faces))\n geometry.computeVertexNormals()\n\n if (objColors) {\n const scale = wasScaled ? 1000 : 1\n transferVertexColors(geometry, objColors.positions, objColors.colors, scale)\n }\n\n return { geometry, wasScaled, innerShellExtracted, componentDebug }\n } catch (error) {\n console.error(\"WASM processing failed:\", error)\n return null\n } finally {\n if (meshSet) try { meshSet.free() } catch { /* ignore */ }\n }\n}\n\n/** Fallback: process OBJ string with Three.js OBJLoader */\nexport function processWithObjLoader(objContents: string): THREE.BufferGeometry | null {\n const loader = new OBJLoader()\n const obj = loader.parse(objContents)\n let foundGeometry: THREE.BufferGeometry | null = null\n obj.traverse((child) => { if ((child as THREE.Mesh).isMesh && !foundGeometry) foundGeometry = (child as THREE.Mesh).geometry as THREE.BufferGeometry })\n return foundGeometry\n}\n","import { STLLoader } from \"three/examples/jsm/loaders/STLLoader.js\"\n\n/** Convert STL binary/ascii into OBJ text so it can go through the WASM pipeline */\nexport async function stlToObjString(file: File): Promise<string> {\n const buffer = await file.arrayBuffer()\n const loader = new STLLoader()\n const geometry = loader.parse(buffer)\n const pos = geometry.getAttribute(\"position\")\n if (!pos || pos.count === 0) throw new Error(\"Empty STL geometry\")\n const lines: string[] = []\n for (let i = 0; i < pos.count; i++) {\n lines.push(`v ${pos.getX(i)} ${pos.getY(i)} ${pos.getZ(i)}`)\n }\n for (let i = 0; i < pos.count; i += 3) {\n lines.push(`f ${i + 1} ${i + 2} ${i + 3}`)\n }\n return lines.join(\"\\n\")\n}\n","import * as THREE from \"three\"\nimport { Vector3, Plane, Box3, Line3 } from \"three\"\nimport { MeshBVH } from \"three-mesh-bvh\"\nimport { WELD_EPSILON, BVH_MAX_LEAF_TRIS, RETRY_OFFSETS } from \"./constants\"\nimport type { Seg, SliceResult } from \"./types\"\n\nexport function weldKey(v: Vector3, eps: number) {\n const k = 1 / eps\n return `${Math.round(v.x * k)}_${Math.round(v.y * k)}_${Math.round(v.z * k)}`\n}\n\nexport function cleanLoop(points: Vector3[], eps: number): Vector3[] {\n if (!points.length) return []\n const cleaned: Vector3[] = []\n for (const p of points) {\n if (cleaned.length === 0 || cleaned[cleaned.length - 1].distanceTo(p) > eps) cleaned.push(p.clone())\n }\n if (cleaned.length > 2 && cleaned[0].distanceTo(cleaned[cleaned.length - 1]) > eps) cleaned.push(cleaned[0].clone())\n return cleaned\n}\n\nexport function calcLineLength(points: Vector3[]): number {\n let total = 0\n for (let i = 0; i < points.length - 1; i++) total += points[i].distanceTo(points[i + 1])\n return total\n}\n\nexport function stitchOneLoop(segments: Seg[], eps = 1e-3, preferInner = false): Vector3[] {\n if (!segments.length) return []\n const keyToVec = new Map<string, Vector3>()\n const weld = (v: Vector3) => {\n const key = weldKey(v, eps)\n let out = keyToVec.get(key)\n if (!out) { out = v.clone(); keyToVec.set(key, out) }\n return out\n }\n const remaining = segments.map((s) => ({ a: weld(s.a), b: weld(s.b) }))\n const polylines: Vector3[][] = []\n while (remaining.length) {\n const seg = remaining.pop()!\n const line: Vector3[] = [seg.a, seg.b]\n let expanded = true\n while (expanded) {\n expanded = false\n for (let i = remaining.length - 1; i >= 0; i--) {\n const { a, b } = remaining[i]\n if (a.equals(line[line.length - 1])) { line.push(b) }\n else if (b.equals(line[line.length - 1])) { line.push(a) }\n else if (a.equals(line[0])) { line.unshift(b) }\n else if (b.equals(line[0])) { line.unshift(a) }\n else continue\n remaining.splice(i, 1)\n expanded = true\n }\n }\n const cleaned = cleanLoop(line, eps)\n if (cleaned.length > 1) polylines.push(cleaned)\n }\n if (!polylines.length) return []\n polylines.sort((a, b) => calcLineLength(b) - calcLineLength(a))\n if (!preferInner) return polylines[0] ?? []\n // For inner surface: pick the shortest loop that is >= 30% of the longest\n // (filters out tiny artifacts while selecting the inner wall over the outer)\n const longestLen = calcLineLength(polylines[0])\n const substantial = polylines.filter(p => calcLineLength(p) >= longestLen * 0.3)\n return substantial[substantial.length - 1] ?? polylines[0]\n}\n\nexport function computeSliceAtYOnce(bvh: MeshBVH, geometry: THREE.BufferGeometry, yPosition: number, useInnerSurface = false): SliceResult {\n const slicePlane = new Plane(new Vector3(0, 1, 0), -yPosition)\n const segments: Seg[] = []\n const box = new Box3()\n box.setFromBufferAttribute(geometry.getAttribute(\"position\") as THREE.BufferAttribute)\n const emptyResult: SliceResult = { linePoints: [], lineLength: 0, rightmostPoint: new Vector3(0, yPosition, 0) }\n if (!slicePlane.intersectsBox(box)) return emptyResult\n\n const localTempLine = new Line3()\n const localTempVec = new Vector3()\n bvh.shapecast({\n intersectsBounds: (nodeBox) => slicePlane.intersectsBox(nodeBox),\n intersectsTriangle: (tri) => {\n const p: Vector3[] = []\n localTempLine.set(tri.a, tri.b)\n if (slicePlane.intersectLine(localTempLine, localTempVec)) p.push(localTempVec.clone())\n localTempLine.set(tri.b, tri.c)\n if (slicePlane.intersectLine(localTempLine, localTempVec)) p.push(localTempVec.clone())\n localTempLine.set(tri.c, tri.a)\n if (slicePlane.intersectLine(localTempLine, localTempVec)) p.push(localTempVec.clone())\n if (p.length === 2) segments.push({ a: p[0], b: p[1] })\n },\n })\n\n const ordered = stitchOneLoop(segments, WELD_EPSILON, useInnerSurface)\n const lineLength = calcLineLength(ordered)\n if (ordered.length < 2) return emptyResult\n\n let maxX = -Infinity\n let rightmostPoint = new Vector3(0, yPosition, 0)\n for (const v of ordered) { if (v.x > maxX) { maxX = v.x; rightmostPoint = v.clone() } }\n\n const isClosed = ordered.length > 2 && ordered[0].distanceTo(ordered[ordered.length - 1]) < WELD_EPSILON * 10\n return { linePoints: ordered, lineLength, rightmostPoint, isClosed }\n}\n\nexport function computeSliceAtY(bvh: MeshBVH, geometry: THREE.BufferGeometry, yPosition: number, useInnerSurface = false): SliceResult {\n const result = computeSliceAtYOnce(bvh, geometry, yPosition, useInnerSurface)\n if (result.isClosed && result.linePoints.length >= 3) return result\n\n console.warn(`[slice] y=${yPosition.toFixed(2)} failed (pts=${result.linePoints.length}, closed=${result.isClosed}), retrying...`)\n let bestResult = result\n for (const offset of RETRY_OFFSETS) {\n const retry = computeSliceAtYOnce(bvh, geometry, yPosition + offset, useInnerSurface)\n if (retry.isClosed && retry.linePoints.length >= 3) {\n console.log(`[slice] y=${yPosition.toFixed(2)} recovered with offset ${offset > 0 ? '+' : ''}${offset}mm (pts=${retry.linePoints.length}, len=${retry.lineLength.toFixed(1)}mm)`)\n return retry\n }\n if (retry.linePoints.length > bestResult.linePoints.length) bestResult = retry\n }\n console.warn(`[slice] y=${yPosition.toFixed(2)} all retries exhausted (pts=${bestResult.linePoints.length}, closed=${bestResult.isClosed})`)\n return bestResult\n}\n\n/** Compute circumference of the slice at an arbitrary plane (any normal). */\nexport function computeCircumferenceAtPlane(\n bvh: MeshBVH,\n geometry: THREE.BufferGeometry,\n planePoint: Vector3,\n planeNormal: Vector3\n): number {\n const plane = new Plane().setFromNormalAndCoplanarPoint(planeNormal.clone().normalize(), planePoint)\n const box = new Box3()\n box.setFromBufferAttribute(geometry.getAttribute(\"position\") as THREE.BufferAttribute)\n if (!plane.intersectsBox(box)) return 0\n\n const segments: Seg[] = []\n const localTempLine = new Line3()\n const localTempVec = new Vector3()\n bvh.shapecast({\n intersectsBounds: (nodeBox) => plane.intersectsBox(nodeBox),\n intersectsTriangle: (tri) => {\n const p: Vector3[] = []\n localTempLine.set(tri.a, tri.b)\n if (plane.intersectLine(localTempLine, localTempVec)) p.push(localTempVec.clone())\n localTempLine.set(tri.b, tri.c)\n if (plane.intersectLine(localTempLine, localTempVec)) p.push(localTempVec.clone())\n localTempLine.set(tri.c, tri.a)\n if (plane.intersectLine(localTempLine, localTempVec)) p.push(localTempVec.clone())\n if (p.length === 2) segments.push({ a: p[0], b: p[1] })\n },\n })\n\n const ordered = stitchOneLoop(segments, WELD_EPSILON)\n return calcLineLength(ordered)\n}\n\n/** Compute BVH for a geometry (used in useCachedBVH hook and standalone) */\nexport function buildBVH(geometry: THREE.BufferGeometry): MeshBVH {\n return new MeshBVH(geometry, { maxLeafTris: BVH_MAX_LEAF_TRIS })\n}\n","import * as THREE from \"three\"\nimport { Vector3, Quaternion, Plane, Line3 } from \"three\"\nimport { MeshBVH } from \"three-mesh-bvh\"\nimport { BVH_MAX_LEAF_TRIS } from \"./constants\"\nimport { weldKey, cleanLoop, calcLineLength } from \"./slice\"\nimport type { Seg } from \"./types\"\n\nexport function intersectMeshWithPlane(\n bvhOrGeometry: MeshBVH | THREE.BufferGeometry,\n planePoint: Vector3,\n planeNormal: Vector3\n): Seg[] {\n const bvh = bvhOrGeometry instanceof MeshBVH\n ? bvhOrGeometry\n : new MeshBVH(bvhOrGeometry, { maxLeafTris: BVH_MAX_LEAF_TRIS })\n const plane = new Plane().setFromNormalAndCoplanarPoint(planeNormal.clone().normalize(), planePoint)\n const segments: Seg[] = []\n const tempLine = new Line3()\n const tempVec = new Vector3()\n\n bvh.shapecast({\n intersectsBounds: (nodeBox) => plane.intersectsBox(nodeBox),\n intersectsTriangle: (tri) => {\n const pts: Vector3[] = []\n tempLine.set(tri.a, tri.b)\n if (plane.intersectLine(tempLine, tempVec)) pts.push(tempVec.clone())\n tempLine.set(tri.b, tri.c)\n if (plane.intersectLine(tempLine, tempVec)) pts.push(tempVec.clone())\n tempLine.set(tri.c, tri.a)\n if (plane.intersectLine(tempLine, tempVec)) pts.push(tempVec.clone())\n if (pts.length === 2) segments.push({ a: pts[0], b: pts[1] })\n },\n })\n return segments\n}\n\n/** Like stitchOneLoop but picks the loop whose centroid is closest to `nearPoint` */\nexport function stitchLoopNearPoint(segments: Seg[], nearPoint: Vector3, eps = 1e-3): Vector3[] {\n if (!segments.length) return []\n const keyToVec = new Map<string, Vector3>()\n const weld = (v: Vector3) => {\n const key = weldKey(v, eps)\n let out = keyToVec.get(key)\n if (!out) { out = v.clone(); keyToVec.set(key, out) }\n return out\n }\n const remaining = segments.map((s) => ({ a: weld(s.a), b: weld(s.b) }))\n const polylines: Vector3[][] = []\n while (remaining.length) {\n const seg = remaining.pop()!\n const line: Vector3[] = [seg.a, seg.b]\n let expanded = true\n while (expanded) {\n expanded = false\n for (let i = remaining.length - 1; i >= 0; i--) {\n const { a, b } = remaining[i]\n if (a.equals(line[line.length - 1])) { line.push(b) }\n else if (b.equals(line[line.length - 1])) { line.push(a) }\n else if (a.equals(line[0])) { line.unshift(b) }\n else if (b.equals(line[0])) { line.unshift(a) }\n else continue\n remaining.splice(i, 1)\n expanded = true\n }\n }\n const cleaned = cleanLoop(line, eps)\n if (cleaned.length > 1) polylines.push(cleaned)\n }\n if (!polylines.length) return []\n\n let bestLoop: Vector3[] = []\n let bestDist = Infinity\n for (const poly of polylines) {\n if (poly.length < 3) continue\n const closed = poly[0].distanceTo(poly[poly.length - 1]) < 2.0\n if (!closed) continue\n const centroid = new Vector3()\n for (const p of poly) centroid.add(p)\n centroid.divideScalar(poly.length)\n const dist = centroid.distanceTo(nearPoint)\n if (dist < bestDist) { bestDist = dist; bestLoop = poly }\n }\n if (bestLoop.length === 0) {\n for (const poly of polylines) {\n if (poly.length < 3) continue\n const centroid = new Vector3()\n for (const p of poly) centroid.add(p)\n centroid.divideScalar(poly.length)\n const dist = centroid.distanceTo(nearPoint)\n if (dist < bestDist) { bestDist = dist; bestLoop = poly }\n }\n }\n return bestLoop\n}\n\n/** Compute the centroid of a closed loop of points */\nexport function loopCentroid(loop: Vector3[]): Vector3 {\n const c = new Vector3()\n for (const p of loop) c.add(p)\n return c.divideScalar(loop.length)\n}\n\nexport function findBestCutPlane(\n geometry: THREE.BufferGeometry,\n greenPoint: Vector3,\n redPoint: Vector3\n): { normal: Vector3; circumference: number } {\n const bvh = new MeshBVH(geometry, { maxLeafTris: BVH_MAX_LEAF_TRIS })\n const roughDir = new Vector3().subVectors(greenPoint, redPoint).normalize()\n\n const limbLen = greenPoint.distanceTo(redPoint)\n const sliceSpacing = limbLen * 0.05\n let axisNormal = roughDir.clone()\n\n const fitAxisFromCentroids = (sliceDir: Vector3): Vector3 | null => {\n const centroids: Vector3[] = []\n for (let i = -10; i <= 0; i++) {\n const slicePoint = greenPoint.clone().addScaledVector(sliceDir, i * sliceSpacing)\n const segs = intersectMeshWithPlane(bvh, slicePoint, sliceDir)\n const loop = stitchLoopNearPoint(segs, slicePoint, 1.0)\n if (loop.length >= 3 && loop[0].distanceTo(loop[loop.length - 1]) < 1.0) {\n centroids.push(loopCentroid(loop))\n }\n }\n if (centroids.length < 3) return null\n\n const mean = new Vector3()\n for (const c of centroids) mean.add(c)\n mean.divideScalar(centroids.length)\n\n let cxx = 0, cxy = 0, cxz = 0, cyy = 0, cyz = 0, czz = 0\n for (const c of centroids) {\n const dx = c.x - mean.x, dy = c.y - mean.y, dz = c.z - mean.z\n cxx += dx * dx; cxy += dx * dy; cxz += dx * dz\n cyy += dy * dy; cyz += dy * dz; czz += dz * dz\n }\n\n let axis = sliceDir.clone()\n for (let iter = 0; iter < 30; iter++) {\n const nx = cxx * axis.x + cxy * axis.y + cxz * axis.z\n const ny = cxy * axis.x + cyy * axis.y + cyz * axis.z\n const nz = cxz * axis.x + cyz * axis.y + czz * axis.z\n const newAxis = new Vector3(nx, ny, nz)\n const len = newAxis.length()\n if (len < 1e-10) break\n newAxis.divideScalar(len)\n if (axis.distanceTo(newAxis) < 1e-8) break\n axis = newAxis\n }\n if (axis.dot(roughDir) < 0) axis.negate()\n return axis\n }\n\n for (let pass = 0; pass < 3; pass++) {\n const refined = fitAxisFromCentroids(axisNormal)\n if (!refined) break\n const change = axisNormal.angleTo(refined)\n axisNormal = refined\n if (change < 0.001) break\n }\n\n const ortho1 = new Vector3()\n if (Math.abs(axisNormal.x) < 0.9) ortho1.set(1, 0, 0)\n else ortho1.set(0, 1, 0)\n ortho1.crossVectors(axisNormal, ortho1).normalize()\n const ortho2 = new Vector3().crossVectors(axisNormal, ortho1).normalize()\n\n const evaluatePlane = (normal: Vector3): { circumference: number; closed: boolean } => {\n const segments = intersectMeshWithPlane(bvh, greenPoint, normal)\n const loop = stitchLoopNearPoint(segments, greenPoint, 1.0)\n if (loop.length < 3) return { circumference: Infinity, closed: false }\n const closed = loop[0].distanceTo(loop[loop.length - 1]) < 1.0\n const circumference = calcLineLength(loop)\n return { circumference, closed }\n }\n\n let bestNormal = axisNormal.clone()\n let bestCircumference = Infinity\n\n for (let a1 = -3; a1 <= 3; a1 += 1) {\n for (let a2 = -3; a2 <= 3; a2 += 1) {\n const rad1 = (a1 * Math.PI) / 180\n const rad2 = (a2 * Math.PI) / 180\n const candidate = axisNormal.clone()\n .applyQuaternion(new Quaternion().setFromAxisAngle(ortho1, rad1))\n .applyQuaternion(new Quaternion().setFromAxisAngle(ortho2, rad2))\n .normalize()\n const result = evaluatePlane(candidate)\n if (result.closed && result.circumference < bestCircumference) {\n bestCircumference = result.circumference\n bestNormal = candidate\n }\n }\n }\n\n const microBase = bestNormal.clone()\n const mOrtho1 = new Vector3()\n if (Math.abs(microBase.x) < 0.9) mOrtho1.set(1, 0, 0)\n else mOrtho1.set(0, 1, 0)\n mOrtho1.crossVectors(microBase, mOrtho1).normalize()\n const mOrtho2 = new Vector3().crossVectors(microBase, mOrtho1).normalize()\n\n for (let a1 = -5; a1 <= 5; a1 += 1) {\n for (let a2 = -5; a2 <= 5; a2 += 1) {\n const rad1 = (a1 * 0.1 * Math.PI) / 180\n const rad2 = (a2 * 0.1 * Math.PI) / 180\n const candidate = microBase.clone()\n .applyQuaternion(new Quaternion().setFromAxisAngle(mOrtho1, rad1))\n .applyQuaternion(new Quaternion().setFromAxisAngle(mOrtho2, rad2))\n .normalize()\n const result = evaluatePlane(candidate)\n if (result.closed && result.circumference < bestCircumference) {\n bestCircumference = result.circumference\n bestNormal = candidate\n }\n }\n }\n\n if (bestCircumference === Infinity) {\n const fallback = evaluatePlane(axisNormal)\n bestCircumference = fallback.circumference\n bestNormal = axisNormal\n }\n\n return { normal: bestNormal, circumference: bestCircumference }\n}\n","import * as THREE from \"three\"\nimport { Vector3, Plane } from \"three\"\nimport { MeshBVH } from \"three-mesh-bvh\"\nimport { BVH_MAX_LEAF_TRIS } from \"./constants\"\n\nexport interface ShellDetectionResult {\n isDoubleShell: boolean\n sampledFaces: number\n opposingPairs: number\n confidence: number\n}\n\n/**\n * Detect whether a mesh is single-shell or double-shell (has wall thickness).\n *\n * Method: BVH ray intersection counting.\n * For each of 3 cross-sections perpendicular to the red→green axis, the centroid\n * is computed, then 12 rays are cast radially outward from it. Each ray counts all\n * triangle intersections (both front and back faces via double-sided testing).\n *\n * Single shell → each ray exits through 1 wall → avg hits ≈ 1\n * Double shell → each ray exits through inner wall + outer wall → avg hits ≈ 2\n *\n * This is independent of normal direction and surface texture/roughness.\n * At least 2 of 3 sections must independently show avg hits > 1.5 to classify as\n * double-shell, preventing false positives from irregular endpoints.\n */\nexport function detectDoubleShell(\n geometry: THREE.BufferGeometry,\n redPoint: Vector3,\n greenPoint: Vector3,\n): ShellDetectionResult {\n const posAttr = geometry.getAttribute(\"position\")\n const indexAttr = geometry.getIndex()\n if (!indexAttr) return { isDoubleShell: false, sampledFaces: 0, opposingPairs: 0, confidence: 0 }\n\n const indices = indexAttr.array\n const positions = posAttr.array as Float32Array\n\n const axis = new Vector3().subVectors(greenPoint, redPoint).normalize()\n const axisLen = greenPoint.distanceTo(redPoint)\n const sliceHalfWidth = Math.min(axisLen * 0.06, 15)\n\n // Build BVH once for all ray queries\n const bvh = new MeshBVH(geometry, { maxLeafTris: BVH_MAX_LEAF_TRIS })\n\n // Two vectors spanning the cross-section plane (Gram-Schmidt)\n let perp1 = new Vector3(1, 0, 0)\n if (Math.abs(axis.dot(perp1)) > 0.9) perp1 = new Vector3(0, 1, 0)\n perp1.sub(axis.clone().multiplyScalar(axis.dot(perp1))).normalize()\n const perp2 = new Vector3().crossVectors(axis, perp1).normalize()\n\n const NUM_RAYS = 12\n const hitTarget = new Vector3()\n let totalHits = 0\n let totalRays = 0\n let sectionsAboveThreshold = 0\n\n // Sample near the green point (brim) — that's where socket double walls are visible\n for (const t of [0.65, 0.78, 0.90]) {\n const sliceCenter = new Vector3().lerpVectors(redPoint, greenPoint, t)\n\n // Compute cross-section centroid\n let sumCx = 0, sumCy = 0, sumCz = 0, count = 0\n for (let f = 0; f < indices.length; f += 3) {\n const i0 = indices[f], i1 = indices[f + 1], i2 = indices[f + 2]\n const cx = (positions[i0 * 3] + positions[i1 * 3] + positions[i2 * 3]) / 3\n const cy = (positions[i0 * 3 + 1] + positions[i1 * 3 + 1] + positions[i2 * 3 + 1]) / 3\n const cz = (positions[i0 * 3 + 2] + positions[i1 * 3 + 2] + positions[i2 * 3 + 2]) / 3\n const dcx = cx - sliceCenter.x, dcy = cy - sliceCenter.y, dcz = cz - sliceCenter.z\n if (Math.abs(dcx * axis.x + dcy * axis.y + dcz * axis.z) > sliceHalfWidth) continue\n sumCx += cx; sumCy += cy; sumCz += cz; count++\n }\n if (count < 8) continue\n\n const origin = new Vector3(sumCx / count, sumCy / count, sumCz / count)\n\n // Cast NUM_RAYS evenly-spaced radial rays and count all intersections\n let sectionHits = 0\n for (let i = 0; i < NUM_RAYS; i++) {\n const angle = (i / NUM_RAYS) * Math.PI * 2\n const dir = new Vector3()\n .addScaledVector(perp1, Math.cos(angle))\n .addScaledVector(perp2, Math.sin(angle))\n\n const ray = new THREE.Ray(origin, dir)\n let rayHits = 0\n\n bvh.shapecast({\n intersectsBounds: (box) => ray.intersectsBox(box),\n intersectsTriangle: (tri) => {\n // Double-sided: check both winding orders\n if (ray.intersectTriangle(tri.a, tri.b, tri.c, false, hitTarget)) rayHits++\n return false // continue traversal\n },\n })\n\n sectionHits += rayHits\n totalRays++\n }\n\n totalHits += sectionHits\n const avgHits = sectionHits / NUM_RAYS\n // Double shell → avg ~2 hits; single shell → avg ~1 hit\n if (avgHits > 1.5) sectionsAboveThreshold++\n }\n\n if (totalRays === 0) return { isDoubleShell: false, sampledFaces: 0, opposingPairs: 0, confidence: 0 }\n\n const avgHitsOverall = totalHits / totalRays\n const isDoubleShell = sectionsAboveThreshold >= 2\n\n return {\n isDoubleShell,\n sampledFaces: totalRays,\n opposingPairs: totalHits,\n confidence: avgHitsOverall,\n }\n}\n\n/** Compute barycentric coordinates of point p with respect to triangle (a, b, c) */\nexport function computeBarycentricCoords(p: Vector3, a: Vector3, b: Vector3, c: Vector3): { u: number; v: number; w: number } {\n const v0 = new Vector3().subVectors(b, a)\n const v1 = new Vector3().subVectors(c, a)\n const v2 = new Vector3().subVectors(p, a)\n const dot00 = v0.dot(v0), dot01 = v0.dot(v1), dot02 = v0.dot(v2), dot11 = v1.dot(v1), dot12 = v1.dot(v2)\n const invDenom = 1 / (dot00 * dot11 - dot01 * dot01)\n const v = (dot11 * dot02 - dot01 * dot12) * invDenom\n const w = (dot00 * dot12 - dot01 * dot02) * invDenom\n return { u: 1 - v - w, v, w }\n}\n\n/** Slice mesh at an arbitrary plane. By default keeps only the component closest to `keepPoint`;\n * pass `keepAllComponents = true` to retain all geometry on the kept side (e.g. double-shell). */\nexport function sliceMeshAtPlane(\n geometry: THREE.BufferGeometry,\n planeOrigin: Vector3,\n planeNormal: Vector3,\n keepPoint: Vector3,\n keepAllComponents = false\n): THREE.BufferGeometry {\n const normal = planeNormal.clone().normalize()\n const posAttr = geometry.getAttribute(\"position\")\n const indexAttr = geometry.getIndex()\n if (!indexAttr) throw new Error(\"No index buffer\")\n\n const keepDot = new Vector3().subVectors(keepPoint, planeOrigin).dot(normal)\n const keepSideSign = Math.abs(keepDot) < 1e-6 ? 1 : Math.sign(keepDot)\n\n const oldPositions = posAttr.array as Float32Array\n const oldIndices = indexAttr.array\n const colorAttr = geometry.getAttribute(\"color\")\n const oldColors = colorAttr ? (colorAttr.array as Float32Array) : null\n const newPositions: number[] = []\n const newColors: number[] = []\n const newIndices: number[] = []\n\n const addVertex = (x: number, y: number, z: number): number => {\n const idx = newPositions.length / 3; newPositions.push(x, y, z); return idx\n }\n const getVertex = (idx: number): Vector3 => new Vector3(oldPositions[idx * 3], oldPositions[idx * 3 + 1], oldPositions[idx * 3 + 2])\n const interpolateAtPlane = (v1: Vector3, v2: Vector3): Vector3 => {\n const d1 = new Vector3().subVectors(v1, planeOrigin).dot(normal)\n const d2 = new Vector3().subVectors(v2, planeOrigin).dot(normal)\n const t = d1 / (d1 - d2)\n return new Vector3().lerpVectors(v1, v2, t)\n }\n\n const vertexCache = new Map<number, number>()\n const edgeCache = new Map<string, number>()\n\n const distCache = new Map<number, number>()\n const signedDist = (idx: number): number => {\n let d = distCache.get(idx)\n if (d === undefined) {\n d = new Vector3().subVectors(getVertex(idx), planeOrigin).dot(normal)\n distCache.set(idx, d)\n }\n return d\n }\n\n const getOrAddOldVertex = (oldIdx: number): number => {\n if (vertexCache.has(oldIdx)) return vertexCache.get(oldIdx)!\n const v = getVertex(oldIdx)\n const newIdx = addVertex(v.x, v.y, v.z)\n if (oldColors) newColors.push(oldColors[oldIdx * 3], oldColors[oldIdx * 3 + 1], oldColors[oldIdx * 3 + 2])\n vertexCache.set(oldIdx, newIdx)\n return newIdx\n }\n const getEdgeIntersection = (idx1: number, idx2: number): number => {\n const key = idx1 < idx2 ? `${idx1}_${idx2}` : `${idx2}_${idx1}`\n if (edgeCache.has(key)) return edgeCache.get(key)!\n const v = interpolateAtPlane(getVertex(idx1), getVertex(idx2))\n const newIdx = addVertex(v.x, v.y, v.z)\n if (oldColors) {\n const d1 = signedDist(idx1), d2 = signedDist(idx2)\n const t = d1 / (d1 - d2)\n newColors.push(\n oldColors[idx1 * 3] + t * (oldColors[idx2 * 3] - oldColors[idx1 * 3]),\n oldColors[idx1 * 3 + 1] + t * (oldColors[idx2 * 3 + 1] - oldColors[idx1 * 3 + 1]),\n oldColors[idx1 * 3 + 2] + t * (oldColors[idx2 * 3 + 2] - oldColors[idx1 * 3 + 2])\n )\n }\n edgeCache.set(key, newIdx)\n return newIdx\n }\n\n const isKept = (idx: number): boolean => { const d = signedDist(idx); return Math.sign(d) === keepSideSign || Math.abs(d) < 1e-6 }\n\n for (let i = 0; i < oldIndices.length; i += 3) {\n const i0 = oldIndices[i], i1 = oldIndices[i + 1], i2 = oldIndices[i + 2]\n const k0 = isKept(i0), k1 = isKept(i1), k2 = isKept(i2)\n const keepCount = (k0 ? 1 : 0) + (k1 ? 1 : 0) + (k2 ? 1 : 0)\n\n if (keepCount === 0) continue\n if (keepCount === 3) {\n newIndices.push(getOrAddOldVertex(i0), getOrAddOldVertex(i1), getOrAddOldVertex(i2))\n } else if (keepCount === 1) {\n let keptIdx: number, discIdx1: number, discIdx2: number\n if (k0) { keptIdx = i0; discIdx1 = i1; discIdx2 = i2 }\n else if (k1) { keptIdx = i1; discIdx1 = i2; discIdx2 = i0 }\n else { keptIdx = i2; discIdx1 = i0; discIdx2 = i1 }\n newIndices.push(getOrAddOldVertex(keptIdx), getEdgeIntersection(keptIdx, discIdx1), getEdgeIntersection(keptIdx, discIdx2))\n } else {\n let discIdx: number, keptIdx1: number, keptIdx2: number\n if (!k0) { discIdx = i0; keptIdx1 = i1; keptIdx2 = i2 }\n else if (!k1) { discIdx = i1; keptIdx1 = i2; keptIdx2 = i0 }\n else { discIdx = i2; keptIdx1 = i0; keptIdx2 = i1 }\n const vK1 = getOrAddOldVertex(keptIdx1), vK2 = getOrAddOldVertex(keptIdx2)\n const vInt1 = getEdgeIntersection(keptIdx1, discIdx), vInt2 = getEdgeIntersection(keptIdx2, discIdx)\n newIndices.push(vK1, vInt1, vK2)\n newIndices.push(vK2, vInt1, vInt2)\n }\n }\n\n const numFaces = newIndices.length / 3\n\n let facesToKeep: number[]\n if (keepAllComponents) {\n // Keep every face on the kept side — needed for double-shell sockets where\n // inner and outer shells may be separate connected components.\n facesToKeep = Array.from({ length: numFaces }, (_, i) => i)\n } else {\n // Find connected components, keep the one closest to keepPoint\n const vtxToFaces = new Map<number, number[]>()\n for (let f = 0; f < numFaces; f++) {\n for (let j = 0; j < 3; j++) {\n const vi = newIndices[f * 3 + j]\n if (!vtxToFaces.has(vi)) vtxToFaces.set(vi, [])\n vtxToFaces.get(vi)!.push(f)\n }\n }\n const visitedFaces = new Set<number>()\n const components: number[][] = []\n for (let f = 0; f < numFaces; f++) {\n if (visitedFaces.has(f)) continue\n const comp: number[] = []\n const queue = [f]\n visitedFaces.add(f)\n while (queue.length > 0) {\n const cur = queue.shift()!\n comp.push(cur)\n for (let j = 0; j < 3; j++) {\n const vi = newIndices[cur * 3 + j]\n for (const neighbor of vtxToFaces.get(vi)!) {\n if (!visitedFaces.has(neighbor)) { visitedFaces.add(neighbor); queue.push(neighbor) }\n }\n }\n }\n components.push(comp)\n }\n let bestComp = components[0] || []\n let bestCompDist = Infinity\n for (const comp of components) {\n let minDist = Infinity\n for (const fIdx of comp) {\n for (let j = 0; j < 3; j++) {\n const vi = newIndices[fIdx * 3 + j]\n const dx = newPositions[vi * 3] - keepPoint.x\n const dy = newPositions[vi * 3 + 1] - keepPoint.y\n const dz = newPositions[vi * 3 + 2] - keepPoint.z\n const d = dx * dx + dy * dy + dz * dz\n if (d < minDist) minDist = d\n }\n if (minDist < bestCompDist) break\n }\n if (minDist < bestCompDist) { bestCompDist = minDist; bestComp = comp }\n }\n facesToKeep = bestComp\n }\n\n const finalVMap = new Map<number, number>()\n const finalPos: number[] = []\n const finalCol: number[] = []\n const finalIdx: number[] = []\n let nextVtx = 0\n for (const fIdx of facesToKeep) {\n for (let j = 0; j < 3; j++) {\n const oldV = newIndices[fIdx * 3 + j]\n if (!finalVMap.has(oldV)) {\n finalPos.push(newPositions[oldV * 3], newPositions[oldV * 3 + 1], newPositions[oldV * 3 + 2])\n if (oldColors) finalCol.push(newColors[oldV * 3], newColors[oldV * 3 + 1], newColors[oldV * 3 + 2])\n finalVMap.set(oldV, nextVtx++)\n }\n finalIdx.push(finalVMap.get(oldV)!)\n }\n }\n\n const newGeo = new THREE.BufferGeometry()\n newGeo.setAttribute(\"position\", new THREE.Float32BufferAttribute(finalPos, 3))\n if (oldColors && finalCol.length > 0) newGeo.setAttribute(\"color\", new THREE.Float32BufferAttribute(finalCol, 3))\n newGeo.setIndex(finalIdx)\n newGeo.computeVertexNormals()\n newGeo.computeBoundingBox()\n return newGeo\n}\n","import * as THREE from \"three\"\nimport { Vector3 } from \"three\"\n\n/** Run PCA alignment on a region from minY to maxY. Returns the principal axis or null. */\nexport function runPCAOnRegion(geometry: THREE.BufferGeometry, minY: number, maxY: number): Vector3 | null {\n const posAttr = geometry.getAttribute(\"position\")\n const regionHeight = maxY - minY\n if (regionHeight < 1) return null\n\n const numSlices = 30\n const sliceHeight = regionHeight / numSlices\n const centroids: Vector3[] = []\n\n for (let s = 0; s < numSlices; s++) {\n const sliceMinY = minY + s * sliceHeight\n const sliceMaxY = minY + (s + 1) * sliceHeight\n let sumX = 0, sumY = 0, sumZ = 0, count = 0\n for (let i = 0; i < posAttr.count; i++) {\n const y = posAttr.getY(i)\n if (y >= sliceMinY && y < sliceMaxY) { sumX += posAttr.getX(i); sumY += y; sumZ += posAttr.getZ(i); count++ }\n }\n if (count > 20) centroids.push(new Vector3(sumX / count, sumY / count, sumZ / count))\n }\n\n if (centroids.length < 5) return null\n\n const centroidMean = new Vector3()\n for (const c of centroids) centroidMean.add(c)\n centroidMean.divideScalar(centroids.length)\n\n let cxx = 0, cxy = 0, cxz = 0, cyy = 0, cyz = 0, czz = 0\n for (const c of centroids) {\n const dx = c.x - centroidMean.x, dy = c.y - centroidMean.y, dz = c.z - centroidMean.z\n cxx += dx * dx; cxy += dx * dy; cxz += dx * dz; cyy += dy * dy; cyz += dy * dz; czz += dz * dz\n }\n\n let axis = new Vector3(0.01, 1, 0.01).normalize()\n for (let pi = 0; pi < 30; pi++) {\n const nx = cxx * axis.x + cxy * axis.y + cxz * axis.z\n const ny = cxy * axis.x + cyy * axis.y + cyz * axis.z\n const nz = cxz * axis.x + cyz * axis.y + czz * axis.z\n const newAxis = new Vector3(nx, ny, nz)\n const len = newAxis.length()\n if (len < 1e-10) break\n newAxis.divideScalar(len)\n if (axis.distanceTo(newAxis) < 1e-8) break\n axis = newAxis\n }\n\n if (axis.y < 0) axis.negate()\n return axis\n}\n","import * as THREE from \"three\"\nimport { MeshBVH } from \"three-mesh-bvh\"\nimport { BVH_MAX_LEAF_TRIS } from \"./constants\"\nimport { computeSliceAtY } from \"./slice\"\n\n/** Validate processing results: check geometry is non-empty, height, and circumference ratios */\nexport function validateProcessingResult(\n finalGeometry: THREE.BufferGeometry,\n greenY: number,\n redY: number,\n spacing: number\n): { valid: boolean; reason: string } {\n const indexAttr = finalGeometry.getIndex()\n const faceCount = indexAttr ? indexAttr.count / 3 : 0\n if (faceCount < 10) return { valid: false, reason: `Geometry is empty or degenerate (${faceCount} faces)` }\n\n const height = greenY - redY\n if (height < 4) return { valid: false, reason: `Height too small (${height.toFixed(1)}mm < 4mm)` }\n if (height > 1000) return { valid: false, reason: `Height too large (${height.toFixed(1)}mm > 1000mm)` }\n\n const bvh = new MeshBVH(finalGeometry, { maxLeafTris: BVH_MAX_LEAF_TRIS })\n const firstSlice = computeSliceAtY(bvh, finalGeometry, greenY)\n if (firstSlice.lineLength === 0) return { valid: false, reason: \"No circumference at green point — mesh may be empty at that height\" }\n\n const secondSliceY = greenY - spacing\n if (secondSliceY <= redY) return { valid: true, reason: \"\" }\n const secondSlice = computeSliceAtY(bvh, finalGeometry, secondSliceY)\n\n if (firstSlice.lineLength > 0 && secondSlice.lineLength > 0) {\n const ratio = firstSlice.lineLength / secondSlice.lineLength\n if (ratio < 0.5) {\n return { valid: false, reason: `First circumference is too small relative to second (ratio ${ratio.toFixed(2)} < 0.5) — possible trimmed angle` }\n }\n }\n\n const thirdSliceY = greenY - spacing * 2\n if (thirdSliceY > redY) {\n const thirdSlice = computeSliceAtY(bvh, finalGeometry, thirdSliceY)\n if (secondSlice.lineLength > 0 && thirdSlice.lineLength > 0) {\n const ratio23 = secondSlice.lineLength / thirdSlice.lineLength\n if (ratio23 < 0.5) {\n return { valid: false, reason: `Second circumference is too small relative to third (ratio ${ratio23.toFixed(2)} < 0.5) — possible trimmed angle` }\n }\n }\n }\n\n return { valid: true, reason: \"\" }\n}\n","import * as THREE from \"three\"\nimport { Vector3, Quaternion, Matrix4 } from \"three\"\nimport { MM_PER_INCH } from \"./constants\"\nimport { findBestCutPlane } from \"./cut-plane\"\nimport { sliceMeshAtPlane, detectDoubleShell } from \"./mesh-ops\"\nimport { runPCAOnRegion } from \"./alignment\"\nimport { buildBVH, computeCircumferenceAtPlane } from \"./slice\"\nimport { validateProcessingResult } from \"./validation\"\n\nexport interface PipelineCallbacks {\n onStatus: (message: string) => void\n setDoubleShell?: (isDoubleShell: boolean) => void\n /** When true, skip double-shell detection (inner shell was already extracted during WASM processing) */\n skipDoubleShellDetection?: boolean\n addLandmarkPoint: (point: { faceIndex: number; vertexIndices: [number, number, number]; position: { x: number; y: number; z: number }; barycentricCoords: { u: number; v: number; w: number } }) => void\n removeLandmarkPoint: (index: number) => void\n updateLandmarkPositions: (positions: { x: number; y: number; z: number }[]) => void\n setAligned: (aligned: boolean) => void\n setCut: (cut: boolean) => void\n setModelSize: (size: number) => void\n setOriginalEndY: (y: number) => void\n setAdjustedStartY: (y: number | null) => void\n setAdjustedEndY: (y: number | null) => void\n setError: (error: string | null) => void\n setClippedReferenceGeometry?: (geometry: THREE.BufferGeometry | null) => void\n}\n\ninterface RetryStrategy {\n nudge: number\n angle: number\n cutOffset: number\n}\n\nconst RETRY_STRATEGIES: RetryStrategy[] = [\n { nudge: 3, angle: 0, cutOffset: 5 },\n { nudge: 5, angle: Math.PI * 2 / 3, cutOffset: 3 },\n { nudge: 8, angle: Math.PI * 4 / 3, cutOffset: 4 },\n { nudge: -5, angle: 0, cutOffset: 6 },\n]\n\nconst MAX_RETRIES = 5\n\nfunction applyRotation(\n geometry: THREE.BufferGeometry,\n landmarks: Vector3[],\n axis: Vector3,\n angle: number\n): Vector3[] {\n const q = new Quaternion().setFromAxisAngle(axis, angle)\n geometry.applyMatrix4(new Matrix4().makeRotationFromQuaternion(q))\n return landmarks.map(p => p.clone().applyQuaternion(q))\n}\n\n/** Apply rotation to a geometry without landmarks */\nfunction rotateGeometry(geometry: THREE.BufferGeometry, axis: Vector3, angle: number): void {\n const q = new Quaternion().setFromAxisAngle(axis, angle)\n geometry.applyMatrix4(new Matrix4().makeRotationFromQuaternion(q))\n}\n\n/** Cut mesh at Y-plane, keep geometry below cutY, keep largest component closest to redPoint */\nexport function cutMeshAtY(\n mesh: THREE.Mesh,\n currentLandmarks: Vector3[],\n geometry: THREE.BufferGeometry,\n cutOffsetInches: number,\n callbacks: PipelineCallbacks,\n refGeo?: THREE.BufferGeometry | null\n): Vector3[] {\n const positionAttr = geometry.getAttribute(\"position\")\n const index = geometry.getIndex()\n if (!index) return currentLandmarks\n\n const greenY = currentLandmarks[1].y\n const cutY = greenY + cutOffsetInches * MM_PER_INCH\n\n const oldPositions = positionAttr.array as Float32Array\n const oldIndices = index.array\n const colorAttrCut = geometry.getAttribute(\"color\")\n const oldColorsCut = colorAttrCut ? (colorAttrCut.array as Float32Array) : null\n const newPositions: number[] = []\n const newColorsCut: number[] = []\n const newIndices: number[] = []\n\n const addVertex = (x: number, y: number, z: number): number => { const idx = newPositions.length / 3; newPositions.push(x, y, z); return idx }\n const getVertex = (idx: number): [number, number, number] => [oldPositions[idx * 3], oldPositions[idx * 3 + 1], oldPositions[idx * 3 + 2]]\n const interpolateAtPlane = (v1: [number, number, number], v2: [number, number, number]): [number, number, number] => {\n const t = (cutY - v1[1]) / (v2[1] - v1[1])\n return [v1[0] + t * (v2[0] - v1[0]), cutY, v1[2] + t * (v2[2] - v1[2])]\n }\n\n const vertexCache = new Map<number, number>()\n const edgeCache = new Map<string, number>()\n\n const getOrAddOldVertex = (oldIdx: number): number => {\n if (vertexCache.has(oldIdx)) return vertexCache.get(oldIdx)!\n const [x, y, z] = getVertex(oldIdx)\n const newIdx = addVertex(x, y, z)\n if (oldColorsCut) newColorsCut.push(oldColorsCut[oldIdx * 3], oldColorsCut[oldIdx * 3 + 1], oldColorsCut[oldIdx * 3 + 2])\n vertexCache.set(oldIdx, newIdx)\n return newIdx\n }\n\n const getEdgeIntersection = (idx1: number, idx2: number): number => {\n const key = idx1 < idx2 ? `${idx1}_${idx2}` : `${idx2}_${idx1}`\n if (edgeCache.has(key)) return edgeCache.get(key)!\n const v1 = getVertex(idx1), v2 = getVertex(idx2)\n const [x, y, z] = interpolateAtPlane(v1, v2)\n const newIdx = addVertex(x, y, z)\n if (oldColorsCut) {\n const t = (cutY - v1[1]) / (v2[1] - v1[1])\n newColorsCut.push(\n oldColorsCut[idx1 * 3] + t * (oldColorsCut[idx2 * 3] - oldColorsCut[idx1 * 3]),\n oldColorsCut[idx1 * 3 + 1] + t * (oldColorsCut[idx2 * 3 + 1] - oldColorsCut[idx1 * 3 + 1]),\n oldColorsCut[idx1 * 3 + 2] + t * (oldColorsCut[idx2 * 3 + 2] - oldColorsCut[idx1 * 3 + 2])\n )\n }\n edgeCache.set(key, newIdx)\n return newIdx\n }\n\n for (let i = 0; i < oldIndices.length; i += 3) {\n const i0 = oldIndices[i], i1 = oldIndices[i + 1], i2 = oldIndices[i + 2]\n const v0 = getVertex(i0), v1 = getVertex(i1), v2 = getVertex(i2)\n const below0 = v0[1] < cutY, below1 = v1[1] < cutY, below2 = v2[1] < cutY\n const belowCount = (below0 ? 1 : 0) + (below1 ? 1 : 0) + (below2 ? 1 : 0)\n\n if (belowCount === 0) continue\n else if (belowCount === 3) {\n newIndices.push(getOrAddOldVertex(i0), getOrAddOldVertex(i1), getOrAddOldVertex(i2))\n } else if (belowCount === 1) {\n let belowIdx: number, above1Idx: number, above2Idx: number\n if (below0) { belowIdx = i0; above1Idx = i1; above2Idx = i2 }\n else if (below1) { belowIdx = i1; above1Idx = i2; above2Idx = i0 }\n else { belowIdx = i2; above1Idx = i0; above2Idx = i1 }\n newIndices.push(getOrAddOldVertex(belowIdx), getEdgeIntersection(belowIdx, above1Idx), getEdgeIntersection(belowIdx, above2Idx))\n } else {\n let aboveIdx: number, below1Idx: number, below2Idx: number\n if (!below0) { aboveIdx = i0; below1Idx = i1; below2Idx = i2 }\n else if (!below1) { aboveIdx = i1; below1Idx = i2; below2Idx = i0 }\n else { aboveIdx = i2; below1Idx = i0; below2Idx = i1 }\n const vBelow1 = getOrAddOldVertex(below1Idx), vBelow2 = getOrAddOldVertex(below2Idx)\n const vInt1 = getEdgeIntersection(below1Idx, aboveIdx), vInt2 = getEdgeIntersection(below2Idx, aboveIdx)\n newIndices.push(vBelow1, vInt1, vBelow2)\n newIndices.push(vBelow2, vInt1, vInt2)\n }\n }\n\n // Keep largest component closest to red point\n const numFaces = newIndices.length / 3\n const vertexToFaces = new Map<number, number[]>()\n for (let f = 0; f < numFaces; f++) {\n for (let j = 0; j < 3; j++) {\n const v = newIndices[f * 3 + j]\n if (!vertexToFaces.has(v)) vertexToFaces.set(v, [])\n vertexToFaces.get(v)!.push(f)\n }\n }\n\n const faceAdjacency = new Map<number, Set<number>>()\n for (let f = 0; f < numFaces; f++) faceAdjacency.set(f, new Set())\n for (const [, faces] of vertexToFaces) {\n for (const f1 of faces) for (const f2 of faces) if (f1 !== f2) faceAdjacency.get(f1)!.add(f2)\n }\n\n const visited = new Set<number>()\n const components: number[][] = []\n for (let f = 0; f < numFaces; f++) {\n if (visited.has(f)) continue\n const component: number[] = []\n const queue = [f]\n visited.add(f)\n while (queue.length > 0) {\n const current = queue.shift()!\n component.push(current)\n for (const neighbor of faceAdjacency.get(current)!) {\n if (!visited.has(neighbor)) { visited.add(neighbor); queue.push(neighbor) }\n }\n }\n components.push(component)\n }\n\n const redPt = currentLandmarks[0]\n let bestComponent = components[0] || []\n let bestCompDist = Infinity\n for (const comp of components) {\n let minDist = Infinity\n for (const fIdx of comp) {\n for (let j2 = 0; j2 < 3; j2++) {\n const vi = newIndices[fIdx * 3 + j2]\n const dx = newPositions[vi * 3] - redPt.x\n const dy = newPositions[vi * 3 + 1] - redPt.y\n const dz = newPositions[vi * 3 + 2] - redPt.z\n const d = dx * dx + dy * dy + dz * dz\n if (d < minDist) minDist = d\n }\n if (minDist < bestCompDist) break\n }\n if (minDist < bestCompDist) { bestCompDist = minDist; bestComponent = comp }\n }\n\n const finalVertexMap = new Map<number, number>()\n const finalPositions: number[] = []\n const finalColorsCut: number[] = []\n const finalIndices: number[] = []\n let finalVertexIndex = 0\n\n for (const faceIdx of bestComponent) {\n for (let j = 0; j < 3; j++) {\n const oldV = newIndices[faceIdx * 3 + j]\n if (!finalVertexMap.has(oldV)) {\n finalPositions.push(newPositions[oldV * 3], newPositions[oldV * 3 + 1], newPositions[oldV * 3 + 2])\n if (oldColorsCut) finalColorsCut.push(newColorsCut[oldV * 3], newColorsCut[oldV * 3 + 1], newColorsCut[oldV * 3 + 2])\n finalVertexMap.set(oldV, finalVertexIndex++)\n }\n finalIndices.push(finalVertexMap.get(oldV)!)\n }\n }\n\n const newGeometry = new THREE.BufferGeometry()\n newGeometry.setAttribute(\"position\", new THREE.Float32BufferAttribute(finalPositions, 3))\n if (oldColorsCut && finalColorsCut.length > 0) newGeometry.setAttribute(\"color\", new THREE.Float32BufferAttribute(finalColorsCut, 3))\n newGeometry.setIndex(finalIndices)\n newGeometry.computeVertexNormals()\n newGeometry.computeBoundingBox()\n\n mesh.geometry.dispose()\n mesh.geometry = newGeometry\n\n // Post-cut PCA refinement\n callbacks.onStatus(\"Refining alignment...\")\n const targetY = new Vector3(0, 1, 0)\n let landmarks = [...currentLandmarks]\n\n const rotate = (axis: Vector3, angle: number) => {\n landmarks = applyRotation(newGeometry, landmarks, axis, angle)\n if (refGeo) rotateGeometry(refGeo, axis, angle)\n }\n\n for (let iter = 0; iter < 5; iter++) {\n const positionAttrNew = newGeometry.getAttribute(\"position\")\n const minY = Math.min(landmarks[0].y, landmarks[1].y)\n const maxY = Math.max(landmarks[0].y, landmarks[1].y)\n const regionHeight = maxY - minY\n if (regionHeight < 1) break\n\n const numSlices = 30\n const sliceHeight = regionHeight / numSlices\n const centroids: Vector3[] = []\n\n for (let s = 0; s < numSlices; s++) {\n const sliceMinY = minY + s * sliceHeight\n const sliceMaxY = minY + (s + 1) * sliceHeight\n let sumX = 0, sumY = 0, sumZ = 0, count = 0\n for (let i = 0; i < positionAttrNew.count; i++) {\n const y = positionAttrNew.getY(i)\n if (y >= sliceMinY && y < sliceMaxY) { sumX += positionAttrNew.getX(i); sumY += y; sumZ += positionAttrNew.getZ(i); count++ }\n }\n if (count > 20) centroids.push(new Vector3(sumX / count, sumY / count, sumZ / count))\n }\n\n if (centroids.length < 5) break\n\n const centroidMean = new Vector3()\n for (const c of centroids) centroidMean.add(c)\n centroidMean.divideScalar(centroids.length)\n\n let cxx = 0, cxy = 0, cxz = 0, cyy = 0, cyz = 0, czz = 0\n for (const c of centroids) {\n const dx = c.x - centroidMean.x, dy = c.y - centroidMean.y, dz = c.z - centroidMean.z\n cxx += dx * dx; cxy += dx * dy; cxz += dx * dz; cyy += dy * dy; cyz += dy * dz; czz += dz * dz\n }\n\n let axis = new Vector3(0.01, 1, 0.01).normalize()\n for (let pi = 0; pi < 30; pi++) {\n const nx = cxx * axis.x + cxy * axis.y + cxz * axis.z\n const ny = cxy * axis.x + cyy * axis.y + cyz * axis.z\n const nz = cxz * axis.x + cyz * axis.y + czz * axis.z\n const newAxis = new Vector3(nx, ny, nz)\n const len = newAxis.length()\n if (len < 1e-10) break\n newAxis.divideScalar(len)\n if (axis.distanceTo(newAxis) < 1e-8) break\n axis = newAxis\n }\n\n if (axis.y < 0) axis.negate()\n const dot = axis.dot(targetY)\n if (Math.acos(Math.min(1, Math.abs(dot))) * 180 / Math.PI < 0.1) break\n\n const rotAxis = new Vector3().crossVectors(axis, targetY)\n if (rotAxis.length() > 0.0001) {\n rotAxis.normalize()\n rotate(rotAxis, Math.acos(Math.min(1, Math.max(-1, dot))))\n }\n }\n\n if (landmarks[0].y > landmarks[1].y) rotate(new Vector3(1, 0, 0), Math.PI)\n\n const finalRed = landmarks[0]\n newGeometry.translate(-finalRed.x, -finalRed.y, -finalRed.z)\n if (refGeo) refGeo.translate(-finalRed.x, -finalRed.y, -finalRed.z)\n landmarks = landmarks.map(p => new Vector3(p.x - finalRed.x, p.y - finalRed.y, p.z - finalRed.z))\n\n // Re-trim after PCA rotation\n const ABOVE_POINT_OFFSET = 5\n const reTrimY = landmarks[1].y + ABOVE_POINT_OFFSET * MM_PER_INCH\n const reTrimGeo = sliceMeshAtPlane(\n newGeometry,\n new Vector3(0, reTrimY, 0),\n new Vector3(0, 1, 0),\n landmarks[0]\n )\n mesh.geometry.dispose()\n mesh.geometry = reTrimGeo\n\n reTrimGeo.computeVertexNormals()\n reTrimGeo.computeBoundingBox()\n\n callbacks.updateLandmarkPositions(landmarks.map(p => ({ x: p.x, y: p.y, z: p.z })))\n\n const box = reTrimGeo.boundingBox!\n const size = new Vector3(); box.getSize(size)\n callbacks.setModelSize(Math.max(size.x, size.y, size.z))\n\n callbacks.setCut(true)\n callbacks.setAdjustedStartY(null)\n callbacks.setAdjustedEndY(null)\n callbacks.setOriginalEndY(landmarks[1].y + 2 * MM_PER_INCH)\n\n return landmarks\n}\n\n/**\n * Pipeline for double-shell meshes.\n * No rotation or translation — mesh stays in its original (already-aligned) coordinate system.\n * Cuts horizontally at 2\" above the green point, then sets measurement bounds from\n * redPoint.y (blue/distal) up to greenPoint.y (brim), counting down from green.\n */\nfunction runDoubleShellPipeline(\n mesh: THREE.Mesh,\n originalLandmarkPositions: { position: { x: number; y: number; z: number } }[],\n measurementSpacingMm: number,\n callbacks: PipelineCallbacks\n): void {\n const landmarks = originalLandmarkPositions.map(p => new Vector3(p.position.x, p.position.y, p.position.z))\n const redPoint = landmarks[0]\n const greenPoint = landmarks[1]\n\n // Cut horizontally (Y-plane) at 2\" above green to cleanly trim the top\n callbacks.onStatus(\"Cutting double shell above green point...\")\n const cutY = greenPoint.y + 2 * MM_PER_INCH\n const cutOrigin = new Vector3(greenPoint.x, cutY, greenPoint.z)\n const geometry = mesh.geometry as THREE.BufferGeometry\n const slicedGeo = sliceMeshAtPlane(geometry, cutOrigin, new Vector3(0, 1, 0), redPoint, true)\n geometry.dispose()\n mesh.geometry = slicedGeo\n slicedGeo.computeVertexNormals()\n slicedGeo.computeBoundingBox()\n\n // Blue point at the red point (distal end), so measurements run from red down to green\n callbacks.onStatus(\"Setting blue point...\")\n callbacks.addLandmarkPoint({\n faceIndex: -1,\n vertexIndices: [0, 1, 2],\n position: { x: redPoint.x, y: redPoint.y, z: redPoint.z },\n barycentricCoords: { u: 0.33, v: 0.33, w: 0.34 },\n })\n landmarks.push(redPoint.clone())\n\n callbacks.updateLandmarkPositions(landmarks.map(p => ({ x: p.x, y: p.y, z: p.z })))\n callbacks.setAligned(true)\n callbacks.setCut(true)\n callbacks.setAdjustedStartY(null)\n callbacks.setAdjustedEndY(null)\n // Measurements count from greenPoint (brim) downward to redPoint (distal)\n callbacks.setOriginalEndY(greenPoint.y)\n\n const box = slicedGeo.boundingBox!\n const size = new Vector3()\n box.getSize(size)\n callbacks.setModelSize(Math.max(size.x, size.y, size.z))\n\n callbacks.onStatus(\"Validating results...\")\n const validation = validateProcessingResult(slicedGeo, greenPoint.y, redPoint.y, measurementSpacingMm)\n if (!validation.valid) {\n console.warn(`Double shell validation warning: ${validation.reason}`)\n }\n}\n\n/** Full processing pipeline: find cut plane, slice, align, PCA, cut, validate with retries */\nexport function runProcessingPipeline(\n mesh: THREE.Mesh,\n landmarkPoints: { position: { x: number; y: number; z: number } }[],\n measurementSpacingMm: number,\n callbacks: PipelineCallbacks\n): void {\n const originalGeometry = mesh.geometry.clone()\n const originalLandmarkPositions = landmarkPoints.map(p => ({ ...p }))\n const targetY = new Vector3(0, 1, 0)\n\n // If inner shell was already extracted during WASM processing, skip detection\n // and proceed with the normal single-shell pipeline.\n if (!callbacks.skipDoubleShellDetection) {\n const redPt = new Vector3(landmarkPoints[0].position.x, landmarkPoints[0].position.y, landmarkPoints[0].position.z)\n const greenPt = new Vector3(landmarkPoints[1].position.x, landmarkPoints[1].position.y, landmarkPoints[1].position.z)\n callbacks.onStatus(\"Detecting shell type...\")\n const shellResult = detectDoubleShell(mesh.geometry as THREE.BufferGeometry, redPt, greenPt)\n console.log(`Shell detection: ${shellResult.isDoubleShell ? \"DOUBLE\" : \"SINGLE\"} shell (${shellResult.opposingPairs} inward/${shellResult.sampledFaces} total faces, confidence ${(shellResult.confidence * 100).toFixed(0)}%)`)\n\n if (shellResult.isDoubleShell) {\n callbacks.setDoubleShell?.(true)\n runDoubleShellPipeline(mesh, originalLandmarkPositions, measurementSpacingMm, callbacks)\n if (callbacks.setClippedReferenceGeometry) {\n originalGeometry.computeVertexNormals()\n callbacks.setClippedReferenceGeometry(originalGeometry)\n } else {\n originalGeometry.dispose()\n }\n return\n }\n callbacks.setDoubleShell?.(false)\n } else {\n console.log(\"Skipping double-shell detection: inner shell already extracted\")\n }\n\n let lastFailReason = \"\"\n\n for (let attempt = 0; attempt < MAX_RETRIES; attempt++) {\n try {\n if (attempt > 0) {\n callbacks.onStatus(`Retry ${attempt}/${MAX_RETRIES - 1} — ${lastFailReason}`)\n mesh.geometry.dispose()\n mesh.geometry = originalGeometry.clone()\n callbacks.removeLandmarkPoint(2)\n callbacks.setAligned(false)\n callbacks.setCut(false)\n }\n\n let geometry = mesh.geometry as THREE.BufferGeometry\n let currentLandmarks = originalLandmarkPositions.map(p => new Vector3(p.position.x, p.position.y, p.position.z))\n\n // Reference geometry: clone of original that receives the same rotations/translations (but not cuts)\n const refGeo = callbacks.setClippedReferenceGeometry ? originalGeometry.clone() : null\n\n let cutOffsetInches = 5\n if (attempt > 0) {\n const strategy = RETRY_STRATEGIES[attempt - 1]\n cutOffsetInches = strategy.cutOffset\n const redToGreen = new Vector3().subVectors(currentLandmarks[1], currentLandmarks[0]).normalize()\n\n if (strategy.nudge < 0) {\n currentLandmarks[1].addScaledVector(redToGreen, strategy.nudge)\n } else {\n const perp = new Vector3()\n if (Math.abs(redToGreen.x) < 0.9) perp.crossVectors(redToGreen, new Vector3(1, 0, 0)).normalize()\n else perp.crossVectors(redToGreen, new Vector3(0, 0, 1)).normalize()\n perp.applyAxisAngle(redToGreen, strategy.angle)\n currentLandmarks[1].addScaledVector(perp, strategy.nudge)\n }\n\n const posAttr = geometry.getAttribute(\"position\")\n let bestDist = Infinity\n let bestIdx = 0\n for (let i = 0; i < posAttr.count; i++) {\n const dx = posAttr.getX(i) - currentLandmarks[1].x\n const dy = posAttr.getY(i) - currentLandmarks[1].y\n const dz = posAttr.getZ(i) - currentLandmarks[1].z\n const d = dx * dx + dy * dy + dz * dz\n if (d < bestDist) { bestDist = d; bestIdx = i }\n }\n currentLandmarks[1].set(posAttr.getX(bestIdx), posAttr.getY(bestIdx), posAttr.getZ(bestIdx))\n console.log(`Retry ${attempt}: nudge=${strategy.nudge}mm angle=${(strategy.angle * 180 / Math.PI).toFixed(0)}° cutOffset=${strategy.cutOffset}\" → green=(${currentLandmarks[1].x.toFixed(1)}, ${currentLandmarks[1].y.toFixed(1)}, ${currentLandmarks[1].z.toFixed(1)})`)\n }\n\n const rotate = (axis: Vector3, angle: number) => {\n currentLandmarks = applyRotation(geometry, currentLandmarks, axis, angle)\n if (refGeo) rotateGeometry(refGeo, axis, angle)\n }\n\n // Step 1: find_cut_plane\n const redPoint = currentLandmarks[0]\n const greenPoint = currentLandmarks[1]\n const { normal: cutNormal } = findBestCutPlane(geometry, greenPoint, redPoint)\n\n // Step 2: slice_at_plane\n callbacks.onStatus(attempt > 0 ? `Retry ${attempt}: Slicing mesh...` : \"Slicing mesh at cut plane...\")\n const awayDir = new Vector3().subVectors(greenPoint, redPoint).normalize()\n const offsetSign = Math.sign(awayDir.dot(cutNormal))\n const planeOrigin = greenPoint.clone().addScaledVector(cutNormal, offsetSign * cutOffsetInches * MM_PER_INCH)\n const slicedGeo = sliceMeshAtPlane(geometry, planeOrigin, cutNormal, redPoint)\n geometry.dispose()\n geometry = slicedGeo\n mesh.geometry = geometry\n\n // Step 3: rough_align\n callbacks.onStatus(attempt > 0 ? `Retry ${attempt}: Rough alignment...` : \"Rough alignment...\")\n const roughAxis = new Vector3().subVectors(currentLandmarks[1], currentLandmarks[0]).normalize()\n let dot = roughAxis.dot(targetY)\n let rotAxis = new Vector3().crossVectors(roughAxis, targetY)\n if (rotAxis.length() > 0.0001) {\n rotAxis.normalize()\n rotate(rotAxis, Math.acos(Math.min(1, Math.max(-1, dot))))\n }\n if (currentLandmarks[0].y > currentLandmarks[1].y) {\n rotate(new Vector3(1, 0, 0), Math.PI)\n }\n geometry.computeVertexNormals()\n\n // Step 4: translate_origin\n callbacks.onStatus(attempt > 0 ? `Retry ${attempt}: Translating...` : \"Translating to origin...\")\n const origin = currentLandmarks[0].clone()\n geometry.translate(-origin.x, -origin.y, -origin.z)\n if (refGeo) refGeo.translate(-origin.x, -origin.y, -origin.z)\n currentLandmarks = currentLandmarks.map(p => new Vector3(p.x - origin.x, p.y - origin.y, p.z - origin.z))\n\n // Step 4.5: isolate_limb_region\n // Scan circumferences upward from green to detect body junction (pelvis/torso).\n // When circumference suddenly jumps, cut there to isolate the limb.\n callbacks.onStatus(attempt > 0 ? `Retry ${attempt}: Isolating limb...` : \"Isolating limb region...\")\n {\n const isoBvh = buildBVH(geometry)\n const isoRedY = currentLandmarks[0].y\n const isoGreenY = currentLandmarks[1].y\n const yUp = new Vector3(0, 1, 0)\n const SCAN_STEP = 5\n\n // Scan circumferences from red upward\n geometry.computeBoundingBox()\n const isoMaxY = geometry.boundingBox!.max.y\n const circumferences: { y: number; circ: number }[] = []\n\n for (let y = isoRedY + SCAN_STEP; y < isoMaxY; y += SCAN_STEP) {\n const circ = computeCircumferenceAtPlane(isoBvh, geometry, new Vector3(0, y, 0), yUp)\n if (circ > 0) circumferences.push({ y, circ })\n }\n\n if (circumferences.length > 5) {\n // Baseline: median circumference in stable region (30-70% of limb span)\n const limbSpan = isoGreenY - isoRedY\n const stableMin = isoRedY + limbSpan * 0.3\n const stableMax = isoRedY + limbSpan * 0.7\n const stableSlices = circumferences.filter(s => s.y >= stableMin && s.y <= stableMax)\n\n if (stableSlices.length >= 3) {\n const stableCircs = stableSlices.map(s => s.circ).sort((a, b) => a - b)\n const baseline = stableCircs[Math.floor(stableCircs.length / 2)]\n\n // Scan from just below green upward: find sudden jump >60% above baseline\n const JUMP_THRESHOLD = 1.6\n let cutY: number | null = null\n\n for (const s of circumferences) {\n if (s.y < isoGreenY - SCAN_STEP * 2) continue\n if (s.circ > baseline * JUMP_THRESHOLD) {\n cutY = s.y - SCAN_STEP\n break\n }\n }\n\n // Also check for lateral anomaly: if circumference at green level is\n // already way above baseline, scan downward to find where it normalizes\n if (cutY === null) {\n const greenSlice = circumferences.find(s => Math.abs(s.y - isoGreenY) < SCAN_STEP)\n if (greenSlice && greenSlice.circ > baseline * JUMP_THRESHOLD) {\n // Scan downward from green to find where it drops back to normal\n for (let i = circumferences.length - 1; i >= 0; i--) {\n if (circumferences[i].y > isoGreenY + SCAN_STEP) continue\n if (circumferences[i].circ <= baseline * JUMP_THRESHOLD) {\n cutY = circumferences[i].y + SCAN_STEP\n break\n }\n }\n }\n }\n\n if (cutY !== null && cutY > isoRedY + limbSpan * 0.5) {\n console.log(`Limb isolation: cutting at Y=${cutY.toFixed(1)}mm (baseline circ=${baseline.toFixed(1)}mm, threshold=${(baseline * JUMP_THRESHOLD).toFixed(1)}mm)`)\n const slicedGeo = sliceMeshAtPlane(\n geometry,\n new Vector3(0, cutY, 0),\n yUp,\n currentLandmarks[0] // keep side with red point\n )\n geometry.dispose()\n geometry = slicedGeo\n mesh.geometry = geometry\n geometry.computeVertexNormals()\n geometry.computeBoundingBox()\n } else {\n console.log(`Limb isolation: no anomaly detected (baseline=${baseline.toFixed(1)}mm)`)\n }\n }\n }\n }\n\n // Step 5: iterative_pca (top-down: green -> red)\n callbacks.onStatus(attempt > 0 ? `Retry ${attempt}: PCA alignment...` : \"Iterative PCA alignment...\")\n const STEP_SIZE = 10\n const MAX_ITERATIONS = 80\n const redY = currentLandmarks[0].y\n const greenY = currentLandmarks[1].y\n let currentHeight = greenY - STEP_SIZE\n\n for (let iteration = 0; iteration < MAX_ITERATIONS; iteration++) {\n const regionMin = Math.min(currentHeight, greenY)\n const regionMax = Math.max(currentHeight, greenY)\n const pcaAxis = runPCAOnRegion(geometry, regionMin, regionMax)\n\n if (pcaAxis) {\n dot = pcaAxis.dot(targetY)\n const angleDeg = Math.acos(Math.min(1, Math.abs(dot))) * 180 / Math.PI\n if (angleDeg > 0.1) {\n rotAxis = new Vector3().crossVectors(pcaAxis, targetY)\n if (rotAxis.length() > 0.0001) {\n rotAxis.normalize()\n rotate(rotAxis, Math.acos(Math.min(1, Math.max(-1, dot))))\n const newOrigin = currentLandmarks[0].clone()\n geometry.translate(-newOrigin.x, -newOrigin.y, -newOrigin.z)\n if (refGeo) refGeo.translate(-newOrigin.x, -newOrigin.y, -newOrigin.z)\n currentLandmarks = currentLandmarks.map(p => new Vector3(p.x - newOrigin.x, p.y - newOrigin.y, p.z - newOrigin.z))\n }\n }\n }\n\n currentHeight -= STEP_SIZE\n if (currentHeight <= redY) break\n }\n geometry.computeVertexNormals()\n\n // Step 6: set_blue_point\n callbacks.onStatus(attempt > 0 ? `Retry ${attempt}: Setting blue point...` : \"Setting blue point...\")\n const bluePoint = new Vector3(currentLandmarks[0].x, currentLandmarks[0].y, currentLandmarks[0].z)\n currentLandmarks.push(bluePoint)\n callbacks.addLandmarkPoint({\n faceIndex: -1,\n vertexIndices: [0, 1, 2],\n position: { x: bluePoint.x, y: bluePoint.y, z: bluePoint.z },\n barycentricCoords: { u: 0.33, v: 0.33, w: 0.34 },\n })\n\n // Step 7: final_pca\n callbacks.onStatus(attempt > 0 ? `Retry ${attempt}: Final PCA...` : \"Final PCA refinement...\")\n for (let iter = 0; iter < 3; iter++) {\n const pcaAxis = runPCAOnRegion(geometry, 0, currentLandmarks[1].y)\n if (pcaAxis) {\n dot = pcaAxis.dot(targetY)\n const angleDeg = Math.acos(Math.min(1, Math.abs(dot))) * 180 / Math.PI\n if (angleDeg < 0.1) break\n rotAxis = new Vector3().crossVectors(pcaAxis, targetY)\n if (rotAxis.length() > 0.0001) {\n rotAxis.normalize()\n rotate(rotAxis, Math.acos(Math.min(1, Math.max(-1, dot))))\n const newOrigin = currentLandmarks[0].clone()\n geometry.translate(-newOrigin.x, -newOrigin.y, -newOrigin.z)\n if (refGeo) refGeo.translate(-newOrigin.x, -newOrigin.y, -newOrigin.z)\n currentLandmarks = currentLandmarks.map(p => new Vector3(p.x - newOrigin.x, p.y - newOrigin.y, p.z - newOrigin.z))\n }\n }\n }\n if (currentLandmarks[1].y < currentLandmarks[0].y) {\n rotate(new Vector3(1, 0, 0), Math.PI)\n const newOrigin = currentLandmarks[0].clone()\n geometry.translate(-newOrigin.x, -newOrigin.y, -newOrigin.z)\n if (refGeo) refGeo.translate(-newOrigin.x, -newOrigin.y, -newOrigin.z)\n currentLandmarks = currentLandmarks.map(p => new Vector3(p.x - newOrigin.x, p.y - newOrigin.y, p.z - newOrigin.z))\n }\n geometry.computeVertexNormals()\n geometry.computeBoundingBox()\n\n // Step 7.5: circumference_refinement\n // Take 3 slices 1\" apart below green, search for a small rotation that\n // minimizes total circumference → ensures slices are perpendicular to the true axis.\n callbacks.onStatus(attempt > 0 ? `Retry ${attempt}: Circumference refinement...` : \"Circumference refinement...\")\n {\n const bvh = buildBVH(geometry)\n const gY = currentLandmarks[1].y\n const rY = currentLandmarks[0].y\n // 3 slices 1\" apart below green, but above red\n const sliceYs = [gY - MM_PER_INCH, gY - 2 * MM_PER_INCH, gY - 3 * MM_PER_INCH]\n .filter(y => y > rY + 5)\n\n if (sliceYs.length >= 2) {\n const DEG = Math.PI / 180\n const totalCirc = (tiltX: number, tiltZ: number): number => {\n const n = new Vector3(0, 1, 0)\n if (Math.abs(tiltX) > 1e-10) n.applyQuaternion(new Quaternion().setFromAxisAngle(new Vector3(1, 0, 0), tiltX))\n if (Math.abs(tiltZ) > 1e-10) n.applyQuaternion(new Quaternion().setFromAxisAngle(new Vector3(0, 0, 1), tiltZ))\n let sum = 0\n for (const y of sliceYs) sum += computeCircumferenceAtPlane(bvh, geometry, new Vector3(0, y, 0), n)\n return sum\n }\n\n let bestTX = 0, bestTZ = 0, bestC = totalCirc(0, 0)\n\n // Coarse search: ±3° in 0.5° steps\n for (let tx = -3; tx <= 3; tx += 0.5) {\n for (let tz = -3; tz <= 3; tz += 0.5) {\n const c = totalCirc(tx * DEG, tz * DEG)\n if (c > 0 && c < bestC) { bestC = c; bestTX = tx * DEG; bestTZ = tz * DEG }\n }\n }\n\n // Fine search: ±0.5° around best in 0.1° steps\n const cTX = bestTX, cTZ = bestTZ\n for (let tx = -5; tx <= 5; tx++) {\n for (let tz = -5; tz <= 5; tz++) {\n const tTX = cTX + tx * 0.1 * DEG, tTZ = cTZ + tz * 0.1 * DEG\n const c = totalCirc(tTX, tTZ)\n if (c > 0 && c < bestC) { bestC = c; bestTX = tTX; bestTZ = tTZ }\n }\n }\n\n const totalAngle = Math.sqrt(bestTX * bestTX + bestTZ * bestTZ)\n if (totalAngle > 0.05 * DEG) {\n console.log(`Circumference refinement: rotating ${(-bestTX / DEG).toFixed(2)}°X ${(-bestTZ / DEG).toFixed(2)}°Z`)\n // The optimal tilt = mesh axis offset from Y → rotate mesh opposite\n if (Math.abs(bestTX) > 0.01 * DEG) rotate(new Vector3(1, 0, 0), -bestTX)\n if (Math.abs(bestTZ) > 0.01 * DEG) rotate(new Vector3(0, 0, 1), -bestTZ)\n\n const newOrigin = currentLandmarks[0].clone()\n geometry.translate(-newOrigin.x, -newOrigin.y, -newOrigin.z)\n if (refGeo) refGeo.translate(-newOrigin.x, -newOrigin.y, -newOrigin.z)\n currentLandmarks = currentLandmarks.map(p => new Vector3(p.x - newOrigin.x, p.y - newOrigin.y, p.z - newOrigin.z))\n geometry.computeVertexNormals()\n } else {\n console.log(`Circumference refinement: already optimal (${(totalAngle / DEG).toFixed(3)}°)`)\n }\n }\n }\n\n const finalPositions = currentLandmarks.map(p => ({ x: p.x, y: p.y, z: p.z }))\n callbacks.updateLandmarkPositions(finalPositions)\n callbacks.setAligned(true)\n\n // Step 8: cut_mesh\n callbacks.onStatus(attempt > 0 ? `Retry ${attempt}: Cutting mesh...` : \"Cutting mesh 2\\\" above green...\")\n currentLandmarks = cutMeshAtY(mesh, currentLandmarks, geometry, 5, callbacks, refGeo)\n\n // Step 9: validate\n callbacks.onStatus(\"Validating results...\")\n const finalGeo = mesh.geometry as THREE.BufferGeometry\n const finalGreenY = currentLandmarks[1].y\n const finalRedY = currentLandmarks[0].y\n const validation = validateProcessingResult(finalGeo, finalGreenY, finalRedY, measurementSpacingMm)\n\n if (validation.valid) {\n console.log(`Processing succeeded on attempt ${attempt + 1}`)\n if (refGeo && callbacks.setClippedReferenceGeometry) {\n refGeo.computeVertexNormals()\n callbacks.setClippedReferenceGeometry(refGeo)\n }\n break\n }\n\n console.warn(`Attempt ${attempt + 1} failed validation: ${validation.reason}`)\n lastFailReason = validation.reason\n if (refGeo) refGeo.dispose()\n\n if (attempt === MAX_RETRIES - 1) {\n callbacks.setError(`Processing produced unusual results after ${MAX_RETRIES} attempts: ${validation.reason}`)\n mesh.geometry.dispose()\n mesh.geometry = originalGeometry.clone()\n callbacks.removeLandmarkPoint(2)\n callbacks.setAligned(false)\n callbacks.setCut(false)\n }\n\n } catch (err) {\n console.error(\"Processing failed:\", err)\n callbacks.setError(err instanceof Error ? err.message : \"Failed to process mesh.\")\n break\n }\n }\n\n originalGeometry.dispose()\n}\n","export const ErrorDisplay = ({ message, onDismiss }: { message: string; onDismiss: () => void }) => (\n <div style={{\n position: \"absolute\", top: 16, right: 16, padding: \"12px 16px\",\n backgroundColor: \"rgba(220, 53, 69, 0.95)\", borderRadius: 8, color: \"#fff\",\n fontSize: 14, maxWidth: 300, zIndex: 100, display: \"flex\", alignItems: \"flex-start\", gap: 12,\n }}>\n <div style={{ flex: 1 }}>\n <div style={{ fontWeight: \"bold\", marginBottom: 4 }}>Error</div>\n <div style={{ fontSize: 12, opacity: 0.9 }}>{message}</div>\n </div>\n <button onClick={onDismiss} style={{ background: \"none\", border: \"none\", color: \"#fff\", cursor: \"pointer\", fontSize: 18, padding: 0, lineHeight: 1, opacity: 0.7 }}>x</button>\n </div>\n)\n","export const LoadingSpinner = ({ message }: { message?: string }) => (\n <div style={{\n position: \"absolute\", top: 0, left: 0, right: 0, bottom: 0,\n backgroundColor: \"rgba(0, 0, 0, 0.7)\", display: \"flex\", flexDirection: \"column\",\n alignItems: \"center\", justifyContent: \"center\", zIndex: 100,\n }}>\n <div style={{ width: 48, height: 48, border: \"4px solid rgba(255, 255, 255, 0.2)\", borderTopColor: \"#4a90d9\", borderRadius: \"50%\", animation: \"spin 1s linear infinite\" }} />\n {message && <div style={{ marginTop: 16, color: \"#fff\", fontSize: 14 }}>{message}</div>}\n <style>{`@keyframes spin { to { transform: rotate(360deg); } }`}</style>\n </div>\n)\n","import { useCallback, useMemo } from \"react\"\nimport type { ThreeEvent } from \"@react-three/fiber\"\nimport * as THREE from \"three\"\nimport { Vector3 } from \"three\"\nimport { useMeasurementStore } from \"../store\"\nimport { computeBarycentricCoords } from \"../processing/mesh-ops\"\nimport type { LandmarkPoint } from \"../processing/types\"\n\nexport interface ClickableMeshProps {\n mesh: THREE.Mesh\n maxPoints?: number\n meshColor?: string\n meshOpacity?: number\n}\n\nexport const ClickableMesh = ({ mesh, maxPoints = 2, meshColor = \"#c8c8c8\", meshOpacity = 1 }: ClickableMeshProps) => {\n const { addLandmarkPoint, landmarkPoints } = useMeasurementStore()\n\n const handleClick = useCallback((event: ThreeEvent<MouseEvent>) => {\n if (landmarkPoints.length >= maxPoints) return\n event.stopPropagation()\n const intersection = event.intersections[0]\n const faceIndex = intersection?.faceIndex\n if (!intersection || faceIndex == null) return\n\n const geometry = mesh.geometry as THREE.BufferGeometry\n const index = geometry.index\n\n let vertexIndices: [number, number, number]\n if (index) {\n vertexIndices = [index.getX(faceIndex * 3), index.getX(faceIndex * 3 + 1), index.getX(faceIndex * 3 + 2)]\n } else {\n vertexIndices = [faceIndex * 3, faceIndex * 3 + 1, faceIndex * 3 + 2]\n }\n\n const positionAttr = geometry.getAttribute(\"position\")\n const v0 = new Vector3().fromBufferAttribute(positionAttr, vertexIndices[0])\n const v1 = new Vector3().fromBufferAttribute(positionAttr, vertexIndices[1])\n const v2 = new Vector3().fromBufferAttribute(positionAttr, vertexIndices[2])\n v0.applyMatrix4(mesh.matrixWorld)\n v1.applyMatrix4(mesh.matrixWorld)\n v2.applyMatrix4(mesh.matrixWorld)\n\n const point = intersection.point\n const bary = computeBarycentricCoords(point, v0, v1, v2)\n\n const landmarkPoint: LandmarkPoint = {\n faceIndex,\n vertexIndices,\n position: { x: point.x, y: point.y, z: point.z },\n barycentricCoords: bary,\n }\n addLandmarkPoint(landmarkPoint)\n }, [mesh, addLandmarkPoint, landmarkPoints.length, maxPoints])\n\n const hasVertexColors = useMemo(() => {\n const geometry = mesh.geometry as THREE.BufferGeometry\n return !!geometry.getAttribute(\"color\")\n }, [mesh])\n\n const material = useMemo(() => {\n return new THREE.MeshStandardMaterial({\n color: hasVertexColors ? \"#ffffff\" : meshColor,\n side: THREE.DoubleSide,\n roughness: 0.6,\n metalness: 0.1,\n transparent: meshOpacity < 1,\n opacity: meshOpacity,\n vertexColors: hasVertexColors,\n })\n }, [meshColor, meshOpacity, hasVertexColors])\n\n return (\n <primitive\n object={mesh}\n onClick={handleClick}\n material={material}\n />\n )\n}\n","import { useState } from \"react\"\nimport { Html } from \"@react-three/drei\"\nimport { useMeasurementStore } from \"../store\"\nimport type { LandmarkPoint } from \"../processing/types\"\n\nconst LandmarkMarker = ({ point, index, markerSize, color, label }: {\n point: LandmarkPoint; index: number; markerSize: number; color: string; label: string\n}) => {\n const [hovered, setHovered] = useState(false)\n return (\n <mesh\n key={index}\n position={[point.position.x, point.position.y, point.position.z]}\n onPointerOver={() => setHovered(true)}\n onPointerOut={() => setHovered(false)}\n >\n <sphereGeometry args={[markerSize, 16, 16]} />\n <meshBasicMaterial color={color} />\n {hovered && (\n <Html center style={{ pointerEvents: \"none\" }}>\n <div style={{\n padding: \"3px 8px\",\n backgroundColor: \"rgba(0, 0, 0, 0.75)\",\n borderRadius: 4,\n color: \"#fff\",\n fontSize: 12,\n fontFamily: \"system-ui, sans-serif\",\n whiteSpace: \"nowrap\",\n transform: \"translateY(-24px)\",\n }}>\n {label}\n </div>\n </Html>\n )}\n </mesh>\n )\n}\n\nexport interface LandmarkMarkersProps {\n modelSize: number\n labels?: string[]\n}\n\nexport const LandmarkMarkers = ({ modelSize, labels }: LandmarkMarkersProps) => {\n const { landmarkPoints } = useMeasurementStore()\n const markerSize = modelSize * 0.02\n const colors = [\"#ff4444\", \"#44ff44\", \"#4444ff\"]\n const defaultLabels = [\"Origin\", \"MPT\", \"Cut Plane\"]\n const resolvedLabels = labels ?? defaultLabels\n return (\n <>\n {landmarkPoints.map((point, index) => (\n <LandmarkMarker key={index} point={point} index={index} markerSize={markerSize} color={colors[index]} label={resolvedLabels[index]} />\n ))}\n </>\n )\n}\n","import { useMemo } from \"react\"\nimport * as THREE from \"three\"\nimport { MeshBVH } from \"three-mesh-bvh\"\nimport { BVH_MAX_LEAF_TRIS } from \"../processing/constants\"\n\nexport function useCachedBVH(geometry: THREE.BufferGeometry | null): MeshBVH | null {\n return useMemo(() => geometry ? new MeshBVH(geometry, { maxLeafTris: BVH_MAX_LEAF_TRIS }) : null, [geometry])\n}\n","import { useRef, useEffect, useMemo, memo } from \"react\"\nimport { useFrame } from \"@react-three/fiber\"\nimport { Html, Line } from \"@react-three/drei\"\nimport * as THREE from \"three\"\nimport { Vector3 } from \"three\"\nimport { MeshBVH } from \"three-mesh-bvh\"\nimport { computeSliceAtY } from \"../processing/slice\"\nimport type { MeasurementData } from \"../processing/types\"\n\nconst varianceColor = (scanValue: number, formValue: number): string => {\n const absDiff = Math.abs(scanValue - formValue)\n return absDiff < 1 ? \"#8BC34A\" : absDiff < 5 ? \"#FFC107\" : \"#FF5722\"\n}\n\n// green → yellow → red lerp based on local point distance\nconst GREEN = new THREE.Color(\"#8BC34A\")\nconst YELLOW = new THREE.Color(\"#FFC107\")\nconst RED = new THREE.Color(\"#FF5722\")\n\nconst varianceColorAt = (dist: number): THREE.Color => {\n if (dist < 1) return GREEN.clone()\n if (dist < 5) {\n const t = (dist - 1) / 4\n return GREEN.clone().lerp(YELLOW, t)\n }\n const t = Math.min((dist - 5) / 5, 1)\n return YELLOW.clone().lerp(RED, t)\n}\n\nconst buildRibbonMesh = (scanPts: Vector3[], formPts: Vector3[]): THREE.Mesh => {\n const n = scanPts.length\n const positions = new Float32Array(n * 2 * 3)\n const colors = new Float32Array(n * 2 * 3)\n const indices: number[] = []\n\n for (let i = 0; i < n; i++) {\n const s = scanPts[i], f = formPts[i]\n const dist = s.distanceTo(f)\n const c = varianceColorAt(dist)\n\n // scan vertex\n positions[i * 6] = s.x; positions[i * 6 + 1] = s.y; positions[i * 6 + 2] = s.z\n colors[i * 6] = c.r; colors[i * 6 + 1] = c.g; colors[i * 6 + 2] = c.b\n // form vertex\n positions[i * 6 + 3] = f.x; positions[i * 6 + 4] = f.y; positions[i * 6 + 5] = f.z\n colors[i * 6 + 3] = c.r; colors[i * 6 + 4] = c.g; colors[i * 6 + 5] = c.b\n\n if (i < n - 1) {\n const a = i * 2, b = a + 1, c2 = (i + 1) * 2, d = c2 + 1\n indices.push(a, b, c2, b, d, c2)\n }\n }\n\n const geom = new THREE.BufferGeometry()\n geom.setAttribute(\"position\", new THREE.Float32BufferAttribute(positions, 3))\n geom.setAttribute(\"color\", new THREE.Float32BufferAttribute(colors, 3))\n geom.setIndex(indices)\n\n const mat = new THREE.MeshBasicMaterial({\n vertexColors: true, transparent: true, opacity: 0.25,\n side: THREE.DoubleSide, depthTest: false, depthWrite: false,\n })\n return new THREE.Mesh(geom, mat)\n}\n\nexport interface CircumferenceSliceProps {\n bvh: MeshBVH; geometry: THREE.BufferGeometry; yPosition: number; color?: string; labelX: number\n onDataChange?: (data: MeasurementData) => void\n displayUnit?: \"mm\" | \"inch\"\n useInnerSurface?: boolean\n formValue?: number\n lineWidth?: number\n}\n\nconst CircumferenceSliceInner = ({ bvh, geometry, yPosition, color = \"#00ff00\", labelX, onDataChange, displayUnit = \"mm\", useInnerSurface = false, formValue, lineWidth = 1.5 }: CircumferenceSliceProps) => {\n const sliceData = useMemo(() => computeSliceAtY(bvh, geometry, yPosition, useInnerSurface), [bvh, geometry, yPosition, useInnerSurface])\n const { linePoints, lineLength } = sliceData\n\n const formRingPoints = useMemo(() => {\n if (formValue == null || lineLength <= 0 || linePoints.length < 2) return null\n const scale = formValue / lineLength\n const cx = linePoints.reduce((s, p) => s + p.x, 0) / linePoints.length\n const cz = linePoints.reduce((s, p) => s + p.z, 0) / linePoints.length\n return linePoints.map(pt => new Vector3(\n cx + (pt.x - cx) * scale,\n pt.y,\n cz + (pt.z - cz) * scale,\n ))\n }, [linePoints, lineLength, formValue])\n\n const ribbonMesh = useMemo(() => {\n if (!formRingPoints || linePoints.length < 2) return null\n return buildRibbonMesh(linePoints, formRingPoints)\n }, [linePoints, formRingPoints])\n\n useEffect(() => () => {\n if (ribbonMesh) {\n ribbonMesh.geometry.dispose()\n ;(ribbonMesh.material as THREE.Material).dispose()\n }\n }, [ribbonMesh])\n\n const labelGroupRef = useRef<THREE.Group>(null)\n const leaderLine = useMemo(() => {\n const geom = new THREE.BufferGeometry()\n geom.setAttribute('position', new THREE.Float32BufferAttribute(new Float32Array(6), 3))\n const mat = new THREE.LineBasicMaterial({ color: 0x666666, depthTest: false, depthWrite: false, transparent: true })\n return new THREE.Line(geom, mat)\n }, [])\n\n useEffect(() => () => {\n leaderLine.geometry.dispose()\n ; (leaderLine.material as THREE.Material).dispose()\n }, [leaderLine])\n\n useEffect(() => {\n if (lineLength > 0) onDataChange?.({ yPosition, originalValue: lineLength, modifiedValue: null })\n }, [lineLength, yPosition, onDataChange])\n\n useFrame(({ camera }) => {\n if (!labelGroupRef.current || linePoints.length < 2) return\n const forward = new Vector3()\n camera.getWorldDirection(forward)\n const forwardXZ = new Vector3(forward.x, 0, forward.z)\n if (forwardXZ.lengthSq() < 1e-8) return\n forwardXZ.normalize()\n const right = new Vector3().crossVectors(forwardXZ, new Vector3(0, 1, 0)).normalize()\n\n let maxProj = -Infinity\n let sidePoint = linePoints[0]\n for (const pt of linePoints) {\n const proj = right.x * pt.x + right.z * pt.z\n if (proj > maxProj) { maxProj = proj; sidePoint = pt }\n }\n\n const labelDist = labelX * 0.35\n const labelPos = new Vector3(\n sidePoint.x + right.x * labelDist,\n yPosition,\n sidePoint.z + right.z * labelDist\n )\n labelGroupRef.current.position.copy(labelPos)\n\n const posAttr = leaderLine.geometry.getAttribute('position') as THREE.BufferAttribute\n posAttr.setXYZ(0, sidePoint.x, sidePoint.y, sidePoint.z)\n posAttr.setXYZ(1, labelPos.x, labelPos.y, labelPos.z)\n posAttr.needsUpdate = true\n })\n\n if (linePoints.length < 2) return null\n\n return (\n <group>\n <Line points={linePoints} color={color} lineWidth={lineWidth} depthTest={false} depthWrite={false} transparent />\n {ribbonMesh && <primitive object={ribbonMesh} />}\n {formRingPoints && formValue != null && <Line points={formRingPoints} color={varianceColor(lineLength, formValue)} lineWidth={2.5} dashed dashSize={2} gapSize={1.5} depthTest={false} depthWrite={false} transparent opacity={0.8} />}\n <primitive object={leaderLine} />\n <group ref={labelGroupRef}>\n <Html zIndexRange={[100, 0]} style={{ pointerEvents: \"none\", transform: \"translateY(-50%)\" }}>\n <div style={{ display: \"flex\", alignItems: \"stretch\", gap: 0, marginLeft: 10, pointerEvents: \"none\", whiteSpace: \"nowrap\" }}>\n <div style={{\n display: \"flex\", alignItems: \"center\", gap: 4, padding: \"5px 10px\",\n backgroundColor: \"rgba(0, 0, 0, 0.75)\",\n borderRadius: formValue != null ? \"4px 0 0 4px\" : 4,\n }}>\n <span style={{ fontSize: 14, color: \"#fff\", fontFamily: \"monospace\", minWidth: 52, textAlign: \"right\" }}>{displayUnit === \"inch\" ? (lineLength / 25.4).toFixed(2) : lineLength.toFixed(1)}</span>\n <span style={{ fontSize: 11, color: \"rgba(255,255,255,0.6)\", fontFamily: \"monospace\" }}>{displayUnit === \"inch\" ? \"in\" : \"mm\"}</span>\n </div>\n {formValue != null && lineLength > 0 && (() => {\n const diff = lineLength - formValue\n const arrow = diff > 0.5 ? \"\\u25B2\" : diff < -0.5 ? \"\\u25BC\" : \"\"\n const diffColor = varianceColor(lineLength, formValue)\n return (\n <div style={{\n display: \"flex\", alignItems: \"center\", gap: 5, padding: \"5px 10px\",\n backgroundColor: \"rgba(0, 0, 0, 0.55)\",\n borderRadius: \"0 4px 4px 0\", borderLeft: \"1px solid rgba(255,255,255,0.12)\",\n }}>\n {arrow && <span style={{ fontSize: 10, color: diffColor, lineHeight: 1 }}>{arrow}</span>}\n <span style={{ fontSize: 13, color: diffColor, fontFamily: \"monospace\", fontWeight: 600 }}>\n {diff > 0 ? \"+\" : \"\"}{displayUnit === \"inch\" ? (diff / 25.4).toFixed(2) : diff.toFixed(1)}\n </span>\n <span style={{ fontSize: 11, color: \"rgba(255,255,255,0.4)\", fontFamily: \"monospace\" }}>\n form {displayUnit === \"inch\" ? (formValue / 25.4).toFixed(2) : formValue.toFixed(0)}\n </span>\n </div>\n )\n })()}\n </div>\n </Html>\n </group>\n </group>\n )\n}\n\nexport const CircumferenceSlice = memo(CircumferenceSliceInner)\n","import { useRef, useEffect, useMemo, useCallback } from \"react\"\nimport * as THREE from \"three\"\nimport { useCachedBVH } from \"../hooks/useCachedBVH\"\nimport { LABEL_X_OFFSET_RATIO } from \"../processing/constants\"\nimport { CircumferenceSlice } from \"./CircumferenceSlice\"\nimport type { MeasurementData } from \"../processing/types\"\n\nexport interface CircumferenceMeasurementsProps {\n mesh: THREE.Mesh; startY: number; endY: number; spacing: number; modelSize: number\n onMeasurementsChange?: (measurements: MeasurementData[]) => void\n reverseOrder?: boolean\n displayUnit?: \"mm\" | \"inch\"\n useInnerSurface?: boolean\n formMeasurements?: number[]\n originY?: number\n}\n\nexport const CircumferenceMeasurements = ({ mesh, startY, endY, spacing, modelSize, onMeasurementsChange, reverseOrder = false, displayUnit = \"mm\", useInnerSurface = false, formMeasurements, originY }: CircumferenceMeasurementsProps) => {\n const measurementsRef = useRef<Map<number, MeasurementData>>(new Map())\n const geometry = mesh.geometry as THREE.BufferGeometry\n const cachedBVH = useCachedBVH(geometry)\n\n const sliceYPositions = useMemo(() => {\n const positions: number[] = []\n if (reverseOrder) {\n for (let y = endY; y >= startY; y -= spacing) positions.push(y)\n } else {\n for (let y = startY; y <= endY; y += spacing) positions.push(y)\n }\n return positions\n }, [startY, endY, spacing, reverseOrder])\n\n useEffect(() => { measurementsRef.current.clear() }, [sliceYPositions])\n\n const colors = [\"#5B9BD5\"]\n const labelX = modelSize * LABEL_X_OFFSET_RATIO\n\n const handleSliceDataChange = useCallback((data: MeasurementData) => {\n measurementsRef.current.set(data.yPosition, data)\n const sortedMeasurements = Array.from(measurementsRef.current.values()).sort((a, b) =>\n reverseOrder ? b.yPosition - a.yPosition : a.yPosition - b.yPosition\n )\n onMeasurementsChange?.(sortedMeasurements)\n }, [onMeasurementsChange, reverseOrder])\n\n if (!cachedBVH) return null\n\n return (\n <>\n {sliceYPositions.map((y, index) => (\n <CircumferenceSlice key={y} bvh={cachedBVH} geometry={geometry} yPosition={y} color={originY != null && Math.abs(y - originY) < spacing * 0.5 ? \"#44ff44\" : colors[index % colors.length]} labelX={labelX} onDataChange={handleSliceDataChange} displayUnit={displayUnit} useInnerSurface={useInnerSurface} formValue={formMeasurements?.[index]} lineWidth={originY != null && Math.abs(y - originY) < spacing * 0.5 ? 4 : 1.5} />\n ))}\n </>\n )\n}\n","import { useRef } from \"react\"\nimport { useFrame } from \"@react-three/fiber\"\nimport { Html, Line } from \"@react-three/drei\"\nimport * as THREE from \"three\"\nimport { Vector3 } from \"three\"\n\nexport interface VerticalDimensionProps {\n mesh: THREE.Mesh\n greenY: number\n modelSize: number\n displayUnit?: \"mm\" | \"inch\"\n}\n\nexport const VerticalDimension = ({ mesh, greenY, modelSize, displayUnit = \"mm\" }: VerticalDimensionProps) => {\n const geometry = mesh.geometry as THREE.BufferGeometry\n geometry.computeBoundingBox()\n const minY = geometry.boundingBox?.min.y ?? 0\n const distance = greenY - minY\n\n const offset = modelSize * 0.4\n const tickSize = modelSize * 0.03\n const groupRef = useRef<THREE.Group>(null)\n\n useFrame(({ camera }) => {\n if (!groupRef.current) return\n const forward = new Vector3()\n camera.getWorldDirection(forward)\n const forwardXZ = new Vector3(forward.x, 0, forward.z)\n if (forwardXZ.lengthSq() < 1e-8) return\n forwardXZ.normalize()\n const left = new Vector3().crossVectors(new Vector3(0, 1, 0), forwardXZ).normalize()\n groupRef.current.position.set(left.x * offset, 0, left.z * offset)\n const dx = camera.position.x - groupRef.current.position.x\n const dz = camera.position.z - groupRef.current.position.z\n groupRef.current.rotation.y = Math.atan2(dx, dz)\n })\n\n const topPoint = new Vector3(0, greenY, 0)\n const bottomPoint = new Vector3(0, minY, 0)\n const midPoint = new Vector3(0, (greenY + minY) / 2, 0)\n const topTickLeft = new Vector3(-tickSize, greenY, 0)\n const topTickRight = new Vector3(tickSize, greenY, 0)\n const bottomTickLeft = new Vector3(-tickSize, minY, 0)\n const bottomTickRight = new Vector3(tickSize, minY, 0)\n\n return (\n <group ref={groupRef}>\n <Line points={[topPoint, bottomPoint]} color=\"#888888\" lineWidth={1.5} depthTest={false} />\n <Line points={[topTickLeft, topTickRight]} color=\"#888888\" lineWidth={1.5} depthTest={false} />\n <Line points={[bottomTickLeft, bottomTickRight]} color=\"#888888\" lineWidth={1.5} depthTest={false} />\n <mesh position={midPoint}>\n <Html center style={{ pointerEvents: \"none\" }}>\n <div style={{\n padding: \"4px 8px\",\n backgroundColor: \"rgba(0, 0, 0, 0.7)\",\n borderRadius: 4,\n color: \"#fff\",\n fontSize: 16,\n fontFamily: \"monospace\",\n whiteSpace: \"nowrap\",\n transform: \"rotate(-90deg)\",\n transformOrigin: \"center center\",\n pointerEvents: \"none\",\n }}>\n {displayUnit === \"inch\" ? (distance / 25.4).toFixed(2) : distance.toFixed(1)} {displayUnit === \"inch\" ? \"in\" : \"mm\"}\n </div>\n </Html>\n </mesh>\n </group>\n )\n}\n","import { useRef, useEffect, useCallback } from \"react\"\nimport { useThree } from \"@react-three/fiber\"\nimport * as THREE from \"three\"\nimport { Vector3 } from \"three\"\n\nexport interface CameraFitProps {\n modelSize: number\n isAligned: boolean\n isCut: boolean\n mesh: THREE.Mesh | null\n viewMode: \"3D\" | \"2D\"\n sliceY?: number\n landmarkCount?: number\n}\n\nexport const CameraFit = ({ modelSize, isAligned, isCut, mesh, viewMode, sliceY, landmarkCount = 0 }: CameraFitProps) => {\n const { set, size, camera, invalidate } = useThree()\n const initializedRef = useRef(false)\n const prevAlignedRef = useRef(isAligned)\n const prevCutRef = useRef(isCut)\n const prevViewModeRef = useRef(viewMode)\n const meshSizeRef = useRef<Vector3>(new Vector3())\n const saved3DCameraRef = useRef<THREE.Camera | null>(null)\n const prevLandmarkCountRef = useRef(landmarkCount)\n\n const setupFrontCamera = useCallback(() => {\n if (!mesh || modelSize <= 0) return\n const geometry = mesh.geometry as THREE.BufferGeometry\n geometry.computeBoundingBox()\n const box = geometry.boundingBox!\n const center = new Vector3(); box.getCenter(center)\n const meshSize = new Vector3(); box.getSize(meshSize)\n meshSizeRef.current.copy(meshSize)\n\n const aspect = size.width / size.height\n const frustumHeight = Math.max(meshSize.y, meshSize.x / aspect) * 1.2\n const frustumWidth = frustumHeight * aspect\n\n const orthoCamera = new THREE.OrthographicCamera(-frustumWidth / 2, frustumWidth / 2, frustumHeight / 2, -frustumHeight / 2, 0.1, modelSize * 10)\n orthoCamera.position.set(0, center.y, modelSize * 2)\n orthoCamera.lookAt(0, center.y, 0)\n set({ camera: orthoCamera })\n }, [mesh, modelSize, size, set])\n\n // Small orbit nudge to force three.js raycast matrix updates\n const nudgeCamera = useCallback((cam: THREE.Camera) => {\n const pos = cam.position.clone()\n const r = pos.length()\n const theta = Math.atan2(pos.x, pos.z)\n const phi = Math.acos(pos.y / r)\n const nudgeAngle = 0.02 // ~1 degree\n const newTheta = theta + nudgeAngle\n cam.position.set(\n r * Math.sin(phi) * Math.sin(newTheta),\n r * Math.cos(phi),\n r * Math.sin(phi) * Math.cos(newTheta),\n )\n cam.lookAt(0, 0, 0)\n cam.updateMatrixWorld(true)\n invalidate()\n }, [invalidate])\n\n useEffect(() => {\n if (modelSize > 0 && !initializedRef.current && !isAligned) {\n initializedRef.current = true\n const perspCamera = new THREE.PerspectiveCamera(50, size.width / size.height, 0.1, modelSize * 10)\n perspCamera.position.set(modelSize * 0.3, modelSize * 0.2, modelSize * 1.5)\n perspCamera.lookAt(0, 0, 0)\n set({ camera: perspCamera })\n // Nudge after a frame to force raycast internals to update\n requestAnimationFrame(() => nudgeCamera(perspCamera))\n }\n }, [modelSize, size, set, isAligned, nudgeCamera])\n\n // Nudge after first landmark point is placed\n useEffect(() => {\n const prev = prevLandmarkCountRef.current\n prevLandmarkCountRef.current = landmarkCount\n if (prev === 0 && landmarkCount === 1 && !isAligned) {\n requestAnimationFrame(() => nudgeCamera(camera))\n }\n }, [landmarkCount, isAligned, camera, nudgeCamera])\n\n useEffect(() => {\n if (prevAlignedRef.current === isAligned && prevCutRef.current === isCut) return\n prevAlignedRef.current = isAligned; prevCutRef.current = isCut\n if (isAligned && viewMode === \"3D\") setupFrontCamera()\n }, [isAligned, isCut, viewMode, setupFrontCamera])\n\n useEffect(() => {\n if (prevViewModeRef.current === viewMode) return\n const prevMode = prevViewModeRef.current\n prevViewModeRef.current = viewMode\n if (!isAligned || !mesh || modelSize <= 0) return\n\n if (viewMode === \"2D\" && sliceY != null) {\n saved3DCameraRef.current = camera\n\n const geometry = mesh.geometry as THREE.BufferGeometry\n const posAttr = geometry.getAttribute(\"position\") as THREE.BufferAttribute\n const positions = posAttr.array as Float32Array\n const band = modelSize * 0.15\n let minX = Infinity, maxX = -Infinity, minZ = Infinity, maxZ = -Infinity\n let found = false\n for (let i = 0; i < posAttr.count; i++) {\n if (Math.abs(positions[i * 3 + 1] - sliceY) < band) {\n const x = positions[i * 3], z = positions[i * 3 + 2]\n if (x < minX) minX = x; if (x > maxX) maxX = x\n if (z < minZ) minZ = z; if (z > maxZ) maxZ = z\n found = true\n }\n }\n if (!found) {\n geometry.computeBoundingBox()\n const box = geometry.boundingBox!\n minX = box.min.x; maxX = box.max.x; minZ = box.min.z; maxZ = box.max.z\n }\n const cx = (minX + maxX) / 2, cz = (minZ + maxZ) / 2\n const aspect = size.width / size.height\n const margin = 1.4\n const contentW = (maxX - minX) * margin\n const contentH = (maxZ - minZ) * margin\n let frustumWidth: number, frustumHeight2: number\n if (contentW / contentH > aspect) {\n frustumWidth = contentW\n frustumHeight2 = contentW / aspect\n } else {\n frustumHeight2 = contentH\n frustumWidth = contentH * aspect\n }\n\n const orthoCamera = new THREE.OrthographicCamera(-frustumWidth / 2, frustumWidth / 2, frustumHeight2 / 2, -frustumHeight2 / 2, 0.1, modelSize * 10)\n orthoCamera.position.set(cx, sliceY + modelSize * 2, cz)\n orthoCamera.up.set(0, 0, -1)\n orthoCamera.lookAt(cx, sliceY, cz)\n set({ camera: orthoCamera })\n } else if (prevMode === \"2D\") {\n if (saved3DCameraRef.current) {\n //@ts-ignore\n set({ camera: saved3DCameraRef.current })\n saved3DCameraRef.current = null\n } else {\n setupFrontCamera()\n }\n }\n }, [viewMode, sliceY, isAligned, mesh, modelSize, size, set, camera, setupFrontCamera])\n\n useEffect(() => {\n if (!isAligned || !camera || !(camera as THREE.OrthographicCamera).isOrthographicCamera) return\n const orthoCamera = camera as THREE.OrthographicCamera\n\n if (viewMode === \"2D\") {\n if (!mesh || sliceY == null) return\n const geometry = mesh.geometry as THREE.BufferGeometry\n const posAttr = geometry.getAttribute(\"position\") as THREE.BufferAttribute\n const positions = posAttr.array as Float32Array\n const band = modelSize * 0.15\n let minX = Infinity, maxX = -Infinity, minZ = Infinity, maxZ = -Infinity\n let found = false\n for (let i = 0; i < posAttr.count; i++) {\n if (Math.abs(positions[i * 3 + 1] - sliceY) < band) {\n const x = positions[i * 3], z = positions[i * 3 + 2]\n if (x < minX) minX = x; if (x > maxX) maxX = x\n if (z < minZ) minZ = z; if (z > maxZ) maxZ = z\n found = true\n }\n }\n if (!found) {\n geometry.computeBoundingBox()\n const box = geometry.boundingBox!\n minX = box.min.x; maxX = box.max.x; minZ = box.min.z; maxZ = box.max.z\n }\n const aspect = size.width / size.height\n const margin = 1.4\n const contentW = (maxX - minX) * margin\n const contentH = (maxZ - minZ) * margin\n let frustumWidth: number, frustumHeight2: number\n if (contentW / contentH > aspect) {\n frustumWidth = contentW\n frustumHeight2 = contentW / aspect\n } else {\n frustumHeight2 = contentH\n frustumWidth = contentH * aspect\n }\n orthoCamera.left = -frustumWidth / 2; orthoCamera.right = frustumWidth / 2\n orthoCamera.top = frustumHeight2 / 2; orthoCamera.bottom = -frustumHeight2 / 2\n } else {\n const meshSize = meshSizeRef.current\n const aspect = size.width / size.height\n const frustumHeight = Math.max(meshSize.y, meshSize.x / aspect) * 1.2\n const frustumWidth = frustumHeight * aspect\n orthoCamera.left = -frustumWidth / 2; orthoCamera.right = frustumWidth / 2\n orthoCamera.top = frustumHeight / 2; orthoCamera.bottom = -frustumHeight / 2\n }\n orthoCamera.updateProjectionMatrix()\n }, [size.width, size.height, isAligned, camera, viewMode, mesh])\n\n return null\n}\n","import * as THREE from \"three\"\nimport { Vector3 } from \"three\"\nimport { OrbitControls } from \"@react-three/drei\"\n\nexport const AlignedOrbitControls = ({ mesh, isDragging }: { mesh: THREE.Mesh; isDragging: boolean }) => {\n const geometry = mesh.geometry as THREE.BufferGeometry\n geometry.computeBoundingBox()\n const center = new Vector3()\n geometry.boundingBox?.getCenter(center)\n\n return (\n <OrbitControls\n enableDamping={false}\n enablePan={false}\n minPolarAngle={Math.PI * 0.15}\n maxPolarAngle={Math.PI * 0.85}\n minZoom={0.5}\n maxZoom={3}\n enabled={!isDragging}\n target={[center.x, center.y, center.z]}\n />\n )\n}\n","export interface ScaleNoticeProps {\n wasAutoScaled: boolean\n onDismiss: () => void\n}\n\nexport const ScaleNotice = ({ wasAutoScaled, onDismiss }: ScaleNoticeProps) => (\n <div style={{\n position: \"absolute\", bottom: 16, left: 16, zIndex: 10,\n display: \"flex\", alignItems: \"flex-start\", gap: 10,\n padding: \"10px 14px\", maxWidth: 320,\n backgroundColor: wasAutoScaled ? \"rgba(30, 70, 160, 0.92)\" : \"rgba(40, 40, 40, 0.88)\",\n borderRadius: 8, boxShadow: \"0 2px 12px rgba(0,0,0,0.15)\",\n fontFamily: \"system-ui, sans-serif\",\n }}>\n <span style={{ fontSize: 13, color: \"#fff\", lineHeight: \"20px\" }}>\n {wasAutoScaled\n ? \"Units detected as meters - converted to mm\"\n : \"Units detected as mm\"}\n </span>\n <button onClick={onDismiss} style={{\n background: \"none\", border: \"none\", color: \"rgba(255,255,255,0.7)\",\n cursor: \"pointer\", fontSize: 16, lineHeight: \"20px\", padding: 0, marginLeft: \"auto\", flexShrink: 0,\n }}>X</button>\n </div>\n)\n","export interface ShellNoticeProps {\n isDoubleShell: boolean\n onDismiss: () => void\n}\n\nexport const ShellNotice = ({ isDoubleShell, onDismiss }: ShellNoticeProps) => (\n <div style={{\n position: \"absolute\", bottom: 68, left: 16, zIndex: 10,\n display: \"flex\", alignItems: \"flex-start\", gap: 10,\n padding: \"10px 14px\", maxWidth: 320,\n backgroundColor: isDoubleShell ? \"rgba(130, 80, 20, 0.92)\" : \"rgba(40, 40, 40, 0.88)\",\n borderRadius: 8, boxShadow: \"0 2px 12px rgba(0,0,0,0.15)\",\n fontFamily: \"system-ui, sans-serif\",\n }}>\n <span style={{ fontSize: 13, color: \"#fff\", lineHeight: \"20px\" }}>\n {isDoubleShell\n ? \"Double shell scan detected\"\n : \"Single shell scan detected\"}\n </span>\n <button onClick={onDismiss} style={{\n background: \"none\", border: \"none\", color: \"rgba(255,255,255,0.7)\",\n cursor: \"pointer\", fontSize: 16, lineHeight: \"20px\", padding: 0, marginLeft: \"auto\", flexShrink: 0,\n }}>X</button>\n </div>\n)\n","export interface StepperStep {\n label: string\n number: number\n}\n\nexport interface StepperProps {\n steps: StepperStep[]\n currentStep: number\n accentColor?: string\n}\n\nexport const Stepper = ({ steps, currentStep, accentColor = \"rgb(12, 67, 173)\" }: StepperProps) => (\n <div style={{ backgroundColor: \"#fff\", borderBottom: \"1px solid #e0e0e0\", display: \"flex\", alignItems: \"center\", padding: \"24px 24px\", flexShrink: 0 }}>\n {steps.map((step, i) => {\n const isCompleted = step.number < currentStep\n const isActive = step.number === currentStep\n return (\n <div key={step.number} style={{ display: \"contents\" }}>\n <div style={{ display: \"flex\", alignItems: \"center\", gap: 8, padding: \"0 8px\", flexShrink: 0, cursor: \"default\" }}>\n <div style={{\n width: 24, height: 24, borderRadius: \"50%\",\n backgroundColor: isCompleted || isActive ? accentColor : \"rgba(0, 0, 0, 0.38)\",\n color: \"#fff\",\n display: \"flex\", alignItems: \"center\", justifyContent: \"center\",\n fontSize: 12, fontFamily: \"system-ui, sans-serif\", flexShrink: 0,\n }}>\n {isCompleted ? \"\\u2713\" : step.number}\n </div>\n <div style={{\n fontSize: 14, fontWeight: isActive ? 600 : 400,\n color: isActive ? \"rgba(0, 0, 0, 0.87)\" : \"rgba(0, 0, 0, 0.54)\",\n fontFamily: \"system-ui, sans-serif\", whiteSpace: \"nowrap\",\n }}>\n {step.label}\n </div>\n </div>\n {i < steps.length - 1 && (\n <div style={{ flex: \"auto\", borderTop: \"1px solid #bdbdbd\", margin: \"0 8px\" }} />\n )}\n </div>\n )\n })}\n </div>\n)\n","import { useMemo } from \"react\"\nimport { Html, Line } from \"@react-three/drei\"\nimport * as THREE from \"three\"\nimport { Vector3, Plane } from \"three\"\nimport { MeshBVH } from \"three-mesh-bvh\"\nimport { BVH_MAX_LEAF_TRIS } from \"../processing/constants\"\nimport { computeSliceAtY } from \"../processing/slice\"\n\nexport interface TransverseViewProps {\n mesh: THREE.Mesh\n upperY: number\n originY: number\n modelSize: number\n meshColor?: string\n displayUnit?: \"mm\" | \"inch\"\n}\n\nexport const TransverseView = ({ mesh, upperY, originY, modelSize, meshColor = \"#c8c8c8\", displayUnit = \"mm\" }: TransverseViewProps) => {\n const geometry = mesh.geometry as THREE.BufferGeometry\n const bvh = useMemo(() => new MeshBVH(geometry, { maxLeafTris: BVH_MAX_LEAF_TRIS }), [geometry])\n const originSlice = useMemo(() => computeSliceAtY(bvh, geometry, originY), [bvh, geometry, originY])\n const clipPlane = useMemo(() => new Plane(new Vector3(0, -1, 0), upperY), [upperY])\n\n const { mlLine, apLine, mlWidth, apWidth } = useMemo(() => {\n let mlLine: [Vector3, Vector3] | null = null\n let apLine: [Vector3, Vector3] | null = null\n let mlWidth = 0\n let apWidth = 0\n if (originSlice.linePoints.length >= 2) {\n let minXPt = originSlice.linePoints[0], maxXPt = originSlice.linePoints[0]\n let minZPt = originSlice.linePoints[0], maxZPt = originSlice.linePoints[0]\n for (const p of originSlice.linePoints) {\n if (p.x < minXPt.x) minXPt = p\n if (p.x > maxXPt.x) maxXPt = p\n if (p.z < minZPt.z) minZPt = p\n if (p.z > maxZPt.z) maxZPt = p\n }\n mlLine = [new Vector3(minXPt.x, originY, minXPt.z), new Vector3(maxXPt.x, originY, maxXPt.z)]\n apLine = [new Vector3(minZPt.x, originY, minZPt.z), new Vector3(maxZPt.x, originY, maxZPt.z)]\n mlWidth = mlLine[0].distanceTo(mlLine[1])\n apWidth = apLine[0].distanceTo(apLine[1])\n }\n return { mlLine, apLine, mlWidth, apWidth }\n }, [originSlice, originY])\n\n const formatValue = (mm: number) => displayUnit === \"inch\" ? (mm / 25.4).toFixed(2) : mm.toFixed(1)\n const unitLabel = displayUnit === \"inch\" ? \"in\" : \"mm\"\n\n return (\n <>\n <mesh geometry={mesh.geometry}>\n <meshStandardMaterial color={meshColor} side={THREE.DoubleSide} transparent opacity={0.15} depthWrite={false} clippingPlanes={[clipPlane]} />\n </mesh>\n {originSlice.linePoints.length >= 2 && (\n <Line points={originSlice.linePoints} color=\"#00ff00\" lineWidth={3} depthTest={false} depthWrite={false} transparent />\n )}\n {mlLine && (\n <>\n <Line points={mlLine} color=\"#ff8800\" lineWidth={2} depthTest={false} depthWrite={false} transparent />\n <Html position={[mlLine[0].x, originY, mlLine[0].z - modelSize * 0.02]} center style={{ pointerEvents: \"none\" }}>\n <div style={{ whiteSpace: \"nowrap\", padding: \"2px 6px\", backgroundColor: \"rgba(0,0,0,0.75)\", borderRadius: 3 }}>\n <span style={{ fontSize: 12, color: \"#ff8800\", fontFamily: \"monospace\" }}>ML {formatValue(mlWidth)} {unitLabel}</span>\n </div>\n </Html>\n </>\n )}\n {apLine && (\n <>\n <Line points={apLine} color=\"#ff00ff\" lineWidth={2} depthTest={false} depthWrite={false} transparent />\n <Html position={[Math.max(apLine[0].x, apLine[1].x) + modelSize * 0.02, originY, apLine[0].z > apLine[1].z ? apLine[0].z : apLine[1].z]} center style={{ pointerEvents: \"none\" }}>\n <div style={{ whiteSpace: \"nowrap\", padding: \"2px 6px\", backgroundColor: \"rgba(0,0,0,0.75)\", borderRadius: 3 }}>\n <span style={{ fontSize: 12, color: \"#ff00ff\", fontFamily: \"monospace\" }}>AP {formatValue(apWidth)} {unitLabel}</span>\n </div>\n </Html>\n </>\n )}\n </>\n )\n}\n","import { useMemo } from \"react\"\nimport * as THREE from \"three\"\nimport { Vector3 } from \"three\"\nimport { Line, Html } from \"@react-three/drei\"\nimport { runPCAOnRegion } from \"../processing/alignment\"\nimport { buildBVH, computeCircumferenceAtPlane } from \"../processing/slice\"\nimport type { ComponentDebugInfo } from \"../processing/wasm-loader\"\n\nexport interface DebugLayerVisibility {\n pcaAxes: boolean\n obb: boolean\n obbAxis: boolean\n shellComponents: boolean\n circumferenceScan: boolean\n landmarkAxis: boolean\n iterativePCA: boolean\n fullRegionPCA: boolean\n}\n\nexport const DEFAULT_DEBUG_LAYERS: DebugLayerVisibility = {\n pcaAxes: true,\n obb: true,\n obbAxis: true,\n shellComponents: true,\n circumferenceScan: false,\n landmarkAxis: true,\n iterativePCA: false,\n fullRegionPCA: true,\n}\n\nexport interface DebugOverlaysProps {\n mesh: THREE.Mesh\n modelSize: number\n layers: DebugLayerVisibility\n landmarkPoints?: { position: { x: number; y: number; z: number } }[]\n componentDebug?: ComponentDebugInfo | null\n}\n\ninterface PCAResult {\n axes: [Vector3, Vector3, Vector3]\n eigenvalues: [number, number, number]\n center: Vector3\n halfExtents: [number, number, number]\n}\n\nconst AXIS_COLORS: [string, string, string] = [\"#ff4444\", \"#44cc44\", \"#4488ff\"]\n\nfunction computeFullPCA(geometry: THREE.BufferGeometry): PCAResult {\n const posAttr = geometry.getAttribute(\"position\")\n const n = posAttr.count\n\n const center = new Vector3()\n for (let i = 0; i < n; i++) {\n center.x += posAttr.getX(i)\n center.y += posAttr.getY(i)\n center.z += posAttr.getZ(i)\n }\n center.divideScalar(n)\n\n let cxx = 0, cxy = 0, cxz = 0, cyy = 0, cyz = 0, czz = 0\n for (let i = 0; i < n; i++) {\n const dx = posAttr.getX(i) - center.x\n const dy = posAttr.getY(i) - center.y\n const dz = posAttr.getZ(i) - center.z\n cxx += dx * dx; cxy += dx * dy; cxz += dx * dz\n cyy += dy * dy; cyz += dy * dz; czz += dz * dz\n }\n cxx /= n; cxy /= n; cxz /= n; cyy /= n; cyz /= n; czz /= n\n\n const axes: Vector3[] = []\n const eigenvalues: number[] = []\n const deflatedCov = [[cxx, cxy, cxz], [cxy, cyy, cyz], [cxz, cyz, czz]]\n\n for (let k = 0; k < 3; k++) {\n let v = new Vector3(1 + k * 0.1, 1 - k * 0.1, 0.5 + k * 0.3).normalize()\n let eigenvalue = 0\n\n for (let iter = 0; iter < 100; iter++) {\n const nx = deflatedCov[0][0] * v.x + deflatedCov[0][1] * v.y + deflatedCov[0][2] * v.z\n const ny = deflatedCov[1][0] * v.x + deflatedCov[1][1] * v.y + deflatedCov[1][2] * v.z\n const nz = deflatedCov[2][0] * v.x + deflatedCov[2][1] * v.y + deflatedCov[2][2] * v.z\n const newV = new Vector3(nx, ny, nz)\n eigenvalue = newV.length()\n if (eigenvalue < 1e-12) break\n newV.divideScalar(eigenvalue)\n if (v.distanceTo(newV) < 1e-10) { v = newV; break }\n v = newV\n }\n\n axes.push(v.clone())\n eigenvalues.push(eigenvalue)\n\n for (let i = 0; i < 3; i++) {\n for (let j = 0; j < 3; j++) {\n const vi = [v.x, v.y, v.z][i]\n const vj = [v.x, v.y, v.z][j]\n deflatedCov[i][j] -= eigenvalue * vi * vj\n }\n }\n }\n\n const trueCenter = new Vector3()\n for (let i = 0; i < n; i++) {\n trueCenter.x += posAttr.getX(i)\n trueCenter.y += posAttr.getY(i)\n trueCenter.z += posAttr.getZ(i)\n }\n trueCenter.divideScalar(n)\n\n const halfExtents: [number, number, number] = [0, 0, 0]\n for (let k = 0; k < 3; k++) {\n let minProj = Infinity, maxProj = -Infinity\n const axis = axes[k]\n for (let i = 0; i < n; i++) {\n const dx = posAttr.getX(i) - trueCenter.x\n const dy = posAttr.getY(i) - trueCenter.y\n const dz = posAttr.getZ(i) - trueCenter.z\n const proj = dx * axis.x + dy * axis.y + dz * axis.z\n if (proj < minProj) minProj = proj\n if (proj > maxProj) maxProj = proj\n }\n halfExtents[k] = (maxProj - minProj) / 2\n }\n\n return {\n axes: axes as [Vector3, Vector3, Vector3],\n eigenvalues: eigenvalues as [number, number, number],\n center: trueCenter,\n halfExtents,\n }\n}\n\n// ── Layer: PCA Axes (full mesh covariance) ──\nfunction PCAAxes({ pca }: { pca: PCAResult }) {\n return (\n <group>\n {pca.axes.map((axis, i) => {\n const end = pca.center.clone().addScaledVector(axis, pca.halfExtents[i])\n const negEnd = pca.center.clone().addScaledVector(axis, -pca.halfExtents[i])\n return <Line key={i} points={[negEnd, end]} color={AXIS_COLORS[i]} lineWidth={2} />\n })}\n </group>\n )\n}\n\n// ── Layer: OBB Wireframe ──\nfunction OBBWireframe({ pca }: { pca: PCAResult }) {\n const edges = useMemo(() => {\n const { center, axes, halfExtents } = pca\n const corners: Vector3[] = []\n for (let i = -1; i <= 1; i += 2) {\n for (let j = -1; j <= 1; j += 2) {\n for (let k = -1; k <= 1; k += 2) {\n corners.push(\n center.clone()\n .addScaledVector(axes[0], i * halfExtents[0])\n .addScaledVector(axes[1], j * halfExtents[1])\n .addScaledVector(axes[2], k * halfExtents[2])\n )\n }\n }\n }\n const pairs: [number, number][] = [\n [0, 1], [2, 3], [4, 5], [6, 7],\n [0, 2], [1, 3], [4, 6], [5, 7],\n [0, 4], [1, 5], [2, 6], [3, 7],\n ]\n return pairs.map(([a, b]) => [corners[a], corners[b]] as [Vector3, Vector3])\n }, [pca])\n\n return (\n <group>\n {edges.map((edge, i) => (\n <Line key={i} points={edge} color=\"#ffaa00\" lineWidth={1} transparent opacity={0.5} />\n ))}\n </group>\n )\n}\n\n// ── Layer: Landmark Axis (rough alignment result) ──\n// Shows the red→green vector. After rough align this should be vertical (along Y).\nfunction LandmarkAxis({ redPoint, greenPoint }: { redPoint: Vector3; greenPoint: Vector3 }) {\n const dir = useMemo(() => new Vector3().subVectors(greenPoint, redPoint).normalize(), [redPoint, greenPoint])\n const angleFromY = useMemo(() => {\n const dot = dir.dot(new Vector3(0, 1, 0))\n return Math.acos(Math.min(1, Math.abs(dot))) * 180 / Math.PI\n }, [dir])\n\n // Color: green if well-aligned (<1°), yellow if okay (<5°), red if misaligned\n const color = angleFromY < 1 ? \"#44ff44\" : angleFromY < 5 ? \"#ffcc00\" : \"#ff4444\"\n\n return (\n <group>\n <Line points={[redPoint, greenPoint]} color={color} lineWidth={3} />\n {/* Small sphere at red */}\n <mesh position={redPoint}>\n <sphereGeometry args={[1.5, 8, 8]} />\n <meshBasicMaterial color=\"#ff4444\" />\n </mesh>\n {/* Small sphere at green */}\n <mesh position={greenPoint}>\n <sphereGeometry args={[1.5, 8, 8]} />\n <meshBasicMaterial color=\"#44ff44\" />\n </mesh>\n </group>\n )\n}\n\n// ── Layer: Iterative PCA (step 5 visualization) ──\n// Re-runs PCA on expanding windows from green downward in 10mm steps.\n// Each axis is drawn at the midpoint of its region. Shows how the algorithm\n// progressively refines alignment by growing the analysis window.\nfunction IterativePCAAxes({ geometry, redY, greenY, modelSize }: {\n geometry: THREE.BufferGeometry\n redY: number\n greenY: number\n modelSize: number\n}) {\n const STEP_SIZE = 10\n const axisLength = modelSize * 0.15\n\n const steps = useMemo(() => {\n const result: { axis: Vector3; regionMin: number; regionMax: number; angleDeg: number }[] = []\n let currentHeight = greenY - STEP_SIZE\n const targetY = new Vector3(0, 1, 0)\n\n while (currentHeight > redY) {\n const regionMin = Math.min(currentHeight, greenY)\n const regionMax = Math.max(currentHeight, greenY)\n const pcaAxis = runPCAOnRegion(geometry, regionMin, regionMax)\n\n if (pcaAxis) {\n const dot = pcaAxis.dot(targetY)\n const angleDeg = Math.acos(Math.min(1, Math.abs(dot))) * 180 / Math.PI\n result.push({ axis: pcaAxis, regionMin, regionMax, angleDeg })\n }\n\n currentHeight -= STEP_SIZE\n }\n return result\n }, [geometry, redY, greenY])\n\n return (\n <group>\n {steps.map((step, i) => {\n const midY = (step.regionMin + step.regionMax) / 2\n const origin = new Vector3(0, midY, 0)\n const end = origin.clone().addScaledVector(step.axis, axisLength)\n const negEnd = origin.clone().addScaledVector(step.axis, -axisLength)\n // Fade from cyan (top/green) to magenta (bottom/red)\n const t = i / Math.max(1, steps.length - 1)\n const color = step.angleDeg < 0.5 ? `hsl(${120 - t * 120}, 80%, 60%)` : `hsl(${40 - step.angleDeg * 2}, 90%, 55%)`\n\n return (\n <group key={i}>\n <Line points={[negEnd, end]} color={color} lineWidth={1.5} transparent opacity={0.7} />\n {/* Region bounds — thin horizontal lines */}\n <Line\n points={[new Vector3(-axisLength * 0.3, step.regionMin, 0), new Vector3(axisLength * 0.3, step.regionMin, 0)]}\n color={color} lineWidth={0.5} transparent opacity={0.3}\n />\n </group>\n )\n })}\n </group>\n )\n}\n\n// ── Layer: Full Region PCA (step 7 visualization) ──\n// PCA on the entire red-to-green region. This is what final_pca aligns to.\nfunction FullRegionPCAAxis({ geometry, redY, greenY, modelSize }: {\n geometry: THREE.BufferGeometry\n redY: number\n greenY: number\n modelSize: number\n}) {\n const result = useMemo(() => {\n const pcaAxis = runPCAOnRegion(geometry, redY, greenY)\n if (!pcaAxis) return null\n const dot = pcaAxis.dot(new Vector3(0, 1, 0))\n const angleDeg = Math.acos(Math.min(1, Math.abs(dot))) * 180 / Math.PI\n return { axis: pcaAxis, angleDeg }\n }, [geometry, redY, greenY])\n\n if (!result) return null\n\n const midY = (redY + greenY) / 2\n const origin = new Vector3(0, midY, 0)\n const halfLen = modelSize * 0.4\n const end = origin.clone().addScaledVector(result.axis, halfLen)\n const negEnd = origin.clone().addScaledVector(result.axis, -halfLen)\n\n // White/cyan if well-aligned, orange/red if off\n const color = result.angleDeg < 0.5 ? \"#00ffff\" : result.angleDeg < 2 ? \"#ffcc00\" : \"#ff6600\"\n\n return (\n <group>\n <Line points={[negEnd, end]} color={color} lineWidth={3} dashed dashSize={3} gapSize={2} />\n </group>\n )\n}\n\n// ── Layer: OBB Primary Axis (PC1 from full mesh) ──\nfunction OBBAxis({ pca, modelSize }: { pca: PCAResult; modelSize: number }) {\n const axis = pca.axes[0]\n const halfLen = modelSize * 0.6\n const end = pca.center.clone().addScaledVector(axis, halfLen)\n const negEnd = pca.center.clone().addScaledVector(axis, -halfLen)\n\n return (\n <Line points={[negEnd, end]} color=\"#ff8800\" lineWidth={2} dashed dashSize={3} gapSize={2} />\n )\n}\n\n// ── Layer: Circumference Scan (step 4.5 visualization) ──\n// Horizontal bars at each Y level, width proportional to circumference.\n// Color-coded: green (<1.3× baseline), yellow (1.3-1.6×), red (>1.6× baseline).\nfunction CircumferenceScanLayer({ geometry, redY, greenY, modelSize }: {\n geometry: THREE.BufferGeometry\n redY: number\n greenY: number\n modelSize: number\n}) {\n const scanData = useMemo(() => {\n const bvh = buildBVH(geometry)\n const yUp = new Vector3(0, 1, 0)\n const SCAN_STEP = 5\n\n geometry.computeBoundingBox()\n const maxY = geometry.boundingBox!.max.y\n const circumferences: { y: number; circ: number }[] = []\n\n for (let y = redY + SCAN_STEP; y < maxY; y += SCAN_STEP) {\n const circ = computeCircumferenceAtPlane(bvh, geometry, new Vector3(0, y, 0), yUp)\n if (circ > 0) circumferences.push({ y, circ })\n }\n\n if (circumferences.length < 5) return null\n\n const limbSpan = greenY - redY\n const stableMin = redY + limbSpan * 0.3\n const stableMax = redY + limbSpan * 0.7\n const stableSlices = circumferences.filter(s => s.y >= stableMin && s.y <= stableMax)\n if (stableSlices.length < 3) return null\n\n const stableCircs = stableSlices.map(s => s.circ).sort((a, b) => a - b)\n const baseline = stableCircs[Math.floor(stableCircs.length / 2)]\n const maxCirc = Math.max(...circumferences.map(s => s.circ))\n\n return { circumferences, baseline, maxCirc }\n }, [geometry, redY, greenY])\n\n if (!scanData) return null\n\n const { circumferences, baseline, maxCirc } = scanData\n const barScale = modelSize * 0.3 / maxCirc\n\n return (\n <group>\n {circumferences.map(({ y, circ }, i) => {\n const ratio = circ / baseline\n const color = ratio > 1.6 ? \"#ff4444\" : ratio > 1.3 ? \"#ffcc00\" : \"#22cc66\"\n const halfWidth = circ * barScale\n return (\n <Line\n key={i}\n points={[new Vector3(-halfWidth, y, 0), new Vector3(halfWidth, y, 0)]}\n color={color}\n lineWidth={1.5}\n transparent\n opacity={0.6}\n />\n )\n })}\n {/* Threshold lines at 1.6× baseline */}\n {(() => {\n const threshWidth = baseline * 1.6 * barScale\n const minY = circumferences[0].y\n const maxY = circumferences[circumferences.length - 1].y\n return (\n <>\n <Line\n points={[new Vector3(-threshWidth, minY, 0), new Vector3(-threshWidth, maxY, 0)]}\n color=\"#ff4444\" lineWidth={1} dashed dashSize={3} gapSize={2} transparent opacity={0.4}\n />\n <Line\n points={[new Vector3(threshWidth, minY, 0), new Vector3(threshWidth, maxY, 0)]}\n color=\"#ff4444\" lineWidth={1} dashed dashSize={3} gapSize={2} transparent opacity={0.4}\n />\n </>\n )\n })()}\n </group>\n )\n}\n\n// ── Layer: Shell Components (pre-extraction component visualization) ──\nfunction ShellComponents({ componentDebug }: { componentDebug: ComponentDebugInfo }) {\n return (\n <group>\n {componentDebug.geometries.map((geo, i) => {\n const color = componentDebug.colors[i] ?? \"#888888\"\n const isInner = i === componentDebug.innerIdx\n\n // Compute centroid for label placement\n geo.computeBoundingBox()\n const center = new Vector3()\n geo.boundingBox!.getCenter(center)\n\n return (\n <group key={i}>\n <mesh geometry={geo} renderOrder={isInner ? 2 : 1}>\n <meshStandardMaterial\n color={color}\n transparent\n opacity={isInner ? 0.5 : 0.2}\n side={THREE.DoubleSide}\n depthWrite={false}\n polygonOffset\n polygonOffsetFactor={1}\n polygonOffsetUnits={1}\n />\n </mesh>\n <mesh geometry={geo} renderOrder={isInner ? 2 : 1}>\n <meshBasicMaterial color={color} wireframe transparent opacity={isInner ? 0.4 : 0.15} />\n </mesh>\n <group position={center}>\n <Html center style={{ pointerEvents: \"none\" }}>\n <div style={{\n padding: \"2px 8px\",\n backgroundColor: \"rgba(0,0,0,0.8)\",\n borderRadius: 4,\n border: `1px solid ${color}`,\n whiteSpace: \"nowrap\",\n }}>\n <span style={{ fontSize: 11, color, fontFamily: \"monospace\", fontWeight: isInner ? 700 : 400 }}>\n {componentDebug.labels[i]}\n </span>\n </div>\n </Html>\n </group>\n </group>\n )\n })}\n </group>\n )\n}\n\nexport function DebugOverlays({ mesh, layers, landmarkPoints, componentDebug }: DebugOverlaysProps) {\n const geometry = mesh.geometry as THREE.BufferGeometry\n\n const pca = useMemo(() => {\n if (!geometry.getAttribute(\"position\")) return null\n return computeFullPCA(geometry)\n }, [geometry])\n\n const landmarks = useMemo(() => {\n if (!landmarkPoints || landmarkPoints.length < 2) return null\n return {\n red: new Vector3(landmarkPoints[0].position.x, landmarkPoints[0].position.y, landmarkPoints[0].position.z),\n green: new Vector3(landmarkPoints[1].position.x, landmarkPoints[1].position.y, landmarkPoints[1].position.z),\n }\n }, [landmarkPoints])\n\n return (\n <group>\n {layers.pcaAxes && pca && <PCAAxes pca={pca} />}\n {layers.obb && pca && <OBBWireframe pca={pca} />}\n {layers.obbAxis && pca && <OBBAxis pca={pca} modelSize={pca.halfExtents[0] ? Math.max(...pca.halfExtents) * 2 : 100} />}\n {layers.shellComponents && componentDebug && <ShellComponents componentDebug={componentDebug} />}\n {layers.circumferenceScan && landmarks && (\n <CircumferenceScanLayer\n geometry={geometry}\n redY={landmarks.red.y}\n greenY={landmarks.green.y}\n modelSize={pca?.halfExtents[0] ? Math.max(...pca.halfExtents) * 2 : 100}\n />\n )}\n {layers.landmarkAxis && landmarks && (\n <LandmarkAxis redPoint={landmarks.red} greenPoint={landmarks.green} />\n )}\n {layers.iterativePCA && landmarks && (\n <IterativePCAAxes\n geometry={geometry}\n redY={landmarks.red.y}\n greenY={landmarks.green.y}\n modelSize={pca?.halfExtents[0] ? Math.max(...pca.halfExtents) * 2 : 100}\n />\n )}\n {layers.fullRegionPCA && landmarks && (\n <FullRegionPCAAxis\n geometry={geometry}\n redY={landmarks.red.y}\n greenY={landmarks.green.y}\n modelSize={pca?.halfExtents[0] ? Math.max(...pca.halfExtents) * 2 : 100}\n />\n )}\n </group>\n )\n}\n\n// ── Standalone: OBB axis line (always visible, non-debug) ──\nexport interface OBBAlignmentLineProps {\n mesh: THREE.Mesh\n}\n\nexport function OBBAlignmentLine({ mesh }: OBBAlignmentLineProps) {\n const geometry = mesh.geometry as THREE.BufferGeometry\n\n const result = useMemo(() => {\n if (!geometry.getAttribute(\"position\")) return null\n const pca = computeFullPCA(geometry)\n const axis = pca.axes[0]\n const halfLen = pca.halfExtents[0] * 1.3\n return { axis, center: pca.center, halfLen }\n }, [geometry])\n\n if (!result) return null\n\n const end = result.center.clone().addScaledVector(result.axis, result.halfLen)\n const negEnd = result.center.clone().addScaledVector(result.axis, -result.halfLen)\n\n return (\n <Line points={[negEnd, end]} color=\"#666\" lineWidth={1} dashed dashSize={4} gapSize={3} transparent opacity={0.4} depthTest={false} renderOrder={999} />\n )\n}\n","import type { DebugLayerVisibility } from \"./DebugOverlays\"\n\nexport interface DebugPanelProps {\n layers: DebugLayerVisibility\n onToggleLayer: (layer: keyof DebugLayerVisibility) => void\n}\n\ninterface LayerEntry {\n key: keyof DebugLayerVisibility\n label: string\n color: string\n group: string\n}\n\nconst LAYER_CONFIG: LayerEntry[] = [\n { key: \"pcaAxes\", label: \"PCA Axes (full mesh)\", color: \"#ff4444\", group: \"Geometry\" },\n { key: \"obb\", label: \"OBB Wireframe\", color: \"#ffaa00\", group: \"Geometry\" },\n { key: \"obbAxis\", label: \"OBB Primary Axis\", color: \"#ff8800\", group: \"Geometry\" },\n { key: \"shellComponents\", label: \"Shell Components\", color: \"#4488ff\", group: \"Shell Detection\" },\n { key: \"circumferenceScan\", label: \"Circumference Scan (step 4.5)\", color: \"#22cc66\", group: \"Isolation\" },\n { key: \"landmarkAxis\", label: \"Landmark Axis (rough align)\", color: \"#44ff44\", group: \"Alignment\" },\n { key: \"iterativePCA\", label: \"Iterative PCA (step 5)\", color: \"#cc66ff\", group: \"Alignment\" },\n { key: \"fullRegionPCA\", label: \"Full Region PCA (step 7)\", color: \"#00ffff\", group: \"Alignment\" },\n]\n\nconst groups = [...new Set(LAYER_CONFIG.map(l => l.group))]\n\nexport function DebugPanel({ layers, onToggleLayer }: DebugPanelProps) {\n return (\n <div style={{\n position: \"absolute\",\n top: 16,\n left: 16,\n zIndex: 20,\n backgroundColor: \"rgba(7, 6, 17, 0.9)\",\n border: \"1px solid rgba(255,255,255,0.1)\",\n borderRadius: 6,\n padding: \"10px 12px\",\n fontFamily: \"system-ui, sans-serif\",\n fontSize: 12,\n color: \"#ccc\",\n minWidth: 180,\n backdropFilter: \"blur(8px)\",\n }}>\n <div style={{ fontSize: 10, fontWeight: 600, textTransform: \"uppercase\", letterSpacing: \"0.5px\", color: \"#888\", marginBottom: 8 }}>\n Debug Layers\n </div>\n {groups.map(group => (\n <div key={group}>\n <div style={{ fontSize: 9, fontWeight: 600, textTransform: \"uppercase\", letterSpacing: \"0.5px\", color: \"#555\", marginTop: 6, marginBottom: 4 }}>\n {group}\n </div>\n {LAYER_CONFIG.filter(l => l.group === group).map(({ key, label, color }) => (\n <label key={key} style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: 8,\n padding: \"3px 0\",\n cursor: \"pointer\",\n userSelect: \"none\",\n }}>\n <input\n type=\"checkbox\"\n checked={layers[key]}\n onChange={() => onToggleLayer(key)}\n style={{ accentColor: color, width: 14, height: 14, cursor: \"pointer\" }}\n />\n <span style={{\n width: 8,\n height: 8,\n borderRadius: \"50%\",\n backgroundColor: color,\n opacity: layers[key] ? 1 : 0.3,\n flexShrink: 0,\n }} />\n <span style={{ opacity: layers[key] ? 1 : 0.5 }}>{label}</span>\n </label>\n ))}\n </div>\n ))}\n </div>\n )\n}\n","import { Canvas } from \"@react-three/fiber\"\nimport { OrbitControls } from \"@react-three/drei\"\nimport { useState, useCallback, useEffect, useRef } from \"react\"\nimport type { DragEvent } from \"react\"\nimport * as THREE from \"three\"\nimport { Vector3 } from \"three\"\n\nimport { useMeasurementStore } from \"./store\"\nimport { GirthManagerConfigContext, type GirthManagerConfig } from \"./config\"\nimport { MM_PER_INCH } from \"./processing/constants\"\nimport { processWithWasm, processWithObjLoader } from \"./processing/wasm-loader\"\nimport { stlToObjString } from \"./processing/stl-convert\"\nimport { runProcessingPipeline } from \"./processing/pipeline\"\nimport { computeSliceAtY, buildBVH } from \"./processing/slice\"\nimport { ErrorDisplay } from \"./components/ErrorDisplay\"\nimport { LoadingSpinner } from \"./components/LoadingSpinner\"\nimport { ClickableMesh } from \"./components/ClickableMesh\"\nimport { LandmarkMarkers } from \"./components/LandmarkMarkers\"\nimport { CircumferenceMeasurements } from \"./components/CircumferenceMeasurements\"\nimport { VerticalDimension } from \"./components/VerticalDimension\"\nimport { CameraFit } from \"./components/CameraFit\"\nimport { AlignedOrbitControls } from \"./components/AlignedOrbitControls\"\nimport { ScaleNotice } from \"./components/ScaleNotice\"\nimport { ShellNotice } from \"./components/ShellNotice\"\nimport { Stepper } from \"./components/Stepper\"\nimport { TransverseView } from \"./components/TransverseView\"\nimport { DebugOverlays, DEFAULT_DEBUG_LAYERS, OBBAlignmentLine } from \"./components/DebugOverlays\"\nimport { DebugPanel } from \"./components/DebugPanel\"\nimport type { MeasurementData, WasmMeshSetType } from \"./processing/types\"\nimport type { DebugLayerVisibility } from \"./components/DebugOverlays\"\nimport type { ComponentDebugInfo } from \"./processing/wasm-loader\"\n\n// ── Result type emitted by onComplete ──\n\nexport interface GirthManagerResult {\n spacingType: \"AK\" | \"BK\"\n sourceUnit: \"mm\" | \"inch\"\n fileFormat: \"obj\" | \"stl\"\n measurementSource: \"scan_derived\" | \"form_provided\"\n isDoubleWall: boolean\n isUnitConverted: boolean\n formMeasurements: number[] | undefined\n scanMeasurements: MeasurementData[]\n frontalHeight: number\n transverseML: number\n transverseAP: number\n scanUrl: string | undefined\n}\n\n// ── Props ──\n\nexport interface GirthManagerCoreProps {\n /** Feature config — controls which UI elements are rendered */\n config: GirthManagerConfig\n\n /** Pre-set amputation/spacing type (skips the modal when set) */\n spacingType?: \"AK\" | \"BK\"\n\n /** URL to auto-load a scan file from (widget mode) */\n scanUrl?: string\n\n /** Form-provided circumference measurements in mm, ordered by slice position (widget mode) */\n formMeasurements?: number[]\n\n /** Called when \"Continue to Next Step\" is clicked */\n onComplete?: (result: GirthManagerResult) => void\n\n /** Whether current user can access debug features */\n isDebugUser?: boolean\n\n /** Called when analytics events should fire (internal app wires this to PostHog) */\n onAnalyticsEvent?: (eventName: string, properties: Record<string, unknown>) => void\n\n /** Provide a loaded WASM module. If not provided, the core will attempt to dynamically import 'galileo-core-geo'. */\n wasmModule?: { WasmMeshSet: new () => WasmMeshSetType } | null\n}\n\nexport const GirthManagerCore = ({\n config,\n spacingType: presetSpacingType,\n scanUrl,\n formMeasurements: presetFormMeasurements,\n onComplete,\n isDebugUser = false,\n onAnalyticsEvent,\n wasmModule: externalWasmModule,\n}: GirthManagerCoreProps) => {\n // ── State ──\n const [mesh, setMesh] = useState<THREE.Mesh | null>(null)\n const [modelSize, setModelSize] = useState(0)\n const [isDragging, setIsDragging] = useState(false)\n const [isProcessing, setIsProcessing] = useState(false)\n const [processingStatus, setProcessingStatus] = useState(\"\")\n const [viewMode, setViewMode] = useState<\"3D\" | \"2D\">(\"3D\")\n const [measurementSpacingInches, setMeasurementSpacingInches] = useState<1 | 2>(\n presetSpacingType === \"AK\" ? 2 : 1\n )\n const [showAmputationModal, setShowAmputationModal] = useState(false)\n const [pendingGeometry, setPendingGeometry] = useState<{\n geometry: THREE.BufferGeometry\n wasScaled: boolean\n innerShellExtracted?: boolean\n componentDebug?: ComponentDebugInfo | null\n } | null>(null)\n const [componentDebug, setComponentDebug] = useState<ComponentDebugInfo | null>(null)\n const [amputationType, setAmputationType] = useState<\"AK\" | \"BK\" | null>(presetSpacingType ?? null)\n const [displayUnit, setDisplayUnit] = useState<\"mm\" | \"inch\">(\"mm\")\n const [isComputing, setIsComputing] = useState(false)\n const [computingMessage, setComputingMessage] = useState(\"\")\n const [wasAutoScaled, setWasAutoScaled] = useState(false)\n const [showScaleNotice, setShowScaleNotice] = useState(false)\n const [isDoubleShell, setIsDoubleShell] = useState(false)\n const [innerShellExtracted, setInnerShellExtracted] = useState(false)\n const [showShellNotice, setShowShellNotice] = useState(false)\n const [measurements, setMeasurements] = useState<MeasurementData[]>([])\n const [adjustedStartY, setAdjustedStartY] = useState<number | null>(null)\n const [adjustedEndY, setAdjustedEndY] = useState<number | null>(null)\n const [originalEndY, setOriginalEndY] = useState<number | null>(null)\n const [error, setError] = useState<string | null>(null)\n const [debugMode, setDebugMode] = useState(false)\n const [debugLayers, setDebugLayers] = useState<DebugLayerVisibility>(DEFAULT_DEBUG_LAYERS)\n const [showClippedRef, setShowClippedRef] = useState(false)\n const [clippedRefGeo, setClippedRefGeo] = useState<THREE.BufferGeometry | null>(null)\n const [fileFormat, setFileFormat] = useState<\"obj\" | \"stl\">(\"obj\")\n const [showInsertModal, setShowInsertModal] = useState(false)\n const [formMeasurements, setFormMeasurements] = useState<Record<string, string>>({})\n const [savedFormMeasurements, setSavedFormMeasurements] = useState<number[] | undefined>(\n presetFormMeasurements\n )\n const [showFormOverlay, setShowFormOverlay] = useState(true)\n const [meshColor] = useState(\"#c8c8c8\")\n const [meshOpacity] = useState(1)\n const [wasmReady, setWasmReady] = useState(false)\n const wasmModuleRef = useRef<{ WasmMeshSet: new () => WasmMeshSetType } | null>(null)\n\n const {\n landmarkPoints, clearLandmarkPoints, addLandmarkPoint,\n removeLandmarkPoint, updateLandmarkPositions,\n setAligned, isAligned, setCut, isCut,\n } = useMeasurementStore()\n\n const measurementSpacingMm = measurementSpacingInches * MM_PER_INCH\n\n // ── Sync preset form measurements when they change ──\n useEffect(() => {\n if (presetFormMeasurements) setSavedFormMeasurements(presetFormMeasurements)\n }, [presetFormMeasurements])\n\n // Clear form measurements when spacing changes\n useEffect(() => {\n if (!presetFormMeasurements) {\n setSavedFormMeasurements(undefined)\n setFormMeasurements({})\n }\n }, [measurementSpacingInches])\n\n // ── Analytics: fire once when measurements are ready ──\n const didCaptureRef = useRef(false)\n useEffect(() => {\n if (!isAligned || measurements.length === 0 || didCaptureRef.current) return\n if (!onAnalyticsEvent) return\n didCaptureRef.current = true\n const spanMm = landmarkPoints.length >= 3\n ? Math.abs(landmarkPoints[2].position.y - landmarkPoints[1].position.y)\n : null\n onAnalyticsEvent(\"dimensions_calculated\", {\n spacing_type: amputationType,\n source_unit: \"mm\",\n file_format: fileFormat,\n measurement_source: \"scan_derived\",\n is_double_wall: isDoubleShell,\n is_unit_converted: false,\n form_measurements: savedFormMeasurements?.filter(v => v != null) ?? null,\n scan_measurements: measurements.map(m => +(m.modifiedValue ?? m.originalValue).toFixed(1)),\n measurement_variance: savedFormMeasurements ? measurements.map((m, i) => {\n const form = savedFormMeasurements[i]\n if (form == null) return null\n return +((m.modifiedValue ?? m.originalValue) - form).toFixed(1)\n }) : null,\n frontal_height: spanMm !== null ? +spanMm.toFixed(1) : null,\n })\n }, [isAligned, measurements])\n\n // ── Accept WASM module from consumer ──\n useEffect(() => {\n if (externalWasmModule !== undefined) {\n wasmModuleRef.current = externalWasmModule\n }\n // Always mark ready — JS fallback (OBJLoader) works without WASM\n setWasmReady(true)\n }, [externalWasmModule])\n\n // ── Finalize geometry after WASM processing ──\n const finalizeGeometry = useCallback((geometry: THREE.BufferGeometry, wasScaled: boolean) => {\n geometry.computeBoundingBox()\n const box = geometry.boundingBox!\n const center = new Vector3()\n box.getCenter(center)\n geometry.translate(-center.x, -center.y, -center.z)\n geometry.computeBoundingBox()\n const scaledBox = geometry.boundingBox!\n const size = new Vector3()\n scaledBox.getSize(size)\n setModelSize(Math.max(size.x, size.y, size.z))\n const resultMesh = new THREE.Mesh(\n geometry,\n new THREE.MeshStandardMaterial({ color: 0x888888, side: THREE.DoubleSide })\n )\n setMesh(resultMesh)\n setWasAutoScaled(wasScaled)\n setShowScaleNotice(true)\n }, [])\n\n // ── Process raw file contents (shared between drag-drop and URL loading) ──\n const processFileContents = useCallback(async (contents: string | ArrayBuffer, fileName: string) => {\n setError(null)\n const name = fileName.toLowerCase()\n const isStl = name.endsWith(\".stl\")\n const isObj = name.endsWith(\".obj\")\n if (!isObj && !isStl) {\n setError(\"Unsupported file format. Please use OBJ or STL.\")\n return\n }\n setFileFormat(isStl ? \"stl\" : \"obj\")\n setIsProcessing(true)\n setProcessingStatus(\"Processing file...\")\n try {\n let objContents: string\n if (isStl) {\n setProcessingStatus(\"Converting STL...\")\n // For URL-loaded STL, contents may be an ArrayBuffer\n if (contents instanceof ArrayBuffer) {\n const blob = new Blob([contents])\n const file = new File([blob], fileName)\n objContents = await stlToObjString(file)\n } else {\n const blob = new Blob([contents])\n const file = new File([blob], fileName)\n objContents = await stlToObjString(file)\n }\n } else {\n objContents = typeof contents === \"string\" ? contents : new TextDecoder().decode(contents)\n }\n\n const wasmResult = wasmModuleRef.current\n ? await processWithWasm(objContents, wasmModuleRef.current, setProcessingStatus)\n : null\n\n if (wasmResult) {\n if (config.showAmputationModal && !presetSpacingType) {\n setPendingGeometry(wasmResult)\n setShowAmputationModal(true)\n } else {\n // Widget mode: skip modal, finalize immediately\n finalizeGeometry(wasmResult.geometry, wasmResult.wasScaled)\n if (wasmResult.innerShellExtracted) {\n setInnerShellExtracted(true)\n setIsDoubleShell(true)\n }\n if (wasmResult.componentDebug) {\n setComponentDebug(wasmResult.componentDebug)\n }\n }\n } else {\n setProcessingStatus(\"Using fallback loader...\")\n const geometry = processWithObjLoader(objContents)\n if (geometry) {\n if (config.showAmputationModal && !presetSpacingType) {\n setPendingGeometry({ geometry, wasScaled: false, innerShellExtracted: false })\n setShowAmputationModal(true)\n } else {\n finalizeGeometry(geometry, false)\n }\n } else {\n setError(\"Failed to parse the mesh.\")\n }\n }\n } catch (err) {\n setError(err instanceof Error ? err.message : \"Failed to process the mesh file.\")\n } finally {\n setIsProcessing(false)\n setProcessingStatus(\"\")\n }\n }, [wasmReady, config.showAmputationModal, presetSpacingType, finalizeGeometry])\n\n // ── Auto-load from URL (widget mode) ──\n useEffect(() => {\n if (!scanUrl || !wasmReady) return\n const load = async () => {\n setIsProcessing(true)\n setProcessingStatus(\"Downloading scan...\")\n try {\n const response = await fetch(scanUrl)\n if (!response.ok) throw new Error(`Failed to download scan: ${response.status}`)\n const urlPath = new URL(scanUrl).pathname\n const fileName = urlPath.split(\"/\").pop() || \"scan.obj\"\n const isStl = fileName.toLowerCase().endsWith(\".stl\")\n if (isStl) {\n const buffer = await response.arrayBuffer()\n await processFileContents(buffer, fileName)\n } else {\n const text = await response.text()\n await processFileContents(text, fileName)\n }\n } catch (err) {\n setError(err instanceof Error ? err.message : \"Failed to load scan from URL.\")\n setIsProcessing(false)\n setProcessingStatus(\"\")\n }\n }\n load()\n }, [scanUrl, wasmReady])\n\n // ── Drag & Drop (only when enabled) ──\n const handleDragOver = useCallback((e: DragEvent<HTMLDivElement>) => {\n e.preventDefault()\n setIsDragging(true)\n }, [])\n const handleDragLeave = useCallback((e: DragEvent<HTMLDivElement>) => {\n e.preventDefault()\n setIsDragging(false)\n }, [])\n const handleDrop = useCallback(async (e: DragEvent<HTMLDivElement>) => {\n e.preventDefault()\n setIsDragging(false)\n if (!wasmReady) { setError(\"WASM module is still loading. Please wait.\"); return }\n const file = e.dataTransfer.files[0]\n if (!file) return\n const name = file.name.toLowerCase()\n if (!name.endsWith(\".obj\") && !name.endsWith(\".stl\")) {\n setError(\"Please drop an OBJ or STL file.\")\n return\n }\n if (name.endsWith(\".stl\")) {\n setFileFormat(\"stl\")\n setIsProcessing(true)\n setProcessingStatus(\"Converting STL...\")\n try {\n const objContents = await stlToObjString(file)\n await processFileContents(objContents, file.name)\n } catch (err) {\n setError(err instanceof Error ? err.message : \"Failed to process STL file.\")\n setIsProcessing(false)\n setProcessingStatus(\"\")\n }\n } else {\n const text = await file.text()\n await processFileContents(text, file.name)\n }\n }, [wasmReady, processFileContents])\n\n // ── Amputation type selection ──\n const handleAmputationSelect = useCallback((type: \"AK\" | \"BK\") => {\n setAmputationType(type)\n setMeasurementSpacingInches(type === \"AK\" ? 2 : 1)\n setShowAmputationModal(false)\n if (pendingGeometry) {\n finalizeGeometry(pendingGeometry.geometry, pendingGeometry.wasScaled)\n if (pendingGeometry.innerShellExtracted) {\n setInnerShellExtracted(true)\n setIsDoubleShell(true)\n }\n if (pendingGeometry.componentDebug) {\n setComponentDebug(pendingGeometry.componentDebug)\n }\n setPendingGeometry(null)\n }\n onAnalyticsEvent?.(\"file_loaded\", {\n spacing_type: type,\n file_format: fileFormat,\n is_double_wall: pendingGeometry?.innerShellExtracted ?? false,\n })\n }, [pendingGeometry, finalizeGeometry, onAnalyticsEvent, fileFormat])\n\n // ── Processing pipeline ──\n const handleProcess = useCallback(() => {\n if (!mesh || landmarkPoints.length < 2) return\n setIsComputing(true)\n setComputingMessage(\"Please wait...\")\n setTimeout(() => {\n runProcessingPipeline(mesh, landmarkPoints, measurementSpacingMm, {\n onStatus: setComputingMessage,\n addLandmarkPoint,\n removeLandmarkPoint,\n updateLandmarkPositions,\n setAligned,\n setCut,\n setModelSize,\n setOriginalEndY,\n setAdjustedStartY,\n setAdjustedEndY,\n setError,\n setDoubleShell: (ds) => { setIsDoubleShell(ds); setShowShellNotice(true) },\n setClippedReferenceGeometry: setClippedRefGeo,\n skipDoubleShellDetection: innerShellExtracted,\n })\n didCaptureRef.current = false\n setIsComputing(false)\n }, 50)\n }, [mesh, landmarkPoints, updateLandmarkPositions, setAligned, addLandmarkPoint, removeLandmarkPoint, setCut, measurementSpacingMm, innerShellExtracted])\n\n // ── Continue to Next Step (widget output) ──\n const handleContinue = useCallback(() => {\n if (!onComplete || !mesh || measurements.length === 0 || !amputationType) return\n\n // Compute transverse dimensions from the origin slice\n let transverseML = 0\n let transverseAP = 0\n const frontalHeight = landmarkPoints.length >= 3\n ? Math.abs(landmarkPoints[2].position.y - landmarkPoints[1].position.y)\n : 0\n\n if (landmarkPoints.length >= 2) {\n const geo = mesh.geometry as THREE.BufferGeometry\n const upperLandmark = landmarkPoints[1]\n const originY = upperLandmark.position.y\n try {\n const bvh = buildBVH(geo)\n const slice = computeSliceAtY(bvh, geo, originY)\n if (slice.linePoints.length >= 2) {\n let minXPt = slice.linePoints[0], maxXPt = slice.linePoints[0]\n let minZPt = slice.linePoints[0], maxZPt = slice.linePoints[0]\n for (const p of slice.linePoints) {\n if (p.x < minXPt.x) minXPt = p\n if (p.x > maxXPt.x) maxXPt = p\n if (p.z < minZPt.z) minZPt = p\n if (p.z > maxZPt.z) maxZPt = p\n }\n transverseML = new Vector3(minXPt.x, originY, minXPt.z).distanceTo(new Vector3(maxXPt.x, originY, maxXPt.z))\n transverseAP = new Vector3(minZPt.x, originY, minZPt.z).distanceTo(new Vector3(maxZPt.x, originY, maxZPt.z))\n }\n } catch { /* transverse dimensions remain 0 */ }\n }\n\n onComplete({\n spacingType: amputationType,\n sourceUnit: \"mm\",\n fileFormat,\n measurementSource: savedFormMeasurements ? \"form_provided\" : \"scan_derived\",\n isDoubleWall: isDoubleShell,\n isUnitConverted: false,\n formMeasurements: savedFormMeasurements,\n scanMeasurements: measurements,\n frontalHeight,\n transverseML,\n transverseAP,\n scanUrl,\n })\n }, [onComplete, mesh, measurements, amputationType, landmarkPoints, fileFormat, isDoubleShell, savedFormMeasurements, scanUrl])\n\n // ── Derived state ──\n const currentStep = isAligned ? 4 : !mesh ? 1 : landmarkPoints.length === 0 ? 2 : 3\n const stepperSteps = [\n { label: \"Load File\", number: 1 },\n { label: \"Set Origin\", number: 2 },\n { label: amputationType === \"AK\" ? \"Set IT/Perineum\" : \"Set MPT\", number: 3 },\n { label: \"Results\", number: 4 },\n ]\n\n return (\n <GirthManagerConfigContext.Provider value={config}>\n <div style={{ flex: 1, display: \"flex\", flexDirection: \"column\", backgroundColor: \"#F9F9FA\", minWidth: 0, position: \"relative\", height: \"100%\" }}>\n {/* Top Toolbar Placeholder (internal only) */}\n {config.showToolbar && (\n <div style={{ height: 83, backgroundColor: \"#9e9e9e\", flexShrink: 0, position: \"relative\", overflow: \"hidden\" }}>\n <div style={{ position: \"absolute\", inset: 0, opacity: 0.1, backgroundImage: \"repeating-linear-gradient(45deg, transparent, transparent 10px, #fff 10px, #fff 12px)\", pointerEvents: \"none\" }} />\n </div>\n )}\n\n {/* Stepper */}\n <Stepper steps={stepperSteps} currentStep={currentStep} />\n\n <div style={{ flex: 1, display: \"flex\", flexDirection: \"column\", minHeight: 0 }}>\n {/* 3D Canvas area */}\n <div\n style={{ flex: 1, position: \"relative\", minHeight: 0, overflow: \"hidden\" }}\n onDragOver={config.showDragDrop ? handleDragOver : undefined}\n onDragLeave={config.showDragDrop ? handleDragLeave : undefined}\n onDrop={config.showDragDrop ? handleDrop : undefined}\n >\n {/* Drop zone (internal only) */}\n {config.showDragDrop && !mesh && !isProcessing && (\n <div style={{ position: \"absolute\", inset: 16, border: \"3px dashed #ccc\", borderRadius: 4, display: \"flex\", alignItems: \"center\", justifyContent: \"center\", pointerEvents: \"none\" }}>\n {!wasmReady ? (\n <div style={{ textAlign: \"center\" }}>\n <div style={{ width: 32, height: 32, border: \"3px solid rgba(0,0,0,0.1)\", borderTopColor: \"#4a90d9\", borderRadius: \"50%\", animation: \"spin 1s linear infinite\", margin: \"0 auto 12px\" }} />\n <div style={{ fontSize: 16, color: \"#999\", fontFamily: \"system-ui, sans-serif\" }}>Loading WASM module...</div>\n <style>{`@keyframes spin { to { transform: rotate(360deg); } }`}</style>\n </div>\n ) : (\n <div style={{ fontSize: 18, color: \"#aaa\", fontWeight: 400, fontFamily: \"system-ui, sans-serif\" }}>Drag & Drop Files Here</div>\n )}\n </div>\n )}\n\n {/* Widget loading state (no drag-drop) */}\n {!config.showDragDrop && !mesh && !isProcessing && !error && (\n <div style={{ position: \"absolute\", inset: 0, display: \"flex\", alignItems: \"center\", justifyContent: \"center\" }}>\n <div style={{ textAlign: \"center\" }}>\n <div style={{ width: 32, height: 32, border: \"3px solid rgba(0,0,0,0.1)\", borderTopColor: \"#4a90d9\", borderRadius: \"50%\", animation: \"spin 1s linear infinite\", margin: \"0 auto 12px\" }} />\n <div style={{ fontSize: 16, color: \"#999\", fontFamily: \"system-ui, sans-serif\" }}>Loading scan...</div>\n <style>{`@keyframes spin { to { transform: rotate(360deg); } }`}</style>\n </div>\n </div>\n )}\n\n {/* Instruction prompts */}\n {mesh && !isAligned && landmarkPoints.length === 0 && (\n <div style={{ position: \"absolute\", top: 16, left: \"50%\", transform: \"translateX(-50%)\", display: \"flex\", alignItems: \"center\", gap: 8, padding: \"8px 16px\", backgroundColor: \"rgba(0, 0, 0, 0.6)\", borderRadius: 8, color: \"#fff\", fontSize: 13, pointerEvents: \"none\", zIndex: 5, fontFamily: \"system-ui, sans-serif\" }}>\n <div style={{ width: 10, height: 10, borderRadius: \"50%\", backgroundColor: \"#ff4444\", flexShrink: 0 }} />\n Click mesh to set Origin\n </div>\n )}\n {mesh && !isAligned && landmarkPoints.length === 1 && (\n <div style={{ position: \"absolute\", top: 16, left: \"50%\", transform: \"translateX(-50%)\", display: \"flex\", alignItems: \"center\", gap: 8, padding: \"8px 16px\", backgroundColor: \"rgba(0, 0, 0, 0.6)\", borderRadius: 8, color: \"#fff\", fontSize: 13, pointerEvents: \"none\", zIndex: 5, fontFamily: \"system-ui, sans-serif\" }}>\n <div style={{ width: 10, height: 10, borderRadius: \"50%\", backgroundColor: \"#44ff44\", flexShrink: 0 }} />\n Click mesh to set {amputationType === \"AK\" ? \"IT/Perineum\" : \"MPT\"}\n </div>\n )}\n\n {isProcessing && <LoadingSpinner message={processingStatus || \"Processing mesh...\"} />}\n {isComputing && <LoadingSpinner message={computingMessage} />}\n {error && <ErrorDisplay message={error} onDismiss={() => setError(null)} />}\n\n {/* AK/BK Modal (internal only) */}\n {config.showAmputationModal && showAmputationModal && (\n <div style={{ position: \"absolute\", inset: 0, backgroundColor: \"rgba(0,0,0,0.32)\", display: \"flex\", alignItems: \"center\", justifyContent: \"center\", zIndex: 20 }}>\n <div style={{ backgroundColor: \"#fff\", borderRadius: 4, width: 560, 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)\", fontFamily: \"system-ui, sans-serif\" }}>\n <div style={{ padding: \"24px 24px 20px\" }}>\n <div style={{ fontSize: 20, fontWeight: 500, color: \"rgba(0,0,0,0.87)\", marginBottom: 8 }}>Select Spacing Type</div>\n <div style={{ fontSize: 14, color: \"rgba(0,0,0,0.54)\", marginBottom: 24 }}>Choose the measurement spacing for this scan</div>\n <div style={{ display: \"flex\", gap: 16 }}>\n {([\"AK\", \"BK\"] as const).map(type => (\n <label key={type} onClick={() => setAmputationType(type)} style={{ flex: 1, display: \"flex\", flexDirection: \"column\", padding: \"20px 24px\", border: \"2px solid\", borderRadius: 4, cursor: \"pointer\", borderColor: amputationType === type ? \"rgb(12, 67, 173)\" : \"#e0e0e0\", backgroundColor: amputationType === type ? \"rgba(12, 67, 173, 0.04)\" : \"#fff\", transition: \"border-color 0.15s, background-color 0.15s\" }}>\n <input type=\"radio\" name=\"ampType\" checked={amputationType === type} onChange={() => setAmputationType(type)} style={{ accentColor: \"rgb(12, 67, 173)\", marginBottom: 12, width: 18, height: 18 }} />\n <span style={{ fontSize: 18, fontWeight: 600, color: \"rgba(0,0,0,0.87)\", marginBottom: 4 }}>{type}</span>\n <span style={{ fontSize: 13, color: \"rgba(0,0,0,0.54)\" }}>{type === \"AK\" ? \"2\" : \"1\"}-inch measurement spacing</span>\n </label>\n ))}\n </div>\n </div>\n <div style={{ display: \"flex\", justifyContent: \"flex-end\", gap: 8, padding: \"12px 24px 20px\", borderTop: \"1px solid #e0e0e0\" }}>\n <button onClick={() => { setShowAmputationModal(false); setPendingGeometry(null) }} style={{ padding: \"6px 16px\", borderRadius: 4, fontSize: 14, fontWeight: 500, backgroundColor: \"#fff\", border: \"1px solid #bdbdbd\", color: \"rgba(0,0,0,0.87)\", cursor: \"pointer\", fontFamily: \"system-ui, sans-serif\", lineHeight: \"36px\", letterSpacing: \"0.4px\" }}>\n Cancel\n </button>\n <button onClick={() => amputationType && handleAmputationSelect(amputationType)} disabled={!amputationType} style={{ padding: \"6px 16px\", borderRadius: 4, fontSize: 14, fontWeight: 500, backgroundColor: amputationType ? \"rgb(12, 67, 173)\" : \"#e0e0e0\", border: \"none\", color: amputationType ? \"#fff\" : \"#9e9e9e\", cursor: amputationType ? \"pointer\" : \"not-allowed\", fontFamily: \"system-ui, sans-serif\", lineHeight: \"36px\", letterSpacing: \"0.4px\" }}>\n {\"Next \\u00bb\"}\n </button>\n </div>\n </div>\n </div>\n )}\n\n {config.showDragDrop && isDragging && (\n <div style={{ position: \"absolute\", inset: 0, backgroundColor: \"rgba(12, 67, 173, 0.1)\", border: \"2px dashed rgb(12, 67, 173)\", pointerEvents: \"none\", zIndex: 10 }} />\n )}\n\n {/* Three.js Canvas */}\n <Canvas camera={{ position: [0, 0, 5] }} style={{ display: mesh ? \"block\" : \"none\", backgroundColor: debugMode ? \"#070611\" : undefined }} gl={{ localClippingEnabled: true }} scene={{ background: debugMode ? new THREE.Color(\"#070611\") : null }}>\n <ambientLight intensity={0.4} />\n <directionalLight position={[10, 10, 5]} intensity={1.2} />\n <directionalLight position={[-5, 5, -5]} intensity={0.4} />\n <directionalLight position={[0, -10, 0]} intensity={0.2} />\n\n {mesh && viewMode === \"3D\" && <ClickableMesh mesh={mesh} maxPoints={2} meshColor={meshColor} meshOpacity={debugMode ? 0.3 : meshOpacity} />}\n {showClippedRef && clippedRefGeo && viewMode === \"3D\" && (\n <mesh geometry={clippedRefGeo} renderOrder={1}>\n <meshStandardMaterial color=\"#c8c8c8\" transparent opacity={0.35} side={THREE.DoubleSide} depthWrite={false} polygonOffset polygonOffsetFactor={1} polygonOffsetUnits={1} />\n </mesh>\n )}\n {mesh && viewMode === \"3D\" && <LandmarkMarkers modelSize={modelSize} labels={[\"Origin\", amputationType === \"AK\" ? \"IT/Perineum\" : \"MPT\", \"Cut Plane\"]} />}\n <CameraFit modelSize={modelSize} isAligned={isAligned} isCut={isCut} mesh={mesh} viewMode={viewMode}\n sliceY={isAligned && landmarkPoints.length >= 2 ? (adjustedEndY ?? (originalEndY ?? landmarkPoints[1].position.y)) : undefined}\n landmarkCount={landmarkPoints.length} />\n {!isAligned && <OrbitControls enableDamping={false} />}\n {isAligned && measurements.length > 0 && mesh && viewMode === \"3D\" && (\n <AlignedOrbitControls mesh={mesh} isDragging={false} />\n )}\n\n {mesh && isAligned && landmarkPoints.length >= 3 && (() => {\n const geo = mesh.geometry as THREE.BufferGeometry\n const idx = geo.getIndex()\n if (!idx || idx.count < 30) return null\n\n const lowerLandmark = landmarkPoints[2]\n const upperLandmark = landmarkPoints[1]\n const lowerY = adjustedStartY ?? lowerLandmark.position.y\n const upperY = adjustedEndY ?? (originalEndY ?? upperLandmark.position.y)\n\n if (viewMode === \"2D\") {\n return <TransverseView mesh={mesh} upperY={upperY} originY={upperLandmark.position.y} modelSize={modelSize} meshColor={meshColor} displayUnit={displayUnit} />\n }\n\n return (\n <>\n <CircumferenceMeasurements mesh={mesh} startY={lowerY} endY={upperY}\n spacing={measurementSpacingMm} modelSize={modelSize} onMeasurementsChange={setMeasurements} reverseOrder={true} displayUnit={displayUnit} useInnerSurface={isDoubleShell && !innerShellExtracted} formMeasurements={showFormOverlay ? savedFormMeasurements : undefined} originY={upperLandmark.position.y} />\n {(!isDoubleShell || innerShellExtracted) && <VerticalDimension mesh={mesh} greenY={upperLandmark.position.y} modelSize={modelSize} displayUnit={displayUnit} />}\n </>\n )\n })()}\n\n {mesh && isAligned && viewMode === \"3D\" && (\n <OBBAlignmentLine mesh={mesh} />\n )}\n\n {mesh && config.showDebug && debugMode && viewMode === \"3D\" && (\n <DebugOverlays mesh={mesh} modelSize={modelSize} layers={debugLayers} landmarkPoints={landmarkPoints} componentDebug={componentDebug} />\n )}\n </Canvas>\n\n {/* Start Over + Insert Measurement buttons (internal only) */}\n {mesh && (config.showStartOver || config.showInsertMeasurement) && (\n <div style={{ position: \"absolute\", top: 16, left: 16, zIndex: 10, display: \"flex\", gap: 8 }}>\n {config.showStartOver && (\n <button onClick={() => window.location.reload()} style={{ padding: \"6px 16px\", borderRadius: 4, fontSize: 13, fontWeight: 500, backgroundColor: \"#fff\", border: \"1px solid #bdbdbd\", color: \"#333\", cursor: \"pointer\", fontFamily: \"system-ui, sans-serif\", letterSpacing: \"0.4px\", boxShadow: \"0 2px 8px rgba(0,0,0,0.1)\" }}>\n Start Over\n </button>\n )}\n {config.showInsertMeasurement && (\n <button onClick={() => setShowInsertModal(true)} style={{ padding: \"6px 16px\", borderRadius: 4, fontSize: 13, fontWeight: 500, backgroundColor: \"rgb(12, 67, 173)\", border: \"none\", color: \"#fff\", cursor: \"pointer\", fontFamily: \"system-ui, sans-serif\", letterSpacing: \"0.4px\", boxShadow: \"0 2px 8px rgba(0,0,0,0.1)\" }}>\n Insert Measurement\n </button>\n )}\n </div>\n )}\n\n {/* Debug panel (internal only) */}\n {config.showDebug && debugMode && mesh && viewMode === \"3D\" && (\n <DebugPanel layers={debugLayers} onToggleLayer={(layer) => setDebugLayers(prev => ({ ...prev, [layer]: !prev[layer] }))} />\n )}\n\n {/* View controls */}\n {isAligned && measurements.length > 0 && (\n <div style={{ position: \"absolute\", top: 16, right: 16, display: \"flex\", gap: 8, zIndex: 10 }}>\n <div style={{ display: \"flex\", borderRadius: 6, overflow: \"hidden\", border: \"1px solid #ccc\", boxShadow: \"0 2px 8px rgba(0,0,0,0.1)\" }}>\n <button onClick={() => setViewMode(\"3D\")} style={{ padding: \"6px 14px\", fontSize: 13, fontWeight: viewMode === \"3D\" ? 600 : 400, backgroundColor: viewMode === \"3D\" ? \"rgb(12, 67, 173)\" : \"#fff\", color: viewMode === \"3D\" ? \"#fff\" : \"#666\", border: \"none\", cursor: \"pointer\", fontFamily: \"system-ui, sans-serif\" }}>Frontal</button>\n <button onClick={() => setViewMode(\"2D\")} style={{ padding: \"6px 14px\", fontSize: 13, fontWeight: viewMode === \"2D\" ? 600 : 400, backgroundColor: viewMode === \"2D\" ? \"rgb(12, 67, 173)\" : \"#fff\", color: viewMode === \"2D\" ? \"#fff\" : \"#666\", border: \"none\", borderLeft: \"1px solid #ccc\", cursor: \"pointer\", fontFamily: \"system-ui, sans-serif\" }}>Transverse</button>\n </div>\n <div style={{ display: \"flex\", borderRadius: 6, overflow: \"hidden\", border: \"1px solid #ccc\", boxShadow: \"0 2px 8px rgba(0,0,0,0.1)\" }}>\n <button onClick={() => setDisplayUnit(\"mm\")} style={{ padding: \"6px 14px\", fontSize: 13, fontWeight: displayUnit === \"mm\" ? 600 : 400, backgroundColor: displayUnit === \"mm\" ? \"rgb(12, 67, 173)\" : \"#fff\", color: displayUnit === \"mm\" ? \"#fff\" : \"#666\", border: \"none\", cursor: \"pointer\", fontFamily: \"system-ui, sans-serif\" }}>mm</button>\n <button onClick={() => setDisplayUnit(\"inch\")} style={{ padding: \"6px 14px\", fontSize: 13, fontWeight: displayUnit === \"inch\" ? 600 : 400, backgroundColor: displayUnit === \"inch\" ? \"rgb(12, 67, 173)\" : \"#fff\", color: displayUnit === \"inch\" ? \"#fff\" : \"#666\", border: \"none\", borderLeft: \"1px solid #ccc\", cursor: \"pointer\", fontFamily: \"system-ui, sans-serif\" }}>in</button>\n </div>\n {config.showSpacingToggle && viewMode === \"3D\" && (\n <div style={{ display: \"flex\", borderRadius: 6, overflow: \"hidden\", border: \"1px solid #ccc\", boxShadow: \"0 2px 8px rgba(0,0,0,0.1)\" }}>\n <button onClick={() => setMeasurementSpacingInches(1)} style={{ padding: \"6px 14px\", fontSize: 13, fontWeight: measurementSpacingInches === 1 ? 600 : 400, backgroundColor: measurementSpacingInches === 1 ? \"rgb(12, 67, 173)\" : \"#fff\", color: measurementSpacingInches === 1 ? \"#fff\" : \"#666\", border: \"none\", cursor: \"pointer\", fontFamily: \"system-ui, sans-serif\" }}>1\"</button>\n <button onClick={() => setMeasurementSpacingInches(2)} style={{ padding: \"6px 14px\", fontSize: 13, fontWeight: measurementSpacingInches === 2 ? 600 : 400, backgroundColor: measurementSpacingInches === 2 ? \"rgb(12, 67, 173)\" : \"#fff\", color: measurementSpacingInches === 2 ? \"#fff\" : \"#666\", border: \"none\", borderLeft: \"1px solid #ccc\", cursor: \"pointer\", fontFamily: \"system-ui, sans-serif\" }}>2\"</button>\n </div>\n )}\n {viewMode === \"3D\" && clippedRefGeo && (\n <div style={{ display: \"flex\", borderRadius: 6, overflow: \"hidden\", border: \"1px solid #ccc\", boxShadow: \"0 2px 8px rgba(0,0,0,0.1)\" }}>\n <button onClick={() => setShowClippedRef(s => !s)} style={{ padding: \"6px 14px\", fontSize: 13, fontWeight: showClippedRef ? 600 : 400, backgroundColor: showClippedRef ? \"rgb(12, 67, 173)\" : \"#fff\", color: showClippedRef ? \"#fff\" : \"#666\", border: \"none\", cursor: \"pointer\", fontFamily: \"system-ui, sans-serif\" }}>Show Full Scan</button>\n </div>\n )}\n {viewMode === \"3D\" && savedFormMeasurements && (\n <div style={{ display: \"flex\", borderRadius: 6, overflow: \"hidden\", border: \"1px solid #ccc\", boxShadow: \"0 2px 8px rgba(0,0,0,0.1)\" }}>\n <button onClick={() => setShowFormOverlay(s => !s)} style={{ padding: \"6px 14px\", fontSize: 13, fontWeight: showFormOverlay ? 600 : 400, backgroundColor: showFormOverlay ? \"rgb(12, 67, 173)\" : \"#fff\", color: showFormOverlay ? \"#fff\" : \"#666\", border: \"none\", cursor: \"pointer\", fontFamily: \"system-ui, sans-serif\" }}>Form Overlay</button>\n </div>\n )}\n {config.showDebug && isDebugUser && (\n <div style={{ display: \"flex\", borderRadius: 6, overflow: \"hidden\", border: \"1px solid #ccc\", boxShadow: \"0 2px 8px rgba(0,0,0,0.1)\" }}>\n <button onClick={() => setDebugMode(d => !d)} style={{ padding: \"6px 14px\", fontSize: 13, fontWeight: debugMode ? 600 : 400, backgroundColor: debugMode ? \"#e65100\" : \"#fff\", color: debugMode ? \"#fff\" : \"#666\", border: \"none\", cursor: \"pointer\", fontFamily: \"system-ui, sans-serif\" }}>Debug</button>\n </div>\n )}\n </div>\n )}\n\n {/* Scale notice */}\n {mesh && showScaleNotice && <ScaleNotice wasAutoScaled={wasAutoScaled} onDismiss={() => setShowScaleNotice(false)} />}\n {/* Shell type notice */}\n {mesh && showShellNotice && isAligned && <ShellNotice isDoubleShell={isDoubleShell} onDismiss={() => setShowShellNotice(false)} />}\n </div>\n\n {/* Bottom Action Bar */}\n <div style={{ padding: \"12px 24px\", backgroundColor: \"#fff\", borderTop: \"1px solid #e0e0e0\", display: \"flex\", alignItems: \"center\", justifyContent: \"flex-end\", gap: 8, flexShrink: 0 }}>\n {mesh && !isAligned && landmarkPoints.length >= 2 && (\n <button onClick={handleProcess} style={{ padding: \"6px 16px\", borderRadius: 4, fontSize: 14, fontWeight: 500, backgroundColor: \"rgb(12, 67, 173)\", border: \"none\", color: \"#fff\", cursor: \"pointer\", fontFamily: \"system-ui, sans-serif\", letterSpacing: \"0.4px\", lineHeight: \"36px\" }}>\n {\"Next \\u00bb\"}\n </button>\n )}\n {mesh && !isAligned && landmarkPoints.length >= 1 && (\n <button onClick={clearLandmarkPoints} style={{ padding: \"6px 16px\", borderRadius: 4, fontSize: 14, fontWeight: 500, backgroundColor: \"#fff\", border: \"1px solid #bdbdbd\", color: \"#333\", cursor: \"pointer\", fontFamily: \"system-ui, sans-serif\", letterSpacing: \"0.4px\", lineHeight: \"36px\" }}>\n Reset Points\n </button>\n )}\n {isAligned && (\n <button\n onClick={handleContinue}\n disabled={measurements.length === 0}\n style={{ padding: \"6px 16px\", borderRadius: 4, fontSize: 14, fontWeight: 500, backgroundColor: measurements.length > 0 ? \"rgb(12, 67, 173)\" : \"#e0e0e0\", border: \"none\", color: measurements.length > 0 ? \"#fff\" : \"#9e9e9e\", cursor: measurements.length > 0 ? \"pointer\" : \"not-allowed\", fontFamily: \"system-ui, sans-serif\", letterSpacing: \"0.4px\", lineHeight: \"36px\" }}\n >\n Continue to Next Step\n </button>\n )}\n </div>\n </div>\n </div>\n\n {/* Insert Measurement Modal (internal only) */}\n {config.showInsertMeasurement && showInsertModal && (() => {\n const ref = amputationType === \"AK\" ? \"IT/Perineum\" : \"MPT\"\n const sp = measurementSpacingInches\n const labels: string[] = []\n for (let i = 2; i >= 1; i -= sp) labels.push(`${i}\\u2033 above ${ref}`)\n labels.push(`At ${ref}`)\n for (let i = sp; i <= 9; i += sp) labels.push(`${i}\\u2033 below ${ref}`)\n return (\n <div style={{ position: \"fixed\", inset: 0, backgroundColor: \"rgba(0,0,0,0.32)\", display: \"flex\", alignItems: \"center\", justifyContent: \"flex-start\", paddingLeft: 40, zIndex: 9999 }}>\n <div style={{ backgroundColor: \"#fff\", borderRadius: 4, width: 620, maxHeight: \"80vh\", display: \"flex\", flexDirection: \"column\", 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)\", fontFamily: \"system-ui, sans-serif\" }}>\n <div style={{ padding: \"24px 24px 0\" }}>\n <div style={{ fontSize: 20, fontWeight: 500, color: \"rgba(0,0,0,0.87)\", marginBottom: 4 }}>\n {amputationType} Circumferences\n </div>\n <div style={{ fontSize: 13, color: \"rgba(0,0,0,0.54)\", marginBottom: 20 }}>\n Enter form measurements (mm). {sp}{'\\u2033'} spacing.\n </div>\n </div>\n <div style={{ padding: \"0 24px\", overflowY: \"auto\", flex: 1 }}>\n <div style={{ display: \"grid\", gridTemplateColumns: \"1fr 1fr\", gap: \"16px 24px\" }}>\n {labels.map((label, i) => (\n <div key={i}>\n <label style={{ display: \"block\", fontSize: 13, fontWeight: 500, color: \"rgb(12, 67, 173)\", marginBottom: 6 }}>{label} (mm):</label>\n <input\n type=\"number\"\n step=\"0.1\"\n value={formMeasurements[label] ?? \"\"}\n onChange={e => setFormMeasurements(prev => ({ ...prev, [label]: e.target.value }))}\n style={{ width: \"100%\", padding: \"10px 12px\", fontSize: 15, border: \"2px solid rgb(12, 67, 173)\", borderRadius: 4, outline: \"none\", boxSizing: \"border-box\", fontFamily: \"system-ui, sans-serif\" }}\n />\n </div>\n ))}\n </div>\n </div>\n <div style={{ display: \"flex\", justifyContent: \"flex-end\", gap: 8, padding: \"16px 24px\", borderTop: \"1px solid #e0e0e0\", marginTop: 16 }}>\n <button onClick={() => { setShowInsertModal(false); setFormMeasurements({}) }} style={{ padding: \"6px 16px\", borderRadius: 4, fontSize: 14, fontWeight: 500, backgroundColor: \"#fff\", border: \"1px solid #bdbdbd\", color: \"rgba(0,0,0,0.87)\", cursor: \"pointer\", fontFamily: \"system-ui, sans-serif\", lineHeight: \"36px\", letterSpacing: \"0.4px\" }}>\n Cancel\n </button>\n <button onClick={() => {\n const values = labels.map(l => parseFloat(formMeasurements[l] || \"\"))\n const filled = values.filter(v => !isNaN(v))\n setSavedFormMeasurements(filled.length > 0 ? values.map(v => isNaN(v) ? undefined as unknown as number : v) : undefined)\n setShowInsertModal(false)\n }} style={{ padding: \"6px 16px\", borderRadius: 4, fontSize: 14, fontWeight: 500, backgroundColor: \"rgb(12, 67, 173)\", border: \"none\", color: \"#fff\", cursor: \"pointer\", fontFamily: \"system-ui, sans-serif\", lineHeight: \"36px\", letterSpacing: \"0.4px\" }}>\n Save\n </button>\n </div>\n </div>\n </div>\n )\n })()}\n </GirthManagerConfigContext.Provider>\n )\n}\n","/**\n * Input contract for the Girth Manager widget.\n * Mirrors the schema in docs/widget_interface.ts.\n */\nexport interface WidgetRequest {\n /** Spacing type: above-knee or below-knee */\n spacing_type: \"AK\" | \"BK\"\n /** URL to the uploaded 3D scan file */\n scan_url: string\n /** Optional circumference measurements from the order form (mm). Omit if not provided. */\n form_measurements?: Circumference\n}\n\n/**\n * Output contract emitted by the widget when \"Continue to Next Step\" is clicked.\n * Mirrors the schema in docs/widget_interface.ts.\n */\nexport interface WidgetResponse {\n /** Spacing type: above-knee or below-knee */\n spacing_type: \"AK\" | \"BK\"\n /** Unit of all measurements in this response */\n source_unit: \"mm\" | \"inch\"\n /** File format of the scan */\n file_format: \"obj\" | \"stl\"\n /** Whether measurements were derived from the scan or taken from the order form */\n measurement_source: \"scan_derived\" | \"form_provided\"\n /** Whether the spacing uses a double-wall construction */\n is_double_wall: boolean\n /** Whether measurements were converted from their original unit */\n is_unit_converted: boolean\n /** Circumference measurements from the order form (mm). Only includes fields the user filled in. Omitted if none were provided. */\n form_measurements?: Circumference\n /** Circumference measurements derived from the 3D scan (mm) */\n scan_measurements: Circumference\n /** Difference between form and scan measurements (mm). Only present for positions where both form and scan values exist. Omitted if no form data was provided. */\n measurement_variance?: Circumference\n /** URL to the uploaded 3D scan file */\n scan_url: string\n /** Frontal height of the residual limb (mm) */\n frontal_height: number\n /** Medio-lateral transverse dimension (mm) */\n transverse_ml: number\n /** Anterior-posterior transverse dimension (mm) */\n transverse_ap: number\n}\n\nexport interface Circumference {\n /** 2\" above the reference landmark (mm) */\n \"2_above\"?: number | undefined | null\n /** 1\" above the reference landmark (mm) */\n \"1_above\"?: number | undefined | null\n /** At the reference landmark (mm) */\n at_ref?: number | undefined | null\n /** 1\" below the reference landmark (mm) */\n \"1_below\"?: number | undefined | null\n /** 2\" below the reference landmark (mm) */\n \"2_below\"?: number | undefined | null\n /** 3\" below the reference landmark (mm) */\n \"3_below\"?: number | undefined | null\n /** 4\" below the reference landmark (mm) */\n \"4_below\"?: number | undefined | null\n /** 5\" below the reference landmark (mm) */\n \"5_below\"?: number | undefined | null\n /** 6\" below the reference landmark (mm) */\n \"6_below\"?: number | undefined | null\n /** 7\" below the reference landmark (mm) */\n \"7_below\"?: number | undefined | null\n /** 8\" below the reference landmark (mm) */\n \"8_below\"?: number | undefined | null\n /** 9\" below the reference landmark (mm) */\n \"9_below\"?: number | undefined | null\n}\n\n/** Ordered keys for mapping measurement arrays to Circumference fields */\nexport function getCircumferenceKeys(spacingType: \"AK\" | \"BK\"): (keyof Circumference)[] {\n const spacing = spacingType === \"AK\" ? 2 : 1\n const keys: (keyof Circumference)[] = []\n\n // Above reference (descending from 2 to 1)\n for (let i = 2; i >= 1; i -= spacing) {\n keys.push(`${i}_above` as keyof Circumference)\n }\n\n // At reference\n keys.push(\"at_ref\")\n\n // Below reference (ascending from 1 to 9)\n for (let i = spacing; i <= 9; i += spacing) {\n keys.push(`${i}_below` as keyof Circumference)\n }\n\n return keys\n}\n\n/** Convert a measurement values array to a Circumference object */\nexport function arrayToCircumference(values: (number | null | undefined)[], spacingType: \"AK\" | \"BK\"): Circumference {\n const keys = getCircumferenceKeys(spacingType)\n const result: Circumference = {}\n for (let i = 0; i < Math.min(values.length, keys.length); i++) {\n const val = values[i]\n if (val != null && !isNaN(val)) {\n (result as Record<string, number>)[keys[i]] = val\n }\n }\n return result\n}\n\n/** Convert a Circumference object to an ordered measurement values array */\nexport function circumferenceToArray(circ: Circumference | undefined, spacingType: \"AK\" | \"BK\"): number[] | undefined {\n if (!circ) return undefined\n const keys = getCircumferenceKeys(spacingType)\n const values = keys.map(key => {\n const val = circ[key]\n return val != null ? val : undefined\n })\n // Return undefined if all values are empty\n if (values.every(v => v == null)) return undefined\n return values as number[]\n}\n","import { useEffect, useMemo, useState } from \"react\"\nimport {\n GirthManagerCore,\n WIDGET_CONFIG,\n type GirthManagerResult,\n type WasmMeshSetType,\n} from \"@galileo/girth-manager-ui\"\n\nimport type { WidgetRequest, WidgetResponse } from \"./types\"\nimport { arrayToCircumference, circumferenceToArray } from \"./types\"\n\nexport interface GirthManagerWidgetProps {\n /** Widget input configuration */\n request: WidgetRequest\n /** Called when \"Continue to Next Step\" is clicked with the full response payload */\n onComplete?: (response: WidgetResponse) => void\n /** Pre-loaded WASM module. If omitted, the widget auto-loads galileo-core-geo. */\n wasmModule?: { WasmMeshSet: new () => WasmMeshSetType } | null\n}\n\nexport const GirthManagerWidget = ({ request, onComplete, wasmModule: externalWasm }: GirthManagerWidgetProps) => {\n const [autoWasm, setAutoWasm] = useState<{ WasmMeshSet: new () => WasmMeshSetType } | null>(null)\n const [wasmLoaded, setWasmLoaded] = useState(externalWasm !== undefined)\n\n // Auto-load WASM if no external module provided\n useEffect(() => {\n if (externalWasm !== undefined) {\n setWasmLoaded(true)\n return\n }\n let cancelled = false\n import(\"galileo-core-geo\").then(async (wasm) => {\n await wasm.default()\n if (!cancelled) {\n setAutoWasm(wasm)\n setWasmLoaded(true)\n }\n }).catch(() => {\n // WASM not available — proceed with JS fallback\n if (!cancelled) setWasmLoaded(true)\n })\n return () => { cancelled = true }\n }, [externalWasm])\n\n const wasmModule = externalWasm !== undefined ? externalWasm : autoWasm\n // Convert form measurements from Circumference object to ordered array for the core component\n const formMeasurementsArray = useMemo(\n () => circumferenceToArray(request.form_measurements, request.spacing_type),\n [request.form_measurements, request.spacing_type]\n )\n\n const handleComplete = (result: GirthManagerResult) => {\n // Build the WidgetResponse in the documented schema\n const scanValues = result.scanMeasurements.map(m => +(m.modifiedValue ?? m.originalValue).toFixed(1))\n const scanCircumference = arrayToCircumference(scanValues, request.spacing_type)\n\n let formCircumference: WidgetResponse[\"form_measurements\"] | undefined\n let varianceCircumference: WidgetResponse[\"measurement_variance\"] | undefined\n\n if (result.formMeasurements) {\n formCircumference = arrayToCircumference(result.formMeasurements, request.spacing_type)\n\n // Compute variance where both form and scan values exist\n const varianceValues = result.scanMeasurements.map((m, i) => {\n const form = result.formMeasurements?.[i]\n if (form == null || isNaN(form)) return null\n return +((m.modifiedValue ?? m.originalValue) - form).toFixed(1)\n })\n varianceCircumference = arrayToCircumference(varianceValues, request.spacing_type)\n }\n\n const response: WidgetResponse = {\n spacing_type: request.spacing_type,\n source_unit: \"mm\",\n file_format: result.fileFormat,\n measurement_source: result.formMeasurements ? \"form_provided\" : \"scan_derived\",\n is_double_wall: result.isDoubleWall,\n is_unit_converted: false,\n form_measurements: formCircumference,\n scan_measurements: scanCircumference,\n measurement_variance: varianceCircumference,\n scan_url: request.scan_url,\n frontal_height: +result.frontalHeight.toFixed(1),\n transverse_ml: +result.transverseML.toFixed(1),\n transverse_ap: +result.transverseAP.toFixed(1),\n }\n\n // Output to console as specified\n console.log(\"[GirthManagerWidget] WidgetResponse:\", JSON.stringify(response, null, 2))\n\n // Also call the callback if provided\n onComplete?.(response)\n }\n\n if (!wasmLoaded) {\n return (\n <div style={{ width: \"100%\", height: \"100%\", display: \"flex\", alignItems: \"center\", justifyContent: \"center\" }}>\n <span>Initializing...</span>\n </div>\n )\n }\n\n return (\n <div style={{ width: \"100%\", height: \"100%\", display: \"flex\" }}>\n <GirthManagerCore\n config={WIDGET_CONFIG}\n spacingType={request.spacing_type}\n scanUrl={request.scan_url}\n formMeasurements={formMeasurementsArray}\n onComplete={handleComplete}\n wasmModule={wasmModule}\n />\n </div>\n )\n}\n"],"names":["INTERNAL_CONFIG","WIDGET_CONFIG","GirthManagerConfigContext","createContext","useMeasurementStore","create","set","get","point","state","index","_","i","positions","aligned","cut","LABEL_X_OFFSET_RATIO","BVH_MAX_LEAF_TRIS","WELD_EPSILON","MM_PER_INCH","AUTO_SCALE_VOLUME_THRESHOLD","RETRY_OFFSETS","parseObjVertexColors","objText","lines","colors","hasColors","line","parts","r","g","b","transferVertexColors","geometry","origPositions","origColors","scaleFactor","posAttr","vertCount","outColors","origVertCount","minX","minY","minZ","maxX","maxY","maxZ","j","ox","oy","oz","gridRes","cellSizeX","cellSizeY","cellSizeZ","grid","gx","gy","gz","key","cell","x","y","z","bestDist","bestIdx","dx","dy","dz","nx","ny","nz","dist","THREE","MAX_WALL_THICKNESS_MM","COMPONENT_COLORS","buildComponentDebugGeometries","meshSet","innerIdx","vertices","faces","labels","componentFaces","comp","sortedKeys","a","geometries","geoLabels","compIdx","faceIndices","usedVerts","indices","fi","vi","newIdx","geo","label","processWithWasm","objContents","wasmModule","onStatus","objColors","wasScaled","innerShellExtracted","componentDebug","preExtractDebug","scale","error","processWithObjLoader","obj","OBJLoader","foundGeometry","child","stlToObjString","file","buffer","pos","STLLoader","weldKey","v","eps","k","cleanLoop","points","cleaned","p","calcLineLength","total","stitchOneLoop","segments","preferInner","keyToVec","weld","out","remaining","s","polylines","seg","expanded","longestLen","substantial","computeSliceAtYOnce","bvh","yPosition","useInnerSurface","slicePlane","Plane","Vector3","box","Box3","emptyResult","localTempLine","Line3","localTempVec","nodeBox","tri","ordered","lineLength","rightmostPoint","isClosed","computeSliceAtY","result","bestResult","offset","retry","computeCircumferenceAtPlane","planePoint","planeNormal","plane","buildBVH","MeshBVH","intersectMeshWithPlane","bvhOrGeometry","tempLine","tempVec","pts","stitchLoopNearPoint","nearPoint","bestLoop","poly","centroid","loopCentroid","loop","c","findBestCutPlane","greenPoint","redPoint","roughDir","sliceSpacing","axisNormal","fitAxisFromCentroids","sliceDir","centroids","slicePoint","segs","mean","cxx","cxy","cxz","cyy","cyz","czz","axis","iter","newAxis","len","pass","refined","change","ortho1","ortho2","evaluatePlane","normal","closed","bestNormal","bestCircumference","a1","a2","rad1","rad2","candidate","Quaternion","microBase","mOrtho1","mOrtho2","detectDoubleShell","indexAttr","axisLen","sliceHalfWidth","perp1","perp2","NUM_RAYS","hitTarget","totalHits","totalRays","sectionsAboveThreshold","t","sliceCenter","sumCx","sumCy","sumCz","count","f","i0","i1","i2","cx","cy","cz","dcx","dcy","dcz","origin","sectionHits","angle","dir","ray","rayHits","avgHitsOverall","computeBarycentricCoords","v0","v1","v2","dot00","dot01","dot02","dot11","dot12","invDenom","w","sliceMeshAtPlane","planeOrigin","keepPoint","keepAllComponents","keepDot","keepSideSign","oldPositions","oldIndices","colorAttr","oldColors","newPositions","newColors","newIndices","addVertex","idx","getVertex","interpolateAtPlane","d1","d2","vertexCache","edgeCache","distCache","signedDist","d","getOrAddOldVertex","oldIdx","getEdgeIntersection","idx1","idx2","isKept","k0","k1","k2","keepCount","keptIdx","discIdx1","discIdx2","discIdx","keptIdx1","keptIdx2","vK1","vK2","vInt1","vInt2","numFaces","facesToKeep","vtxToFaces","visitedFaces","components","queue","cur","neighbor","bestComp","bestCompDist","minDist","fIdx","finalVMap","finalPos","finalCol","finalIdx","nextVtx","oldV","newGeo","runPCAOnRegion","regionHeight","numSlices","sliceHeight","sliceMinY","sliceMaxY","sumX","sumY","sumZ","centroidMean","pi","validateProcessingResult","finalGeometry","greenY","redY","spacing","faceCount","height","firstSlice","secondSliceY","secondSlice","ratio","thirdSliceY","thirdSlice","ratio23","RETRY_STRATEGIES","MAX_RETRIES","applyRotation","landmarks","q","Matrix4","rotateGeometry","cutMeshAtY","mesh","currentLandmarks","cutOffsetInches","callbacks","refGeo","positionAttr","cutY","colorAttrCut","oldColorsCut","newColorsCut","below0","below1","below2","belowCount","belowIdx","above1Idx","above2Idx","aboveIdx","below1Idx","below2Idx","vBelow1","vBelow2","vertexToFaces","faceAdjacency","f1","f2","visited","component","current","redPt","bestComponent","j2","finalVertexMap","finalPositions","finalColorsCut","finalIndices","finalVertexIndex","faceIdx","newGeometry","targetY","rotate","positionAttrNew","dot","rotAxis","finalRed","reTrimY","reTrimGeo","size","runDoubleShellPipeline","originalLandmarkPositions","measurementSpacingMm","cutOrigin","slicedGeo","validation","runProcessingPipeline","landmarkPoints","originalGeometry","greenPt","shellResult","lastFailReason","attempt","strategy","redToGreen","perp","cutNormal","awayDir","offsetSign","roughAxis","isoBvh","isoRedY","isoGreenY","yUp","SCAN_STEP","isoMaxY","circumferences","circ","limbSpan","stableMin","stableMax","stableSlices","stableCircs","baseline","JUMP_THRESHOLD","greenSlice","STEP_SIZE","MAX_ITERATIONS","currentHeight","iteration","regionMin","regionMax","pcaAxis","newOrigin","bluePoint","gY","rY","sliceYs","DEG","totalCirc","tiltX","tiltZ","n","sum","bestTX","bestTZ","bestC","tx","tz","cTX","cTZ","tTX","tTZ","totalAngle","finalGeo","finalGreenY","finalRedY","err","ErrorDisplay","message","onDismiss","jsxs","jsx","LoadingSpinner","ClickableMesh","maxPoints","meshColor","meshOpacity","addLandmarkPoint","handleClick","useCallback","event","intersection","faceIndex","vertexIndices","bary","landmarkPoint","hasVertexColors","useMemo","material","LandmarkMarker","markerSize","color","hovered","setHovered","useState","Html","LandmarkMarkers","modelSize","resolvedLabels","Fragment","useCachedBVH","varianceColor","scanValue","formValue","absDiff","GREEN","YELLOW","RED","varianceColorAt","buildRibbonMesh","scanPts","formPts","c2","geom","mat","CircumferenceSliceInner","labelX","onDataChange","displayUnit","lineWidth","sliceData","linePoints","formRingPoints","pt","ribbonMesh","useEffect","labelGroupRef","useRef","leaderLine","useFrame","camera","forward","forwardXZ","right","maxProj","sidePoint","proj","labelDist","labelPos","Line","diff","arrow","diffColor","CircumferenceSlice","memo","CircumferenceMeasurements","startY","endY","onMeasurementsChange","reverseOrder","formMeasurements","originY","measurementsRef","cachedBVH","sliceYPositions","handleSliceDataChange","data","sortedMeasurements","VerticalDimension","distance","tickSize","groupRef","left","topPoint","bottomPoint","midPoint","topTickLeft","topTickRight","bottomTickLeft","bottomTickRight","CameraFit","isAligned","isCut","viewMode","sliceY","landmarkCount","invalidate","useThree","initializedRef","prevAlignedRef","prevCutRef","prevViewModeRef","meshSizeRef","saved3DCameraRef","prevLandmarkCountRef","setupFrontCamera","center","meshSize","aspect","frustumHeight","frustumWidth","orthoCamera","nudgeCamera","cam","theta","phi","newTheta","perspCamera","prev","prevMode","band","found","margin","contentW","contentH","frustumHeight2","AlignedOrbitControls","isDragging","OrbitControls","ScaleNotice","wasAutoScaled","ShellNotice","isDoubleShell","Stepper","steps","currentStep","accentColor","step","isCompleted","isActive","TransverseView","upperY","originSlice","clipPlane","mlLine","apLine","mlWidth","apWidth","minXPt","maxXPt","minZPt","maxZPt","formatValue","mm","unitLabel","DEFAULT_DEBUG_LAYERS","AXIS_COLORS","computeFullPCA","axes","eigenvalues","deflatedCov","eigenvalue","newV","vj","trueCenter","halfExtents","minProj","PCAAxes","pca","end","negEnd","OBBWireframe","edges","corners","edge","LandmarkAxis","angleFromY","IterativePCAAxes","axisLength","angleDeg","midY","FullRegionPCAAxis","halfLen","OBBAxis","CircumferenceScanLayer","scanData","maxCirc","barScale","halfWidth","threshWidth","ShellComponents","isInner","DebugOverlays","layers","OBBAlignmentLine","LAYER_CONFIG","groups","l","DebugPanel","onToggleLayer","group","GirthManagerCore","config","presetSpacingType","scanUrl","presetFormMeasurements","onComplete","isDebugUser","onAnalyticsEvent","externalWasmModule","setMesh","setModelSize","setIsDragging","isProcessing","setIsProcessing","processingStatus","setProcessingStatus","setViewMode","measurementSpacingInches","setMeasurementSpacingInches","showAmputationModal","setShowAmputationModal","pendingGeometry","setPendingGeometry","setComponentDebug","amputationType","setAmputationType","setDisplayUnit","isComputing","setIsComputing","computingMessage","setComputingMessage","setWasAutoScaled","showScaleNotice","setShowScaleNotice","setIsDoubleShell","setInnerShellExtracted","showShellNotice","setShowShellNotice","measurements","setMeasurements","adjustedStartY","setAdjustedStartY","adjustedEndY","setAdjustedEndY","originalEndY","setOriginalEndY","setError","debugMode","setDebugMode","debugLayers","setDebugLayers","showClippedRef","setShowClippedRef","clippedRefGeo","setClippedRefGeo","fileFormat","setFileFormat","showInsertModal","setShowInsertModal","setFormMeasurements","savedFormMeasurements","setSavedFormMeasurements","showFormOverlay","setShowFormOverlay","wasmReady","setWasmReady","wasmModuleRef","clearLandmarkPoints","removeLandmarkPoint","updateLandmarkPositions","setAligned","setCut","didCaptureRef","spanMm","m","form","finalizeGeometry","scaledBox","resultMesh","processFileContents","contents","fileName","name","isStl","blob","wasmResult","response","text","handleDragOver","e","handleDragLeave","handleDrop","handleAmputationSelect","type","handleProcess","ds","handleContinue","transverseML","transverseAP","frontalHeight","slice","stepperSteps","Canvas","lowerLandmark","upperLandmark","lowerY","layer","ref","sp","values","filled","getCircumferenceKeys","spacingType","keys","arrayToCircumference","val","circumferenceToArray","GirthManagerWidget","request","externalWasm","autoWasm","setAutoWasm","wasmLoaded","setWasmLoaded","cancelled","wasm","formMeasurementsArray","handleComplete","scanValues","scanCircumference","formCircumference","varianceCircumference","varianceValues"],"mappings":"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"}
|