Public
Edited
Apr 14
1 fork
5 stars
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
{
const { data, range } = heightmap;
const N = data.length;
//const values = stepper(range, 20);
const values = [value];
const plot = Plot();

const paths = [];
const vec = ([x1, y1], [x2, y2]) => [x2 - x1, y2 - y1];
const move = ([x, y]) => plot.move(x, -y);
const draw = ([x, y]) => plot.draw(x, -y);
let current;
for (const value of values) {
const paths = generatePaths(cells, value);
for (const path of paths) {
move(vec([0, N], (current = path.shift())));
path.forEach((pt) => draw(vec(current, (current = pt))));
move(vec(current, [0, N]));
}
}

const attrs = { viewBox: `-10 -10 ${N + 19}, ${N + 19}` };
return viewer([width, Math.min(width, 500)], attrs).view(plot, attrs);
}
Insert cell
Cells = function* (N, data, nb) {
const step = N / nb;
const pt = (i, j) => [[i, j], data(i, j)];
for (let pi = 0, i = pi + step; i < N; pi = i, i += step)
for (let pj = 0, j = pj + step; j < N; pj = j, j += step)
yield [pt(pi, pj), pt(i, pj), pt(i, j), pt(pi, j)];
}
Insert cell
cells = {
const { data } = heightmap;
const fl = Math.floor;
return [...Cells(data.length, (i, j) => data[fl(i)][fl(j)], nb)];
}
Insert cell
cell2segments = {
const interp = (v1, v2, f) => (v1 == v2 ? v1 : v1 + f * (v2 - v1));
const test = ([pt1, v1], [pt2, v2], value) => {
if ((value >= v1 && value <= v2) || (value <= v1 && value >= v2)) {
const [[i1, j1], [i2, j2]] = [pt1, pt2];
const f = (value - v1) / (v2 - v1);
return [interp(i1, i2, f), interp(j1, j2, f)];
}
};
return ([pt1, pt2, pt3, pt4], value) => {
const [p1, p2] = [test(pt1, pt2, value), test(pt2, pt3, value)];
const [p3, p4] = [test(pt3, pt4, value), test(pt4, pt1, value)];
if (p1 && p2 && p3 && p4) {
const mean = (pt1[1] + pt2[1] + pt2[1] + pt3[1]) / 4;
const pair1 = mean > value ? [p1, p2] : [p1, p4];
const pair2 = mean > value ? [p3, p4] : [p3, p2];
return [pair1, pair2];
}
if (p1 && p2) return [[p1, p2]];
if (p2 && p3) return [[p2, p3]];
if (p3 && p4) return [[p3, p4]];
if (p4 && p1) return [[p4, p1]];
if (p1 && p3) return [[p1, p3]];
if (p2 && p4) return [[p2, p4]];
return [];
};
}
Insert cell
generatePaths = (cells, value) => {
const S = Segments();
for (const cell of cells)
for (const segment of cell2segments(cell, value)) S.addSegment(segment);
return S.getPaths();
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
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