在同心圆上绘制点

时间:2016-07-13 15:24:00

标签: javascript math geometry trigonometry

我有一系列项目,我想放在同心圆上。见图。我在数学方面遇到了麻烦。

我可以计算“步数”变量(每个项目是40x40,所以步长是圆周除以宽度加上边距)。我可以计算给定半径和步长的点,但我不知道如何根据当前项目索引计算半径。

for(var i = 0; i < items.length; i++) {
    var radius = functionOf(i)??;
    var steps = Math.floor((2*radius*Math.PI)/60);
    var x = Math.floor(0 + radius * Math.cos(2 * Math.PI * index / steps));
    var y = Math.floor(0 + radius * Math.sin(2 * Math.PI * index / steps));
    //draw item at x,y
}

关于如何计算半径作为i函数的思考?

2 个答案:

答案 0 :(得分:0)

您可以使用算术级数的总和来计算每个项目的半径(对于等距离的圆形项目形成该级数),但是有更简单和更快的方法 - 圆形填充后的更改半径(伪代码)

var radius = 0;
var i = 0;
while (i < items.length) {
    var steps = Math.floor((2*radius*Math.PI)/60);
    for(var index = 0; index < steps; index++) {
        var x = Math.floor(0 + radius * Math.cos(2 * Math.PI * index / steps));
        var y = Math.floor(0 + radius * Math.sin(2 * Math.PI * index / steps));
        //draw item at x,y
        i++;
        if (i == items.length) 
           break;     
    }
    radius = radius + 60; //start next circle
}

关于arithmetic progression
对于第一个项目a0的进展和差异d,前n个成员的总和是

 S = n * (2 * a0 + d * (n - 1)) / 2

所以为了找到某个索引S所属的圈子,我们必须解决二次不等式(找到最大整数x来满足条件)

 x^2 * d + x * (2 * a0 - d) - 2 * S <= 0

在Delphi中检查解决方案:

  function GetCircle(a0, d, i: Integer): Integer;
  var
    Discr: Double;
  begin
    Discr := (2 * a0 - d) * (2 * a0 - d) + 8 * i * d;
    if Discr < 0 then
      Exit(0);
    Result := Floor((d - 2 * a0 + Sqrt(Discr)) / (2 * d));
  end;

对于案例a0 = 1,d = 6(你的图片有点不同 - 进展不准确)它给出了

 i=0:       0
 i=1..7:    1
 i=8..20:   2
 i=21..39:  3
 and so on 

这意味着:
第0项位于半径为0的圆上 半径为1 * R
的圆的第3项 圆形的第11项,半径为2 * R
...

答案 1 :(得分:0)

鉴于你的样本图像,一个简单的方法是为每个外圈添加6个元素,这样我们就可以得到序列:1,6,12,18 ......

然后每个圆的半径可以放大一个恒定的量,大于元素大小:

// center of the circles
var centerx = 350;
var centery = 350;
// start drawing the central (first) element
if ( items.length > 0 ) {
  // draw item at centerx, centery
}
var k = 1;
var i = 1;
while ( i < items.length ) {
    // number of elements on this circle
    var steps = k * 6;
    // angular distance between elements
    var angle_range = 2 * Math.PI / steps;
    // every circle is bigger then the previuos of the same amount
    var radius = k * 60;
    var j = 0;
    while ( j < steps  &&  i < items.length ) {
        var angle = j * angle_range;
        var x = Math.round(centerx + radius * Math.cos(angle));
        var y = Math.round(centery + radius * Math.sin(angle));
        //draw item at x,y

        i++;
        j++;
    }
    k++;
}

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8"/>
  <title>Circles</title>
  <link href="stile.css"/>
</head>
<body>
  <canvas id="myCanvas" width="700" height="700" style="border:1px solid #000000;">
  </canvas>
  <script>
  // dummy draw function
  function draw_item( itm, cntx, x, y) {
    cntx.fillStyle = "#0022FF";
    cntx.fillRect(x - 20, y - 20, 40, 40);
    cntx.font = "14px Arial";
    cntx.fillStyle = "#FFFFFF";
    cntx.fillText(itm, x - 7, y + 5);
  }

  var c = document.getElementById("myCanvas");
  var ctx = c.getContext("2d");

  // dummy array
  var items = [];
  for ( var i = 0; i < 91; i++ ) {
    items.push(i);
  }

  // center of the circles
  var centerx = 350;
  var centery = 350;
  // start drawing the central (first) element
  if ( items.length > 0 ) {
    draw_item(items[0], ctx, centerx, centery);
  }
  var k = 1;
  var i = 1;
  while ( i < items.length ) {
      // number of elements on this circle
      var steps = k * 6;
      // angular distance between elements
      var angle_range = 2 * Math.PI / steps;
      // every circle is bigger then the previuos of the same amount
      var radius = k * 60;
      var j = 0;
      while ( j < steps  &&  i < items.length ) {
          var angle = j * angle_range;
          var x = Math.round(centerx + radius * Math.cos(angle));
          var y = Math.round(centery + radius * Math.sin(angle));
          //draw item at x,y
          draw_item(items[i], ctx, x, y);
          i++;
          j++;
      }
      k++;
  }
  </script>
</body>
</html>