C++ 改进的点集最小距离滤波器
我为点创建了一个最小距离过滤器。 该函数获取点流(x1、y1、x2、y2…)并删除相应的点C++ 改进的点集最小距离滤波器,c++,algorithm,c++11,computational-geometry,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
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
}
}
}
}
void minDistanceFilter(向量和点,浮动距离=0.0)
{
浮点数p0x,p0y;
浮点数dx,dy,dsq;
float mdsq=距离*距离;//最小距离平方
无符号i,j,n=points.size();
对于(i=0;i查找范围树,例如en.wikipedia.org/wiki/range_tree。您可以使用此结构存储二维点,并非常快速地查找位于查询矩形内的所有点。由于您希望查找距离点(a,b)一定距离d内的点,因此您的查询矩形需要为[a-d,a+d]x[b-d,b+d]然后测试在矩形内找到的任何点,以确保它们实际上在(a,b)的距离d内。范围树可以在O(n logn)时间和空间中构建,范围查询需要O(logn+k)时间,其中k是在矩形中找到的点的数量。似乎最适合您的问题。查找范围树,例如en.wikipedia.org/wiki/range_tree。您可以使用此结构存储二维点,并非常快速地找到位于查询矩形内的所有点。因为您希望找到一定距离d内的点对于一个点(a,b),您的查询矩形需要是[a-d,a+d]x[b-d,b+d],然后您测试在矩形内找到的任何点,以确保它们实际上在(a,b)的距离d内。范围树可以在O(n logn)时间和空间中构建,范围查询需要O(logn+k)时间,其中k是在矩形中找到的点数。似乎最适合您的问题。kd树或范围树可以用于您的问题。但是,如果您想从头开始编写代码并想要更简单的内容,则可以使用哈希表结构。对于每个点(a,b),使用键进行哈希(舍入(a/d),舍入(b/d))并将具有相同键的所有点存储在列表中。然后,对于哈希表中的每个键(m,n),将列表中的所有点与具有键(m',n')的点列表进行比较,其中m'=m+(-1或0或1)和n'=n+(-1或0或1)。这些是唯一可以在具有关键点(m,n)的点的距离d内的点。与kd树或范围树相比,其缺点是,对于给定的点,您实际上是在边长为3*d的平方内搜索可能具有距离d或更小的点,而不是在边长为2*d的平方内搜索,如果您使用kd树或范围树,则会得到边长为2*d的点。但是如果您是从头开始编码,这更容易编码;而且,如果您只关心所有点的一个通用距离d,kd树和范围树就有点过分了。kd树或范围树可以用于解决您的问题。但是,如果您想从头开始编码,并且想要更简单的东西,那么您可以使用哈希表结构。对于每个点(a,b),使用键(舍入(a/d)、舍入(b/d))进行散列,并将具有相同键的所有点存储在列表中。然后,对于散列表中的每个键(m,n),将列表中的所有点与具有键(m',n')的点列表进行比较,其中m'=m+(-1或0或1)和n'=n+(-1或0或1)。这些是唯一可以在具有关键点(m,n)的点的距离d内的点。与kd树或范围树相比,其缺点是,对于给定的点,您实际上是在边长为3*d的平方内搜索可能具有距离d或更小的点,而不是在边长为2*d的平方内搜索,如果您使用kd树或范围树,则会得到边长为2*d的点。但是如果您是从头开始编码,这更容易编码;而且kd树和距离树也有点过分了,如果你对所有点都只关心一个通用距离d。你可能现在就想要一个。构建四叉树也相对较慢。如果我多次进行距离测试,这会很有效率。不是吗?@Armin:没关系,但我需要执行这个测试在一个数据集上只测试一次。因此,在我看来,总是在一个新数据集上构建一个四叉树来执行单个测试是非常低效的。你可能现在就需要一个测试。构建一个四叉树也相对缓慢。如果我多次进行距离测试,这将是非常有效的。不是吗?@Armin:没关系,但我只需要执行一次测试所以在我看来,总是在一个新的数据集上构建一个四叉树来执行一个测试是非常低效的。