planos anatomicos

Signed-off-by: Rodrigo Bertoldo de Sousa Martins <rodrigo@MacBook-Air-de-Rodrigo.local>
This commit is contained in:
Rodrigo Bertoldo de Sousa Martins committed 2026-09-14 21:06:47 -03:00
1 parent 06ace7505c
commit 19bc92356f
1 file changed
+141 -30
+141 -30
View File
@@ -19,24 +19,111 @@ const PLANES: PlaneDef[] = [
{ key: "transverse", label: "Plano Transversal (Axial)", color: "#f2c14e", args: [1.2, 1.2], position: [0, 0.9, 0], rotation: [Math.PI / 2, 0, 0] },
];
const AXES: { label: string; from: [number, number, number]; to: [number, number, number]; color: string }[] = [
{ label: "Superior", from: [0, 0.9, 0], to: [0, 1.9, 0], color: "#f87171" },
{ label: "Inferior", from: [0, 0.9, 0], to: [0, -0.1, 0], color: "#f87171" },
{ label: "Anterior", from: [0, 0.9, 0], to: [0, 0.9, 0.9], color: "#34d399" },
{ label: "Posterior", from: [0, 0.9, 0], to: [0, 0.9, -0.9], color: "#34d399" },
{ label: "Direita (do paciente)", from: [0, 0.9, 0], to: [-0.7, 0.9, 0], color: "#a78bfa" },
{ label: "Esquerda (do paciente)", from: [0, 0.9, 0], to: [0.7, 0.9, 0], color: "#a78bfa" },
interface AxisDef {
label: string;
from: [number, number, number];
to: [number, number, number];
color: string;
}
interface AxisGroup {
key: string;
label: string;
hint: string;
axes: AxisDef[];
}
// Cada grupo é ancorado numa região reconhecível do boneco (tronco, braço,
// perna) — como pedido, usando o modelo de regiões do corpo como base pras
// setas em vez de setas soltas no espaço. Ficam com toggle independente
// porque mostrar todos os pares de uma vez deixaria o modelo ilegível.
const AXIS_GROUPS: AxisGroup[] = [
{
key: "principal",
label: "Eixos principais do corpo",
hint: "Superior/Inferior, Anterior/Posterior, Direita/Esquerda",
axes: [
{ label: "Superior", from: [0, 0.9, 0], to: [0, 1.9, 0], color: "#f87171" },
{ label: "Inferior", from: [0, 0.9, 0], to: [0, -0.1, 0], color: "#f87171" },
{ label: "Anterior", from: [0, 0.9, 0], to: [0, 0.9, 0.9], color: "#34d399" },
{ label: "Posterior", from: [0, 0.9, 0], to: [0, 0.9, -0.9], color: "#34d399" },
{ label: "Direita (do paciente)", from: [0, 0.9, 0], to: [-0.7, 0.9, 0], color: "#a78bfa" },
{ label: "Esquerda (do paciente)", from: [0, 0.9, 0], to: [0.7, 0.9, 0], color: "#a78bfa" },
],
},
{
key: "medial-lateral",
label: "Medial / Lateral (no braço)",
hint: "Em relação à linha média do corpo",
axes: [
{ label: "Medial", from: [-0.28, 1.1, 0.06], to: [-0.04, 1.1, 0.06], color: "#f2c14e" },
{ label: "Lateral", from: [-0.28, 1.1, 0.06], to: [-0.58, 1.1, 0.06], color: "#f2c14e" },
],
},
{
key: "proximal-distal",
label: "Proximal / Distal (na perna)",
hint: "Em relação à raiz do membro (tronco)",
axes: [
{ label: "Proximal", from: [-0.11, 0.32, 0], to: [-0.11, 0.62, 0], color: "#60a5fa" },
{ label: "Distal", from: [-0.11, 0.32, 0], to: [-0.11, -0.02, 0], color: "#60a5fa" },
],
},
{
key: "superficial-profundo",
label: "Superficial / Profundo (no abdome)",
hint: "Em relação à superfície do corpo",
axes: [
{ label: "Superficial", from: [0, 0.75, 0], to: [0, 0.75, 0.32], color: "#f472b6" },
{ label: "Profundo", from: [0, 0.75, 0.32], to: [0, 0.75, -0.18], color: "#f472b6" },
],
},
];
const GLOSSARY: { term: string; def: string }[] = [
{ term: "Anterior / Posterior", def: "Em direção à frente (ventral) ou para trás (dorsal) do corpo." },
{ term: "Superior / Inferior", def: "Em direção à cabeça (cranial) ou aos pés (caudal)." },
{ term: "Medial / Lateral", def: "Mais próximo (medial) ou mais distante (lateral) do plano mediano/sagital." },
{ term: "Proximal / Distal", def: "Mais próximo (proximal) ou mais distante (distal) do tronco/raiz do membro." },
{ term: "Superficial / Profundo", def: "Mais próximo (superficial) ou mais distante (profundo) da superfície do corpo." },
{ term: "Plano Sagital", def: "Divide o corpo em partes esquerda e direita (é 'mediano' quando passa exatamente pelo centro)." },
{ term: "Plano Coronal (Frontal)", def: "Divide o corpo em partes anterior e posterior." },
{ term: "Plano Transversal (Axial)", def: "Divide o corpo em partes superior e inferior." },
interface GlossaryEntry {
term: string;
def: string;
}
interface GlossaryGroup {
heading: string;
entries: GlossaryEntry[];
}
const GLOSSARY_GROUPS: GlossaryGroup[] = [
{
heading: "Eixos principais",
entries: [
{ term: "Anterior / Posterior", def: "Em direção à frente (ventral) ou para trás (dorsal) do corpo. Em quadrúpedes e embriologia usa-se \"Ventral/Dorsal\" com o mesmo sentido." },
{ term: "Superior / Inferior", def: "Em direção à cabeça (cranial) ou aos pés (caudal). \"Cranial/Caudal\" é usado sobretudo em neuroanatomia e no tronco." },
{ term: "Direita / Esquerda", def: "Sempre referidas ao lado do PACIENTE, não de quem observa — por isso é comum escrever \"direita do paciente\" pra evitar confusão em imagens." },
],
},
{
heading: "Relação entre partes",
entries: [
{ term: "Medial / Lateral", def: "Mais próximo (medial) ou mais distante (lateral) do plano mediano (o plano sagital que passa exatamente pelo centro do corpo)." },
{ term: "Superficial / Profundo", def: "Mais próximo (superficial) ou mais distante (profundo) da superfície do corpo." },
{ term: "Externo / Interno", def: "Mais distante (externo) ou mais próximo (interno) do centro de um órgão oco ou cavidade — ex.: camada externa vs. interna da parede do intestino." },
{ term: "Ipsilateral / Contralateral", def: "Duas estruturas do MESMO lado do corpo (ipsilateral) ou de lados OPOSTOS (contralateral) — ex.: o nervo frênico direito é ipsilateral ao pulmão direito e contralateral ao esquerdo." },
],
},
{
heading: "Nos membros",
entries: [
{ term: "Proximal / Distal", def: "Mais próximo (proximal) ou mais distante (distal) da raiz do membro (onde ele se une ao tronco)." },
{ term: "Palmar / Dorsal (mão)", def: "Face da palma da mão (palmar, também chamada volar) ou face do dorso da mão (dorsal)." },
{ term: "Plantar / Dorsal (pé)", def: "Face da sola do pé (plantar) ou face de cima do pé (dorsal)." },
],
},
{
heading: "Planos de secção",
entries: [
{ term: "Plano Sagital", def: "Divide o corpo em partes esquerda e direita (é \"mediano\" quando passa exatamente pelo centro)." },
{ term: "Plano Coronal (Frontal)", def: "Divide o corpo em partes anterior e posterior." },
{ term: "Plano Transversal (Axial)", def: "Divide o corpo em partes superior e inferior." },
],
},
];
export default function PlanesPage() {
@@ -45,7 +132,12 @@ export default function PlanesPage() {
coronal: false,
transverse: false,
});
const [showAxes, setShowAxes] = useState(true);
const [visibleAxisGroups, setVisibleAxisGroups] = useState<Record<string, boolean>>({
principal: true,
"medial-lateral": false,
"proximal-distal": false,
"superficial-profundo": false,
});
const [leftOpen, setLeftOpen] = useState(false);
const [rightOpen, setRightOpen] = useState(false);
@@ -78,10 +170,23 @@ export default function PlanesPage() {
</label>
))}
<label className="flex items-center gap-2 text-sm cursor-pointer pt-2 border-t border-white/10 mt-3">
<input type="checkbox" checked={showAxes} onChange={() => setShowAxes((v) => !v)} className="accent-accent" />
Eixos e termos de direção
</label>
<h3 className="text-xs uppercase tracking-wide text-slate-400 pt-3 border-t border-white/10 mt-3">
Termos de Direção
</h3>
{AXIS_GROUPS.map((g) => (
<label key={g.key} className="flex items-start gap-2 text-sm cursor-pointer">
<input
type="checkbox"
checked={visibleAxisGroups[g.key]}
onChange={() => setVisibleAxisGroups((v) => ({ ...v, [g.key]: !v[g.key] }))}
className="accent-accent mt-0.5"
/>
<span>
{g.label}
<span className="block text-[11px] text-slate-500">{g.hint}</span>
</span>
</label>
))}
</aside>
{(leftOpen || rightOpen) && (
@@ -121,9 +226,9 @@ export default function PlanesPage() {
</mesh>
))}
{showAxes &&
AXES.map((a) => (
<group key={a.label}>
{AXIS_GROUPS.filter((g) => visibleAxisGroups[g.key]).flatMap((g) =>
g.axes.map((a) => (
<group key={`${g.key}-${a.label}`}>
<Line points={[a.from, a.to]} color={a.color} lineWidth={2} />
<Html position={a.to} center distanceFactor={4}>
<div
@@ -134,7 +239,8 @@ export default function PlanesPage() {
</div>
</Html>
</group>
))}
)),
)}
<CameraControls makeDefault />
</Canvas>
@@ -142,7 +248,7 @@ export default function PlanesPage() {
<aside
className={`fixed md:static inset-y-0 right-0 z-30 w-[86vw] max-w-[320px] md:w-auto
border-l border-white/10 bg-panel p-4 overflow-y-auto space-y-3
border-l border-white/10 bg-panel p-4 overflow-y-auto space-y-4
transition-transform duration-200 md:translate-x-0
${rightOpen ? "translate-x-0" : "translate-x-full"}`}
>
@@ -154,10 +260,15 @@ export default function PlanesPage() {
✕ Fechar
</button>
<h3 className="text-xs uppercase tracking-wide text-slate-400">Glossário de Direções</h3>
{GLOSSARY.map((g) => (
<div key={g.term}>
<p className="text-sm font-medium text-white">{g.term}</p>
<p className="text-xs text-slate-400">{g.def}</p>
{GLOSSARY_GROUPS.map((group) => (
<div key={group.heading} className="space-y-2">
<p className="text-[11px] uppercase tracking-wide text-slate-500">{group.heading}</p>
{group.entries.map((g) => (
<div key={g.term}>
<p className="text-sm font-medium text-white">{g.term}</p>
<p className="text-xs text-slate-400">{g.def}</p>
</div>
))}
</div>
))}
</aside>