Published
Edited
Feb 14, 2020
1 fork
9 stars
Insert cell
Insert cell
Insert cell
canvas = {
replay;
const n = 320;
const context = DOM.context2d(width, height);
let points0 = Float64Array.from({length: n * 2}, (_, i) => Math.random() * (i & 1 ? height : width));
let points1 = new Float64Array(n * 2);
for (let i = 0; i < 480; ++i) {
const delaunay = new d3.Delaunay(points0);
context.clearRect(0, 0, width, height);
for (let p0 = 0; p0 < n; ++p0) {
const p1 = nearestNeighbor(delaunay, p0);
const x0 = points0[p0 * 2];
const y0 = points0[p0 * 2 + 1];
const x1 = points0[p1 * 2];
const y1 = points0[p1 * 2 + 1];
const r = Math.sqrt((x1 - x0) ** 2 + (y1 - y0) ** 2);
if (x0 >= 0 && x0 <= width && y0 >= 0 && y0 <= height) {
points1[p0 * 2] = x0 - (x1 - x0) / (r * 4);
points1[p0 * 2 + 1] = y0 - (y1 - y0) / (r * 4);
}
context.beginPath();
context.moveTo(x0 + 2, y0);
context.arc(x0, y0, 2, 0, 2 * Math.PI);
context.fill();
context.beginPath();
context.moveTo(x0 + r / 2, y0);
context.arc(x0, y0, r / 2, 0, 2 * Math.PI);
context.strokeStyle = "#000"
context.stroke();
}
points0 = points1;
yield context.canvas;
}
}
Insert cell
function nearestNeighbor(delaunay, i) {
const {points} = delaunay;
let minDistance = Infinity;
let minNeighbor;
const x0 = points[i * 2];
const y0 = points[i * 2 + 1];
for (const neighbor of delaunay.neighbors(i)) {
const x1 = points[neighbor * 2];
const y1 = points[neighbor * 2 + 1];
const distance = (x0 - x1) ** 2 + (y0 - y1) ** 2;
if (distance < minDistance) {
minDistance = distance;
minNeighbor = neighbor;
}
}
return minNeighbor;
}
Insert cell
height = 600
Insert cell
d3 = require("d3-delaunay@5")
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more