209 lines
6.3 KiB
JavaScript
209 lines
6.3 KiB
JavaScript
let uInput = document.getElementById("u");
|
|
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 stepInput = document.getElementById("steps");
|
|
let lenOutput = document.getElementById("len");
|
|
|
|
let height = 0;
|
|
let radius = 0;
|
|
let spillRadius = 0;
|
|
let numberOfPanels = 0;
|
|
|
|
let multiplier = 1;
|
|
let accuracy = 8;
|
|
|
|
let 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;
|
|
let unit = "px";
|
|
let strokeWidth = 1;
|
|
|
|
// maths
|
|
function approx(n) {
|
|
return Math.round(n * (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);
|
|
step = radius / parseInt(stepInput.value);
|
|
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;
|
|
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 += `${approx(point.x)},${(maxY) - approx(point.y)} `;
|
|
pointsB +=`${approx(point.x)},${approx((point.y + maxY))} `;
|
|
}
|
|
outputdiv.innerHTML = `
|
|
<svg width="297mm"
|
|
height="210mm"
|
|
xmlns="http://www.w3.org/2000/svg">
|
|
<g id="layer1">
|
|
<line
|
|
x1="${approx(panelPoints[0].x)}${unit}"
|
|
x2="${panelPoints[0].x}${unit}"
|
|
y1="${maxY - approx(panelPoints[0].y)}${unit}"
|
|
y2="${approx((panelPoints[0].y + maxY))}${unit}"
|
|
fill="none"
|
|
stroke="black"
|
|
stroke-width="${strokeWidth}"
|
|
/>
|
|
<line
|
|
x1="${approx(panelPoints[panelPoints.length - 1].x)}${unit}"
|
|
x2="${panelPoints[panelPoints.length - 1].x}${unit}"
|
|
y1="${maxY - approx(panelPoints[panelPoints.length - 1].y)}${unit}"
|
|
y2="${approx((panelPoints[panelPoints.length - 1].y + maxY))}${unit}"
|
|
fill="none"
|
|
stroke="black"
|
|
stroke-width="${strokeWidth}"
|
|
/>
|
|
<line
|
|
x1="${approx(panelPoints[0].x)}${unit}"
|
|
x2="${panelPoints[panelPoints.length - 1].x}${unit}"
|
|
y1="${(maxY - approx(panelPoints[0].y) + approx((panelPoints[0].y + maxY))) / 2}${unit}"
|
|
y2="${(maxY - approx(panelPoints[panelPoints.length - 1].y) + 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: ${approx(maxX - minX)} ${unit}`;
|
|
}
|
|
|
|
|
|
// main func
|
|
function generatePanel() {
|
|
unit=uInput.value;
|
|
getValues();
|
|
getPoints();
|
|
getPointsOfTangentIntersection();
|
|
getDistancesBetweenIntersections();
|
|
generateCoordinates();
|
|
plotSVG();
|
|
}
|
|
|
|
|