算法帮助 - 针对小对象的命中测试

时间:2013-05-11 23:05:20

标签: algorithm collision-detection processing hittest

在处理草图中实现选择算法时,我循环遍历场景中的每个对象,并检查它是否在鼠标点击的几个像素范围内。有很多物体,它们非常小。

正如你可以想象的那样,一旦场景充满物体,这就变得非常麻烦。有没有简单的方法来加快搜索速度?我可以轻松地制作这个二进制搜索吗?我的场景中的对象是点,因此多边形命中测试算法似乎不是正确的解决方案。

2 个答案:

答案 0 :(得分:2)

将场景划分为多个存储桶,分为N个存储桶和M个存储桶,或者划分为N * M x * y存储桶。在前一种情况下,存储桶存储在两个数组中(x数组和y数组);在后一种情况下,存储桶存储在一个数组数组中(外部数组索引x坐标,内部数组索引y坐标)。在任何一种情况下,桶都存储对桶所索引区域内所有点的引用;例如,点(8,12)将位于x-bucket [5,10]和y-bucket [10,15]中,否则它将位于x * y桶中[[5,10]) ,[10,15])。

查找某个点时,要么查找相应的x和y桶,要么只需查找相应的x * y桶。在前一种情况下,请intersection(union(x-buckets), union(y-buckets))。您可能需要根据命中半径查找多个存储桶,例如,如果您正在查找半径为2的x坐标9,那么您需要[5,10]和[10,15]存储桶。

使用单独的x和y存储桶占用更少的空间(N + M存储桶而不是N * M存储桶)并使索引更容易(两个独立的数组与一个嵌套数组),而x * y存储桶使速度更快查找,因为您不需要采取任何设置交叉点。

您的存储桶越小,数据结构占用的空间就越大,但您将检索的误报越少。理想情况下,如果您有足够的内存,则存储桶将覆盖与命中半径相同的间隔。

答案 1 :(得分:1)

也许如果你按一个轴对数组进行排序,让我们说x你可以通过早期返回来加快速度,我在thomas.diewald问题的处理论坛上从this得到了这个例子。它可能适合您的需要。这里只是测试的一部分(你可以看一下上面链接中的comlete代码)。有一个点的ArrayList,它有x和y字段。看看

请注意他正在使用标签返回。

Arrays.sort(points);

  __FIND_NEIGHBORS__:
  for (int i = 0; i < num_points; i++) {
    Point pi = points[i];

    for (int j = i+1; j < num_points; j++) {
      Point pj = points[j];

      // 1. check in x
      float dx = pj.pos.x-pi.pos.x; // always positive -> points are sorted
      if( dx > max_dist ){
        continue __FIND_NEIGHBORS__; // ... no more points within max_dist.
      }

      // 2. check in y
      float dy = Math.abs(pj.pos.y-pi.pos.y); // not always positive
      if( dy > max_dist ){
        continue;
      }  

      // 3. check, could also just draw the line here (Manhattan distance)
      if ((dx*dx+dy*dy) < max_dist_sq) { 
        drawLine(pi, pj);
        connections++;
      }
    }
  }