Generating panels as an svg
This commit is contained in:
22
index.html
Normal file
22
index.html
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Parachute Panel Generator</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>Parachute Panel Generator</h1>
|
||||||
|
<p>Generate the SVG outline of a parachute panel for an elliptical parachute. Find out more <a>here</a>.</p>
|
||||||
|
<br>
|
||||||
|
<label for="h">Height of parachute (h):</label>
|
||||||
|
<input type="number" id="h" min="0"/><br>
|
||||||
|
<label for="r">Radius of parachute (r):</label>
|
||||||
|
<input type="number" id="r" min="0"/><br>
|
||||||
|
<label for="rs">Radius of spill hole (r<sub>s</sub>): (leave blank to use 0.05r)</label>
|
||||||
|
<input type="number" id="rs" /><br>
|
||||||
|
<label for="np">Number of panels (n<sub>p</sub>): </label>
|
||||||
|
<input type="number" id="np" min="3" ><br>
|
||||||
|
<button onclick="generatePanel()">Generate!</button>
|
||||||
|
<div id="output"></div>
|
||||||
|
<script src="index.js" lang="js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
154
index.js
Normal file
154
index.js
Normal file
@@ -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 = `
|
||||||
|
<svg viewBox="0 0 100 200" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<line x1="${approx(panelPoints[0].x*10)}" x2="${panelPoints[0].x*10}" y1="${maxY*10-approx(panelPoints[0].y*10)}" y2="${approx((panelPoints[0].y+maxY)*10)}" fill="none" stroke="black" stroke-width="0.05" />
|
||||||
|
<line x1="${approx(panelPoints[panelPoints.length-1].x*10)}" x2="${panelPoints[panelPoints.length-1].x*10}" y1="${maxY*10-approx(panelPoints[panelPoints.length-1].y*10)}" y2="${approx((panelPoints[panelPoints.length-1].y+maxY)*10)}" fill="none" stroke="black" stroke-width="0.05" />
|
||||||
|
<line x1="${approx(panelPoints[0].x*10)}" x2="${panelPoints[panelPoints.length-1].x*10}" y1="${(maxY*10-approx(panelPoints[0].y*10)+approx((panelPoints[0].y+maxY)*10))/2}" y2="${(maxY*10-approx(panelPoints[panelPoints.length-1].y*10)+approx((panelPoints[panelPoints.length-1].y+maxY)*10))/2}" fill="none" stroke="black" stroke-width="0.05" />
|
||||||
|
<polyline points="${pointsA}" fill="none" stroke="black" stroke-width="0.05" />
|
||||||
|
<polyline points="${pointsB}" fill="none" stroke="black" stroke-width="0.05" />
|
||||||
|
</svg>
|
||||||
|
`
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// main func
|
||||||
|
function generatePanel() {
|
||||||
|
getValues();
|
||||||
|
getPoints();
|
||||||
|
getPointsOfTangentIntersection();
|
||||||
|
getDistancesBetweenIntersections();
|
||||||
|
generateCoordinates();
|
||||||
|
plotSVG();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
13
package-lock.json
generated
Normal file
13
package-lock.json
generated
Normal file
@@ -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"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
16
package.json
Normal file
16
package.json
Normal file
@@ -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"
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user