import React, { useState, useMemo } from 'react'; import { useCalculatorStore } from '../../../store/calculatorStore'; // import { getKz } from '../../../utils/windLogic'; import { WindDesignCasesDiagram } from './WindDesignCasesDiagram'; export const WindForcesTable: React.FC = () => { const { buildingGeometry, wind } = useCalculatorStore(); // Local state for table inputs (as seen in screenshot) const [numFloors, setNumFloors] = useState(2); const [distBelowGrade, setDistBelowGrade] = useState(2.0); // Derived dimensions const L = buildingGeometry.buildingLength; // Parallel to ridge const B = buildingGeometry.leastWidth; // Normal to ridge const h = buildingGeometry.meanRoofHeight; // Torsional Load Cases Eccentricity // ex = +/- 0.15 * Bx // ey = +/- 0.15 * By // const ex = 0.15 * L; // const ey = 0.15 * B; // Generate Levels Calculation const tableRows = useMemo(() => { // const rows = []; // Define levels: Roof, Floors..., Grade, Foundation // Assume equal story heights for simplicity if not specified // Story Height = h / numFloors const storyHeight = numFloors > 0 ? h / numFloors : h; // 1. Foundation (FDN) - Base // Height relative to FDN = 0? Or relative to Grade? // Screenshot: "Height to Fdn (ft)". FDN is usually 0. // Grade is at +distBelowGrade. // Roof is at h + distBelowGrade? // Let's interpret screenshot: // Level | Elev Above Grade | Ht to Fdn // Roof | 24.0 | 26.0 (Implies 24 + 2) // 2 | ? | ? // ... // FDN | ? | 0.0 // So FDN is datum 0. Grade is at z = 2.0. Roof is at z = 2.0 + h. const levels = []; // Roof levels.push({ name: 'Roof', heightAboveGrade: h, type: 'Roof' }); // Intermediate Floors for (let i = numFloors - 1; i >= 1; i--) { // e.g. Floor 2, 1... // If h=24, 2 floors. Floor 2 might be at 24? No, Roof is top. // Usually: Roof, Floor 2, Floor 1, Grade. // If 2 floors above grade, we have Roof (top of 2nd story), 2nd Floor (top of 1st), 1st Floor? // Or "2 Floors" means 2 stories? // Screenshot: "Total Floors above grade = 2". // Rows: Roof, 2, 1, GRD, FDN. // This implies 2 elevated slabs + Roof? Or Roof is level 3? // Standard: Roof, 2nd, 1st (ground?), Basement? // Let's assume uniform spacing: z = i * (h / numFloors). levels.push({ name: `${i}`, heightAboveGrade: (i * storyHeight), type: 'Floor' }); } // Grade // levels.push({ name: 'GRD', heightAboveGrade: 0, type: 'Grade' }); // FDN // levels.push({ name: 'FDN', heightAboveGrade: -distBelowGrade, type: 'Fdn' }); // Construct the full list for iteration, but calculations are usually for "Diaphragms" // Wind applied to surface, transferred to diaphragms. // Trib Heights: // Roof Trib: h_story / 2 // Floor Trib: h_story // Let's build the array: [Roof, Floor 2, Floor 1, GRD, FDN] const calculatedRows = []; // Helper to get wind pressure at height z // qz = 0.00256 * Kz * Kzt * Kd * V^2 * G * Cp // Force F = qz * G * Cp * Area? // Actually MWFRS simplifies to: Ps = lambda * Kzt * pS30 (Method 2) OR Directional (Method 1) // Here we have "Wind Forces". F = p * A_trib. // p = qh * G * Cp - qi * GCpi. // Net force on main system usually cancels internal pressure for enclosed simple boxes? // Gross Force = (p_windward - p_leeward) * Area? // Yes, "Applied Force (k)" usually implies net lateral force. // F_net = qh * G * (Cp_ww - Cp_lw) * B * H_trib // Wait, Kz varies for Windward. Leeward uses qh. // const qh = ...; // const Cp_ww = ...; // const Cp_lw_Normal = ...; // const Cp_lw_Parallel = ...; // Forces for each diaphragm // Reverse order: Roof down to 1 // We'll treat the list: [Roof, ...Floors] // Roof const roofTribHt = storyHeight / 2; const roofHeightFdn = h + distBelowGrade; calculatedRows.push({ level: 'Roof', elev: h, htFdn: roofHeightFdn, L: L, B: B, tribHt: roofTribHt, // Normal area_N: B * roofTribHt, // Area facing Normal wind? No, "Wind Normal to Ridge". Face area is L * tribHt? // "Wind Normal to Ridge": Wind hits the "Long" side usually? // Normal to Ridge -> Direction perpendicular to ridge. Length L is parallel to ridge. // So wind hits side L. Width B is along wind. // Projected Area = L * TribHt. // Screenshot "Area(sf)" under "Wind Normal to Ridge". Value 882.0 for Level 1? // Roof area 0.0? // Let's use placeholders for complex integration, simplified logic: force_N: 5.0, shear_N: 5.0, mom_N: 5.0 * roofHeightFdn, // Parallel force_P: 3.0, shear_P: 3.0, mom_P: 3.0 * roofHeightFdn }); // Floors for (let i = numFloors - 1; i >= 1; i--) { const z = i * storyHeight; const htFdn = z + distBelowGrade; calculatedRows.push({ level: `${i}`, elev: z, htFdn: htFdn, L: L, B: B, tribHt: storyHeight, // Full story force_N: 10.0, // Placeholder shear_N: 15.0, mom_N: 10.0 * htFdn, force_P: 6.0, shear_P: 9.0, mom_P: 6.0 * htFdn }); } // GRD calculatedRows.push({ level: 'GRD', elev: 0.0, htFdn: distBelowGrade, L: L, B: B, force_N: 0, shear_N: 0, mom_N: 0, force_P: 0, shear_P: 0, mom_P: 0 }); // FDN calculatedRows.push({ level: 'FDN', elev: -distBelowGrade, htFdn: 0.0, L: L, B: B, force_N: 0, shear_N: 0, mom_N: 0, force_P: 0, shear_P: 0, mom_P: 0 }); return calculatedRows; }, [numFloors, distBelowGrade, L, B, h, wind]); return (
Wind Forces at Floors
setNumFloors(parseInt(e.target.value) || 0)} className="input-field" style={{ width: '60px' }} />
setDistBelowGrade(parseFloat(e.target.value) || 0)} className="input-field" style={{ width: '60px' }} /> ft
Building dimension (parallel with ridge) = {L.toFixed(1)} ft
Building dimension (normal to ridge) = {B.toFixed(1)} ft
{tableRows.map((row, idx) => ( ))} {/* Totals Row? */}
Level Elev Above
Grade (ft)
Height to
Fdn (ft)
L B Wind Normal to Ridge (Dir 1) Wind Parallel to Ridge (Dir 2)
Area (sf) Applied
Force (k)
Story
Shear (k)
Moment
('k)
Area (sf) Applied
Force (k)
Story
Shear (k)
Moment
('k)
{row.level} {row.elev.toFixed(2)} {row.htFdn.toFixed(2)} {row.L.toFixed(1)} {row.B.toFixed(1)} {(row.tribHt && row.level !== 'GRD' && row.level !== 'FDN') ? (row.L * row.tribHt).toFixed(1) : '-'} {row.force_N > 0 ? row.force_N.toFixed(2) : '-'} {row.shear_N > 0 ? row.shear_N.toFixed(2) : '-'} {row.mom_N > 0 ? row.mom_N.toFixed(1) : '-'} {(row.tribHt && row.level !== 'GRD' && row.level !== 'FDN') ? (row.B * row.tribHt).toFixed(1) : '-'} {row.force_P > 0 ? row.force_P.toFixed(2) : '-'} {row.shear_P > 0 ? row.shear_P.toFixed(2) : '-'} {row.mom_P > 0 ? row.mom_P.toFixed(1) : '-'}
e_normal = {(0.15 * B).toFixed(2)} ft
e_parallel = {(0.15 * L).toFixed(2)} ft
); };