Files
anatomia/frontend/src/components/ClippingControls.tsx
T

109 lines
3.7 KiB
TypeScript

import { useAtlasStore, type ClipAxis } from "../store/useAtlasStore.js";
const AXES: { value: ClipAxis; label: string }[] = [
{ value: "sagittal", label: "Sagital (esq./dir.)" },
{ value: "coronal", label: "Coronal / Frontal (ant./post.)" },
{ value: "transverse", label: "Transversal (sup./inf.)" },
];
export function ClippingControls() {
const clipping = useAtlasStore((s) => s.clipping);
const setClippingEnabled = useAtlasStore((s) => s.setClippingEnabled);
const setClipAxis = useAtlasStore((s) => s.setClipAxis);
const setClipPosition = useAtlasStore((s) => s.setClipPosition);
const setClipTilt = useAtlasStore((s) => s.setClipTilt);
return (
<div className="space-y-2 border-t border-white/10 pt-3">
<label className="flex items-center gap-2 text-sm cursor-pointer">
<input
type="checkbox"
checked={clipping.enabled}
onChange={(e) => setClippingEnabled(e.target.checked)}
className="accent-accent"
/>
Dissecção virtual (plano de corte)
</label>
{clipping.enabled && (
<div className="space-y-3 pl-1">
<div className="space-y-1">
<label className="text-xs text-slate-400">Orientação de base</label>
<select
value={clipping.axis}
onChange={(e) => setClipAxis(e.target.value as ClipAxis)}
className="w-full text-sm bg-white/5 border border-white/10 rounded px-2 py-1"
>
{AXES.map((a) => (
<option key={a.value} value={a.value}>
{a.label}
</option>
))}
</select>
</div>
<div className="space-y-1">
<label className="text-xs text-slate-400">
Posição do corte no corpo ({clipping.position.toFixed(2)})
</label>
<input
type="range"
min={-1}
max={1}
step={0.01}
value={clipping.position}
onChange={(e) => setClipPosition(Number(e.target.value))}
className="w-full accent-accent"
/>
</div>
<div className="space-y-1">
<label className="text-xs text-slate-400">
Inclinação oblíqua — eixo 1 ({clipping.tiltX.toFixed(0)}°)
</label>
<input
type="range"
min={-89}
max={89}
step={1}
value={clipping.tiltX}
onChange={(e) => setClipTilt(Number(e.target.value), clipping.tiltZ)}
className="w-full accent-accent"
/>
</div>
<div className="space-y-1">
<label className="text-xs text-slate-400">
Inclinação oblíqua — eixo 2 ({clipping.tiltZ.toFixed(0)}°)
</label>
<input
type="range"
min={-89}
max={89}
step={1}
value={clipping.tiltZ}
onChange={(e) => setClipTilt(clipping.tiltX, Number(e.target.value))}
className="w-full accent-accent"
/>
</div>
{(clipping.tiltX !== 0 || clipping.tiltZ !== 0) && (
<button
onClick={() => setClipTilt(0, 0)}
className="text-xs text-accent hover:underline"
>
Zerar inclinação (voltar ao corte puro)
</button>
)}
<p className="text-[11px] text-slate-500 leading-snug">
A posição desliza o corte por todo o corpo carregado (não só pelo
centro) e a inclinação permite cortes oblíquos a partir de
qualquer um dos 3 planos anatômicos de base.
</p>
</div>
)}
</div>
);
}