以有效的方式找到最近的点

时间:2010-12-22 13:49:48

标签: c++ algorithm geometry

我在2d平面上有一个点,例如(x0,y0)和一组n个点(x1,y1)......(xn,yn)我想找到最近点(x0,y0) )以比尝试所有点更好的方式。任何解决方案?

我还应该说我的观点是这样排序的:

bool less(point a,point b){
  if(a.x!=b.x)
     return a.x<b.x;
  else
     return a.y<b.y;
 }

6 个答案:

答案 0 :(得分:9)

使用四叉树进行2D http://en.wikipedia.org/wiki/Quadtree

答案 1 :(得分:8)

Voronoi diagram专门用于非常快速地找到最近点。虽然实现起来非常困难,但您可能会发现一些现有的库/实现。

还可以选择在正方形中重复划分平面,从而构建某种树,其中每个非叶节点有4个子节点(右上角正方形,右下角正方形等)。然后,在四个方格中,你找到你的一个方位,并递归地继续它。通常这会产生足够接近的点,因此您可以省去检查其他方块的需要 但是很容易为这个策略创建一个“反例”,这将导致线性时间。

但是你可以用你的排序数组来加速这个过程。您需要一个特殊的数据结构。

修改
第二个结构称为四叉树,感谢 VGE 提供名称。

答案 2 :(得分:6)

对于有效的最近邻搜索,您需要使用空间分区方案,例如kd-tree

答案 3 :(得分:2)

如果您没有使用任何类型的树数据结构来帮助限制您必须查询的值的范围,那么您将必须检查潜在“邻居”范围内的每个点。限制比较的一种方法是检查距离给定点的最小值的平方距离:

Point myPoint = {x, y};
std::vector<Point> otherPoints; // given list of points to check

struct PointDistance
{
    Point pt;
    float dist;
};

std::vector<PointDistance> squaredDistances(otherPoints.size()); // will be filled in with squared distances

float CalculateDistance(const Point& pt1, const Point& pt2)
{
    float deltaX = pt1.x - pt2.x;
    float deltaY = pt1.y - pt2.y;
    return (deltaX * deltaX) + (deltaY * deltaY);
}

// should be changed to use an algorithm, but for clarity done as a loop here
for (int i = 0; i < otherPoints.size(); ++i)
{
    PointDistance pd;
    pd.pt = otherPoints[i];
    pd.dist = CalculateDistance(myPoint, pd.pt);
    squaredDistances.push_back(pd);
}

bool DistanceLess(const PointDistance& lhs, const PointDistance& rhs)
{
    return lhs.dist < rhs.dist;
}

std::sort(squaredDistances.begin(), squaredDistances.end(), DistanceLess);

// squaredDistances[0].pt will be your closest point.

答案 4 :(得分:0)

如果您正在创建N个点的集合,那么您可以根据它们与所考虑的点的线性距离来散列并映射它们,而不是仅将它们推入集合中。因此,具有相同线性距离的点将位于同一个桶中。然后根据距离获取点将是一个恒定的时间操作。

答案 5 :(得分:0)

一个特别好的解决方案是ANN: A Library for Approximate Nearest Neighbor Searching.我已将它用于三角测量中的点位置。你使用点初始化数据结构,在我的例子中,我使用了三角形的中心点。然后你可以传入另一个点并找回近似最近邻点的列表。甚至返回的点数也可以选择作为参数。无论如何,ANN对我来说是一个很棒的图书馆,我建议你看一下。

祝你好运!