From 1612eda6a02a08c7cbcf581e47899e9dfe3d883e Mon Sep 17 00:00:00 2001 From: Elias Fleckenstein Date: Thu, 9 Sep 2021 13:36:22 +0200 Subject: [PATCH] Add code --- index.html | 11 +++ init.js | 203 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 214 insertions(+) create mode 100644 index.html create mode 100644 init.js diff --git a/index.html b/index.html new file mode 100644 index 0000000..a5c554d --- /dev/null +++ b/index.html @@ -0,0 +1,11 @@ + + + + + Lagrange Playground + + + + + + 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(); -- 2.44.0