diff --git a/app/src/lib/export-generic-pdf.tsx b/app/src/lib/export-generic-pdf.tsx
index ef653a7..d7035d9 100644
--- a/app/src/lib/export-generic-pdf.tsx
+++ b/app/src/lib/export-generic-pdf.tsx
@@ -64,11 +64,18 @@ export function appendKgf(val: string | number): string {
export interface GenericPDFSection {
title: string;
- type: 'table' | 'text' | 'grid';
+ type: 'table' | 'text' | 'grid' | 'math-card';
content?: string;
tableHeaders?: string[];
tableRows?: (string | number)[][];
gridItems?: { label: string; value: string | number }[];
+ mathSteps?: {
+ title: string;
+ formula: string;
+ calculation: string;
+ result: string;
+ note?: string;
+ }[];
}
export interface GenericPDFProps {
@@ -240,6 +247,32 @@ const GenericReportDocument = ({ moduleName, sections, wind, sceneImage }: Gener
{appendKgf(sec.content)}
)}
+ {sec.type === 'math-card' && sec.mathSteps && (
+
+ {sec.mathSteps.map((step, sIdx) => (
+
+
+ • {step.title}
+
+
+ Fórmula NBR 6123: {step.formula}
+
+
+ Cálculo: {step.calculation}
+
+
+ Resultado: {appendKgf(step.result)}
+
+ {step.note && (
+
+ Nota: {step.note}
+
+ )}
+
+ ))}
+
+ )}
+
{sec.type === 'grid' && sec.gridItems && (
{sec.gridItems.map((item, i) => (
diff --git a/app/src/pages/ShelterModule.tsx b/app/src/pages/ShelterModule.tsx
index 255201d..ea41a72 100644
--- a/app/src/pages/ShelterModule.tsx
+++ b/app/src/pages/ShelterModule.tsx
@@ -160,6 +160,46 @@ const ShelterModule: React.FC = () => {
},
],
},
+ {
+ title: `Demonstração dos Passos Matemáticos — Pressões Distribuídas por m² (Direção ${angleLabel})`,
+ type: 'math-card',
+ mathSteps: [
+ {
+ title: '1. Pressão na Cobertura (Fz / A_telhado)',
+ formula: 'p_telhado = q · |Cnf_vertical| ou p_telhado = Fz / (d · b)',
+ calculation: `${q.toFixed(2)} kN/m² · |${result.cnfVertical}| = ${(result.forces.fzUp / effAreaRoof).toFixed(2)} kN/m² (onde A_telhado = ${depth.toFixed(1)}m × ${width.toFixed(1)}m = ${effAreaRoof.toFixed(1)}m²)`,
+ result: `${(result.forces.fzUp / effAreaRoof).toFixed(2)} kN/m²`,
+ note: 'A solicitação de arrancamento atua uniformemente distribuída na projeção horizontal da cobertura.',
+ },
+ {
+ title: '2. Pressão na Parede Traseira (Fx / A_efetiva,fundo)',
+ formula: 'p_fundo = q · Cf_parede ou p_fundo = Fx / [ (b · h) · (φ_fundo) ]',
+ calculation: effAreaBack > 0
+ ? `${q.toFixed(2)} kN/m² · ${result.cfBack} = ${(result.forces.fxBack / effAreaBack).toFixed(2)} kN/m² (área de incidência sólida = ${effAreaBack.toFixed(1)}m² para ${backClosure}% fechado)`
+ : `Parede 0% fechada (Sem fechamento traseiro) -> A_efetiva = 0.0 m² e Fx = 0.00 kN`,
+ result: effAreaBack > 0 ? `${(result.forces.fxBack / effAreaBack).toFixed(2)} kN/m²` : '0.00 kN/m² (0% fechado)',
+ note: 'O coeficiente de força e a área são proporcionais à taxa de fechamento da parede de fundo.',
+ },
+ {
+ title: '3. Pressão nas Paredes Laterais (Fy / A_efetiva,laterais)',
+ formula: 'p_lateral = q · Cf_lateral ou p_lateral = Fy / [ 2 · (d · h) · (φ_médio) ]',
+ calculation: effAreaSideTotal > 0
+ ? `${q.toFixed(2)} kN/m² · ${result.cfSide} = ${(result.forces.fySide / effAreaSideTotal).toFixed(2)} kN/m² (área efetiva = ${effAreaSideTotal.toFixed(1)}m²)`
+ : `Sem paredes laterais selecionadas (0% esq + 0% dir) -> A_efetiva = 0.0 m² e Fy = 0.00 kN`,
+ result: effAreaSideTotal > 0 ? `${(result.forces.fySide / effAreaSideTotal).toFixed(2)} kN/m²` : '0.00 kN/m² (0% fechado)',
+ note: effAreaSideTotal > 0
+ ? 'A solicitação lateral é distribuída sobre a área efetiva sólida existente nas paredes esq/dir.'
+ : 'Como nenhuma parede lateral foi adicionada (0%), a área de incidência é nula (0,0 m²) e a pressão atuante é zero.',
+ },
+ {
+ title: '4. Pressão Dinâmica Base do Vento (q)',
+ formula: 'q = 0,613 · Vk² [N/m²] = 0,000613 · Vk² [kN/m²] (NBR 6123 Sec. 4.2)',
+ calculation: `0,613 · (${Math.sqrt((q * 1000) / 0.613).toFixed(1)} m/s)² / 1000 = ${q.toFixed(2)} kN/m²`,
+ result: `${q.toFixed(2)} kN/m²`,
+ note: 'Pressão dinâmica de referência calculada com base na velocidade característica Vk no nível superior do pilar.',
+ },
+ ],
+ },
{
title: 'Envoltória e Comparativo Normativo — As 3 Incidências de Vento (0° • 45° • 90°)',
type: 'table',