transport = {
let dirs = 4,
strength = .8;
const w = width / 2,
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);
const pool = [];
const baseAngle = tau / (1.5 + Math.sqrt(1.25));
let a = 0;
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);
}
deltas.fill(0);
if (pool.length < 100) {
a += baseAngle;
const sa = Math.sin(a),
ca = Math.cos(a);
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]);
pool.unshift({ a, sa, ca, p: projectionq.slice(), o: indicesq.slice() });
}
for (let d = 0; d < Math.min(dirs, pool.length); d++) {
const { a, sa, ca, p, o } = pool[d];
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]);
let i, ideal, delta;
for (let k = 0; k < n; k++) {
i = indices[k];
ideal = p[o[Math.floor(((k + 1) / (n + 1)) * o.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;
d3.shuffle(pool);
};
}