From 7ad330422bf14f9e745589e69f10c735ca790830 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C5=A1per=20Dobrovoljc?= Date: Sun, 24 Nov 2024 20:20:39 +0100 Subject: [PATCH] Naloga 2: Changed coordinates from array to object --- naloga_2/main.js | 142 ++++++++++++++++++++++++----------------------- 1 file changed, 73 insertions(+), 69 deletions(-) diff --git a/naloga_2/main.js b/naloga_2/main.js index 6cf6065..e911b97 100644 --- a/naloga_2/main.js +++ b/naloga_2/main.js @@ -12,7 +12,7 @@ let mouseDown = false; /** @type {number|null} */ let movePointIndex = null; -/** @type {number[][][]} */ +/** @type {{x: number, y: number}[][]} */ const curves = []; addButton.addEventListener('click', () => { @@ -31,15 +31,13 @@ removeButton.addEventListener('click', () => { c0Button.addEventListener('click', () => { if (curves.length <= 1 || selected === null) return; - let p = getClosestEndPoint(curves[selected][0][0], curves[selected][0][1]); - if (p === null) return; - let [curveIndex, pointIndex] = p; - curves[selected][0] = curves[curveIndex][pointIndex]; + let [ci, pi] = getClosestEndPoint(curves[selected][0]); + if (ci === null || pi === null) return; + curves[selected][0] = curves[ci][pi]; - p = getClosestEndPoint(curves[selected][3][0], curves[selected][3][1]); - if (p === null) return; - [curveIndex, pointIndex] = p; - curves[selected][3] = curves[curveIndex][pointIndex]; + [ci, pi] = getClosestEndPoint(curves[selected][3]); + if (ci === null || pi === null) return; + curves[selected][3] = curves[ci][pi]; draw(); }); @@ -47,30 +45,26 @@ c0Button.addEventListener('click', () => { c1Button.addEventListener('click', () => { if (curves.length <= 1 || selected === null) return; - let [curveIndex, pointIndex] = getClosestEndPoint( - curves[selected][0][0], - curves[selected][0][1], - ); + let [ci, pi] = getClosestEndPoint(curves[selected][0]); + if (ci === null || pi === null) return; // Move first point of selected curve to closest found point - curves[selected][0] = curves[curveIndex][pointIndex]; - // Get control point of found point - const h1 = curves[curveIndex][pointIndex === 0 ? 1 : 2]; - // Set control point to location mirrored over the first point - curves[selected][1] = [ - 2 * curves[selected][0][0] - h1[0], - 2 * curves[selected][0][1] - h1[1], - ]; + curves[selected][0] = curves[ci][pi]; + // Get control point of found end point + const handle1 = curves[ci][pi === 0 ? 1 : 2]; + // Set control point to location mirrored over the point + curves[selected][1] = { + x: 2 * curves[selected][0].x - handle1.x, + y: 2 * curves[selected][0].y - handle1.y, + }; - [curveIndex, pointIndex] = getClosestEndPoint( - curves[selected][3][0], - curves[selected][3][1], - ); - curves[selected][3] = curves[curveIndex][pointIndex]; - const h2 = curves[curveIndex][pointIndex === 0 ? 1 : 2]; - curves[selected][2] = [ - 2 * curves[selected][3][0] - h2[0], - 2 * curves[selected][3][1] - h2[1], - ]; + [ci, pi] = getClosestEndPoint(curves[selected][3]); + if (ci === null || pi === null) return; + curves[selected][3] = curves[ci][pi]; + const handle2 = curves[ci][pi === 0 ? 1 : 2]; + curves[selected][2] = { + x: 2 * curves[selected][3].x - handle2.x, + y: 2 * curves[selected][3].y - handle2.y, + }; draw(); }); @@ -81,7 +75,7 @@ c1Button.addEventListener('click', () => { */ function addPoint(x, y) { const curve = curves[curves.length - 1]; - curve.push([x, y]); + curve.push({ x, y }); if (curve.length === 4) { adding = false; } @@ -99,42 +93,44 @@ function lerp(t, a, b) { } /** - * interpolates the points + * interpolates the values * @param {number} t - * @param {number[]} p array of points + * @param {number[]} v array of values */ -function lerpCurve(t, p) { - if (p.length === 1) return p[0]; - return lerp(t, lerpCurve(t, p.slice(0, -1)), lerpCurve(t, p.slice(1))); +function lerpArray(t, v) { + if (v.length === 1) return v[0]; + return lerp(t, lerpArray(t, v.slice(0, -1)), lerpArray(t, v.slice(1))); } function drawCircles() { if (selected === null) return; - for (const [x, y] of curves[selected]) { + for (const { x, y } of curves[selected]) { context.beginPath(); context.ellipse(x, y, 10, 10, 0, 0, Math.PI * 2); context.stroke(); } } +// Failed attempt at adaptive line length + /** * @param {number} tStart * @param {number} tEnd - * @param {number[][]} points + * @param {{x: number, y: number}[]} points * @returns {{x: number, y: number}[]} */ function calcPoints(tStart, tEnd, points) { - const xPoints = points.map((p) => p[0]); - const yPoints = points.map((p) => p[1]); + const xPoints = points.map((p) => p.x); + const yPoints = points.map((p) => p.y); - const x1 = lerpCurve(tStart, xPoints); - const y1 = lerpCurve(tStart, yPoints); - const x2 = lerpCurve((tStart + tEnd) / 2, xPoints); - const y2 = lerpCurve((tStart + tEnd) / 2, yPoints); - const x3 = lerpCurve(tEnd, xPoints); - const y3 = lerpCurve(tEnd, yPoints); + const x1 = lerpArray(tStart, xPoints); + const y1 = lerpArray(tStart, yPoints); + const x2 = lerpArray((tStart + tEnd) / 2, xPoints); + const y2 = lerpArray((tStart + tEnd) / 2, yPoints); + const x3 = lerpArray(tEnd, xPoints); + const y3 = lerpArray(tEnd, yPoints); - const s = + const surface = (1 / 2) * Math.abs(x1 * (y2 - y3) + x2 * (y3 - y1) + x3 * (y1 - y2)); // const d12 = Math.sqrt((x1 - x2) ** 2 + (y1 - y2) ** 2); @@ -143,7 +139,7 @@ function calcPoints(tStart, tEnd, points) { // // const angle = Math.acos((d12 ** 2 + d13 ** 2 - d23 ** 2) / (2 * d12 * d13)); - if (s < 20) { + if (surface < 20) { return [{ x: x3, y: y3 }]; } @@ -157,22 +153,19 @@ function drawLines() { for (let i = 0; i < curves.length; i++) { const curve = curves[i]; for (let j = 0; j < curve.length - 3; j += 3) { - const p1 = curve[j]; - const p2 = curve[j + 1]; - const p3 = curve[j + 2]; - const p4 = curve[j + 3]; + const points = curve.slice(j, j + 4); context.beginPath(); if (selected === i) { - context.moveTo(p1[0], p1[1]); - context.lineTo(p2[0], p2[1]); + context.moveTo(points[0].x, points[0].y); + context.lineTo(points[1].x, points[1].y); - context.moveTo(p3[0], p3[1]); - context.lineTo(p4[0], p4[1]); + context.moveTo(points[2].x, points[2].y); + context.lineTo(points[3].x, points[3].y); } - context.moveTo(p1[0], p1[1]); + context.moveTo(points[0].x, points[0].y); // // const points = calcPoints(0, 1, curve); // @@ -182,8 +175,14 @@ function drawLines() { for (let t = 0; t <= 100; t++) { const tt = t / 100; - const x = lerpCurve(tt, [p1[0], p2[0], p3[0], p4[0]]); - const y = lerpCurve(tt, [p1[1], p2[1], p3[1], p4[1]]); + const x = lerpArray( + tt, + points.map((p) => p.x), + ); + const y = lerpArray( + tt, + points.map((p) => p.y), + ); context.lineTo(x, y); } @@ -221,7 +220,7 @@ function getClosestCurveIndex(x, y) { for (let i = 0; i < curves.length; i++) { for (const point of curves[i]) { const dist = Math.abs( - Math.sqrt((x - point[0]) ** 2 + (y - point[1]) ** 2), + Math.sqrt((x - point.x) ** 2 + (y - point.y) ** 2), ); if (!minDist || dist < minDist) { minDist = dist; @@ -244,7 +243,7 @@ function getSelectedPoint(x, y) { for (let i = 0; i < curves[selected].length; i++) { const point = curves[selected][i]; const dist = Math.abs( - Math.sqrt((x - point[0]) ** 2 + (y - point[1]) ** 2), + Math.sqrt((x - point.x) ** 2 + (y - point.y) ** 2), ); if (dist <= 10) { return i; @@ -255,11 +254,10 @@ function getSelectedPoint(x, y) { /** * Gets the closest end point - * @param {number} x - * @param {number} y - * @returns {number[]|null} + * @param {{x: number, y: number}} point + * @returns {[number|null, number|null]} curveIndex and pointIndex */ -function getClosestEndPoint(x, y) { +function getClosestEndPoint(point) { /** @type {number|null} */ let minDist = null, minCurveIndex = null, @@ -268,7 +266,10 @@ function getClosestEndPoint(x, y) { for (let i = 0; i < curves.length; i++) { if (i === selected) continue; let dist = Math.abs( - Math.sqrt((x - curves[i][0][0]) ** 2 + (y - curves[i][0][1]) ** 2), + Math.sqrt( + (point.x - curves[i][0].x) ** 2 + + (point.y - curves[i][0].y) ** 2, + ), ); if (minDist === null || dist < minDist) { minDist = dist; @@ -277,7 +278,10 @@ function getClosestEndPoint(x, y) { } dist = Math.abs( - Math.sqrt((x - curves[i][3][0]) ** 2 + (y - curves[i][3][1]) ** 2), + Math.sqrt( + (point.x - curves[i][3].x) ** 2 + + (point.y - curves[i][3].y) ** 2, + ), ); if (minDist === null || dist < minDist) { minDist = dist; @@ -312,7 +316,7 @@ canvas.addEventListener('mousedown', (e) => { canvas.addEventListener('mousemove', (e) => { if (!mouseDown) return; if (movePointIndex === null) return; - curves[selected][movePointIndex] = [e.pageX, e.pageY]; + curves[selected][movePointIndex] = { x: e.pageX, y: e.pageY }; draw(); });