Accepted answer

This is in part a repeat of Lars' equations from the comments, but I thought it was worth recapping all at once because the trig identities for converting from angles to x/y coordinates won't match your trig text book.

Most text books assume that angles start at the right horizontal axis and increase counter-clockwise, and that the vertical axis has larger values higher up on the page.

In SVG, larger y values are lower on the page, and the angles created by the pie chart layout (and the example code the OP is using for the sunburst layout) draw an angle of zero as vertical line to the top of the circle, with angles increasing clockwise.

With that information, you can convert to x and y values with the following trig equations:

  g.append("circle") //circles inherit pie chart data from the <g>
      .attr("r", 5) 
      .attr("cx", function(d) { 
          return Math.sin((d.startAngle + d.endAngle)/2) *radius;
      .attr("cy", function(d) { 
          return -Math.cos((d.startAngle + d.endAngle)/2) *radius;

Live example:

Again, this simple example uses a pie chart layout, so the data has startAngle and endAngle values, and the radius is constant. For a sunburst diagram made with the partition layout, you would replace (d.startAngle + d.endAngle)/2 with d.x + d.dx/2, and you would replace radius with a function based on d.depth.


As an alternative to trigonometry, you could use transformations to position the circles. If the first step in a transformation is a rotation, and then you apply a translation afterwards, the translation will be applied in the rotated coordinate system.

A little extra complication, though, is that the d3 pie chart gives angles in radians (since that's what the trigonometry functions use), but the rotation needs angles in degrees.

  var degreesPerRadian = 180/Math.PI;
  g.append("circle") //circles inherit pie chart data from the <g>
      .attr("r", 5)
      .attr("transform", function(d) { 
          return "rotate(" +  degreesPerRadian*((d.startAngle + d.endAngle)/2) 
          + ")" +
              //rotate by the average of the start and end angle
              //Note that d3 specifies angles in radians, but the rotate
              //function needs them in degrees
              "translate(0," + -radius + ")";
              //then translate "up" the distance of the radius;
              //"up" is interpretted according to the rotated coordinates,
              //but for zero rotation it will position the dot at the top
              //of the circle, which is the zero angle for d3

Live example:

(based on this simple pie chart code )

Related Query

More Query from same tag