我正在开发一个处理3D网格的R包.我有一个构造参数网格的函数,但对于某些参数化,它可以生成重复的顶点(长度为3的数值向量).我需要找到重复的顶点,以便将它们合并为一个顶点.我用Rcpp实现了一个算法来做到这一点.
Rvcg包中有一个用于此的函数:vcgClean(mymesh, sel = 0)
.它非常快,和它相比,我的C++算法非常慢.类似地,R基函数duplicated
的速度要快得多.
以下是我的算法的工作原理.假设有n个顶点.
-
我取顶点1,将其与顶点2,3,...,n进行比较.
-
我取顶点2,将其与顶点3,4,...,n进行比较.请注意,如果此顶点已被标记为上一步中顶点1的副本,则可以跳过此比较.我不会那么做的.无论如何,通常会有少量的重复,所以这不是速度慢的原因.
-
以此类推,将顶点3与顶点4、5、...、n进行比较.
为了比较两个顶点,我测试了每个坐标的近似性:
bool test = nearEqual(v1(0), v2(0)) && nearEqual(v1(1), v2(1)) && nearEqual(v1(2), v2(2));
在此之前,我测试了完全相等,这也很慢.我的nearEqual
功能是:
bool nearEqual(double l, double r) {
return r == std::nextafter(l, r);
}
为什么我的算法这么慢?这是不是因为n-1 + n-2 + ... + 1
个比较策略?我不明白我怎么能少做些比较.还是因为nearEqual
的功能?不然怎样?顶点存储在Rcpp中的3 x n
数值矩阵中.
Edit
我刚刚try 了另一种方法来测试两列的近乎相等,但速度仍然很慢:
const Rcpp::NumericMatrix::Column& v1 = Vertices.column(i);
const Rcpp::NumericMatrix::Column& v2 = Vertices.column(j);
bool test = Rcpp::max(Rcpp::abs(v1 - v2)) < 1e-16;