Compare commits
6
Commits
4ec8718cef
..
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
da7e9f6a95
|
||
|
|
0b776a631c
|
||
|
|
17c91429f4
|
||
|
|
403daca793
|
||
|
|
90bfd67c71
|
||
|
|
3cb776566f
|
No files matched your search
Binary file not shown.
+8
-4
@@ -14,6 +14,11 @@
|
||||
<option value="cm">Centimetres</option>
|
||||
<option value="in">Inches</option>
|
||||
</select> <br>
|
||||
<label for="p">Paper size: </label>
|
||||
<select id="p">
|
||||
<option value="a3">A3</option>
|
||||
<option value="a4">A4</option>
|
||||
</select> <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>
|
||||
@@ -22,11 +27,10 @@
|
||||
<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>
|
||||
<label for="steps">Number of steps: </label>
|
||||
<input type="number" id="steps" min="10" /><br>
|
||||
<button id="generate">Generate!</button>
|
||||
<button id="generate" >Generate!</button>
|
||||
<p id="len"></p>
|
||||
<div id="output"></div>
|
||||
<div id="output" style="display: none;"></div>
|
||||
<iframe id="pdf" style="width:100%;height:1000px"></iframe>
|
||||
<script src="src/main.js" lang="js" type="module"></script>
|
||||
</body>
|
||||
</html>
|
||||
+1
-1
@@ -12,7 +12,7 @@
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "vite build",
|
||||
"build": "vite build; tar -cavf build.tar.gz dist",
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"dependencies": {
|
||||
|
||||
+97
-91
@@ -1,4 +1,5 @@
|
||||
import * as maths from "./maths.js";
|
||||
import { createPdf } from "./print.js";
|
||||
|
||||
let uInput = document.getElementById("u");
|
||||
let hInput = document.getElementById("h");
|
||||
@@ -7,31 +8,30 @@ let rsInput = document.getElementById("rs");
|
||||
let npInput = document.getElementById("np");
|
||||
let outputdiv = document.getElementById("output");
|
||||
let stepInput = document.getElementById("steps");
|
||||
let lenOutput = document.getElementById("len");
|
||||
let paperInput = document.getElementById("p");
|
||||
|
||||
// parameters
|
||||
let height = 0;
|
||||
let radius = 0;
|
||||
let spillRadius = 0;
|
||||
let numberOfPanels = 0;
|
||||
let step = 0.001;
|
||||
const offset = 4 * 10 ** -5;
|
||||
|
||||
let multiplier = 1;
|
||||
|
||||
let step = 0.001 * multiplier;
|
||||
// const offset = 3*10**-15 * multiplier;
|
||||
const offset = 4 * 10 ** -5 * multiplier;
|
||||
|
||||
// temporary data
|
||||
let pointsP = [];
|
||||
let pointsQ = [];
|
||||
let distances = [];
|
||||
|
||||
let panelPoints = [];
|
||||
|
||||
// print data
|
||||
let panelPaths = [];
|
||||
let svgSize = { width: 0, height: 0 };
|
||||
let scaleFactor = 1;
|
||||
let paperSize = "a3";
|
||||
|
||||
let n = 0;
|
||||
let unit = "px";
|
||||
let strokeWidth = 1;
|
||||
|
||||
// maths
|
||||
|
||||
|
||||
// logic
|
||||
function getValues() {
|
||||
@@ -39,21 +39,22 @@ function getValues() {
|
||||
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);
|
||||
step = radius / parseInt(stepInput.value);
|
||||
height = (parseFloat(hInput.value) * 1);
|
||||
radius = (parseFloat(rInput.value) * 1);
|
||||
spillRadius = (parseFloat(rsInput.value) * 1);
|
||||
numberOfPanels = (parseFloat(npInput.value) * 1);
|
||||
step = radius / 1000;
|
||||
paperSize = paperInput.value;
|
||||
if (isNaN(spillRadius)) {
|
||||
spillRadius = /* Math.floor */(0.05 * radius);
|
||||
rsInput.value = 0.05 * radius / multiplier;
|
||||
spillRadius = (0.05 * radius);
|
||||
rsInput.value = 0.05 * radius ;
|
||||
}
|
||||
n = ((radius - spillRadius) / (step - offset)) - 1;
|
||||
console.log(`${height}, ${radius}, ${spillRadius}, ${step}, ${offset}`);
|
||||
}
|
||||
|
||||
function getPoints() {
|
||||
for (let x = spillRadius; x < radius; x += step - offset) {
|
||||
// round x to reduce oppourtunity for a NaN to occur from accuracy
|
||||
x = maths.approx(x);
|
||||
pointsP.push({
|
||||
x: x,
|
||||
@@ -64,7 +65,6 @@ function getPoints() {
|
||||
|
||||
function getPointsOfTangentIntersection() {
|
||||
for (let i = 0; i < n; i++) {
|
||||
console.log(`${i}, ${pointsP[i].x} ${pointsP[i].y}, ${pointsP[i + 1].x} ${pointsP[i+1].y}`);
|
||||
pointsQ.push({
|
||||
x: maths.j(pointsP[i], pointsP[i + 1], height, radius),
|
||||
y: maths.g(maths.j(pointsP[i], pointsP[i + 1], height, radius), pointsP[i + 1], height, radius)
|
||||
@@ -90,78 +90,82 @@ function generateCoordinates() {
|
||||
}
|
||||
}
|
||||
|
||||
function plotSVG() {
|
||||
let maxY = 0;
|
||||
let maxX = 0;
|
||||
let minX = 1000;
|
||||
panelPoints.forEach((point) => {
|
||||
if (maxY < point.y) {
|
||||
maxY = point.y;
|
||||
}
|
||||
if (minX > point.x) {
|
||||
minX = point.x;
|
||||
}
|
||||
if (maxX < point.x) {
|
||||
maxX = point.x;
|
||||
}
|
||||
})
|
||||
let pointsA = "";
|
||||
let pointsB = "";
|
||||
for (let i = 0; i < panelPoints.length; i++) {
|
||||
let point = panelPoints[i];
|
||||
pointsA += `${maths.approx(point.x)},${(maxY) - maths.approx(point.y)} `;
|
||||
pointsB +=`${maths.approx(point.x)},${maths.approx((point.y + maxY))} `;
|
||||
}
|
||||
outputdiv.innerHTML = `
|
||||
<svg width="297mm"
|
||||
height="210mm"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<g id="layer1">
|
||||
<line
|
||||
x1="${maths.approx(panelPoints[0].x)}${unit}"
|
||||
x2="${panelPoints[0].x}${unit}"
|
||||
y1="${maxY - maths.approx(panelPoints[0].y)}${unit}"
|
||||
y2="${maths.approx((panelPoints[0].y + maxY))}${unit}"
|
||||
fill="none"
|
||||
stroke="black"
|
||||
stroke-width="${strokeWidth}"
|
||||
/>
|
||||
<line
|
||||
x1="${maths.approx(panelPoints[panelPoints.length - 1].x)}${unit}"
|
||||
x2="${panelPoints[panelPoints.length - 1].x}${unit}"
|
||||
y1="${maxY - maths.approx(panelPoints[panelPoints.length - 1].y)}${unit}"
|
||||
y2="${maths.approx((panelPoints[panelPoints.length - 1].y + maxY))}${unit}"
|
||||
fill="none"
|
||||
stroke="black"
|
||||
stroke-width="${strokeWidth}"
|
||||
/>
|
||||
<line
|
||||
x1="${maths.approx(panelPoints[0].x)}${unit}"
|
||||
x2="${panelPoints[panelPoints.length - 1].x}${unit}"
|
||||
y1="${(maxY - maths.approx(panelPoints[0].y) + maths.approx((panelPoints[0].y + maxY))) / 2}${unit}"
|
||||
y2="${(maxY - maths.approx(panelPoints[panelPoints.length - 1].y) + maths.approx((panelPoints[panelPoints.length - 1].y + maxY))) / 2}${unit}"
|
||||
fill="none"
|
||||
stroke="black"
|
||||
stroke-width="${strokeWidth}"
|
||||
/>
|
||||
<polyline
|
||||
points="${pointsA}"
|
||||
fill="none"
|
||||
stroke="black"
|
||||
stroke-width="${strokeWidth}"
|
||||
/>
|
||||
<polyline
|
||||
points="${pointsB}"
|
||||
fill="none"
|
||||
stroke="black"
|
||||
stroke-width="${strokeWidth}"
|
||||
/>
|
||||
</g>
|
||||
</svg>
|
||||
`;
|
||||
lenOutput.innerText = `Recommended length: ${maths.approx(maxX - minX)} ${unit}`;
|
||||
function createPerimeterPath(maxY) {
|
||||
let path = `M `;
|
||||
|
||||
// first arc
|
||||
for (let i = 0; i < panelPoints.length; i++) {
|
||||
let point = panelPoints[i];
|
||||
path += `${maths.approx(point.x)},${maths.approx((maxY) - point.y)} `;
|
||||
}
|
||||
// second arc
|
||||
for (let i = panelPoints.length-1; i>=0;i--) {
|
||||
let point = panelPoints[i];
|
||||
path +=`${maths.approx(point.x)},${maths.approx((point.y + maxY))} `;
|
||||
}
|
||||
path += `${maths.approx(panelPoints[0].x)},${maths.approx((maxY) - panelPoints[0].y)}`;
|
||||
return path;
|
||||
}
|
||||
|
||||
function createCentrePath(maxY) {
|
||||
return `M ${maths.approx(panelPoints[0].x)},${(maxY - maths.approx(panelPoints[0].y) + maths.approx((panelPoints[0].y + maxY))) / 2} ${panelPoints[panelPoints.length - 1].x},${(maxY - maths.approx(panelPoints[panelPoints.length - 1].y) + maths.approx((panelPoints[panelPoints.length - 1].y + maxY))) / 2}`;
|
||||
}
|
||||
|
||||
function plotSVG() {
|
||||
let maxY = 0;
|
||||
let minY = 1000;
|
||||
let maxX = 0;
|
||||
let minX = 1000;
|
||||
panelPoints.forEach((point) => {
|
||||
if (maxY < point.y) {
|
||||
maxY = point.y;
|
||||
}
|
||||
if (minY > point.y) {
|
||||
minY = point.y;
|
||||
}
|
||||
if (minX > point.x) {
|
||||
minX = point.x;
|
||||
}
|
||||
if (maxX < point.x) {
|
||||
maxX = point.x;
|
||||
}
|
||||
});
|
||||
svgSize.width = panelPoints[panelPoints.length - 1].x - maths.approx(panelPoints[0].x);
|
||||
svgSize.height = (maxY - maths.approx(panelPoints[0].y) + maths.approx((panelPoints[0].y + maxY)));
|
||||
panelPaths[0] = createCentrePath(maxY);
|
||||
panelPaths[1] = createPerimeterPath(maxY);
|
||||
outputdiv.innerHTML = `
|
||||
<svg width="297mm"
|
||||
height="210mm"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<g id="layer1">
|
||||
<path
|
||||
d="${panelPaths[0]}"
|
||||
fill="none"
|
||||
stroke="black"
|
||||
stroke-width="1"
|
||||
/>
|
||||
<path
|
||||
d="${panelPaths[1]}"
|
||||
fill="none"
|
||||
stroke="black"
|
||||
stroke-width="1"
|
||||
/>
|
||||
</g>
|
||||
</svg>`;
|
||||
}
|
||||
|
||||
function calculateScaleFactor(unit) {
|
||||
if (unit == "mm") {
|
||||
scaleFactor = 72/25.4;
|
||||
} else if (unit == "cm") {
|
||||
scaleFactor = 72/2.54;
|
||||
} else if (unit == "in") {
|
||||
scaleFactor = 72;
|
||||
} else if (unit == "px") {
|
||||
scaleFactor = 0.75;
|
||||
}
|
||||
}
|
||||
|
||||
// main func
|
||||
function generatePanel() {
|
||||
@@ -172,6 +176,8 @@ function generatePanel() {
|
||||
getDistancesBetweenIntersections();
|
||||
generateCoordinates();
|
||||
plotSVG();
|
||||
calculateScaleFactor(unit);
|
||||
createPdf(panelPaths, svgSize, scaleFactor, paperSize);
|
||||
}
|
||||
|
||||
document.getElementById("generate").addEventListener("click", () => generatePanel());
|
||||
|
||||
+2
-6
@@ -1,6 +1,7 @@
|
||||
import { sanitiseArguments } from "./utils";
|
||||
|
||||
let accuracy = import.meta.env.VITE_ACCURACY;
|
||||
// decimal places
|
||||
let accuracy = 8;
|
||||
|
||||
export function approx(n) {
|
||||
return Math.round(n * (10 ** accuracy)) / (10 ** accuracy);
|
||||
@@ -13,7 +14,6 @@ export function approx(n) {
|
||||
export function f(x, h, r) {
|
||||
sanitiseArguments(x,h,r)
|
||||
let res = approx(h * Math.sqrt((1 - (Math.pow(x, 2) / Math.pow(r, 2)))));
|
||||
console.log(`f(${x} ${h} ${r}) ${res}`);
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -24,7 +24,6 @@ export function f(x, h, r) {
|
||||
export function fprime(x, h, r) {
|
||||
sanitiseArguments(x,h,r)
|
||||
let res = approx(-1 * ((Math.pow(h, 2) * x) / (Math.pow(r, 2) * f(x, h, r))));
|
||||
console.log(`fprime (${x} ${h} ${r}) ${res}`);
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -36,7 +35,6 @@ export function fprime(x, h, r) {
|
||||
export function g(x, P, h, r) {
|
||||
sanitiseArguments(x,P.x, P.y,h,r)
|
||||
let res = approx(fprime(x, h, r) * (x - P.x) + P.y);
|
||||
console.log(`g (${x} {${P.x} ${P.y}} ${h} ${r}) ${res}`);
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -48,7 +46,6 @@ export function g(x, P, h, r) {
|
||||
export function j(A, B, h, r) {
|
||||
sanitiseArguments(A.x, A.y, B.x, B.y, h,r)
|
||||
let res = approx(A.x * fprime(A.x, h, r) - B.x * fprime(B.x, h, r) - A.y + B.y) / (fprime(A.x, h, r) - fprime(B.x, h, r));
|
||||
console.log(`j ({${A.x} ${A.y}} {${B.x} ${B.y}} ${h} ${r}) ${res}`);
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -58,6 +55,5 @@ export function j(A, B, h, r) {
|
||||
export function d(A, B) {
|
||||
sanitiseArguments(A.x, A.y, B.x, B.y)
|
||||
let 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;
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
import { PDFDocument, degrees, rgb } from "pdf-lib";
|
||||
|
||||
export async function createPdf(paths, svgSize, scaleFactor, paperSize) {
|
||||
const pdfDocument = await PDFDocument.create();
|
||||
|
||||
// calculate number of pages needed
|
||||
|
||||
const margins = { x: 15, y: 15 };
|
||||
|
||||
// paper sizes in pt
|
||||
let sizes = {
|
||||
"a3": {
|
||||
x: 841.89-2*margins.x,
|
||||
y: 1190.55-2*margins.y,
|
||||
},
|
||||
"a4": {
|
||||
x: 595.28-2*margins.x,
|
||||
y: 841.89-2*margins.y,
|
||||
}
|
||||
}
|
||||
|
||||
let nPages = Math.ceil((svgSize.width *scaleFactor) / sizes[paperSize].y);
|
||||
let needsMarkers = false;
|
||||
if (1 < nPages) {
|
||||
needsMarkers = true;
|
||||
}
|
||||
|
||||
console.log(nPages);
|
||||
|
||||
// make enough pages
|
||||
for (let i = 0; i < nPages; i++) {
|
||||
let offset = i*(sizes[paperSize].y - 4 * margins.y);
|
||||
let page = pdfDocument.addPage();
|
||||
page.setSize(sizes[paperSize].x, sizes[paperSize].y);
|
||||
const { width, height } = page.getSize();
|
||||
|
||||
console.log(page.getSize());
|
||||
|
||||
const svgSettings = {
|
||||
x: (width + svgSize.height * scaleFactor)/2,
|
||||
y: height + offset - margins.y,
|
||||
rotate: degrees(-90),
|
||||
borderColor: rgb(0,0,0),
|
||||
borderWidth: 1,
|
||||
scale: scaleFactor
|
||||
};
|
||||
|
||||
page.moveTo(5, height - 5);
|
||||
// panel
|
||||
page.drawSvgPath(paths[0], svgSettings);
|
||||
page.drawSvgPath(paths[1], svgSettings);
|
||||
|
||||
// draw top alignmnet marker
|
||||
if (i != 0 && needsMarkers) {
|
||||
page.drawLine({
|
||||
start: { x: 0, y: height - 2 * margins.y },
|
||||
end: { x: width, y: height - 2 * margins.y },
|
||||
});
|
||||
}
|
||||
|
||||
// draw bottom alignment marker
|
||||
if (i != (nPages-1) && needsMarkers) {
|
||||
page.drawLine({
|
||||
start: { x: 0, y: 2 * margins.y },
|
||||
end: { x: width, y: 2 * margins.y },
|
||||
});
|
||||
}
|
||||
|
||||
// margins
|
||||
page.drawSvgPath(`M ${margins.x/2},${margins.y/2} ${margins.x/2},${height-margins.y/2} ${width-margins.x/2},${height-margins.y/2} ${width-margins.x/2},${margins.y/2} ${margins.x/2},${margins.y/2} Z`, {
|
||||
x:0,
|
||||
y:height,
|
||||
borderColor: rgb(1,1,1),
|
||||
borderWidth: margins.x
|
||||
});
|
||||
}
|
||||
|
||||
const pdfDataUri = await pdfDocument.saveAsBase64({ dataUri: true });
|
||||
document.getElementById("pdf").src = pdfDataUri;
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user