在八叉树中合并叶子

时间:2011-04-27 18:45:13

标签: c++ algorithm tree computational-geometry quadtree

我有一个非常大的点云(> 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->planeneighbor->plane中的指针就不会取代每个指针指着他们的旧飞机。

即使我第一次提出解决方案,解决方案似乎仍然是黑客,现在它的缺陷更加清晰。任何人都可以想到一种方法来解决我想出的合并方法,或者想一个更好的方法吗?

谢谢

2 个答案:

答案 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 );

所以我的观点是:如果课程太大,重建它会更容易。