import { useMemo } from 'react';
import { OrbitControls, Grid, Environment, Text } from '@react-three/drei';
import * as THREE from 'three';
import SceneCanvas from '../SceneCanvas';
import FallbackDiagram from '../FallbackDiagram';
import { useCanvasTheme } from '@/lib/theme';
export interface Bar3DInput {
/** Tipo de seção */
barType: 'flat' | 'circular';
/** Forma (apenas flat): 'placa' | 'l' | 't' | 'i' | 'rectangle' */
section?: 'placa' | 'l' | 't' | 'i' | 'rectangle';
/** Diâmetro (apenas circular, m) */
diameter?: number;
/** Largura da seção (flat, m) */
width?: number;
/** Comprimento da barra (m) */
length: number;
/** Ângulo de incidência (graus) — 0° = face plana contra o vento */
alpha: number;
/** Força Fx (kN) */
fxKN: number;
/** Força Fy (kN) */
fyKN: number;
/** Coeficiente Cx (apenas visualização) */
cx: number;
}
function BarModel({
barType,
section,
diameter,
width,
length,
alpha,
cx,
}: Bar3DInput) {
const theme = useCanvasTheme();
const isDark = theme === 'dark';
const barRadius = barType === 'circular' ? (diameter ?? 0.05) / 2 : Math.min(width ?? 0.1, 0.08) / 2;
const barThickness = barType === 'circular' ? barRadius : barRadius * 0.5;
const barColor = useMemo(() => {
const intensity = Math.min(1, Math.abs(cx) / 2.5);
const hue = 215 - intensity * 215;
const l = isDark ? (55 - intensity * 10) : (45 - intensity * 10);
return new THREE.Color(`hsl(${hue}, ${65 + intensity * 25}%, ${l}%)`);
}, [cx, isDark]);
// Ação do vento deve rotacionar a barra em seu próprio eixo longitudinal (roll).
// O eixo longitudinal na nossa geometria é o X.
const alphaRad = (alpha * Math.PI) / 180;
// A rotação deve ser negativa para que o vento (vindo de -Z) atinja as faces corretas conforme a NBR.
const barRotationX = -alphaRad;
return (
{/* Seta do Vento (Fixa Globalmente, soprando em +Z) */}
{/* Barra Rotacionada (Roll) */}
{/* Eixo principal da barra ao longo do eixo X */}
{barType === 'circular' ? (
) : (
)}
{/* Eixos de referência locais da barra */}
{/* Marca de origem */}
α={alpha}° | Cx={cx.toFixed(2)}
);
}
function SectionShape({
section,
width,
length,
color,
thickness,
}: {
section: 'placa' | 'l' | 't' | 'i' | 'rectangle';
width: number;
length: number;
color: THREE.Color;
thickness: number;
}) {
switch (section) {
case 'placa':
return (
);
case 'l':
return (
);
case 't':
return (
);
case 'i':
return (
);
case 'rectangle':
return (
);
}
}
export default function Bar3DViewer(input: Bar3DInput) {
const theme = useCanvasTheme();
const isDark = theme === 'dark';
const { length, width, diameter } = input;
const size = Math.max(length * 0.6, (width ?? diameter ?? 0.1) * 8);
const fallback = (
);
return (
);
}