【问题标题】:Simplest way to plot points randomly inside a circle在圆圈内随机绘制点的最简单方法
【发布时间】:2015-12-15 00:50:43
【问题描述】:

我有一个基本的 JSFiddle,我想在一个圆圈内绘制随机点。

但我不知道如何将点限制在圆圈内。

这是我目前拥有的:

var ctx = canvas.getContext('2d'),
    count = 1000, // number of random  points
    cx = 150,
    cy = 150,
    radius = 148;

    ctx.beginPath();
    ctx.moveTo(cx, cy);
    ctx.arc(canvas.width/2, canvas.height/2, radius, 0, 2*Math.PI);
    ctx.closePath();
    ctx.fillStyle = '#00000';
    ctx.fill();

// create random points
    ctx.fillStyle = '#ffffff';

while(count) {
    // randomise x:y

    ctx.fillRect(x + canvas.width/2, y + canvas.height/2, 2, 2);
    count--;
}

我将如何生成随机 (x,y) 坐标以在圆内绘制随机点?

我现在的小提琴:http://jsfiddle.net/e8jqdxp3/

【问题讨论】:

    标签: javascript canvas random geometry


    【解决方案1】:

    要在圆中随机绘制点,您可以从radius 平方中选择一个随机值,然后对其进行平方根,选择一个随机角度,然后将极坐标转换为矩形。平方/平方根步骤确保我们得到均匀分布(否则大多数点将靠近圆心)。

    所以在圆中绘制随机点的公式如下,其中r'0之间的随机值>r2,而 θ 是随机值0 之间:

    结果截图:

    现场演示:

    var canvas = document.getElementById("thecanvas");
    
    var ctx = canvas.getContext('2d'),
        count = 1000, // number of random  points
        cx = 150,
        cy = 150,
        radius = 148;
    
    ctx.fillStyle = '#CCCCCC';
    ctx.fillRect(0, 0, canvas.width, canvas.height);
    
    ctx.fillStyle = '#000000';
    
    ctx.beginPath();
    ctx.moveTo(cx, cy);
    ctx.arc(canvas.width / 2, canvas.height / 2, radius, 0, 2 * Math.PI);
    ctx.closePath();
    
    ctx.fill();
    
    // create random points
    ctx.fillStyle = '#ffffff';
    
    while (count) {
        var pt_angle = Math.random() * 2 * Math.PI;
        var pt_radius_sq = Math.random() * radius * radius;
        var pt_x = Math.sqrt(pt_radius_sq) * Math.cos(pt_angle);
        var pt_y = Math.sqrt(pt_radius_sq) * Math.sin(pt_angle);
        ctx.fillRect(pt_x + canvas.width / 2, pt_y + canvas.width / 2, 2, 2);
        count--;
    }
    <canvas id="thecanvas" width="400" height="400"></canvas>

    JSFiddle 版本:https://jsfiddle.net/qc735bqw/

    【讨论】:

    • 很好,你可以避免平方/平方根:r=Math.random()*radius 然后x = cx + r * Math.cos(pt_angle);y = cy + r * Math.sin(pt_angle); 然后fillRect(x,y,2,2)。另请注意,如果随机选择完整半径,则 2px 矩形可以避开圆的边界,因为矩形的 x,y 定义在左上角。一个简单的解决方法是使用 (radius-2),或者更长的解决方法是在角度介于 -PI/2 和 PI/2 之间时捕获边缘情况。
    • 谢谢你,我想知道是否有一种简单的方法可以对椭圆做同样的事情?
    • @Dave 一种简单的方法是在绘制时缩放输出。所以如果你想要一个水平椭圆,而不是画xy,画xy/2(或者Math.floor(y/2))。
    • 所以我只是将最终的 y 计算除以给定的比例。
    • @Dave 是的。 (此处为最小评论长度填充文本)
    【解决方案2】:

    随机选择dSquared (0..radius^2) 和theta (0..2pi),然后

    x = sqrt(dSquared) cos(theta)
    y = sqrt(dSquared) sin(theta)
    

    【讨论】:

      【解决方案3】:

      JSFiddle

      var ctx = canvas.getContext('2d'),
          count = 1000, // number of random  points
          cx = canvas.width/2,
          cy = canvas.height/2,
          radius = 148;
      
          ctx.beginPath();
          ctx.moveTo(cx, cy);
          ctx.arc(0+canvas.width/2, 0+canvas.height/2, radius, 0, 2*Math.PI);
          ctx.closePath();
          ctx.fillStyle = '#00000';
          ctx.fill();
      
          ctx.fillStyle = '#ffffff';
      
      while(count) {
          var x = Math.random() * canvas.width;
          var y = Math.random() * canvas.height;
          var xDiff = cx - x;
          var yDiff = cy - y;
          if(Math.sqrt(xDiff*xDiff+yDiff*yDiff)<radius)
          {
              ctx.fillRect(x, y, 2, 2);
              count--;
          }    
      }
      

      【讨论】:

        【解决方案4】:

        这对我有用:

        const getRandomCoordinateInCircle = radius => {
          var angle = Math.random() * Math.PI * 2;
          const x = Math.cos(angle) * radius * Math.random();
          const y = Math.sin(angle) * radius * Math.random();
          return { x, y };
        };
        
        console.log(getRandomCoordinateInCircle(1000);
        // { x: 118.35662725763385, y: -52.60516556856313 }
        

        返回一个以{ x: 0, y: 0}为圆心的随机点。

        【讨论】:

          猜你喜欢
          • 2019-01-17
          • 2015-07-04
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-03-24
          相关资源
          最近更新 更多