aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorElias Fleckenstein <eliasfleckenstein@web.de>2021-09-09 13:36:22 +0200
committerElias Fleckenstein <eliasfleckenstein@web.de>2021-09-09 13:36:22 +0200
commit1612eda6a02a08c7cbcf581e47899e9dfe3d883e (patch)
treebaa99045f424f429cfef8045ceba4b12cce21fc8
parent14f13172a7434ae488ba6205fab222c236350409 (diff)
downloadlagrange-playground-1612eda6a02a08c7cbcf581e47899e9dfe3d883e.tar.xz
Add code
-rw-r--r--index.html11
-rw-r--r--init.js203
2 files changed, 214 insertions, 0 deletions
diff --git a/index.html b/index.html
new file mode 100644
index 0000000..a5c554d
--- /dev/null
+++ b/index.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>Lagrange Playground</title>
+ <script defer src="init.js"></script>
+ </head>
+ <body>
+ <canvas style="position: fixed; top: 0px; left: 0px"></canvas>
+ </body>
+</html>
diff --git a/init.js b/init.js
new file mode 100644
index 0000000..19fdf95
--- /dev/null
+++ b/init.js
@@ -0,0 +1,203 @@
+const canvas = document.getElementsByTagName("canvas")[0];
+const ctx = canvas.getContext("2d");
+
+let center;
+let centerF = [0.5, 0.5];
+let scale = 50;
+let positions = [];
+let func = null;
+let drag = false;
+let dragPos = null;
+let dragIndex = -1;
+
+const coordinateToScreen = (x, y) => {
+ return [
+ center[0] + x * scale,
+ center[1] + y * scale,
+ ];
+};
+
+const screenToCoordinate = (x, y) => {
+ return [
+ (x - center[0]) / scale,
+ (y - center[1]) / scale,
+ ];
+};
+
+const evalPos = (a, b, c, x) => {
+ return a + (b + c * x) * x;
+};
+
+const lagrange = _ => {
+ func = x => {
+ let sum = 0;
+
+ for (let i = 0; i < positions.length; i++) {
+ let prod = positions[i][1];
+
+ for (let j = 0; j < positions.length; j++)
+ if (j != i)
+ prod *= (x - positions[j][0]) / (positions[i][0] - positions[j][0]);
+
+ sum += prod;
+ }
+
+ return sum;
+ };
+};
+
+const draw = _ => {
+ ctx.clearRect(0, 0, innerWidth, innerHeight);
+
+ for (let x = center[0] % scale; x < innerWidth; x += scale) {
+ ctx.lineWidth = x == center[0] ? 2 : 1;
+ ctx.beginPath();
+ ctx.moveTo(x, 0);
+ ctx.lineTo(x, innerHeight);
+ ctx.stroke();
+ }
+
+ for (let y = center[1] % scale; y < innerHeight; y += scale) {
+ ctx.lineWidth = y == center[1] ? 2 : 1;
+ ctx.beginPath();
+ ctx.moveTo(0, y);
+ ctx.lineTo(innerWidth, y);
+ ctx.stroke();
+ }
+
+ ctx.lineWidth = 2;
+
+ ctx.beginPath();
+ let moved = false;
+
+ for (let x = 0; x < innerWidth; x++) {
+ let y = Math.max(Math.min(center[1] + func((x - center[0]) / scale) * scale, +1e+37), -1e+37);
+
+ if (x == 0)
+ ctx.moveTo(x, y);
+ else
+ ctx.lineTo(x, y);
+ }
+ ctx.stroke();
+
+ ctx.fillStyle = "blue";
+
+ for (let circle of positions) {
+ const [x, y] = coordinateToScreen(circle[0], circle[1]);
+ ctx.beginPath();
+ ctx.arc(x, y, scale * 0.1, 0, Math.PI * 2);
+ ctx.fill();
+ }
+};
+
+const addPosition = pos => {
+ positions.push(pos);
+ lagrange();
+ draw();
+};
+
+const calculateCenter = _ => {
+ center = [
+ centerF[0] * innerWidth,
+ centerF[1] * innerHeight,
+ ];
+
+ draw();
+};
+
+const resize = _ => {
+ canvas.width = innerWidth;
+ canvas.height = innerHeight;
+
+ calculateCenter();
+};
+
+const enableDrag = evt => {
+ dragPos = [evt.clientX / innerWidth, evt.clientY / innerHeight];
+};
+
+const disableDrag = _ => {
+ drag = false;
+ dragPos = null;
+ dragIndex = -1;
+ canvas.style.cursor = "auto";
+};
+
+const init = _ => {
+ lagrange();
+ resize();
+};
+
+canvas.addEventListener("mousedown", evt => {
+ if (evt.button != 0)
+ return;
+
+ enableDrag(evt);
+
+ for (let i = 0; i < positions.length; i++) {
+ const [x, y] = coordinateToScreen(positions[i][0], positions[i][1]);
+
+ if (Math.sqrt(Math.pow(evt.clientX - x, 2) + Math.pow(evt.clientY - y, 2)) < scale * 0.1) {
+ dragIndex = i;
+ break;
+ }
+ }
+});
+
+canvas.addEventListener("mousemove", evt => {
+ if (evt.button != 0)
+ return;
+
+ const oldDragPos = dragPos;
+
+ if (oldDragPos) {
+ drag = true;
+ canvas.style.cursor = "grabbing";
+
+ enableDrag(evt);
+
+ if (dragIndex == -1) {
+ centerF = [
+ centerF[0] + dragPos[0] - oldDragPos[0],
+ centerF[1] + dragPos[1] - oldDragPos[1],
+ ];
+
+ calculateCenter();
+ } else {
+ positions[dragIndex] = screenToCoordinate(dragPos[0] * innerWidth, dragPos[1] * innerHeight);
+
+ lagrange();
+ draw();
+ }
+ }
+});
+
+canvas.addEventListener("mouseup", evt => {
+ if (evt.button != 0)
+ return;
+
+ if (! drag)
+ addPosition(screenToCoordinate(evt.clientX, evt.clientY));
+
+ disableDrag();
+});
+
+canvas.addEventListener("mouseleave", evt => {
+ if (evt.button != 0)
+ return;
+
+ disableDrag();
+});
+
+canvas.addEventListener("wheel", evt => {
+ scale -= evt.deltaY * 0.05;
+ scale = Math.max(7, scale);
+
+ draw();
+});
+
+addEventListener("resize", _ => {
+ resize();
+});
+
+init();