Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can d3 build shapes within a shape?

Tags:

d3.js

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!

like image 788
Mr. Concolato Avatar asked Nov 03 '22 19:11

Mr. Concolato


1 Answers

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.

like image 93
ckersch Avatar answered Nov 23 '22 06:11

ckersch