Public
Edited
Apr 4, 2023
1 star
Insert cell
Insert cell
{
const canvas = DOM.canvas(width, width);
const ctx = canvas.getContext("2d");
const x = d3.scaleLinear().domain(d3.extent(wider)).range([0, width]);
//return canvas;
let i = 0;
ctx.strokeStyle = "gray";
ctx.strokeWidth = 0.5;
for (const [a, b, d] of tree) {
ctx.beginPath();
ctx.moveTo(x(wider[a * 2]), x(wider[a * 2 + 1]));
ctx.lineTo(x(wider[b * 2]), x(wider[b * 2 + 1]));
ctx.stroke();
i++;
if (i % 100000 === 0) {
yield canvas;
}
}
function randcol() {
return Math.floor(Math.random() * 255);
}
ctx.globalAlpha = 1;
for (const cluster of clusters) {
if (Math.random() < 0.001) {
yield canvas;
}
ctx.fillStyle = `rgb(${randcol()},${randcol()},${randcol()})`;
// ctx.fillStyle = `red`;

for (const seed of cluster) {
const c = wider.slice(seed * 2, seed * 2 + 2).map((d) => x(d));
if (c.length === 2) {
ctx.fillRect(
...wider.slice(seed * 2, seed * 2 + 2).map((d) => x(d)),
1,
1
);
}
}
}

yield canvas;
}
Insert cell
clusters = {
const clusters = seeds.map((i) => [i]);
const is_set = new Array(wider.length / 2);
for (let seed of seeds) {
is_set[seed] = 1;
}
let thresh = 0.1;
for (let run of d3.range(350)) {
thresh += 0.005;
for (const cluster of clusters) {
const c = [...cluster];
for (const point of c) {
for (const [partner, dist] of edgelist[point]) {
if (dist < thresh && !is_set[partner]) {
cluster.push(partner);
is_set[partner] = 1;
}
}
}
}
// yield clusters;
}

yield clusters;
}
Insert cell
seeds = {
const seeds = [];
for (let i = 0; i < edgelist.length; i++) {
if (edgelist[i].length > 4) {
seeds.push(i);
}
if (Math.random() < 0.002) {
seeds.push(i);
}
// return edgelist.filter((d) => d.length > 3);
}
return seeds;
}
Insert cell
tree = {
const set = new Uint8Array(delaunay.points.length / 2);
const heap = new FlatQueue();
const tree = [];

// Initialize the heap with the outgoing edges of vertex zero.
set[0] = 1;
for (const i of delaunay.neighbors(0)) {
heap.push([0, i], distance2(0, i));
}

// For each remaining minimum edge in the heap…
let edge;
while ((edge = heap.pop())) {
const [i, j] = edge;

// If j is already connected, skip; otherwise add the new edge to point j.
if (set[j]) continue;
set[j] = 1;
tree.push([...edge, distance2(i, j)]);

// Add each unconnected neighbor k of point j to the heap.
for (const k of delaunay.neighbors(j)) {
if (set[k]) continue;
heap.push([j, k], distance2(j, k));
}
}
return tree;
}
Insert cell
edgelist = {
const edgelist = d3.range(wider.length / 2).map((d) => []);
for (let [a, b, dist] of tree) {
edgelist[a].push([b, dist]);
edgelist[b].push([a, dist]);
}
return edgelist;
}
Insert cell
function distance2(i, j) {
const dx = points[i * 2] - points[j * 2];
const dy = points[i * 2 + 1] - points[j * 2 + 1];
return dx * dx + dy * dy;
}
Insert cell
delaunay = new d3.Delaunay(wider)
Insert cell
wider = new Float32Array(rawpoints.map((d) => d.r))
Insert cell
points = wider
Insert cell
rawpoints = t.query("SELECT UNNEST([X_bert, Y_bert]) r FROM name LIMIT 800000")
Insert cell
t = DuckDBClient.of({ name: t1 })
Insert cell
ids = t.query("SELECT * FROM name LIMIT 2")
Insert cell
FlatQueue = require("flatqueue@1")
Insert cell
t1 = FileAttachment("t1.parquet")
Insert cell

One platform to build and deploy the best data apps

Experiment and prototype by building visualizations in live JavaScript notebooks. Collaborate with your team and decide which concepts to build out.
Use Observable Framework to build data apps locally. Use data loaders to build in any language or library, including Python, SQL, and R.
Seamlessly deploy to Observable. Test before you ship, use automatic deploy-on-commit, and ensure your projects are always up-to-date.
Learn more