2017-05-12 29 views
-1

我想生成所有間距相同的點數,但仍保持隨機性。隨機生成的點將顯示在矩形畫布上。目前我只是用Math.random()產生每個點。我已經嘗試過測試每個點相對於其他點的間距,但是我不知道如何使這個點的點數達到x隨機生成具有相似間距的點

我應該如何去產生這些點?

+0

「間隔均勻,同時仍保持隨意性」:這是矛盾的,請詳細說明您的要求。 –

回答

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>

1

你可以使用類似下一種方法(僞代碼)。

點與正方形網格的節點相連,並具有一些隨機位移。

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 
0

由於雙方@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++; 
    } 
} 

視覺示範

前:

before

後:

after