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);
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;
};
}