如何在javascript中获得正方形的边缘附近的随机点 [英] How to get random point near edges of a square in javascript

查看:135
本文介绍了如何在javascript中获得正方形的边缘附近的随机点的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想创建一个函数,使我从矩形点的边缘附近得到一个随机点.到目前为止,这是我想出的,但是我完全不知道为什么它不起作用.

I want to make a function that gives me a random point near the edges of a rectangle from a point. This is what I came up with so far, but I have absolutely no idea why it is not working.

function Point(x, y) {
  this.x = x;
  this.y = y;
}

function randomNumber(min, max) {
    return Math.floor(Math.random() * (max - min + 1)) + min;
}

function getRandomPointNearEdges(rectPos, width, height, border) {
  var point = new Point(rectPos.x, rectPos.y);
  if (randomNumber(0, 1) == 0) {
    point.x = randomNumber(rectPos.x, rectPos.x + border);
    if (randomNumber(0, 1) == 0) {
      point.y = randomNumber(rectPos.y, rectPos.y + border);
    }
    else {
      point.y = randomNumber(rectPos.y + height, (rectPos.y + height) + border);
    }
  }
  else {
    point.y = randomNumber(rectPos.y, rectPos.y + border);
    if (randomNumber(0, 1) == 0) {
      point.y = randomNumber(rectPos.x, rectPos.x + border);
    }
    else {
      point.y = randomNumber(rectPos.x + height, (rectPos.x + width) + border);
    }
  }
  return point;
};

window.onload = function() {
  canvas = document.getElementById("canvas");
  canvas.width = 700;
  canvas.height = 700;
  var ctx = canvas.getContext("2d");
  ctx.strokeRect(130, 130, 500, 500);
  
  for (var i = 0; i < 30; i++) {
    var point = getRandomPointNearEdges(new Point(130, 130), 500, 500, 100);
    ctx.fillRect(point.x, point.y, 2, 2);
  }
};

<canvas id="canvas"></canvas>

请澄清一下,此不按比例绘制"图中的黑色区域是我要允许该点生成的位置.黑色区域的宽度/高度是代码段中的border属性.

Just to clarify, the black region in this 'Not to scale' diagram is where I want to allow the point to generate. The width / height of that black region is the border property in the code snippet.

为什么我的功能不起作用?谢谢你.

Why is my function not working? Thanks in advanced.

推荐答案

分布均匀的随机数.

只需指出, SimpleJ 的答案在统计上存在缺陷,因为随机位置的分布对拐角处,然后到较短的边,即使它们覆盖的面积要小得多.

Random with even distribution.

Just to point out that the answer by SimpleJ is statistical flawed with the distribution of random locations having a bias to the corners and then to the shorter sides, even though they cover much less area.

理想的随机位置应均匀地分布在所讨论的区域上,如果盒子的高度小于宽度,则侧面得到点的机会就较小.

The ideal random location should be spread equally over the area in question, if the height of the box is less than the width then there is less chance of the the sides getting a point.

以下示例提供了更快,更好的分发.我还添加了给定的答案解决方案,以便您进行比较.

The example below provides a much faster and a much better distribution. I have added the given answers solution as well so you can compare.

获得随机pos的函数.参数xy矩形内部边缘的左上角,wh内部矩形minDist的宽度和高度,maxDist随机点可以从内部的最小和最大距离盒子的边缘.您也可以使用负值将点放置在矩形之外.请注意,距离始终是从盒子的内侧边缘开始.返回时,这些值也会被设置为底数(可以轻松删除并仍然有效)

The function that gets a random pos. The arguments x,y top left inside edge of rectangle, w,h inside width and height of the rectangle minDist, maxDist the min and max dist the random point can be from the inside edge of the box. You can also use negative values have the points outside the rectangle. Note that the distances are always from the inside edge of the box. The values are also floored when return (can easily be remove and still works)

function randomPointNearRect(x, y, w, h, minDist, maxDist) {
  const dist = (Math.random() * (maxDist - minDist) + minDist) | 0;
  x += dist;
  y += dist;
  w -= dist  * 2
  h -= dist  * 2
  if (Math.random() <  w / (w + h)) { // top bottom
    x = Math.random() * w + x;
    y = Math.random() < 0.5 ? y : y + h -1;
  } else {
    y = Math.random() * h + y;
    x = Math.random() < 0.5 ? x: x + w -1;
  }
  return [x | 0, y | 0];
}

请注意,盒子内部略有偏差.可以使用少量演算将其删除,偏差变化率f'(x) = 8*x每像素向内8个像素,并且反导数f(x)=4*(x**2) + c将直接与分布有关.其中x远离边缘,而c与周长有关

Note there is a slight bias to the inside of the box. It can be removed with a little calculus with the bias rate of change f'(x) = 8*x 8 pixels per pixel inward and the anti derivative f(x)=4*(x**2) + c would directly relate to the distribution. Where x is dist from edge and c is related to perimeter length

该示例有两个画布.绘制了许多随机点.单击顶部画布以添加更多点.请注意,由于随机点的偏斜,底部画布的边角和边角如何变暗.

The example has two canvases. Many random points are drawn. click the top canvas to add more points. Note how the bottom canvas sides and corners get darker due to the bias of the random points.

const ctx = canvas.getContext("2d");
canvas.onclick = ()=>{
  getRandomPointsForBox(200, box,4, 18);
  getRandomPoints(200);
}
const edgeClear = 30;
var box = {
  x: edgeClear,
  y: edgeClear,
  w: canvas.width - edgeClear * 2,
  h: canvas.height - edgeClear * 2,
  edge: 4,
}

function drawBox(box) {
  ctx.fillRect(box.x, box.y, box.w, box.h);
  ctx.clearRect(box.x + box.edge, box.y + box.edge, box.w - box.edge * 2, box.h - box.edge * 2);
}

function drawPixel(x, y) {
  ctx.fillRect(x, y, 1, 1);
}

function getRandomPointsForBox(count, box, min, max) {
  min += box.edge;
  max += box.edge;
  while (count--) {
    const [x, y] = randomPointNearRect(box.x, box.y, box.w, box.h, min, max);
    drawPixel(x, y);
  }
  
}

drawBox(box);
getRandomPointsForBox(200, box,4, 18);
ctx.font = "18px arial"
ctx.textAlign = "center"
ctx.textBaseline = "middle"
ctx.fillText("Click to add more random points.",canvas.width / 2, canvas.height / 2);



function randomPointNearRect(x, y, w, h, minDist, maxDist) {
  const dist = (Math.random() * (maxDist - minDist) + minDist) | 0;
  x += dist;
  y += dist;
  w -= dist  * 2
  h -= dist  * 2
  if (Math.random() <  w / (w + h)) { // top bottom
    x = Math.random() * w + x;
    y = Math.random() < 0.5 ? y : y + h -1;
  } else {
    y = Math.random() * h + y;
    x = Math.random() < 0.5 ? x: x + w -1;
  }
  return [x | 0, y | 0];
}









/* The following is from the answer provided by SimpleJ https://stackoverflow.com/a/49581326/3877726 */

const ctx1 = canvas1.getContext('2d');

const rect = {
  x: box.x, y: box.y,
  width: box.w, height: box.h,
};

drawRect(rect);

ctx1.font = "18px arial"
ctx1.textAlign = "center"
ctx1.textBaseline = "middle"
ctx1.fillText("SimpleJ's method.",canvas1.width / 2, canvas1.height / 2);
ctx1.fillText("Note density of sides and corners.",canvas1.width / 2, canvas1.height / 2 + 20);

function getRandomPoints(count) {
  while (count--) {
    drawPoint(randomPointInRect(sample(rects)));
  }
}


var rects = getBorderRects(rect, 10);




function getBorderRects(rect, distance) {
  const { x, y, width, height } = rect;
  return [
    {x: x, y: y, width: width, height: distance}, // top
    {x: x, y: y + height - distance, width: width, height: distance}, // bottom
    {x: x, y: y, width: distance, height: height}, // left
    {x: x + width - distance, y: y, width: distance, height: height}, // right
  ];
}

function sample(array) {
  return array[Math.floor(Math.random() * array.length)];
}

function randomPointInRect({x, y, width, height}) {
  return {
    x: x + (Math.random() * width),
    y: y + (Math.random() * height),
  };
}
function drawRect({x, y, width, height}) {
  ctx1.strokeRect(x, y, width, height);
}
function drawPoint({x, y}) {
  ctx1.fillRect(x, y, 1,1);
}
  getRandomPoints(200);

<canvas id="canvas" width="500" height="200"></canvas>
<canvas id="canvas1" width="500" height="200"></canvas>

这篇关于如何在javascript中获得正方形的边缘附近的随机点的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆