From 7dcc48063bedeecea23e34e857cdb2ecd64ec74d Mon Sep 17 00:00:00 2001 From: pintosum Date: Tue, 10 Mar 2026 19:41:22 +0300 Subject: [PATCH 1/4] added clamp for barycentric --- index.js | 41 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/index.js b/index.js index df80e22..8ac1bb9 100644 --- a/index.js +++ b/index.js @@ -2,6 +2,7 @@ const BACKGROUND = "#141414"; const WHITE = "#FFFFFF"; const RED = "#FF2020"; const CYAN = "#20FFFF"; +const GREEN = "#228B22"; const MARKER_RADIUS = 0.03; const MARKER_ENLARGMENT_FACTOR = 1.2; const FRAME_THICKNESS = 0.01 @@ -63,6 +64,35 @@ function v2sub({x: x1, y: y1}, {x: x2, y: y2}) { } } +function barycentric(p1, p2, p3, p) { + const det = (p2.y - p3.y)*(p1.x - p3.x) + (p3.x - p2.x)*(p1.y - p3.y) + let u = [] + u[0] = ((p2.y - p3.y)*(p.x - p3.x) + (p3.x - p2.x)*(p.y - p3.y))/det + u[1] = ((p3.y - p1.y)*(p.x - p3.x) + (p1.x - p3.x)*(p.y - p3.y))/det + u[2] = 1 - u[0] - u[1] + const sum = u + .filter((u_i)=> u_i >= 0) + .reduce((acc, cur_val) => acc + cur_val, 0); + for (let i = 0; i < u.length; i++) { + if (u[i] < 0) { + u[i] = 0 + } else { + u[i] = u[i] / sum + } + } + return u +} + +function from_bc_to_cartesian(p1, p2, p3, u) { + let p = [p1,p2,p3] + let ret = {x: 0, y: 0} + for (let i = 0; i < p.length; i++) { + const t = v2scale(p[i], u[i]) + ret = v2add(ret, t) + } + return ret +} + function v2len({x, y}) { return Math.sqrt(x*x + y*y); } @@ -114,9 +144,10 @@ let ps = [ triangleCorner(screenCenter(), 0), triangleCorner(screenCenter(), 1), triangleCorner(screenCenter(), 2), + screenCenter() ] let dragging = -1; -let highlighted = [0, 0, 0, 0]; +let highlighted = [0, 0, 0, 0, 0]; function clamp(x, lo, hi) { if (isNaN(x)) return lo; @@ -132,6 +163,9 @@ function redrawScene() { t2 = clamp(t2, 0, 1); ps[0] = inverseCoordinates(ps[1], ps[2], ps[3], t1, t2); + let bc = barycentric(ps[1], ps[2], ps[3], ps[4]) + ps[4] = from_bc_to_cartesian(ps[1], ps[2], ps[3], bc) + drawLine(v2lerp(ps[1], ps[2], t1), v2lerp(ps[1], ps[3], t1), game.height*FRAME_THICKNESS, CYAN); drawLine(ps[1], v2lerp(v2lerp(ps[1], ps[2], t1), v2lerp(ps[1], ps[3], t1), 0.5), game.height*FRAME_THICKNESS, CYAN); @@ -139,10 +173,15 @@ function redrawScene() { drawLine(ps[2], ps[3], game.height*FRAME_THICKNESS, RED); drawLine(ps[3], ps[1], game.height*FRAME_THICKNESS, RED); + drawLine(ps[4], ps[2], game.height*FRAME_THICKNESS, GREEN); + drawLine(ps[4], ps[3], game.height*FRAME_THICKNESS, GREEN); + drawLine(ps[4], ps[1], game.height*FRAME_THICKNESS, GREEN); + fillCircle(ps[1], highlighted[1] ? game.height*MARKER_RADIUS*MARKER_ENLARGMENT_FACTOR : game.height*MARKER_RADIUS, highlighted[1] ? WHITE : RED); fillCircle(ps[2], highlighted[2] ? game.height*MARKER_RADIUS*MARKER_ENLARGMENT_FACTOR : game.height*MARKER_RADIUS, highlighted[2] ? WHITE : RED); fillCircle(ps[3], highlighted[3] ? game.height*MARKER_RADIUS*MARKER_ENLARGMENT_FACTOR : game.height*MARKER_RADIUS, highlighted[3] ? WHITE : RED); fillCircle(ps[0], highlighted[0] ? game.height*MARKER_RADIUS*MARKER_ENLARGMENT_FACTOR : game.height*MARKER_RADIUS, highlighted[0] ? WHITE : CYAN); + fillCircle(ps[4], highlighted[4] ? game.height*MARKER_RADIUS*MARKER_ENLARGMENT_FACTOR : game.height*MARKER_RADIUS, highlighted[4] ? WHITE : GREEN); } redrawScene(); From f66b2cc474ec92052a7428954508f8c23111d820 Mon Sep 17 00:00:00 2001 From: pintosum Date: Tue, 10 Mar 2026 21:03:26 +0300 Subject: [PATCH 2/4] fixed small issues --- index.js | 38 ++++++++++++++++++++------------------ 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/index.js b/index.js index 8ac1bb9..e8f2e3f 100644 --- a/index.js +++ b/index.js @@ -140,11 +140,11 @@ function inverseCoordinates(p1, p2, p3, t1, t2) { } let ps = [ + screenCenter(), screenCenter(), triangleCorner(screenCenter(), 0), triangleCorner(screenCenter(), 1), triangleCorner(screenCenter(), 2), - screenCenter() ] let dragging = -1; let highlighted = [0, 0, 0, 0, 0]; @@ -158,30 +158,30 @@ function redrawScene() { ctx.fillStyle = BACKGROUND ctx.fillRect(0, 0, game.width, game.height); - let {t1, t2} = coordinates(ps[1], ps[2], ps[3], ps[0]); + let {t1, t2} = coordinates(ps[2], ps[3], ps[4], ps[0]); t1 = clamp(t1, 0, 1); t2 = clamp(t2, 0, 1); - ps[0] = inverseCoordinates(ps[1], ps[2], ps[3], t1, t2); + ps[0] = inverseCoordinates(ps[2], ps[3], ps[4], t1, t2); - let bc = barycentric(ps[1], ps[2], ps[3], ps[4]) - ps[4] = from_bc_to_cartesian(ps[1], ps[2], ps[3], bc) + let bc = barycentric(ps[2], ps[3], ps[4], ps[1]) + ps[1] = from_bc_to_cartesian(ps[2], ps[3], ps[4], bc) - drawLine(v2lerp(ps[1], ps[2], t1), v2lerp(ps[1], ps[3], t1), game.height*FRAME_THICKNESS, CYAN); - drawLine(ps[1], v2lerp(v2lerp(ps[1], ps[2], t1), v2lerp(ps[1], ps[3], t1), 0.5), game.height*FRAME_THICKNESS, CYAN); + drawLine(v2lerp(ps[2], ps[3], t1), v2lerp(ps[2], ps[4], t1), game.height*FRAME_THICKNESS, CYAN); + drawLine(ps[2], v2lerp(v2lerp(ps[2], ps[3], t1), v2lerp(ps[2], ps[4], t1), 0.5), game.height*FRAME_THICKNESS, CYAN); - drawLine(ps[1], ps[2], game.height*FRAME_THICKNESS, RED); drawLine(ps[2], ps[3], game.height*FRAME_THICKNESS, RED); - drawLine(ps[3], ps[1], game.height*FRAME_THICKNESS, RED); + drawLine(ps[3], ps[4], game.height*FRAME_THICKNESS, RED); + drawLine(ps[4], ps[2], game.height*FRAME_THICKNESS, RED); - drawLine(ps[4], ps[2], game.height*FRAME_THICKNESS, GREEN); - drawLine(ps[4], ps[3], game.height*FRAME_THICKNESS, GREEN); - drawLine(ps[4], ps[1], game.height*FRAME_THICKNESS, GREEN); + drawLine(ps[1], ps[3], game.height*FRAME_THICKNESS, GREEN); + drawLine(ps[1], ps[4], game.height*FRAME_THICKNESS, GREEN); + drawLine(ps[1], ps[2], game.height*FRAME_THICKNESS, GREEN); - fillCircle(ps[1], highlighted[1] ? game.height*MARKER_RADIUS*MARKER_ENLARGMENT_FACTOR : game.height*MARKER_RADIUS, highlighted[1] ? WHITE : RED); - fillCircle(ps[2], highlighted[2] ? game.height*MARKER_RADIUS*MARKER_ENLARGMENT_FACTOR : game.height*MARKER_RADIUS, highlighted[2] ? WHITE : RED); - fillCircle(ps[3], highlighted[3] ? game.height*MARKER_RADIUS*MARKER_ENLARGMENT_FACTOR : game.height*MARKER_RADIUS, highlighted[3] ? WHITE : RED); + fillCircle(ps[2], highlighted[2] ? game.height*MARKER_RADIUS*MARKER_ENLARGMENT_FACTOR : game.height*MARKER_RADIUS, highlighted[1] ? WHITE : RED); + fillCircle(ps[3], highlighted[3] ? game.height*MARKER_RADIUS*MARKER_ENLARGMENT_FACTOR : game.height*MARKER_RADIUS, highlighted[2] ? WHITE : RED); + fillCircle(ps[4], highlighted[4] ? game.height*MARKER_RADIUS*MARKER_ENLARGMENT_FACTOR : game.height*MARKER_RADIUS, highlighted[3] ? WHITE : RED); fillCircle(ps[0], highlighted[0] ? game.height*MARKER_RADIUS*MARKER_ENLARGMENT_FACTOR : game.height*MARKER_RADIUS, highlighted[0] ? WHITE : CYAN); - fillCircle(ps[4], highlighted[4] ? game.height*MARKER_RADIUS*MARKER_ENLARGMENT_FACTOR : game.height*MARKER_RADIUS, highlighted[4] ? WHITE : GREEN); + fillCircle(ps[1], highlighted[1] ? game.height*MARKER_RADIUS*MARKER_ENLARGMENT_FACTOR : game.height*MARKER_RADIUS, highlighted[4] ? WHITE : GREEN); } redrawScene(); @@ -215,12 +215,14 @@ game.addEventListener('mousemove', (e) => { for (let i = 0; i < ps.length; ++i) { highlighted[i] = v2dist(mouse, ps[i]) <= (highlighted[i] ? game.height*MARKER_RADIUS*MARKER_ENLARGMENT_FACTOR : game.height*MARKER_RADIUS) || i == dragging; } - if (dragging == 0) { + if (dragging == 0 || dragging == 1) { ps[dragging] = mouse; } else if (dragging > 0) { let {t1, t2} = coordinates(ps[1], ps[2], ps[3], ps[0]); ps[dragging] = mouse; ps[0] = inverseCoordinates(ps[1], ps[2], ps[3], t1, t2); - } + let bc = barycentric(ps[1], ps[2], ps[3], ps[4]) + ps[4] = from_bc_to_cartesian(ps[1], ps[2], ps[3], bc) + } redrawScene(); }); From 35ca99833586bbc4e11cee8057ad082d8710090d Mon Sep 17 00:00:00 2001 From: pintosum Date: Wed, 11 Mar 2026 11:15:51 +0300 Subject: [PATCH 3/4] oops --- index.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/index.js b/index.js index e8f2e3f..266bf83 100644 --- a/index.js +++ b/index.js @@ -177,11 +177,11 @@ function redrawScene() { drawLine(ps[1], ps[4], game.height*FRAME_THICKNESS, GREEN); drawLine(ps[1], ps[2], game.height*FRAME_THICKNESS, GREEN); - fillCircle(ps[2], highlighted[2] ? game.height*MARKER_RADIUS*MARKER_ENLARGMENT_FACTOR : game.height*MARKER_RADIUS, highlighted[1] ? WHITE : RED); - fillCircle(ps[3], highlighted[3] ? game.height*MARKER_RADIUS*MARKER_ENLARGMENT_FACTOR : game.height*MARKER_RADIUS, highlighted[2] ? WHITE : RED); - fillCircle(ps[4], highlighted[4] ? game.height*MARKER_RADIUS*MARKER_ENLARGMENT_FACTOR : game.height*MARKER_RADIUS, highlighted[3] ? WHITE : RED); + fillCircle(ps[2], highlighted[2] ? game.height*MARKER_RADIUS*MARKER_ENLARGMENT_FACTOR : game.height*MARKER_RADIUS, highlighted[2] ? WHITE : RED); + fillCircle(ps[3], highlighted[3] ? game.height*MARKER_RADIUS*MARKER_ENLARGMENT_FACTOR : game.height*MARKER_RADIUS, highlighted[3] ? WHITE : RED); + fillCircle(ps[4], highlighted[4] ? game.height*MARKER_RADIUS*MARKER_ENLARGMENT_FACTOR : game.height*MARKER_RADIUS, highlighted[4] ? WHITE : RED); fillCircle(ps[0], highlighted[0] ? game.height*MARKER_RADIUS*MARKER_ENLARGMENT_FACTOR : game.height*MARKER_RADIUS, highlighted[0] ? WHITE : CYAN); - fillCircle(ps[1], highlighted[1] ? game.height*MARKER_RADIUS*MARKER_ENLARGMENT_FACTOR : game.height*MARKER_RADIUS, highlighted[4] ? WHITE : GREEN); + fillCircle(ps[1], highlighted[1] ? game.height*MARKER_RADIUS*MARKER_ENLARGMENT_FACTOR : game.height*MARKER_RADIUS, highlighted[1] ? WHITE : GREEN); } redrawScene(); @@ -218,11 +218,11 @@ game.addEventListener('mousemove', (e) => { if (dragging == 0 || dragging == 1) { ps[dragging] = mouse; } else if (dragging > 0) { - let {t1, t2} = coordinates(ps[1], ps[2], ps[3], ps[0]); + let {t1, t2} = coordinates(ps[2], ps[3], ps[4], ps[0]); ps[dragging] = mouse; - ps[0] = inverseCoordinates(ps[1], ps[2], ps[3], t1, t2); - let bc = barycentric(ps[1], ps[2], ps[3], ps[4]) - ps[4] = from_bc_to_cartesian(ps[1], ps[2], ps[3], bc) + ps[0] = inverseCoordinates(ps[2], ps[3], ps[4], t1, t2); + let bc = barycentric(ps[2], ps[3], ps[4], ps[1]) + ps[1] = from_bc_to_cartesian(ps[2], ps[3], ps[4], bc) } redrawScene(); }); From 516c0dc1b5d3416cd8bae11a033a5be75be2edfc Mon Sep 17 00:00:00 2001 From: pintosum Date: Wed, 11 Mar 2026 11:23:31 +0300 Subject: [PATCH 4/4] idk it works on my machine --- index.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/index.js b/index.js index 266bf83..aef6ae7 100644 --- a/index.js +++ b/index.js @@ -221,8 +221,6 @@ game.addEventListener('mousemove', (e) => { let {t1, t2} = coordinates(ps[2], ps[3], ps[4], ps[0]); ps[dragging] = mouse; ps[0] = inverseCoordinates(ps[2], ps[3], ps[4], t1, t2); - let bc = barycentric(ps[2], ps[3], ps[4], ps[1]) - ps[1] = from_bc_to_cartesian(ps[2], ps[3], ps[4], bc) } redrawScene(); });