分形螺旋图:javascript 中可能存在舍入误差

Fractal Spirographs: possible rounding errors in javascript

我一直在尝试复制 link. So I have started out with two circles, one fixed and one rotating. But the rotating circle is drifting away from the stationary circle and some times it is falling into the stationary circle. Can someone please help me fix this. I have created a live demo of code at the following link 中的示例。下面是完整代码。

// takes two points x1,y1,x2,y2 and return r and Θ 
function coordinateToPolar(x1,y1,x2,y2){
polar={}

polar.r= Math.sqrt(Math.pow(x2-x1,2)+Math.pow(y2-y1,2))

polar.theta=Math.atan2(y2-y1,x2-x1)

return polar;
}

function degreeToRadians(degree){
return (degree/180)*Math.PI;
}

function radiansToDegrees(rad){
return (rad/Math.PI)*180
}

// takes one point h,k the center of circle and r and Θ
function polarToCoordinate(r,theta,h,k){
 point={}
 point.x=h+r*Math.cos(theta);
 point.y=k+r*Math.sin(theta);
 return point;
}



 //circle ds
 function Circle(r,h,k) {
            this.r=r;
            this.h=h;
            this.k=k;
        }



 /// Adjusting the geometric center
 bufferX=250;
 bufferY=250;


 svg=d3.select("body").append("svg");


            startX=200;
            startY=200;
            startR=150;
            dsCircles=[];

            // intiating prevR and lastR to 0 
            prevR=0;
            lastR=0;
            for(i=0;i<2;i++){
                currR=startR>>(i*1);
                dsCircles[i]=new Circle(currR, i==0?bufferX+prevR+currR: bufferX+ prevR+lastR+currR,bufferY+startY)
                lastR=currR;
                prevR +=currR;
            }

            svg.selectAll("circles").data(dsCircles).enter().append("circle").attr("id",function(d,i){return "circle"+(i+1)}).attr("r",function(d){ return d.r}).attr("cy",function(d){return d.k}).attr("cx",function(d){ return d.h});

            window.setInterval(function interval(){
                // static variable initiated only once
                if(interval["itr"]==undefined){
                    // initializing iteration counter to 0
                    interval.itr=0;
                    // getting the polar coordinates of the circles with respect to geometric center
                    interval.theta=coordinateToPolar(dsCircles[0].h,dsCircles[0].k,dsCircles[1].h,dsCircles[1].k).theta;
                    interval.r=coordinateToPolar(dsCircles[0].h,dsCircles[0].k,dsCircles[1].h,dsCircles[1].k).r;
                }




                d3.select("#circle2").attr("cx",function(d){                         
                    // assigning new center x-coordinate 
                    return polarToCoordinate(interval.r,interval.theta,dsCircles[0].h,dsCircles[0].k).x;

                }).attr("cy",function(d){ 
                    // assigning new center y-coordinate  
                    return polarToCoordinate(interval.r,interval.theta +.03,dsCircles[0].h,dsCircles[0].k).y;

                });

                d3.select("#circle2").attr("style",function(d){ return interval.itr%2==0?"stroke:red":"stroke:blue"; })
                interval.itr++;
                interval.theta +=.003

            },10)

有趣的可视化。

这不是对您问题的直接回答,因为我发现您的代码过于混乱且难以调试。您似乎做的数学比您需要的多得多;来回转换到不同的坐标系。此外,在 setTimeout 中设置动画也不是一个好的做法。

这是一个利用 d3.transition 并简化计算的快速重构。也通过数据带动新圈子的加入。

<!DOCTYPE html>
<html>

  <head>
    <script data-require="d3@4.0.0" data-semver="4.0.0" src="https://d3js.org/d3.v4.min.js"></script>
  </head>

  <body>
    <script>
    
      var width = 500,
          height = 500;
    
      var svg = d3.select('body')
        .append('svg')
        .attr('width', width)
        .attr('height', height)
        .append('g')
        .attr('transform','translate(' + width/2 + ',' + height/2 + ')');
        
      var data = [
        {
          r: 75,
          x: 0,
          y: 0,
          c: 'black',
          d: 0
        }, {
          r: 50,
          x: 0,
          y: 0,
          c: 'steelblue',
          d: 7000
        },{
          r: 30,
          x: 0,
          y: 0,
          c: 'orange',
          d: 5000
        },{
          r: 20,
          x: 0,
          y: 0,
          c: 'red',
          d: 2000
        },{
          r: 10,
          x: 0,
          y: 0,
          c: 'green',
          d: 500
        }
      ];
      
      data.forEach(function(d,i){
        if (i === 0) d.pD = null;
        else d.pD = data[i-1];
      });
      
      svg.selectAll('circle')
        .data(data)
        .enter()
        .append('circle')
        .attr('r', function(d){
          return d.r;
        })
        .style('fill', 'none')
        .style('stroke', function(d){
          return d.c
        })
        .each(goRound);
        
      function goRound(d,i){
        
        if (!d.pD) return function(t) { }
        
        var self = d3.select(this);
        
        self.transition()
          .ease(d3.easeLinear)
          .duration(function(d){
            return d.d;
          })
          .tween("go.round", function(){

            var inter = d3.interpolate(0, Math.PI * 2);
            
            return function(t) {
              d.x = Math.cos(inter(t)) * (d.pD.r + d.r) + d.pD.x;
              d.y = Math.sin(inter(t)) * (d.pD.r + d.r) + d.pD.y;
              self.attr('cx', d.x);
              self.attr('cy', d.y);
              
            };
            
          })
          .on('end', goRound);
      }

    </script>
  </body>

</html>

只需在此处删除 cy +.03 的角度偏移:

attr("cy",function(d){ 
                // assigning new center y-coordinate  
                return polarToCoordinate(interval.r,interval.theta +.03,