{
let startTime = new Date().getTime(),
seconds = 0,
secondsRounded = 0,
ticks = 0,
speeds = [];
const ctx = DOM.context2d(myBoids.width(), height);
let projection = d3.geoIdentity();
let path = d3.geoPath(projection).context(ctx);
let holding = false;
while (true && myBoids.flock.length) {
myBoids.tick();
ctx.globalAlpha = 0.9;
ctx.fillStyle = cwf[0];
ctx.fillRect(0, 0, width, height);
ctx.globalAlpha = 1;
let contours = contour(myBoids.flock);
for (const contour of contours) {
const threshold = contour.value;
ctx.beginPath(),
path(contour),
ctx.stroke();
}
ctx.beginPath();
myBoids.each(boid => {
boid.vel[1] = -1.8;
const a = vecmath.trans(boid.pos, boid.ang - Math.PI * .5, 3),
b = vecmath.trans(boid.pos, boid.ang, 9),
c = vecmath.trans(boid.pos, boid.ang + Math.PI * .5, 3);
ctx.moveTo(...a);
ctx.lineTo(...b);
ctx.lineTo(...c);
ctx.lineTo(...a);
ctx.arc(boid.pos[0], boid.pos[1], 1.5, 0, Math.PI * 2);
const color = d3.interpolateRdPu((.6 * myBoids.maxSpeed()) / boid.speed);
ctx.strokeStyle = color;
ctx.strokeStyle = cwf[2];
ctx.fillStyle = d3.color(color).brighter(2);
ctx.fillStyle = "#111";
});
ctx.fill();
ctx.stroke();
seconds = (new Date().getTime() - startTime) / 1e3;
ticks++;
document.querySelector(".ticker").innerHTML = `${
myBoids.flock.length
} boids at ${d3.mean(speeds)} frames per second`;
if (Math.round(seconds) !== secondsRounded) {
speeds.push(ticks);
if (speeds.length > 2) speeds.shift();
secondsRounded = Math.round(seconds);
ticks = 0;
}
yield ctx.canvas;
}
}