fix new exam

This commit is contained in:
Rodrigo Bertoldo de Sousa Martins committed 2026-09-10 21:56:11 -03:00
1 parent 7e8834fbfd
commit 93f92d9587
1 file changed
+27 -6
+27 -6
View File
@@ -136,6 +136,14 @@ export function ExamMarkers({
onSelect: (id: string) => void; onSelect: (id: string) => void;
}) { }) {
const { scene } = useThree(); const { scene } = useThree();
// As mesmas CameraControls registradas pelo Scene.tsx (makeDefault) —
// acessadas aqui pra enquadrar a câmera na região dos pontos assim que
// os ossos são achados, sem depender/competir com o efeito de
// enquadramento "corpo inteiro" do Scene.tsx (que tem sua própria
// corrida contra o carregamento assíncrono do modelo).
const controls = useThree((state) => state.controls) as unknown as {
fitToBox: (box: THREE.Box3, enableTransition: boolean, opts?: Record<string, number>) => void;
} | null;
const contentBox = useAtlasStore((s) => s.contentBox); const contentBox = useAtlasStore((s) => s.contentBox);
const [anchors, setAnchors] = useState<AnchorBoxes>({}); const [anchors, setAnchors] = useState<AnchorBoxes>({});
@@ -143,17 +151,30 @@ export function ExamMarkers({
let cancelled = false; let cancelled = false;
let attempts = 0; let attempts = 0;
let timer: ReturnType<typeof setTimeout>; let timer: ReturnType<typeof setTimeout>;
let framed = false;
const cache = new Map<string, THREE.Box3>(); const cache = new Map<string, THREE.Box3>();
function tryCompute() { function tryCompute() {
if (cancelled) return; if (cancelled) return;
const boxes = computeAnchorBoxes(scene, cache); const boxes = computeAnchorBoxes(scene, cache);
setAnchors(boxes); setAnchors(boxes);
attempts += 1; attempts += 1;
// Só continua tentando o que ainda falta (thorax/pelvis/head) — uma
// vez achados, cada Box3 fica em cache e não é recalculado de novo, // Assim que der pra montar um box com tórax+bacia+crânio, enquadra a
// então parar assim que os 3 principais existirem evita trabalho // câmera nele DIRETAMENTE (uma vez só) — garante que a câmera mostre
// repetido (percorrer geometria) rodando junto com o resto da cena. // exatamente a região onde os pontos de exame estão, não importa o
// que outro efeito de câmera esteja fazendo.
const gotCore = boxes.thorax && boxes.pelvis && boxes.head; const gotCore = boxes.thorax && boxes.pelvis && boxes.head;
if (gotCore && !framed && controls) {
framed = true;
const region = boxes.thorax!.clone().union(boxes.pelvis!).union(boxes.head!);
controls.fitToBox(region, true, {
paddingLeft: 0.3,
paddingRight: 0.3,
paddingTop: 0.2,
paddingBottom: 0.2,
});
}
if (!gotCore && attempts < 30) { if (!gotCore && attempts < 30) {
timer = setTimeout(tryCompute, 300); timer = setTimeout(tryCompute, 300);
} else if (!boxes.thorax) { } else if (!boxes.thorax) {
@@ -170,7 +191,7 @@ export function ExamMarkers({
cancelled = true; cancelled = true;
clearTimeout(timer); clearTimeout(timer);
}; };
}, [scene]); }, [scene, controls]);
const techniqueColor = (t: ExamTechnique) => TECHNIQUES.find((x) => x.key === t)?.color ?? "#fff"; const techniqueColor = (t: ExamTechnique) => TECHNIQUES.find((x) => x.key === t)?.color ?? "#fff";
const bodyBox = contentBox const bodyBox = contentBox
@@ -199,7 +220,7 @@ export function ExamMarkers({
const isSelected = p.id === selectedId; const isSelected = p.id === selectedId;
const color = techniqueColor(p.technique); const color = techniqueColor(p.technique);
return ( return (
<Html key={p.id} position={position} center distanceFactor={4} zIndexRange={[10, 0]}> <Html key={p.id} position={position} center distanceFactor={4}>
<button <button
onClick={() => onSelect(p.id)} onClick={() => onSelect(p.id)}
title={p.name} title={p.name}