viz={
const start=new Date();
const colors = d3[colorScheme];
const {points,intersects}=geometry;
const twopi=2*Math.PI;
const wrap = angle=>(angle+twopi)%twopi;
const [xlo,xhi] = [d3.min(circles, C=>C.x-C.r),d3.max(circles, C=>C.x+C.r)];
const [ylo,yhi] = [d3.min(circles, C=>C.y-C.r),d3.max(circles, C=>C.y+C.r)];
const aspect = (yhi - ylo)/(xhi - xlo);
const w=width;
const h=Math.round(w*aspect);
const X=d3.scaleLinear().domain([xlo,xhi]).range([0,w]);
const Y=d3.scaleLinear().domain([ylo,yhi]).range([h,0]);
const scale=X(1)-X(0);
const c=DOM.context2d(w,h);
c.textAlign = "center";
c.textBaseline = "middle";
c.strokeStyle = "skyblue";
c.fillStyle = "skyblue";
regions.regions.forEach((R,j) => {
const n=R.inside.size;
c.beginPath();
R.edges.forEach(({from,to,dir},k) => {
const [xc,yc] = [X(from.self.x),Y(from.self.y)];
let [ang1,ang2] = [wrap(-from.angle), wrap(-to.angle)];
if(ang1==ang2) ang2=ang1-twopi;
c.arc(xc, yc, scale*from.self.r, ang1, ang2, dir>0);
});
c.fillStyle = n==0? "lightgray" : (colors[(n-1) % colors.length]);
c.fill();
});
c.strokeStyle = c.fillStyle = "#000";
circles.forEach((C,i) => {
c.beginPath();
c.arc(X(C.x), Y(C.y), scale*C.r, 0, 2*Math.PI);
c.stroke();
});
const elapsed=new Date() - start;
c.fillStyle="#000";
c.textAlign="left";
c.textBaseline="bottom";
c.fillText(`${geometry.elapsed} + ${regions.elapsed} + ${elapsed} ms`, 2, h-2);
return c.canvas;
}