1 const canvas = document.getElementsByTagName("canvas")[0];
2 const ctx = canvas.getContext("2d");
5 let centerF = [0.5, 0.5];
20 const coordinateToScreen = (x, y) => {
22 center[0] + x * scale,
23 center[1] + y * scale,
27 const screenToCoordinate = (x, y) => {
29 (x - center[0]) / scale,
30 (y - center[1]) / scale,
34 const evalPos = (a, b, c, x) => {
35 return a + (b + c * x) * x;
38 const lagrange = _ => {
42 for (let i = 0; i < positions.length; i++) {
43 let prod = positions[i][1];
45 for (let j = 0; j < positions.length; j++)
47 prod *= (x - positions[j][0]) / (positions[i][0] - positions[j][0]);
57 ctx.clearRect(0, 0, innerWidth, innerHeight);
59 for (let x = center[0] % scale; x < innerWidth; x += scale) {
60 if (Math.round(x) == Math.round(center[0]))
69 ctx.lineTo(x, innerHeight);
70 ctx.strokeStyle = "grey";
74 for (let y = center[1] % scale; y < innerHeight; y += scale) {
75 if (Math.round(y) == Math.round(center[1]))
84 ctx.lineTo(innerWidth, y);
85 ctx.strokeStyle = "grey";
92 for (let x = 0; x < innerWidth; x++) {
93 let y = Math.max(Math.min(center[1] + func((x - center[0]) / scale) * scale, +1e+37), -1e+37);
100 ctx.strokeStyle = "black";
103 for (let i = 0; i < positions.length; i++) {
104 const pos = positions[i];
106 const [x, y] = coordinateToScreen(pos[0], pos[1]);
108 ctx.arc(x, y, scale * pointSize, 0, Math.PI * 2);
109 ctx.fillStyle = "blue";
113 const last = positions[i - 1];
116 const [lx, ly] = coordinateToScreen(last[0], last[1]);
121 ctx.strokeStyle = "red";
125 if (config.circles) {
126 const [cx, cy] = coordinateToScreen((pos[0] + last[0]) / 2, (pos[1] + last[1]) / 2);
129 ctx.arc(cx, cy, scale * Math.sqrt(Math.pow(pos[0] - last[0], 2) + Math.pow(pos[1] - last[1], 2)) / 2, 0, Math.PI * 2);
130 ctx.strokeStyle = "green";
137 const sortPositions = _ => {
138 positions.sort((a, b) => {
139 return a[0] < b[0] ? -1 : +1;
145 const addPosition = pos => {
150 const calculateCenter = _ => {
152 centerF[0] * innerWidth,
153 centerF[1] * innerHeight,
159 const resize = _ => {
160 canvas.width = innerWidth;
161 canvas.height = innerHeight;
166 const enableDrag = evt => {
167 dragPos = [evt.clientX / innerWidth, evt.clientY / innerHeight];
170 const disableDrag = _ => {
174 canvas.style.cursor = "auto";
182 canvas.addEventListener("mousedown", evt => {
188 for (let i = 0; i < positions.length; i++) {
189 const [x, y] = coordinateToScreen(positions[i][0], positions[i][1]);
191 if (Math.sqrt(Math.pow(evt.clientX - x, 2) + Math.pow(evt.clientY - y, 2)) < scale * pointSize) {
198 canvas.addEventListener("mousemove", evt => {
202 const oldDragPos = dragPos;
209 if (dragIndex == -1) {
210 canvas.style.cursor = "move";
213 centerF[0] + dragPos[0] - oldDragPos[0],
214 centerF[1] + dragPos[1] - oldDragPos[1],
219 canvas.style.cursor = "grabbing";
221 let pos = positions[dragIndex] = screenToCoordinate(dragPos[0] * innerWidth, dragPos[1] * innerHeight);
223 dragIndex = positions.indexOf(pos);
228 canvas.addEventListener("mouseup", evt => {
233 addPosition(screenToCoordinate(evt.clientX, evt.clientY));
238 canvas.addEventListener("mouseleave", evt => {
245 canvas.addEventListener("wheel", evt => {
246 scale -= evt.deltaY * 0.05;
247 scale = Math.max(1, scale);
252 addEventListener("resize", _ => {
256 for (let id of ["grid", "lines", "circles"]) {
257 let elem = document.getElementById(id);
258 elem.checked = config[id];
260 elem.addEventListener("input", evt => {
261 config[id] = elem.checked;