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 ( ); }