Published
Edited
Mar 22, 2021
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
scale = 0.2
Insert cell
isopleth = isoplethFactory(centers, width, height)
Insert cell
data = (replay,
Array.from(
Object.values(states),
d => somevalue || Math.floor(Math.random() * 256)
))
Insert cell
function isoplethFactory(centers, width, height, padding) {
if (!padding) padding = 0;
const scale = 0.2;
const w = Math.round((width + 2 * padding) * scale);
const h = Math.round((height + 2 * padding) * scale);
const x = scaleLinear([-padding, width + padding], [0, w]);
const y = x; // Use scaleLinear([0, height], [0, h]); to change the aspect ratio (usually we wouldn't want that)

const delaunay = Delaunay.from(centers.map(d => [x(d[0]), y(d[1])]));
const nn = nnmap(delaunay, w, h);
const bl = blur().width(w);
const ct = contours().size([w, h]);

function rescale(contour) {
for (const polygon of contour.coordinates) {
for (const ring of polygon) {
for (const pt of ring) {
pt[0] = x.invert(pt[0]);
pt[1] = y.invert(pt[1]);
}
}
}
return contour;
}

function nnmap(delaunay, width, height) {
const site = new Uint16Array(width * height),
distance = new Float32Array(width * height);
width |= 0;
height |= 0;

let n = 0;
for (let i = 0; i < width; i++) {
for (let j = 0; j < height; j++) {
site[i + width * j] = n = delaunay.find(i, j);
distance[i + width * j] = Math.hypot(
delaunay.points[2 * n] - i,
delaunay.points[2 * n + 1] - j
);
}
}
return { site, distance, width, height };
}

function datamap(data, nn, borderradius, defaultValue) {
return borderradius > 0
? Array.from(nn.site, (s, i) =>
nn.distance[i] < borderradius ? data[s] : defaultValue
)
: Array.from(nn.site, s => data[s]);
}

function computecontours(data, bandwidth, borderradius, defaultValue = 0) {
bl.radius(bandwidth * scale);
return ct(bl(datamap(data, nn, borderradius * scale, defaultValue))).map(
rescale
);
}

computecontours.thresholds = _ =>
_ ? (ct.thresholds(_), computecontours) : ct.thresholds();

return computecontours;
}
Insert cell
contours = d3.contours
Insert cell
scaleLinear = d3.scaleLinear
Insert cell
Delaunay = d3.Delaunay
Insert cell
blur = (await require("array-blur")).blur
Insert cell
d3 = require("d3@6", "array-blur@1")
Insert cell
color = d3.scaleSequential(d3["interpolate"+scheme]).domain([0, 255])
Insert cell
centers = Array.from(Object.values(states), d => [
(width * (2 + d.x)) / 15,
(height * (2 - d.y)) / 11
])
Insert cell
height = Math.round(width / Math.sqrt(3))
Insert cell
somevalue = (replay, samevalue && 100 + 150 * Math.random())
Insert cell
states = FileAttachment("tileCoords (1).json").json()
Insert cell
import { checkbox, select, slider } 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