Public
Edited
Sep 6, 2024
Insert cell
Insert cell
Insert cell
C=[
// Each circle is specified by its center (x,y) and radius r.
{x:0,y:0,r:10}, {x:-10,y:10,r:15}, {x:5,y:5,r:12}, {x:25,y:10,r:5},
{x:45,y:10,r:12}, {x:40,y:5,r:3}, {x:-23,y:10,r:2}, {x:25,y:0,r:5}
]
Insert cell
drawCircles(C)
Insert cell
Insert cell
drawCircles(C, {pointFill:"red"})
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
circles=C
Insert cell
Insert cell
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; // isolated circle
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();
//c.fillText(`${i}`, X(C.x), Y(C.y));
});

//points.forEach(P => c.fillText(`${P.idx}`, X(P.pt[0]), Y(P.pt[1])));

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;
}
Insert cell
drawCircles=function(circles, {
w=width, inset=4, colorScheme="Category10",
pointFill=null, pointRadius=4
}={}) {
const {PI}=Math;
// Compute the geometry.
const {points,intersects}=getGeometry(circles)
// Fit a canvas to the circle bounds.
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 h=Math.round(w*aspect);
const X=d3.scaleLinear().domain([xlo,xhi]).range([inset,w-inset]);
const Y=d3.scaleLinear().domain([ylo,yhi]).range([h-inset,inset]);
const scale=X(1)-X(0);
console.log(X(1)-X(0), Y(0)-Y(1));
const c=DOM.context2d(w,h);
// Draw circles.
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();
//c.fillText(`${i}`, X(C.x), Y(C.y));
});
if(pointFill) {
// Draw points.
c.fillStyle = pointFill;
points.forEach(P => {
c.beginPath();
c.arc(X(P.pt[0]), Y(P.pt[1]), pointRadius, 0, 2*PI);
c.fill();
});
}
return c.canvas;
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
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