Published
Edited
May 18, 2022
3 stars
Insert cell
Insert cell
heatmap(V, { width: w, color: d3.interpolatePiYG })
Insert cell
Insert cell
Insert cell
V = {
const V = new Float64Array(w * w).fill(NaN);
const C = new Uint8Array(w * w); // counts

const a = strength / 100;
const ct = Math.cos(transport * radians);
const st = Math.sin(transport * radians);

for (let step = 0; step < 200; step++) {
yield V;

for (let n = 50000; n > 0; n--) {
let x = random();
let y = random();
const i =
Math.floor((0.5 + 0.49 * x) * w) + w * Math.floor((0.5 + 0.49 * y) * w);
if (C[i] > 50) continue; // precision (max: 254 or change C's type to Uint16)

for (let k = 0; k < 10; ++k) {
// determine the sphere centered on <x,y> and of radius r such that it touches the unit disc
const h = Math.hypot(x, y);
const r = 1 - h;

// if we're outside or close to the unit disc, stop
if (r < 0.001) break;

// evaluate the flow field by sampling it on a random point inside the sphere
{
const u = random_unit_vector();
const s = r * Math.sqrt(Math.random());
const sx = x + u[0] * s;
const sy = y + u[1] * s;

// the lines below don't really make sense. todo: think
const h = a / Math.hypot(sx, sy);
x += (sx * ct - sy * st) * h;
y += (sy * ct + sx * st) * h;
}

// random jump on the sphere (WoS step)
{
//const h = Math.hypot(x, y);
//const r = 1 - h;
const u = random_unit_vector();
x += r * u[0];
y += r * u[1];
}
}

// evaluate the function at the border we've reached
const c = Math.sin(3 * Math.atan2(y, x));
V[i] = (C[i] ? C[i] * V[i] + c : c) / ++C[i];
}
}
}
Insert cell
Insert cell
random = {
// this random generator allows to spend more effort in the center
const b = d3.randomBates(3);
return () => 3 * (b() - 0.5);
}
Insert cell
import { heatmap } from "@fil/heatmap"
Insert cell
import { radians } from "@fil/math"
Insert cell
// https://observablehq.com/d/12bcf9c57bb17f4d by @jrus
function random_unit_vector() {
const a = 2 * Math.random() - 1,
b = 1 - a * a,
t = a * (-0.0187108 * b + 0.31583526 + 1.27365776 / b),
// slightly more expensive variant with better uniformity:
// t = a * (((-0.000221184 * b + 0.0024971104) * b - 0.02301937096) * b
// + 0.3182994604 + 1.2732402998 / b),
q = 1 / (1 + t * t);
return [2 * t * q, (1 - t * t) * q];
}

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