D3.js interpolating line on circumference of circle
I'd suggest using nested group elements (&lt;g&gt;s) with transform attributes.

I.e. draw the circle (just as a &lt;circle&gt; element) and the line inside a group, and then draw a nested group with a circle and line within that, and so on. When you rotate the outermost group, the nested ones will follow. Rotate each of them, and you'll get the effect from the demo.

This way, you only need to animate one thing: rotation. For instance:



var width = 200;
var height = 200;
var body = d3.select("body");
var svg = body.append("svg")
        .attr("width", width)
        .attr("height", height)
        .attr("fill", "blue");

function addCircle(container, radius, x, y) {
    // Note the hardcoded rotation; it's just an example
    var group = container.append("g")
        .attr("class", "circle-container")
        .attr("transform", "translate(" + x + ", " + y + ")");

    function rotate() {
        group.transition()
        .duration(10000)
        .ease("linear")
        .attrTween("transform", function (d, i, a) {
            return function (t) {
                var rotation = t * 360;
                return "translate(" + x + ", " + y + ") rotate(" + String(rotation) + ")";
            };
        })
        .each("end", rotate);
    };
    rotate();
    
    group.append("circle")
        .attr("cx", 0)
        .attr("cy", 0)
        .attr("r", radius)
        .style("fill", "none")
        .style("stroke", "steelblue");
    
    group.append("line")
        .attr("x1", 0)
        .attr("y1", 0)
        .attr("x2", radius)
        .attr("y2", 0)
        .style("stroke", "steelblue");
    
    return group;
}

var c1 = addCircle(svg, 30, width/2, height/2); // centered
var c2 = addCircle(c1, 20, 30, 0); // offset by 1st circle's radius
var c3 = addCircle(c2, 15, 20, 0); // offset by 2nd circle's radius
&lt;script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"&gt;&lt;/script&gt;




Heck, you can do this in pure SVG (added extra groups to isolate rotation):



&lt;svg width="200" height="200"&gt;
  &lt;!-- root transform to center everything --&gt;
  &lt;g transform="translate(100, 100)"&gt;
    
    &lt;!-- draw the outermost group and animate it --&gt;
    &lt;g&gt;
      &lt;animateTransform attributeName="transform" type="rotate" from="0" to="360" dur="10s" repeatCount="indefinite" /&gt;
      &lt;circle cx="0" cy="0" r="40" fill="none" stroke="steelblue" /&gt;
      &lt;line x1="0" y1="0" x2="0" y2="40" stroke="steelblue" /&gt;
      
      &lt;!-- offset the children --&gt;
      &lt;g transform="translate(0, 40)"&gt;
      
        &lt;!-- now repeat, only smaller --&gt;
        &lt;g&gt;
          &lt;animateTransform attributeName="transform" type="rotate" from="0" to="360" dur="10s" repeatCount="indefinite" /&gt;
          &lt;circle cx="0" cy="0" r="30" fill="none" stroke="steelblue" /&gt;
          &lt;line x1="0" y1="0" x2="0" y2="30" stroke="steelblue" /&gt;
          
          &lt;g transform="translate(0, 30)"&gt;
            
            &lt;!-- and again --&gt;
            &lt;g&gt;
              &lt;animateTransform attributeName="transform" type="rotate" from="0" to="360" dur="10s" repeatCount="indefinite" /&gt;
              &lt;circle cx="0" cy="0" r="20" fill="none" stroke="steelblue" /&gt;
              &lt;line x1="0" y1="0" x2="0" y2="20" stroke="steelblue" /&gt;
            &lt;/g&gt;
            
          &lt;/g&gt;
        &lt;/g&gt;
      &lt;/g&gt;
    &lt;/g&gt; 
  &lt;/g&gt;
&lt;/svg&gt;




At any rate, you can simply skip all the getPointAtLength calls. Your path is a circle, so a) you can use a &lt;circle&gt; element, and b) any point on its circumference can be described using some simple math:

var x = Math.cos(t) * radius + centerX;
var y = Math.sin(t) * radius + centerY;


where t is something between 0 and 2π (or beyond that; it'll just loop around). So your animation needs only change the value of t to find a point on the circle.