title: D3 Donut chart projected to sphere/globe
body: <p>I want to use d3 for the next task:
  display rotating globe with donut chart in center of every country. It should be possible to interact with globe (select country, zoom, rotate).
  Seems d3 provide an easy way to implement every part of it but I can not get donuts part working as I need.</p>
  
  <p>There is an easy way draw donut chart with the help of d3.arc:</p>
  
  <pre><code>var arc = d3.arc();
  var data = [3, 23, 17, 35, 4];
  var radius = 15/scale;
  var _arc = arc.innerRadius(radius - 7/scale)
            .outerRadius(radius).context(donutsContext);
  var pieData = pie(data);
  for (var i = 0; i &lt; pieData.length; i++) {
      donutsContext.beginPath();
      donutsContext.fillStyle = color(i);
      _arc(pieData[i]);
  }
  </code></pre>
  
  <p>by with code as it is donuts are displayed on a plane on top of the globe, like:
  <a href="https://i.stack.imgur.com/FbB1o.png" rel="nofollow noreferrer">globe with donut</a>
  ​</p>
  
  <p>while I want them to be 'wrapped' around the globe</p>
  
  <p>There is d3.geoCircle method that can be projected to globe correctly. I got 'ring' projected correctly to the globe with the help of two circles:</p>
  
  <pre><code>var circle = d3.geoCircle()
    .center(centroid)
    .radius(2);
  var outerCircle = circle();
  var circle = d3.geoCircle()
    .center(centroid)
    .radius(1);
  var innerCircle = circle();
  
  var interCircleCoordinates = [];
  for (var i = innerCircle.coordinates[0].length - 1; i &gt;= 0; i--) {
      interCircleCoordinates.push(innerCircle.coordinates[0][i]);
  }
  outerCircle.coordinates.push(interCircleCoordinates);
  </code></pre>
  
  <p>​<a href="https://i.stack.imgur.com/0nIKq.png" rel="nofollow noreferrer">globe with rings</a></p>
  
  <p>but I really need to get a donut.</p>
  
  <p>The other way I tried is getting image from donuts and wrapping this image around globe with the help of pixels manipulation:</p>
  
  <pre><code>var image = new Image;
  image.onload = onload;
  image.src = img;
  
  function onload() {
      window.dx = image.width;
      window.dy = image.height;
  
      context.drawImage(image, 0, 0, dx, dy);  
      sourceData = context.getImageData(0, 0, dx, dy).data;
            target = context.createImageData(width, height);
            targetData = target.data;
  
      for (var y = 0, i = -1; y &lt; height; ++y) {
          for (var x = 0; x &lt; width; ++x) {
              var p = projection.invert([x, y]), λ = p[0], φ = p[1];
                  if (λ &gt; 180 || λ &lt; -180 || φ &gt; 90 || φ &lt; -90) { i += 4; continue; }
                  var q = ((90 - φ) / 180 * dy | 0) * dx + ((180 + λ) / 360 * dx | 0) &lt;&lt; 2;
                  var r = sourceData[q];
                  var g = sourceData[++q];
                  var b = sourceData[++q];
                  targetData[++i] = r;
                  targetData[++i] = g;
                  targetData[++i] = b;
                  targetData[++i] = 125;//
          }
      }   
      context.clearRect(0,0, width, height);
      context.putImageData(target, 0,  0);
  };
  </code></pre>
  
  <p>by this way I get extremely slow rotating and interaction with a globe for a globe size I need (1000px)</p>
  
  <p>So my questions are:</p>
  
  <ol>
  <li>Is there is some way to project donuts that are generated with the help of d3.arc to a sphere (globe, orthographic projection)?</li>
  <li>Is there is some way to get a donut from geoCircle?</li>
  <li>Maybe there is some other way to achieve my goal I do not see</li>
  </ol>