我有一个非常大的点云(> 100000点),我想检测平面排列。我决定使用八叉树将点分解成非常小的平面簇,然后合并相邻的共面簇。我用C ++编写的代码可以快速将点云分成小的平面簇,但是如何有效地合并它们却让我不知所措......
我的Octree
实现使用指针结构:OctreeNode
个数组OctreeNode* children[8]
包含指向其子节点的指针,或者所有NULL
指针(如果它是一个叶子)节点
我的第一个想法是,在每个OctreeNode
对象中,保留指向Plane
对象的指针。在第一次分割点之后,八叉树中的每个叶子将得到Plane
,表示适合叶子中包含的所有点的最小二乘。然后我迭代树中的每个叶节点。对于每个叶子节点,我检查其每个邻居叶子节点:如果邻居的平面应该与当前叶子的平面合并,我调用Plane* newPlane = Plane::mergePlanes(this->plane, neighbor->plane);
来创建一个代表两个节点中的点的新平面。
这是我遇到麻烦的地方......我首先想到我可以简单地用新的平面替换两个平面,即plane = newPlane; neighbor->plane = newPlane;
并完成(内存泄漏;我在实际代码中处理它们) )。不幸的是,这在实践中不起作用。合并多个平面后,可能会有几个不同的OctreeNode
指向单个Plane
,只需替换this->plane
和neighbor->plane
中的指针就不会取代每个指针指着他们的旧飞机。
即使我第一次提出解决方案,解决方案似乎仍然是黑客,现在它的缺陷更加清晰。任何人都可以想到一种方法来解决我想出的合并方法,或者想一个更好的方法吗?
谢谢
答案 0 :(得分:2)
标准修复是延迟修复节点。有一个访问方法,查看您指向的平面,然后查看它是否已指向其他位置。如果有,则递归搜索直到找到它的位置,然后将所有对象修复回当前对象,然后再将右侧平面移回。
这比跟踪指针贵得多,但实际上这并不像你想象的那么昂贵,因为大部分时间最终对象都在你看的第一个或第二个位置。
答案 1 :(得分:0)
VTK有一个类似的点句处理类vtkIncrementalOctreePointLocator。我认为合并插入点的理想点。
E.g:
double xyz[3]; // location
id_type point_id; // we get back the point id
// bool InsertUniquePoint( double xyz[3], id_type &point_id );
// return value is true, if new point inserted
bool value = inserter->InsertUniquePoint( xyz, point_id );
所以我的观点是:如果课程太大,重建它会更容易。