5. Deflection Check
Moment of Inertia (Ix) = ${Ix} in⁴, E = 29,000 ksi
Max Deflection (Δ) = ${Delta_max.toFixed(3)} in (L/${(L_in/Delta_max).toFixed(0)})
`;
document.getElementById('sarg-analysis-text').innerHTML = analysisHTML;
// Store data for canvas
window.sargData = { type, L_ft, w_klf, R1, R2, V_max, M_max_kft };
sargDrawCanvas();
};
// --- CANVAS DRAWING ---
window.sargDrawCanvas = function() {
const canvas = document.getElementById('sarg-beam-canvas');
if (!canvas.offsetParent) return; // Hidden
// Resize for High DPI
const rect = canvas.getBoundingClientRect();
canvas.width = rect.width * 2;
canvas.height = rect.height * 2;
const ctx = canvas.getContext('2d');
ctx.scale(2, 2);
// Clear
ctx.clearRect(0, 0, rect.width, rect.height);
const data = window.sargData;
if (!data) return;
// Coords
const marginX = 50;
const beamY = 80;
const beamW = rect.width - (marginX * 2);
const beamH = 6;
// 1. Draw Beam
ctx.fillStyle = '#333';
ctx.fillRect(marginX, beamY, beamW, beamH);
// 2. Draw Supports
ctx.fillStyle = '#003366';
if (data.type === 'simple') {
// Left Pin
ctx.beginPath();
ctx.moveTo(marginX, beamY + beamH);
ctx.lineTo(marginX - 10, beamY + beamH + 15);
ctx.lineTo(marginX + 10, beamY + beamH + 15);
ctx.fill();
// Right Roller
ctx.beginPath();
ctx.arc(marginX + beamW, beamY + beamH + 8, 8, 0, 2 * Math.PI);
ctx.fill();
} else {
// Left Fixed
ctx.fillRect(marginX - 5, beamY - 20, 5, 50);
// Hatching
ctx.strokeStyle = '#003366';
for(let i=0; i<6; i++) {
ctx.beginPath();
ctx.moveTo(marginX - 10, beamY - 20 + (i*8));
ctx.lineTo(marginX - 5, beamY - 15 + (i*8));
ctx.stroke();
}
}
// 3. Draw Load (Arrows)
ctx.strokeStyle = '#d35400';
ctx.fillStyle = '#d35400';
const arrows = 10;
const spacing = beamW / arrows;
for (let i = 0; i <= arrows; i++) {
const x = marginX + (i * spacing);
// Line
ctx.beginPath();
ctx.moveTo(x, beamY - 30);
ctx.lineTo(x, beamY);
ctx.stroke();
// Arrowhead
ctx.beginPath();
ctx.moveTo(x - 3, beamY - 5);
ctx.lineTo(x, beamY);
ctx.lineTo(x + 3, beamY - 5);
ctx.fill();
}
// Load Line bar
ctx.fillRect(marginX, beamY - 30, beamW, 2);
ctx.fillText(`w = ${data.w_klf} k/ft`, marginX + beamW/2 - 30, beamY - 35);
// 4. Draw Diagrams (Schematic)
const diagH = 40;
const sfdY = 160;
const bmdY = 240;
// Labels
ctx.fillStyle = '#666';
ctx.fillText("Shear (V)", marginX - 45, sfdY);
ctx.fillText("Moment (M)", marginX - 45, bmdY);
// Axes
ctx.strokeStyle = '#ccc';
ctx.beginPath(); ctx.moveTo(marginX, sfdY); ctx.lineTo(marginX + beamW, sfdY); ctx.stroke();
ctx.beginPath(); ctx.moveTo(marginX, bmdY); ctx.lineTo(marginX + beamW, bmdY); ctx.stroke();
// Shapes
ctx.strokeStyle = '#003366';
ctx.lineWidth = 2;
ctx.beginPath();
if (data.type === 'simple') {
// SFD: Linear Down
ctx.moveTo(marginX, sfdY - diagH); // Up
ctx.lineTo(marginX + beamW, sfdY + diagH); // Down
ctx.lineTo(marginX + beamW, sfdY); // Back to axis
ctx.stroke();
// BMD: Parabolic Up
ctx.beginPath();
ctx.moveTo(marginX, bmdY);
ctx.quadraticCurveTo(marginX + beamW/2, bmdY + diagH*1.5, marginX + beamW, bmdY);
ctx.stroke();
} else {
// Cantilever
// SFD: Triangle (Load accumulates) - actually rectangle for point, triangle for UDL
// For UDL Cantilever: Shear is 0 at free end, Max at support.
ctx.moveTo(marginX, sfdY - diagH); // Max at support
ctx.lineTo(marginX + beamW, sfdY); // Zero at free
ctx.lineTo(marginX, sfdY);
ctx.stroke();
// BMD: Parabolic Down (Negative Moment)
ctx.beginPath();
ctx.moveTo(marginX, bmdY - diagH); // Max negative at support
// quadratic to 0
// Control point for parabola
ctx.quadraticCurveTo(marginX + beamW/2, bmdY, marginX + beamW, bmdY);
ctx.lineTo(marginX, bmdY);
ctx.stroke();
}
};
// --- PDF GENERATION ---
window.sargGeneratePDF = function() {
const element = document.getElementById('sarg-tool-container');
const pdfBtn = document.getElementById('sarg-btn-pdf');
const tabs = document.getElementById('sarg-tabs');
// Prep for print
pdfBtn.style.display = 'none';
tabs.style.display = 'none';
// Force show Dashboard and Analysis, Hide config
const dashboard = document.getElementById('sarg-tab-dashboard');
const analysis = document.getElementById('sarg-tab-analysis');
const config = document.getElementById('sarg-tab-config');
// Capture current state
const dStyle = dashboard.style.display;
const aStyle = analysis.style.display;
const cStyle = config.style.display;
// Layout for PDF
dashboard.style.display = 'block';
analysis.style.display = 'block';
config.style.display = 'none';
// Add page break
analysis.classList.add('html2pdf__page-break');
const opt = {
margin: 0.4,
filename: 'Structural_Calc_Report.pdf',
image: { type: 'jpeg', quality: 0.98 },
html2canvas: { scale: 2, useCORS: true },
jsPDF: { unit: 'in', format: 'letter', orientation: 'portrait' }
};
html2pdf().set(opt).from(element).save().then(() => {
// Restore UI
pdfBtn.style.display = 'block';
tabs.style.display = 'flex';
dashboard.style.display = dStyle;
analysis.style.display = aStyle;
config.style.display = cStyle;
analysis.classList.remove('html2pdf__page-break');
// Fix canvas scale visual glitch if any
sargDrawCanvas();
});
};