diff --git a/app/src/components/WindFlowGrid2D.tsx b/app/src/components/WindFlowGrid2D.tsx index 29a8e0d..8e07ccb 100644 --- a/app/src/components/WindFlowGrid2D.tsx +++ b/app/src/components/WindFlowGrid2D.tsx @@ -1,11 +1,10 @@ - interface WindFlowGrid2DProps { type: string; - params: Record; + params?: Record; } -export function WindFlowGrid2D({ type, params }: WindFlowGrid2DProps) { - // Estilos globais e animações integrados no SVG +export function WindFlowGrid2D({ type }: WindFlowGrid2DProps) { + // Estilos de animação e keyframes para os SVGs const styleBlock = ( ); + // Define quais itens de legenda devem ser exibidos para cada tipo de módulo + const getVisibleLegendItems = () => { + const hasCpi = ['warehouse', 'vault', 'dome', 'cylinder'].includes(type); + const hasVortex = ['cylinder', 'dynamics', 'sign', 'tower'].includes(type); + const hasLift = ['bridge', 'isolated-roof'].includes(type); + + return { + wind: true, + fast: true, + vortex: hasVortex, + vortexSpin: ['cylinder', 'dynamics', 'sign'].includes(type), + cpiPos: hasCpi, + cpiNeg: hasCpi, + lift: hasLift, + }; + }; + const getViewLabel = () => { switch (type) { - case 'tower': - case 'cylinder': - case 'bar': - return 'Vista Aérea (Superior / Planta Baixa)'; case 'bridge': - case 'sign': - case 'warehouse': + case 'isolated-roof': case 'vault': case 'dome': - case 'dynamics': - case 'isolated-roof': + case 'warehouse': return 'Vista Lateral (Corte Transversal)'; + case 'cylinder': + case 'sign': + case 'bar': + case 'dynamics': + case 'tower': + return 'Vista Superior (Planta) / Aérea'; default: return 'Vista Esquemática'; } }; - // Desenha os vetores de Cpi (pressão interna) dentro do perfil do galpão/cilindro/abóbada - const renderCpiVectors = (cpi: number, shape: 'rect' | 'arch' | 'circle' | 'dome') => { - if (cpi === 0) return null; - const isPositive = cpi > 0; - const marker = isPositive ? 'url(#cpi-pos)' : 'url(#cpi-neg)'; - const strokeClass = isPositive ? 'cpi-arrow-pos' : 'cpi-arrow-neg'; + // Renderizador do grid didático de cenários + const renderScenarios = () => { + const legendDef = ( + + + + + + + + + + + + + + + ); - if (shape === 'arch') { - // Abóbada: 3 vetores radiais - return ( - - {isPositive ? ( - <> - - - - - ) : ( - <> - - - - - )} - - ); - } - - if (shape === 'rect') { - // Galpão: paredes e telhado - return ( - - {isPositive ? ( - <> - {/* Paredes */} - - - {/* Telhado */} - - - - ) : ( - <> - - - - - - )} - - ); - } - - if (shape === 'circle') { - // Cilindro: 4 direções - return ( - - {isPositive ? ( - <> - - - - - - ) : ( - <> - - - - - - )} - - ); - } - - if (shape === 'dome') { - // Cúpula - return ( - - {isPositive ? ( - <> - - - - - - - ) : ( - <> - - - - - - - )} - - ); - } - - return null; - }; - - const renderActiveSimulation = () => { switch (type) { - case 'bridge': { - const alpha = Number(params.alpha || 0); - const rotationAngle = alpha * 3; + case 'bridge': return ( - - {styleBlock} - - - - - - - - +
+ {/* Caso 1 */} +
+ Caso A: Vento Frontal Horizontal (0°) +
+ + {styleBlock} + + + + + + +
+

Escoamento simétrico ao redor do tabuleiro. Arrasto máximo horizontal, sustentação nula.

+
- - - - - + {/* Caso 2 */} +
+ Caso B: Vento Ascendente (+5°) +
+ + {styleBlock} + {legendDef} + + + + + + + + {/* Força de sustentação positiva */} + + +Fz (Lift) + +
+

O vento atinge o tabuleiro de baixo para cima, defletindo o fluxo e gerando força de sustentação vertical positiva.

+
- {alpha !== 0 && ( - - 0 ? "M 200,75 L 200,30" : "M 200,125 L 200,170"} - stroke={alpha > 0 ? "#10b981" : "#ef4444"} - strokeWidth="3" - fill="none" - markerEnd="url(#arrow)" - /> - 0 ? 45 : 160} fill={alpha > 0 ? "#10b981" : "#ef4444"} className="text-xs font-bold font-mono"> - {alpha > 0 ? '+Fz (Sustentação)' : '-Fz (Abaixamento)'} - - - )} - - - - - - + {/* Caso 3 */} +
+ Caso C: Vento Descendente (-5°) +
+ + {styleBlock} + {legendDef} + + + + + + + + {/* Força de sustentação negativa */} + + -Fz (Downforce) + +
+

Vento de cima para baixo empurra o tabuleiro para baixo, aumentando a carga vertical sobre as vigas principais.

+
+
); - } - case 'tower': { - const section = params.section || 'square'; - const alphaWind = Number(params.alphaWind || 0); + case 'isolated-roof': return ( - - {styleBlock} - - - - - - - - +
+ {/* Caso 1 */} +
+ Caso A: Escoamento Livre por Baixo +
+ + {styleBlock} + + + + {/* Telhado inclinado */} + + + {/* Linhas de vento desviando suavemente */} + + + + + +
+

Como a estrutura não possui paredes, o ar flui sob a cobertura, gerando sucções menores no intradorso.

+
- - {section === 'square' ? ( - <> - - - - - ) : ( - <> - - - - - - )} - - + {/* Caso 2 */} +
+ Caso B: Efeito de Sucção no Bordo de Ataque +
+ + {styleBlock} + + + + + + {/* Vento inclinado batendo na borda de ataque superior */} + + + + + + {/* Pequena zona vermelha de turbulência no início do telhado */} + + +
+

Vento inclinado gera descolamento brusco na borda esquerda elevada. Isso gera um pico severo de sucção (arrancamento).

+
+
); - } - case 'cylinder': { - const isSmooth = params.surface === 'smooth'; - const cpi = Number(params.cpi || 0); + case 'bar': return ( - - {styleBlock} - {/* Marcadores de setas Cpi */} - - - - - - - - +
+ {/* Caso 1 */} +
+ Caso A: Fluxo Frontal (0°) +
+ + {styleBlock} + + + + + + - - - - - - + {/* Perfil L frontal */} + + + + +
+

Vento atinge perpendicularmente a face. O ar acumula no interior da cantoneira, gerando altíssimo arrasto ($C_a \approx 2.0$).

+
- - - - - + {/* Caso 2 */} +
+ Caso B: Escoamento Oblíquo (45°) +
+ + {styleBlock} + + + + + - {/* Cilindro */} - - - {/* Pressão Interna */} - {renderCpiVectors(cpi, 'circle')} - + {/* Perfil L rotacionado */} + + + + +
+

O vento flui inclinado. O ar contorna a quina da cantoneira, aliviando o empuxo direto e gerando turbulência assimétrica.

+
+
); - } - case 'sign': { - const hasEndPlates = params.hasEndPlates === true; + case 'tower': return ( - - {styleBlock} - - - - - {/* O vento passa reto ou desvia mais dependendo das abas laterais */} - - - - {/* Maior turbulência se houver placas de extremidade */} - - - +
+ {/* Caso 1 */} +
+ Caso A: Vento Frontal a 0° +
+ + {styleBlock} + + + + + {/* Pequenas linhas de turbulência passando por dentro da treliça */} + - {/* Muro */} - - {/* Placas de extremidade (abas de borda) */} - {hasEndPlates && ( - - - - - )} - + {/* Seção quadrada da torre */} + + + + + + +
+

Vento passa através dos vazios das barras. Cada cantoneira gera sua própria microesteira de turbulência.

+
+ + {/* Caso 2 */} +
+ Caso B: Vento Diagonal a 45° +
+ + {styleBlock} + + + + + + + {/* Seção quadrada rotacionada */} + + + + + + +
+

Vento incide na diagonal da torre. O fator de incidência aumenta o esforço nas fundações de canto.

+
+
); - } - case 'warehouse': { - const cpi = Number(params.cpi || 0); + case 'vault': return ( - - {styleBlock} - - - - - - - - +
+ {/* Caso 1 */} +
+ Caso A: Regime de Baixa Turbulência +
+ + {styleBlock} + + + {/* Linhas de vento contornando perfeitamente */} + + + + + {/* Abóbada */} + + +
+

O escoamento contorna colado à casca, gerando sucção simétrica com valor máximo de Cpe no topo do arco.

+
- - - - - - - - - - {/* Galpão */} - - {/* Pressão Interna */} - {renderCpiVectors(cpi, 'rect')} - + {/* Caso 2 */} +
+ Caso B: Regime Turbulento (Série 51/52) +
+ + {styleBlock} + + + {/* Linhas de vento ondulando e descolando antes */} + + + + + + {/* Abóbada */} + + +
+

A turbulência do ar antecipa o descolamento da camada limite, gerando redemoinhos e pressões flutuantes a sotavento.

+
+
); - } - - case 'vault': { - const regime = params.regime || 'laminar-rough'; - const cpi = Number(params.localCpi || 0); - const isTurbulent = regime.startsWith('turbulent'); + case 'dome': return ( - - {styleBlock} - - - - - - - - +
+ {/* Caso 1 */} +
+ Caso A: Cúpula Apoiada no Solo +
+ + {styleBlock} + + + {/* Vento contornando diretamente */} + + + + + {/* Cúpula hemisférica */} + + +
+

Vento escoa diretamente da superfície do terreno, gerando pressões positivas na face esquerda inferior e sucção no topo.

+
- - - - - {/* Linha de vento ondulante / caótica se for turbulento */} - - - {isTurbulent && ( - - )} - - - {/* Abóbada */} - - {/* Pressão Interna */} - {renderCpiVectors(cpi, 'arch')} - + {/* Caso 2 */} +
+ Caso B: Elevada sobre Parede Cilíndrica +
+ + {styleBlock} + + + {/* Vento desviando mais no barlavento devido à parede vertical */} + + + + + {/* Parede + Cúpula */} + + + +
+

A parede de base deflete o fluxo bruscamente, gerando zonas de forte redemoinho sob a quina e alterando o Cpe do domo.

+
+
); - } - case 'dome': { - const cpi = Number(params.cpi || 0); + case 'warehouse': return ( - - {styleBlock} - - - - - - - - +
+ {/* Caso 1 */} +
+ Caso A: Pressões de Vento Externas +
+ + {styleBlock} + + + + + + {/* Galpão */} + + +
+

O vento bate na parede esquerda (barlavento - pressão positiva) e decola no telhado de sotavento (sucção).

+
- + {/* Caso 2 */} +
+ Caso B: Efeito de Pressão Interna (+Cpi) +
+ + {styleBlock} + {legendDef} + + + {/* Setas laranjas apontando para fora (inflado) */} + + + + + +
+

Com abertura na parede de ataque, a pressão interna "infla" a estrutura, empurrando paredes e teto para fora.

+
- - - - - - - {/* Cúpula */} - - - - - {/* Pressão Interna */} - {renderCpiVectors(cpi, 'dome')} - + {/* Caso 3 */} +
+ Caso C: Efeito de Sucção Interna (-Cpi) +
+ + {styleBlock} + {legendDef} + + + {/* Setas azuis apontando para dentro (sugado) */} + + + + + +
+

Com aberturas nas zonas de sucção externas, cria-se vácuo interno. O teto e paredes são puxados para dentro.

+
+
); - } - case 'isolated-roof': { - const typeRoof = params.type || 'shed'; + case 'cylinder': return ( - - {styleBlock} - +
+ {/* Caso 1 */} +
+ Caso A: Escoamento Subcrítico (Superfície Lisa) +
+ + {styleBlock} + + + + + + {/* Esteira de vórtices de Von Kármán larga */} + + + + + + + + +
+

O fluxo descola precocemente (~80°), criando uma esteira de turbulência larga e resultando em arrasto elevado ($C_a \approx 1.2$).

+
- - - - - - + {/* Caso 2 */} +
+ Caso B: Escoamento Supercrítico (Superfície Rugosa) +
+ + {styleBlock} + + + + + + {/* Esteira mais estreita */} + + + + + - - - - {typeRoof === 'shed' ? ( - - ) : ( - - )} - - + + +
+

A camada limite adere mais à casca (descolamento tardio ~120°). A esteira estreita gera menos resistência aerodinâmica ($C_a \approx 0.6$).

+
+
); - } - case 'bar': { - const barType = params.barType || 'flat'; - const section = params.section || 'l'; - const alpha = Number(params.alpha || 0); + case 'sign': return ( - - {styleBlock} - - - - - - +
+ {/* Caso 1 */} +
+ Caso A: Muro sem Abas Laterais +
+ + {styleBlock} + + + + + + {/* Esteira turbulenta no sotavento */} + + - - {barType === 'circular' ? ( - - ) : ( - - {section === 'l' && ( - - )} - {section === 'u' && ( - - )} - {section === 'i' && ( - - )} - - )} - - + {/* Placa/Muro */} + + +
+

O vento contorna as bordas e escapa tridimensionalmente, resultando em um coeficiente de força aliviado.

+
+ + {/* Caso 2 */} +
+ Caso B: Com Abas de Extremidade (End Plates) +
+ + {styleBlock} + + + + + + {/* Esteira turbulenta muito maior */} + + + + {/* Placa/Muro */} + + {/* Abas vermelhas de extremidade */} + + + +
+

As abas (barreiras vermelhas) bloqueiam a fuga lateral de ar. O fluxo é puramente 2D plano, forçando o empuxo ao valor limite superior ($C_f \approx 1.3 - 2.0$).

+
+
); - } - case 'dynamics': { + case 'dynamics': return ( - - {styleBlock} - - - - - - +
+ {/* Caso 1 */} +
+ Caso A: Abaixo da Velocidade Crítica (Sem Vibração) +
+ + {styleBlock} + + + + + + {/* Pequenos vórtices desorganizados */} + + + + - - - - + + +
+

Vórtices desprendem-se sem frequência uniforme. A estrutura permanece estável e as forças dinâmicas são negligenciáveis.

+
- - - - - + {/* Caso 2 */} +
+ Caso B: Velocidade Crítica (Ressonância / Lock-in) +
+ + {styleBlock} + + + + + {/* Vórtices fortes e organizados de Von Kármán */} + + + + + + + {/* Chaminé vibrando lateralmente */} + + + + + +
+

Vórtices desprendem-se na frequência natural da estrutura, provocando oscilações transversais violentas (vibração de lock-in).

+
+
); - } default: + // Caso padrão dinâmico geral (Módulos dinâmicos simples) return ( - - {styleBlock} - - - - - +
+ + {styleBlock} + + + + + +
); } }; + const legendItems = getVisibleLegendItems(); + return (
-

Túnel de Vento Virtual 2D

+

Esquemas e Fluxos Comparativos NBR 6123

{getViewLabel()}
SVG Animado
-
- {renderActiveSimulation()} + {/* Renderiza o grid comparativo */} +
+ {renderScenarios()}
- {/* Caixa de Legenda Didática Expandida */} + {/* Caixa de Legenda Didática Inteligente (Filtra itens não utilizados no módulo ativo) */}
Legenda do Escoamento:
-
- - Linhas de Corrente de Vento -
-
- - Fluxo Acelerado (Alta Vel. / Sucção) -
-
- - Esteira Turbulenta / Recirculação -
-
- - Vórtices de Desprendimento -
- {/* Legenda de Pressão Interna */} -
- - Seta Laranja: Pressão Interna (+Cpi) -
-
- - Seta Azul Escura: Sucção Interna (-Cpi) -
+ {legendItems.wind && ( +
+ + Linhas de Corrente de Vento +
+ )} + {legendItems.fast && ( +
+ + Fluxo Acelerado (Alta Vel. / Sucção) +
+ )} + {legendItems.vortex && ( +
+ + Esteira Turbulenta / Recirculação +
+ )} + {legendItems.vortexSpin && ( +
+ + Vórtices de Desprendimento +
+ )} + {legendItems.cpiPos && ( +
+ + Seta Laranja: Pressão Interna (+Cpi) +
+ )} + {legendItems.cpiNeg && ( +
+ + Seta Azul Escura: Sucção Interna (-Cpi) +
+ )} + {legendItems.lift && ( +
+ + Forças Resultantes (Lift/Downforce) +
+ )}