Aerodynamic Profile Data Generator

Performance Charts

Generated Data Table

Airfoil & Flow Parameters

Angle of Attack ($A_oA$) Range

An error occurred: ${e.message}

`; } } // --- Chart.js Update Function --- function updateCharts(labels, clData, ldData) { if (!clCtx || !ldCtx) return; if (clChart) clChart.destroy(); if (ldChart) ldChart.destroy(); const chartOptions = (title) => ({ responsive: true, maintainAspectRatio: false, plugins: { title: { display: true, text: title, font: { size: 14 } }, legend: { display: false } }, scales: { x: { title: { display: true, text: 'Angle of Attack (deg)' } }, y: { title: { display: true, text: title } } } }); clChart = new Chart(clCtx, { type: 'line', data: { labels: labels, datasets: [{ label: 'Cl', data: clData, borderColor: 'rgb(54, 162, 235)', backgroundColor: 'rgba(54, 162, 235, 0.5)', tension: 0.1 }] }, options: chartOptions('Lift Coefficient (Cl)') }); ldChart = new Chart(ldCtx, { type: 'line', data: { labels: labels, datasets: [{ label: 'L/D', data: ldData, borderColor: 'rgb(75, 192, 192)', backgroundColor: 'rgba(75, 192, 192, 0.5)', tension: 0.1 }] }, options: chartOptions('Lift-to-Drag Ratio (L/D)') }); } // --- PDF Download Function --- function downloadPDF() { if (typeof jspdf === 'undefined' || typeof html2canvas === 'undefined') { console.error('AERO TOOL: jsPDF or html2canvas is not loaded.'); alert('Error: PDF generation libraries failed to load.'); return; } if (tableWrapper.innerHTML.trim() === '') { alert('Please generate data first.'); return; } const originalBtnText = pdfDownloadBtn.textContent; pdfDownloadBtn.textContent = 'Generating PDF...'; pdfDownloadBtn.disabled = true; // Get the dashboard element to capture const dashboardContent = document.getElementById('aero-tab-dashboard'); try { html2canvas(dashboardContent, { scale: 2, // Improve resolution useCORS: true, backgroundColor: '#ffffff', // Ignore the PDF button itself ignoreElements: (element) => element.id === 'aero-pdf-download-btn' }).then((canvas) => { const imgData = canvas.toDataURL('image/png'); const { jsPDF } = window.jspdf; // A4 size: 210 x 297 mm const pdfWidth = 210; const pageHeight = 297; const imgWidth = canvas.width; const imgHeight = canvas.height; const ratio = imgWidth / pdfWidth; const scaledHeight = imgHeight / ratio; const doc = new jsPDF({ orientation: 'portrait', unit: 'mm', format: 'a4' }); doc.text("Aerodynamic Profile Data Report", 10, 15); let position = 20; doc.addImage(imgData, 'PNG', 10, position, pdfWidth - 20, scaledHeight - (position / 2)); doc.save('aerodynamic-dashboard.pdf'); pdfDownloadBtn.textContent = originalBtnText; pdfDownloadBtn.disabled = false; }).catch(err => { console.error('AERO TOOL: html2canvas error:', err); alert('An error occurred while capturing the dashboard.'); pdfDownloadBtn.textContent = originalBtnText; pdfDownloadBtn.disabled = false; }); } catch(e) { console.error('AERO TOOL: PDF generation failed.', e); alert('Error: Could not generate PDF.'); pdfDownloadBtn.textContent = originalBtnText; pdfDownloadBtn.disabled = false; } } // --- Utility Function --- function escapeHTML(str) { if (!str) return ''; return str.replace(/[&<>"']/g, (match) => ({ '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' }[match])); } // --- Attach Event Listeners --- generateBtn.addEventListener('click', generateData); pdfDownloadBtn.addEventListener('click', downloadPDF); // --- Initial Setup --- showTab('aero-tab-dashboard'); // Start on dashboard updateNavButtons(); // Generate sample data on load generateData(); });
Scroll to Top