From bf7ae246a3a06cbb9c96644d9d68b85c7b81f362 Mon Sep 17 00:00:00 2001 From: Mike Lynch Date: Sun, 20 Apr 2025 16:02:41 +1000 Subject: [PATCH] Generalised grids and bands into a single function --- src/components/dots.js | 25 +++++++++++-------------- src/index.md | 10 +++++++--- 2 files changed, 18 insertions(+), 17 deletions(-) diff --git a/src/components/dots.js b/src/components/dots.js index 15ef418..0030bdd 100644 --- a/src/components/dots.js +++ b/src/components/dots.js @@ -1,6 +1,5 @@ // calculate tiles -const SIN_PERIOD = 100 / Math.PI; const RADIUS_OPTS = [ "const", @@ -16,10 +15,8 @@ const RADIUS_OPTS = [ "circle-out", "hyper-in", "hyper-out", + "grid", "noise", - "diamonds", - "horizontal-bands", - "vertical-bands", ]; const RADIUS_DESC = { @@ -37,9 +34,7 @@ const RADIUS_DESC = { "hyper-in": "forming a starlike pattern at the centre", "hyper-out": "leaving a starlike gap in the centre", "noise": "of random sizes", - "diamonds": "in a grid tilted at 45 degrees", - "horizontal-bands": "in horizontal bands", - "vertical-bands": "in a vertical bands", + "grid": "forming a grid pattern", } function distance(dx, dy) { @@ -55,6 +50,10 @@ function int_range(v1, v2) { return [...Array(high - low + 1).keys()].map((i) => i + low); } +function randint(min, max) { + return min + Math.floor(Math.random() * (max + 1)); +} + class DotMaker { constructor(width, height) { this.width = width; @@ -108,17 +107,15 @@ class DotMaker { case "circle-in": return (d, r) => 2 * r * (0.5 * this.wh - distance((d.x - this.cx), (d.y - this.cy))) / this.wh; case "hyper-in": - return (d, r) => r * Math.abs((d.x - this.cx) * (d.y - this.cy)) / this.wh; - case "hyper-out": return (d, r) => r * (1 - Math.abs((d.x - this.cx) * (d.y - this.cy)) / this.wh); + case "hyper-out": + return (d, r) => r * Math.abs((d.x - this.cx) * (d.y - this.cy)) / this.wh; case "noise": return (d, r) => r * Math.random(); - case "horizontal-bands": - return (d, r) => r * (1 + Math.cos(SIN_PERIOD *(d.y - this.cy)/ this.wh)); - case "vertical-bands": - return (d, r) => r * (1 + Math.cos(SIN_PERIOD *(d.x - this.cx)/ this.wh)); case "grid": - return (d, r) => r * (0.5 + 0.5 * (Math.cos(SIN_PERIOD *(d.x - this.cx)/ this.wh) + Math.cos(SIN_PERIOD * (d.y - this.cy)/ this.wh))); + const xk = Math.PI * (2 * randint(1, 10) - 1) / this.width; + const yk = Math.PI * (2 * randint(1, 10) - 1) / this.height; + return (d, r) => r * (0.5 + 0.5 * (Math.sin(xk * d.x) + Math.sin(yk * d.y))); default: return (d, r) => r; } diff --git a/src/index.md b/src/index.md index 5c07cad..4a87cbe 100644 --- a/src/index.md +++ b/src/index.md @@ -137,6 +137,13 @@ const dots1 = dm.dots(1 / m1, n1, false); const dots2 = dm.dots(1 / m2, n2, false); +``` + +```js + +const rfunc1 = dm.radius(f1); +const rfunc2 = dm.radius(f2); + ``` ```js @@ -209,9 +216,6 @@ display(svg.node()); ```js // separate code block for when I understand transitions better - - const rfunc1 = dm.radius(f1); - const rfunc2 = dm.radius(f2); dots_g1.selectAll("circle").attr("r", (d) => rfunc1(d, r1)); dots_g2.selectAll("circle").attr("r", (d) => rfunc2(d, r2));