Published
Edited
Nov 12, 2020
1 fork
10 stars
Hello, A5Chandrupatla’s root-finding methodSidi’s root-finding methodRegular numbersDruidJS workerNatural breaksDistance to a segmentRay out of a convex hullWord Tour: 40k words and their friendsHello, @thi.ng/grid-iteratorsHead/tail breaksPseudo-blue noise shaderHow fast does walk-on-spheres converge?AoC 12: shortest path under constraintsKDE estimationPlot: Correlation heatmapPoisson Finish 2Poisson disk sampling functionsWoS with transportSimple and surprising sortLocal medianTime series topological subsamplingUnion-FindLevel set experiment 1Mean value coordinatesPoisson potentialMiddle-squareWorld of squares (spherical)World of squaresLargest Inscribed SquareHello, PyWaveletsGeothmetic meandianHello, Reorder.jsGeometric MedianImage FFT
Transport to a map
Disc TransportTP3: Power Diagram and Semi-Discrete Optimal TransportThe blue waveHello, genetic-jsSliced Optimal TransportDruidJSSelf-Organizing Maps meet DelaunayHello, polygon-clippingseedrandom, minimalWalk on Spheres 2Walk on SpheresHello, AutoencoderKaprekar’s numberVoronoiMap2DHello, ccwt.jsPolygon TriangulationQuantile.invert?Linear congruential generatorHue blurNeedle in a haystackMoving average blurApollo 11 implementation of trigonometric functions, by Margaret H. Hamilton (march 1969)2D curves intersectionThe 2D approximate Newton-Raphson methodInverting Lee’s Tetrahedral projectionLinde–Buzo–Gray stipplingMean shift clustering with kd-tree2D point distributionsShortest pathKahan SummationHello, delatinDijkstra’s algorithm in gpu.jsLloyd’s relaxation on a graphManhattan DiameterManhattan VoronoiMobility landscapes — an introductionDijkstra’s shortest-path treeH3 odditiesProtein MatrixConvex Spectral WeightsSort stuff by similarityKrigingDelaunay.findTrianglen-dimensions binning?Travelling with a self-organizing mapUMAP-o-MaticMNIST & UMAP-jsHello UMAP-jsMean shift clusteringLevenshtein transitionRd quasi-random sequencesAutomated label placement (countries)Phyllotaxis explainedMotionrugsPlanar hull (Andrew’s monotone chain algorithm)South Africa’s medial axisTravelling salesperson approximation with t-SNEDistance to shoreWorkerngraph: pagerank, louvain…t-SNE VoronoiCloud ContoursCircular function drawingKruskal MazeMyceliumTravelling salesperson approximation on the globe, with t-SNEtsne.jstsne.js & worker
Insert cell
Insert cell
Insert cell
Insert cell
n = 4000 // don't be shy, try 30k!
Insert cell
Insert cell
transport = {
const dirs = 7,
strength = 1;
const w = 400,
h = (height * (w / width)) | 0;

let indices = [],
projection,
deltas;

const sample = Uint32Array.from(
d3.range(w * h).filter(k => bitmap((k % w) / w, Math.floor(k / w) / h))
);
const indicesq = Uint32Array.from(d3.range(sample.length));
const xs = Float32Array.from(indicesq, k => sample[k] % w);
const ys = Float32Array.from(indicesq, k => Math.floor(sample[k] / w));
const projectionq = new Float32Array(indicesq.length);

// batched
return points => {
const n = points.length / 2;
if (n !== indices.length) {
indices = Uint32Array.from(d3.range(n));
projection = new Float32Array(n);
deltas = new Float32Array(2 * n);
}

const a = 2 * Math.PI * Math.random();
deltas.fill(0);
for (let d = 0; d < dirs; d++) {
const ap = a + (Math.PI * d) / dirs,
sa = Math.sin(ap),
ca = Math.cos(ap);

for (let i = 0; i < n; i++)
projection[i] = ca * points[2 * i] + sa * points[2 * i + 1];
indices.sort((i, j) => projection[i] - projection[j]);

for (let i = 0; i < indicesq.length; i++)
projectionq[i] = (ca * xs[i] + sa * ys[i]) * (width / w);

indicesq.sort((i, j) => projectionq[i] - projectionq[j]);

let i, ideal, delta;
for (let k = 0; k < n; k++) {
i = indices[k];
ideal =
projectionq[
indicesq[Math.floor(((k + 1) / (n + 1)) * indicesq.length)]
];
delta = ideal - projection[i];
deltas[2 * i] += ca * delta;
deltas[2 * i + 1] += sa * delta;
}
}
for (let i = 0; i < points.length; i++)
points[i] += (deltas[i] / dirs) * strength;
};
}
Insert cell
points = {
const random = d3.randomNormal(0, 10);
return Float32Array.from(
{ length: 2 * n },
(_, i) => (i % 2 ? height : width) / 2 + random()
);
}
Insert cell
bitmap = {
const w = 400,
h = ((im.height / im.width) * w) | 0;
const context = DOM.context2d(w, h, 1);
context.drawImage(im, 0, 0, w, h);
const pixels = context
.getImageData(0, 0, w, h)
.data.filter((_, i) => i % 4 === 0);
return (x, y) =>
255 - pixels[Math.floor(x * w) + w * Math.floor(y * h)] > 127;
}
Insert cell
height = ((im1.height / im1.width) * width) | 0
Insert cell
im1 = FileAttachment("conformal-dymaxion.png").image()
Insert cell
im = {
if (image === "Earth") return im1;

const context = DOM.context2d(width, height, 1);
context.fillStyle = "white";
context.fillRect(0, 0, width, height);
const n = 3 + Math.random() * 8;
for (let i = 0; i < n; i++) {
context.beginPath();
context.arc(
Math.random() * width,
Math.random() * height,
30 + Math.random() * 60,
0,
tau
);
context.fillStyle = "black";
context.fill();
}
return context.canvas;
}
Insert cell
d3 = require("d3@6")
Insert cell
tau = 2 * Math.PI
Insert cell
import { checkbox, select } from "@jashkenas/inputs"
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