From 87085d70207ad36c14e0a166eba55a8a726e328a Mon Sep 17 00:00:00 2001 From: Rodrigo Bertoldo de Sousa Martins Date: Tue, 8 Sep 2026 13:53:07 -0300 Subject: [PATCH] fix4 --- frontend/src/components/viewer/Scene.tsx | 27 ++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/frontend/src/components/viewer/Scene.tsx b/frontend/src/components/viewer/Scene.tsx index 7bb249e..f6b15ea 100644 --- a/frontend/src/components/viewer/Scene.tsx +++ b/frontend/src/components/viewer/Scene.tsx @@ -24,6 +24,29 @@ function useClippingPlanes(): THREE.Plane[] { }, [enabled, axis, position]); } +function isFiniteVec3(v: THREE.Vector3): boolean { + return Number.isFinite(v.x) && Number.isFinite(v.y) && Number.isFinite(v.z); +} + +// Une o bounding box só das malhas VISÍVEIS e com geometria válida — +// alguns objetos do dataset real (anotações/curvas do Z-Anatomy) podem ter +// vértices degenerados/NaN, e Box3.setFromObject(scene) ingenuamente +// incluiria isso, distorcendo o enquadramento (ou escondendo tudo o mais +// fora do "zoom" resultante). +function computeVisibleBoundingBox(root: THREE.Object3D): THREE.Box3 { + const union = new THREE.Box3(); + const tmp = new THREE.Box3(); + root.traverse((obj) => { + const mesh = obj as THREE.Mesh; + if (!mesh.isMesh || !mesh.visible) return; + tmp.setFromObject(mesh); + if (tmp.isEmpty()) return; + if (!isFiniteVec3(tmp.min) || !isFiniteVec3(tmp.max)) return; + union.union(tmp); + }); + return union; +} + function CameraController({ modelFiles }: { modelFiles: string[] }) { const controlsRef = useRef(null); const { scene, camera } = useThree(); @@ -37,7 +60,7 @@ function CameraController({ modelFiles }: { modelFiles: string[] }) { useEffect(() => { if (!controlsRef.current || modelFiles.length === 0) return; const id = requestAnimationFrame(() => { - const box = new THREE.Box3().setFromObject(scene); + const box = computeVisibleBoundingBox(scene); if (box.isEmpty()) return; const size = box.getSize(new THREE.Vector3()).length(); // Ajusta os planos de corte da câmera ao tamanho real do conteúdo — @@ -60,7 +83,7 @@ function CameraController({ modelFiles }: { modelFiles: string[] }) { if (!focusRequest || !controlsRef.current) return; const obj = scene.getObjectByName(focusRequest.slug); if (!obj) return; - const box = new THREE.Box3().setFromObject(obj); + const box = computeVisibleBoundingBox(obj); if (box.isEmpty()) return; controlsRef.current.fitToBox(box, true, { paddingLeft: 0.4,