Public
Edited
Dec 25, 2023
Insert cell
Insert cell
{
const context = DOM.context2d(width, height);
context.beginPath();
delaunay.renderPoints(context);
 context.fillStyle = "red"
context.fill();
context.beginPath();
voronoi.render(context);
context.stroke();
return context.canvas;
}
Insert cell
{
replay1;
const context = DOM.context2d(width, height);
context.globalCompositeOperation = "darken";
context.beginPath();
delaunay.renderPoints(context);
context.fillStyle = "black";
context.fill();
context.strokeStyel = "lightgray";
yield visibility(context.canvas);
for (let i = 0,n = delaunay.triangles.length / 3; i < n; ++i) {
context.beginPath();
delaunay.renderTriangle(i, context);
context.stroke();
yield context.canvas;
}
}
Insert cell
viewof replay1 = html`<button> Replay`
Insert cell
{
replay2;
const context = DOM.context2d(width, height);
context.globalCompositeOpreration = "darken";
context.beginPath();
delaunay.renderPoints(context);
context.fillStyle = "black";
context.fill();
context.beginPath();
delaunay.render(context);
context.strokeStyle = "lightgray";
context.stroke();
context.fillStyle = "red";
context.strokeStye = "lightgray";
yield visibility(context.canvas);
for (let i = 0, n = delaunay.triangles.length / 3; i < n; ++i) {
let cx = voronoi.circumcenters[i * 2];
let cy = voronoi.circumcenters[i * 2 + 1];
let x0 = delaunay.points[delaunay.triangles[i * 3] * 2];
let y0 = delaunay.points[delaunay.triangles[i * 3] * 2 + 1 ];
let r = Math.sqrt((cx - x0) ** 2 + (cy - y0) **2);
context.beginPath();
context.moveTo(cx+ r, cy);
context.arc(cx, cy, r, 0, 2 * Math.PI);
context.stroke();
context.beginPath();
context.moveTo(cx + 2, cy);
context.arc(cx, cy, 2, 0, 2 * Math.PI);
context.fill();
yield context.canvas;
}
}
Insert cell
viewof replay2 = html`<button> Replay`
Insert cell
delaunay = d3.Delaunay.from(points)
Insert cell
voronoi = delaunay.voronoi([0.5, 0.5, width - 0.5, height - 0.5])
Insert cell
points = [...poissonDiscSampler(width / 8, height/ 8, width *7 / 8, height * 7 / 8, radius)]
Insert cell
height = 600;
Insert cell
radius = 20;
Insert cell
d3 = require("d3-delaunay@4")
Insert cell
function* poissonDiscSampler(x0, y0, x1, y1, radius) {
const k = 30; //maximum number of samples before rejection
const width = x1 - x0;
const height = y1 - y0;
const radius2 = radius * radius;
const radius2_3 = 3 * radius2;
const cellSize = radius * Math.SQRT1_2;
const gridWidth = Math.ceil(width / cellSize);
const gridHeight = Math.ceil(height / cellSize);//Mistype revised
const grid = new Array(gridWidth * gridHeight);
const queue = [];

//Pick first sample.
yield sample(width /2 + Math.random() * radius, height / 2 + Math.random() * radius);

//pick a rabndom exisitindg sample from the queue.
pick: while(queue.length) {
const i = Math.random() * queue.length | 0;
const parent = queue[i];

//Make a new candidate between [radius, 2 * radius] from the exisitng sample.
for (let j = 0; j < k; ++j) {
const a = 2 * Math.PI * Math.random();
const r = Math.sqrt(Math.random() * radius2_3 + radius2);
const x = parent[0] + r * Math.cos(a);
const y = parent[1] + r * Math.sin(a);

//Accept cadidates that are inside the allowed extent
//and father than 2*radius to all exisiting
if (0 <= x && x < width && 0 <= y && y <height && far(x,y)) {
yield sample(x, y);
continue pick;
}
}

//If none of k candidates were accepted, remove it from the queue.
const r = queue.pop();
if (i < queue.length) queue[i] = r;
}
function far(x, y) {
const i =x / cellSize | 0;
const j = y / cellSize |0;
const i0 = Math.max(i - 2, 0);
const j0 = Math.max(j- 2, 0);
const i1 = Math.min(i + 3, gridWidth);
const j1 = Math.min(j + 3, gridHeight);
for(let j = j0; j < j1; ++j) {
const o = j * gridWidth;
for (let i = i0; i < i1; ++i) {
const s = grid[o + i];
if(s) {
const dx = s[0] - x;
const dy = s[1] - y;
if (dx * dx + dy * dy < radius2) return false;
}
}
}
return true;
}
function sample(x, y, parent) {
queue.push(grid[gridWidth * (y / cellSize | 0) + (x / cellSize | 0)] = [x, y]);
return [x + x0, y + y0];
}
}
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