改善点集的最小距离滤波器

时间:2013-07-20 22:12:01

标签: c++ algorithm c++11 computational-geometry

我为点创建了一个最小距离过滤器。 该函数采用点流(x1,y1,x2,y2 ......)并删除相应的点。

void minDistanceFilter(vector<float> &points, float distance = 0.0)
{
    float p0x, p0y;
    float dx, dy, dsq;
    float mdsq = distance*distance; // minimum distance square

    unsigned i, j, n = points.size();

    for(i=0; i<n; ++i)
    {
        p0x = points[i];
        p0y = points[i+1];

        for(j=0; j<n; j+=2)
        {
            //if (i == j) continue; // discard itself (seems like it slows down the algorithm)

            dx = p0x - points[j];   // delta x (p0x - p1x)
            dy = p0y - points[j+1]; // delta y (p0y - p1y)

            dsq = dx*dx + dy*dy; // distance square

            if (dsq < mdsq)
            {
                auto del = points.begin() + j;
                points.erase(del,del+3);
                n = points.size(); // update n
                j -= 2; // decrement j
            }
        }
    }
}

唯一的问题是非常缓慢,因为它针对所有点(n ^ 2)测试所有点。

如何改进?

2 个答案:

答案 0 :(得分:2)

查找范围树,例如en.wikipedia.org/wiki/Range_tree。您可以使用此结构存储二维点,并快速查找查询矩形内的所有点。由于你想在点(a,b)的某个距离d内找到点,你的查询矩形需要是[ad,a + d] x [bd,b + d]然后你测试里面找到的任何点矩形,以确保它们实际上在(a,b)的距离d内。范围树可以在O(n log n)时间和空间中构建,范围查询需要O(log n + k)时间,其中k是矩形中找到的点数。似乎是您的问题的最佳选择。

答案 1 :(得分:2)

kd-trees或range trees可以用于解决您的问题。但是,如果您想从头开始编写代码并希望更简单,那么您可以使用哈希表结构。对于每个点(a,b),使用密钥(圆形(a / d),圆形(b / d))进行散列并将所有具有相同密钥的点存储在列表中。然后,对于哈希表中的每个键(m,n),将列表中的所有点与具有键(m',n')的点列表进行比较,对于(m',n')的所有9个选项,其中m '= m +( - 1或0或1)并且n'= n +( - 1或0或1)。这些是可以在具有键(m,n)的点的距离d内的唯一点。与kd树或范围树相比的缺点是,对于给定点,您有效地在边长3 * d的正方形内搜索可能具有距离d或更小的点,而不是在边长的正方形内搜索2 * d这是你使用kd树或范围树时会得到的。但是如果你从头开始编码,这就更容易编码;如果你只有一个你关心所有点的通用距离d,那么kd-trees和范围树也有点矫枉过正。