【问题标题】:Randomly generate points with similar spacing随机生成间距相似的点
【发布时间】:2017-05-12 01:38:44
【问题描述】:

我想生成x 数量的点,这些点全部间隔相似,同时仍保持随机性。随机生成的点将显示在矩形画布上。目前我只是用Math.random() 生成每个点。我已经尝试测试每个点相对于其他点的间距,但我不知道如何使用 x 点数来实现这一点。

我应该如何生成这些点?

【问题讨论】:

  • “在保持随机性的同时均匀分布”:这是矛盾的,请详细说明您的要求。

标签: javascript canvas random geometry


【解决方案1】:

您可以通过将区域划分为大小相等的网格并在每个网格中随机放置一个点来使用半随机分布。但是您需要知道要添加多少点,否则它将不起作用。

该演示比较了随机分布和加权分布的结果。现实情况是,随着点数的增加,随机函数会产生更均匀的分布。点击画布将点数加倍,比较随机和加权的结果。

const ctx = canvas.getContext("2d");
const ctx1 = canvas1.getContext("2d");
const w = canvas.width;
const h = canvas.height;
canvas.addEventListener("click",drawPoints);
canvas1.addEventListener("click",drawPoints);

function randomPoint(){
    const xx = Math.floor(Math.random() *  w);
    const yy = Math.floor(Math.random() *  h);
    ctx1.fillRect(xx,yy,pointSize,pointSize);
}
function randomPointOf(n, ofM){
    const spread = Math.sqrt(ofM);
    const xs = w / spread; // x spacing
    const ys = h / spread; // y spacing
    n = n % ofM;
    const x = (n % spread) * xs;
    const y = (Math.floor(n / spread)) * ys;
    const xx = Math.floor(Math.random() *  xs + x);
    const yy = Math.floor(Math.random() *  ys + y);
    ctx.fillRect(xx,yy,pointSize,pointSize);
}

function randomPoints(pointCount, distrabutionCount){
    var i;
    for(i = 0; i < pointCount; i ++){
        randomPointOf(i,distrabutionCount); // do distrubuted random
        randomPoint(); // do random
    }
 }
var pointCount = 100;
var pointSize = 1
ctx.font = ctx1.font = "12px arial";
ctx1.fillStyle = ctx.fillStyle = "black";
ctx1.strokeStyle = ctx.strokeStyle = "white";
ctx1.lineWidth = ctx.lineWidth = 3;
drawPoints();
function drawPoints(){
    ctx.clearRect(0,0,w,h);
    ctx1.clearRect(0,0,w,h);
    pointCount *= 2;
    if(pointCount > w * h){
       pointCount = 100;
    }
    pointSize = pointCount < 1600 ? 2 : 1;
    randomPoints(pointCount,100);
    ctx.strokeText("Weighted. "+ pointCount + " points",10,14);
    ctx1.strokeText("Random. "+ pointCount + " points",10,14);
    ctx.fillText("Weighted. "+ pointCount + " points",10,14);
    ctx1.fillText("Random. "+ pointCount + " points",10,14);
}    
    
canvas {
   border : 2px black solid;
}
<canvas id="canvas" width = 256 height = 256></canvas>
<canvas id="canvas1" width = 256 height = 256></canvas>
<div>Click canvas to increase point count</div>

【讨论】:

    【解决方案2】:

    您可以使用类似下一种方法(伪代码)。

    点与方格的节点相连,有一定的随机位移。

    for iy in rowcountrange
        for ix in columncountrange
            points[iy, ix].X = ix * spacing + (random(0..1) - 0.5) * spacing
            points[iy, ix].Y = iy * spacing + (random(0..1) - 0.5) * spacing
    

    【讨论】:

      【解决方案3】:

      感谢@MBo 和@Blindman67。我使用了将画布划分为网格的想法,每个所需的点都有一个平铺。确定网格的尺寸需要一些基于以下等式的简单代数:

      rows * columns = x
      rows / columns = canvasHeight / canvasWidth
      

      使用我能够为行和列创建公式:

      rows = ((canvasHeight * x) / canvasWidth)^(1/2)
      columns = x / ((canvasHeight * x) / canvasWidth)^(1/2)
      

      这是我实现代码的方式:

      var x = 100; // number of points
      var points = [];
      
      // determine increment for grid
      var yIndex = canvas.height / Math.round(Math.sqrt((canvas.height * x) / canvas.width));
      var xIndex = canvas.width / Math.round(x / Math.sqrt((canvas.height * x) / canvas.width));
      
      // generate points randomly across grid
      var k = 0;
      for (var y = 0; y < this.canvas.height; y+=yIndex) {
          for (var x = 0; x < this.canvas.width; x+=xIndex) {
              points[k] = [
                  getRandomArbitrary(x,x+xIndex),
                  getRandomArbitrary(y,y+yIndex),
              ];
              k++;
          }
      }
      

      视觉演示

      之前:

      之后:

      【讨论】:

        猜你喜欢
        • 2019-12-27
        • 1970-01-01
        • 2013-01-24
        • 2011-05-03
        • 2010-11-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-10-15
        相关资源
        最近更新 更多