From 59a7c1c12bdc332e5fcb9224b4bd00e0f0247b8c Mon Sep 17 00:00:00 2001 From: chopster44 Date: Sat, 2 May 2026 21:41:22 +0100 Subject: [PATCH] Generating panels as an svg --- index.html | 22 +++++++ index.js | 154 ++++++++++++++++++++++++++++++++++++++++++++++ package-lock.json | 13 ++++ package.json | 16 +++++ 4 files changed, 205 insertions(+) create mode 100644 index.html create mode 100644 index.js create mode 100644 package-lock.json create mode 100644 package.json diff --git a/index.html b/index.html new file mode 100644 index 0000000..11b885a --- /dev/null +++ b/index.html @@ -0,0 +1,22 @@ + + + + Parachute Panel Generator + + +

Parachute Panel Generator

+

Generate the SVG outline of a parachute panel for an elliptical parachute. Find out more here.

+
+ +
+ +
+ +
+ +
+ +
+ + + diff --git a/index.js b/index.js new file mode 100644 index 0000000..59496df --- /dev/null +++ b/index.js @@ -0,0 +1,154 @@ +let hInput = document.getElementById("h"); +let rInput = document.getElementById("r"); +let rsInput = document.getElementById("rs"); +let npInput = document.getElementById("np"); +let outputdiv = document.getElementById("output"); + +let height = 0; +let radius = 0; +let spillRadius = 0; +let numberOfPanels = 0; + +let multiplier = 1; +let accuracy = 8; + +const step = 0.001 * multiplier; +// const offset = 3*10**-15 * multiplier; +const offset = 4*10**-5 * multiplier; + +let pointsP = []; +let pointsQ = []; +let distances = []; + +let panelPoints = []; + +let n = 0; + +// maths +function approx(x) { + return Math.round(x*(10**accuracy))/(10**accuracy); +} + +function f(x) { + res = approx(height * Math.sqrt((1-(Math.pow(x,2)/Math.pow(radius,2))))); + console.log(`f ${x} ${res}`); + return res; +} + +function fprime(x) { + res = approx(-1*((Math.pow(height,2)*x)/(Math.pow(radius,2)*f(x)))); + console.log(`fprime ${x} ${res}`); + return res; +} + +function g(x, P) { + res = approx(fprime(x)*(x-P.x)+P.y); + console.log(`g ${x} ${P.x} ${P.y} ${res}`); + return res; +} + +function j(A, B) { + res = approx(A.x*fprime(A.x)-B.x*fprime(B.x)-A.y+B.y)/(fprime(A.x)-fprime(B.x)); + console.log(`j ${A.x} ${A.y} ${B.x} ${B.y} ${res}`); + return res; +} + +function d(A, B) { + res = approx(Math.sqrt(Math.pow(A.x-B.x,2)+Math.pow(A.y-B.y,2))); + console.log(`d ${A.x} ${A.y} ${B.x} ${B.y} ${res}`); + return res; +} + +// logic +function getValues() { + pointsP = []; + pointsQ = []; + distances = []; + panelPoints = []; + height = /* /* Math.floor */(parseFloat(hInput.value) *multiplier); + radius = /* Math.floor */(parseFloat(rInput.value) *multiplier); + spillRadius = /* Math.floor */(parseFloat(rsInput.value) *multiplier); + numberOfPanels = /* Math.floor */(parseFloat(npInput.value) *multiplier); + if (isNaN(spillRadius)) { + spillRadius = /* Math.floor */(0.05*radius); + rsInput.value = 0.05*radius /multiplier; + } + n = ((radius-spillRadius)/(step-offset))-1; + console.log(`${height}, ${radius}, ${spillRadius}, ${step}, ${offset}`); +} + +function getPoints() { + for (let x = spillRadius; x < radius; x+=step-offset) { + x=approx(x); + pointsP.push({ + x: x, + y: f(x) + }); + } +} + +function getPointsOfTangentIntersection() { + for (let i = 0; i < n; i++) { + console.log(`${i}, ${pointsP[i]}, ${pointsP[i+1]}`); + pointsQ.push({ + x: j(pointsP[i], pointsP[i+1]), + y: g(j(pointsP[i], pointsP[i+1]), pointsP[i+1]) + }); + } +} + +function getDistancesBetweenIntersections() { + for (let i = 0; i < n-1; i++) { + distances.push(d(pointsQ[i], pointsQ[i+1])); + } +} + +function generateCoordinates() { + let Xi = 0; + for (let i = 0; i < n-2; i++) { + Xi+=distances[i]; + Yi=(Math.PI*pointsQ[i].x)/numberOfPanels; + panelPoints.push({ + x: Xi, + y: Yi + }); + } +} + +function plotSVG() { + let maxY = 0; + panelPoints.forEach((point) => { + if (maxY < point.y) { + maxY=point.y + } + }) + let pointsA = []; + let pointsB = []; + for(let i = 0; i < panelPoints.length; i++) { + let point = panelPoints[i]; + pointsA.push(`${approx(point.x*10)},${(maxY*10)-approx(point.y*10)}`) + pointsB.push(`${approx(point.x*10)},${approx((point.y+maxY)*10)}`); + } + outputdiv.innerHTML = ` + + + + + + + + ` +} + + +// main func +function generatePanel() { + getValues(); + getPoints(); + getPointsOfTangentIntersection(); + getDistancesBetweenIntersections(); + generateCoordinates(); + plotSVG(); +} + + diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..e13fca9 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,13 @@ +{ + "name": "parachute-svg-generator", + "version": "0.1.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "parachute-svg-generator", + "version": "0.1.0", + "license": "SEE LICENSE IN LICENSE" + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..73109e6 --- /dev/null +++ b/package.json @@ -0,0 +1,16 @@ +{ + "name": "parachute-svg-generator", + "version": "0.1.0", + "description": "Generate an SVG outline of a parachute panel for an elliptical parachute", + "repository": { + "type": "git", + "url": "git@git.emaker.limited:chopster44/Parachute-SVG-Generator.git" + }, + "license": "SEE LICENSE IN LICENSE", + "author": "chopster44", + "type": "commonjs", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + } +}