查找属于特定区域的2d数据点

时间:2016-08-04 01:45:49

标签: javascript math geometry

我有一大组数据表示二维平面上的坐标。找到基于变量点的可变半径内的所有x,y对,有效且有效的方法是什么? (任何有关存储数据的提示都会非常受欢迎)

修改

最终的应用程序是用Javascript编写的,特别是Node。

编辑

我发现矩形区域也是允许的而不是半径,但矩形的边框仍然是可变的。我在下面的评论中说明,我应该指定最终数据集将有数百万个条目,并且遍历每个请求的整个集合是不可行的。

2 个答案:

答案 0 :(得分:1)

点对点距离应小于被搜索圆的半径。为了改进搜索,还可以实现二分搜索或kd-tree

var getPoints = (function() {
  var points = [{
    x: 90,
    y: 70
  }, {
    x: 100,
    y: 80
  }, {
    x: 20,
    y: 40
  }]
  return function() {
    return points;
  }
})();

function dist(point1, point2) {
  var pow = Math.pow;
  return Math.sqrt(pow((point2.x - point1.x), 2) + pow((point2.y - point1.y), 2));
}

function drawCircle(centerX, centerY, radius, fill) {
  var canvas = document.getElementById('myCanvas');
  var context = canvas.getContext('2d');

  context.beginPath();
  context.arc(centerX, centerY, radius, 0, 2 * Math.PI, false);
  if (fill) {
    context.fillStyle = 'green';
    context.fill();
  }
  context.lineWidth = 2;
  context.strokeStyle = '#003300';
  context.stroke();
}

function spatialSearch(centerX, centerY, radius) {
  var points = getPoints(),
    res = [],
    len,
    r = 5,
    fill,
    i;

  drawCircle(centerX, centerY, radius);

  for (i = 0, len = points.length; i < len; i += 1) {
    ele = points[i];
    fill = undefined;
    if (dist({
      x: centerX,
      y: centerY
    }, ele) <= radius) {
      res.push(ele);
      fill = 'green';
    }
    drawCircle(ele.x, ele.y, r, fill);
  }
  return res;
}

spatialSearch(100, 75, 50);
<canvas id="myCanvas" width="300" height="150" style="border:1px solid #d3d3d3;">
  Your browser does not support the HTML5 canvas tag.</canvas>

答案 1 :(得分:0)

@ Ayan的方法非常简单,但这里还有其他一些需要考虑的技巧。但是,您将不得不使用实际数据进行衡量,以了解真正有效的方法。

如果您有非常多的点,第一步是摆脱包含您的圆圈的边界框之外的所有点。假设圆的中心位于(ox,oy),半径为r。然后你可以丢弃x值超出ox +/- r的所有点(y值相同)。如果您的点按x坐标排序,您应该能够使用二分搜索在x坐标上缩小它,然后对具有合理y值的其余候选点进行线性扫描。

然后,最直接的方法是比较欧几里德距离的平方与r ^ 2。这避免了在@Ayan上面做的标准距离公式中做平方根,这非常昂贵。因此,只需计算r ^ 2是否小于(ox - px)^ 2 +(oy - py)^ 2。由于后者只是加法和乘法,所以应该相当快。

如果你可以接受一些近似值,你可以考虑沿着圆圈上的某些桶对圆圈的-y和+ y进行采样,并将它们存储在查找表中。然后,对于给定的点(x,y),您查找该x的相应桶,并查看y是否在您预先计算的点之间。尽管如此,你真的必须有很多要点。