From 7e8963135b8f44c195937e4830bdebe4d31f4a48 Mon Sep 17 00:00:00 2001 From: Rodrigo Bertoldo de Sousa Martins Date: Thu, 10 Sep 2026 20:07:34 -0300 Subject: [PATCH] use corpo real exame fisico --- .../src/components/viewer/ExamMarkers.tsx | 58 +++++++++ frontend/src/components/viewer/Scene.tsx | 15 ++- frontend/src/data/physicalExam.ts | 91 ++++++++------- frontend/src/routes/PhysicalExamPage.tsx | 110 +++++++----------- 4 files changed, 166 insertions(+), 108 deletions(-) create mode 100644 frontend/src/components/viewer/ExamMarkers.tsx diff --git a/frontend/src/components/viewer/ExamMarkers.tsx b/frontend/src/components/viewer/ExamMarkers.tsx new file mode 100644 index 0000000..ed4f43e --- /dev/null +++ b/frontend/src/components/viewer/ExamMarkers.tsx @@ -0,0 +1,58 @@ +import { Html } from "@react-three/drei"; +import * as THREE from "three"; +import { useAtlasStore } from "../../store/useAtlasStore.js"; +import type { ExamPoint, ExamTechnique } from "../../data/physicalExam.js"; +import { TECHNIQUES } from "../../data/physicalExam.js"; + +// Roda DENTRO do mesmo do Scene (recebido via prop "children" — +// ver Scene.tsx) pra poder usar do drei e o bounding box real do +// corpo carregado (contentBox no store, o mesmo usado pelo plano de corte e +// pela navegação rápida por região). Cada ponto de exame é dado como +// FRAÇÃO do corpo (ver data/physicalExam.ts), convertida aqui pra +// coordenada absoluta — assim os pontos acompanham o corpo real não +// importa a escala/origem carregada. +export function ExamMarkers({ + points, + selectedId, + onSelect, +}: { + points: ExamPoint[]; + selectedId: string | null; + onSelect: (id: string) => void; +}) { + const contentBox = useAtlasStore((s) => s.contentBox); + if (!contentBox) return null; + + const min = new THREE.Vector3(...contentBox.min); + const max = new THREE.Vector3(...contentBox.max); + const techniqueColor = (t: ExamTechnique) => TECHNIQUES.find((x) => x.key === t)?.color ?? "#fff"; + + return ( + <> + {points.map((p) => { + const [fx, fy, fz] = p.fraction; + const position: [number, number, number] = [ + THREE.MathUtils.lerp(min.x, max.x, fx), + THREE.MathUtils.lerp(min.y, max.y, fy), + THREE.MathUtils.lerp(min.z, max.z, fz), + ]; + const isSelected = p.id === selectedId; + const color = techniqueColor(p.technique); + return ( + + -
+ + + +

Técnicas de Exame

{TECHNIQUES.map((t) => ( @@ -68,24 +85,11 @@ export default function PhysicalExamPage() {
-
-

Como usar

-

- Marque as técnicas que quer estudar e clique nos pontos coloridos - sobre o boneco. Cada ponto explica onde encostar, como fazer a - manobra e o que ela avalia — pensado como revisão rápida de - propedêutica, não substitui a prática supervisionada. -

-
- -
-

Sistemas cobertos

- {[...new Set(EXAM_POINTS.map((p) => p.system))].map((sys) => ( -

- {sys} ({EXAM_POINTS.filter((p) => p.system === sys).length}) -

- ))} -
+

+ Ligue uma camada (ex: Esquelético) como referência, marque as + técnicas que quer estudar e clique nos pontos coloridos sobre o + corpo. Use o menu de regiões pra focar rápido numa parte do corpo. +

{(leftOpen || rightOpen) && ( @@ -99,6 +103,14 @@ export default function PhysicalExamPage() { )}
+ + { + setSelectedId(id); + setRightOpen(true); + }} /> + + + - - - - - - - - - {visiblePoints.map((p) => { - const isSelected = p.id === selectedId; - const color = techniqueColor(p.technique); - return ( - -