Public
Edited
Jun 19, 2023
5 stars
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
X = Array.from({ length: 200 }, d3.randomNormal(0, 60))
Insert cell
Y = Array.from({ length: 200 }, d3.randomNormal(0, 30))
Insert cell
hull = d3.Delaunay.from(X, (d, i) => X[i], (d, i) => Y[i]).hull
Insert cell
Insert cell
ray = (j) => {
const cross = (xa, ya, xb, yb) => xa * yb - xb * ya;
const n = hull.length;
const xc = X[hull.at(j - 2)],
yc = Y[hull.at(j - 2)],
xa = X[hull.at(j - 1)],
ya = Y[hull.at(j - 1)],
xb = X[hull[j]],
yb = Y[hull[j]],
xd = X[hull.at(j + 1 - n)],
yd = Y[hull.at(j + 1 - n)];
const dxab = xa - xb;
const dyab = ya - yb;
const dxca = xc - xa;
const dyca = yc - ya;
const dxbd = xb - xd;
const dybd = yb - yd;
const hab = Math.hypot(dxab, dyab);
const hca = Math.hypot(dxca, dyca);
const hbd = Math.hypot(dxbd, dybd);
return (x, y) => {
const dxa = x - xa;
const dya = y - ya;
const dxb = x - xb;
const dyb = y - yb;
return (
cross(dxa, dya, dxb, dyb) >= 0 &&
cross(dxa, dya, dxab, dyab) * hca >= cross(dxa, dya, dxca, dyca) * hab &&
cross(dxb, dyb, dxab, dyab) * hbd >= cross(dxb, dyb, dxbd, dybd) * hab
);
};
}
Insert cell
Insert cell
color = {
const n = hull.length;
const rays = Array.from({ length: n }, (_, j) => ray(j));
let k = 0; // previous value
return (x, y) => {
for (let l = 0; l < n; ++l) {
const j = (n + k + (l % 2 ? (l + 1) / 2 : -l / 2)) % n;
if (rays[j](x, y)) return (k = j);
}
return undefined; // not found
};
}
Insert cell
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