import { useMemo } from 'react'; import { Grid, Environment, Text } from '@react-three/drei'; import { ViewerOrbitControls as OrbitControls } from './ViewerOrbitControls'; import * as THREE from 'three'; import SceneCanvas from '../SceneCanvas'; import FallbackDiagram from '../FallbackDiagram'; import { WindArrow } from './WindArrow'; import { useCanvasTheme } from '@/lib/theme'; export interface Bridge3DInput { /** Maior vão Lₚ (m) */ lp: number; /** Largura do tabuleiro B (m) */ width: number; /** Altura do tabuleiro z (m) */ deckHeight: number; /** Altura equivalente H_eq (m) — soma de áreas expostas por metro */ heg: number; /** Coeficiente de arrasto Cx (adimensional) */ cx: number; /** Coeficiente de sustentação Cz (adimensional) */ cz: number; /** Força de arrasto por unidade de comprimento Fx (kN/m) */ fxPerLength: number; /** Força de sustentação por unidade de comprimento Fz (kN/m) */ fzPerLength: number; /** Ângulo de ataque do vento (graus) */ alpha: number; } function BridgeModel({ lp, width, deckHeight, heg, cx, alpha, }: Bridge3DInput) { const theme = useCanvasTheme(); const isDark = theme === 'dark'; const halfL = lp / 2; const halfW = width / 2; const deckThickness = Math.max(heg, 0.8); const deckY = deckHeight; // Cor do tabuleiro baseada em Cx const deckColor = useMemo(() => { const intensity = Math.min(1, Math.abs(cx) / 3); const hue = 200 - intensity * 60; const l = isDark ? (60 - intensity * 8) : (50 - intensity * 8); return new THREE.Color(`hsl(${hue}, ${55 + intensity * 30}%, ${l}%)`); }, [cx, isDark]); // Pilar heights: posicionar 3 pilares ao longo do vão const pillarHeights = useMemo(() => [deckY - 0.5, deckY - 0.5, deckY - 0.5], [deckY]); const barrierColor = isDark ? '#cbd5e1' : '#94a3b8'; const pillarColor = isDark ? '#94a3b8' : '#64748b'; return ( {/* Tabuleiro (deck) */} {/* Guarda-rodas/barreira lateral */} {/* Pilares (3 ao longo do comprimento) */} {pillarHeights.map((h, i) => { const x = i === 0 ? -halfL + halfL * 0.3 : i === 1 ? 0 : halfL - halfL * 0.3; return ( ); })} {/* Solo / água */} {/* Seta de Vento (bate no meio do tabuleiro) */} Lp={lp}m | B={width}m | Cx={cx.toFixed(2)} ); } export default function Bridge3DViewer(input: Bridge3DInput) { const theme = useCanvasTheme(); const isDark = theme === 'dark'; const { lp, deckHeight, width } = input; const dist = Math.max(lp * 0.6, deckHeight * 2); const fallback = ( ); return ( ); }