Published
Edited
Mar 28, 2022
7 stars
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
distance = (a, b) => Math.hypot(a[0] - b[0], a[1] - b[1])
Insert cell
kernel = d => Math.exp(-0.5 * (d / sigma) ** 2)
Insert cell
function* meanshift({ points, refs, tree, sigma, kn, delta }) {
const pos = Array.from(points, p => Object.create(p));
if (!refs) refs = points;

delta = delta || 1e-3;
kn = kn || 100;

do {
pos.delta = 0;
for (let i = 0; i < pos.length; i++) {
const p = pos[i],
q = p.map(_ => 0);
let weight = 0;
const nn = Array.from(tree.neighbors(p[0], p[1], kn), j => [
refs[j],
distance(refs[j], p)
]);
for (let j = 0; j < nn.length; j++) {
const ip = nn[j][0],
d = nn[j][1],
w = kernel(d) * (nn[j][0].weight || 1);
weight += w;
for (let k = 0; k < q.length; k++) q[k] += w * ip[k];
}
for (let k = 0; k < q.length; k++) q[k] /= weight;

pos.delta = Math.max(pos.delta, distance(pos[i], q));

pos[i] = q;
}
yield pos;
} while (pos.delta > delta);
}
Insert cell
points = Array.from({ length: N, replay }).map((_, i) => [
i % 2
? Math.random()
: (Math.random() - 0.5) / 4.5 + (0.5 + Math.floor(3 * Math.random())) / 3,
i % 2
? Math.random()
: (Math.random() - 0.5) / 4.5 + (0.5 + Math.floor(3 * Math.random())) / 3
])
Insert cell
Flatbush = require("flatbush@3")
Insert cell
palette = d3.schemePastel2.concat(d3.schemePastel1)
Insert cell
d3 = require("d3@5")
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