Mr. Concolato
Mr. Concolato

Reputation: 2230

Can d3 build shapes within a shape?

I have a newby question. Can D3 draw this: http://www.nytimes.com/interactive/2008/05/03/business/20080403_SPENDING_GRAPHIC.html?_r=0 using the voronoi function within d3? What i am thinking is a svg that behaves like a and binds the voronoi found here http://bl.ocks.org/mbostock/4060366 to a circle. NY Times has accomplished the above visualization using flash. Any ideas? I have tried creating a large circle and embeding the smaller circles, but the voronoi does not show up and the points are not confined to the outer circle. Code generated:

        <svg class="PiYG" width="560" height="570">
    <circle cx="270" cy="300" r="260" style="stroke: rgb(0, 0, 0);">
    <g>

My js code looks something like this:

 var width = 560, height = 570;
var svg = d3.select("#VD1").append("svg")
    .attr("width", width)
    .attr("height", height)
    .attr("class", "PiYG");


var path = svg.append("circle")
        .attr("cx", 270)
        .attr("cy", 300)
        .attr("r", 260)
        .style("stroke", "#000")
        .append("g")
        .selectAll("path"); 

var vertices = d3.range(count).map(function(d) {
  return [Math.random() * width, Math.random() * height];
});
var voronoi = d3.geom.voronoi()
    .clipExtent([[0, 0], [width, height]]);

svg.selectAll("circle")
    .data(vertices.slice(2))
  .enter().append("circle")
    .attr("transform", function(d) { return "translate(" + d + ")"; })
    .attr("r", 2);

Thanks so much!

Upvotes: 5

Views: 1219

Answers (1)

ckersch
ckersch

Reputation: 7687

Not really, but not due to any shortcomings of d3, but rather because that's not what a Voronoi function does. A Voronoi function builds lines based on which regions of a graph are closest to a given point. It is not a way of proportionately dividing a circle into smaller segments, with size corresponding to data.

That being said, it is definitely possible to create a circular Voronoi diagram. To do so, you'll have to make a few changes to the example Voronoi diagram code.

First you'll have to make sure that all of the points fit in a circle. In your example, point location is given by d, here:

.attr("transform", function(d) { return "translate(" + d + ")"; })

Either d (your dataset) needs to fit in the circle, or you need to make some transformation of it. For data normalized to (-1,1) in both dimensions, the function

.attr("transform", function(d) { return "translate([" +
    d[0]*Math.sqrt(1 - Math.pow(d[1],2)/2) 
    + "," +
    d[1]*Math.sqrt(1 - Math.pow(d[0],2)/2)
    + "])"; })

will do so. Here, we've created a new array that will be bounded by a circle from the array originally in d.

Next, you would need to clip your Voronoi diagram to be contained within a circle. The fun part is, there isn't a built in 'circle' geometric object to clip with, so you'll need to get creative! Either build a custom way to do this, or let the Voronoi extend beyond your circle and build an SVG to cover it up. Either should work.

Upvotes: 2

Related Questions