在八叉树中合并叶子
Posted
技术标签:
【中文标题】在八叉树中合并叶子【英文标题】:Merging leaves in an octree 【发布时间】:2011-04-27 18:45:13 【问题描述】:我有一个非常大的点云(> 100000 个点),我想在其中检测平面排列。我决定使用八叉树将这些点分解为非常小的平面簇,然后合并共面的相邻簇。我已经用 C++ 编写了代码,可以快速将点云分割成小的平面集群,但是如何有效地合并它们却让我望而却步……
我的Octree
实现使用指针结构:有OctreeNode
s 数组OctreeNode* children[8]
包含指向其子节点的指针,或者如果它是叶节点,则所有NULL
指针。
我的第一个想法是,在每个 OctreeNode
对象中,保留一个指向 Plane
对象的指针。在第一次拆分点后,八叉树中的每个叶子都会得到一个Plane
,它表示适合叶子中包含的所有点的最小二乘法。然后我遍历树中的每个叶节点。对于每个叶节点,我检查它的每个相邻叶节点:如果邻居的平面应该与当前叶的平面合并,我调用Plane* newPlane = Plane::mergePlanes(this->plane, neighbor->plane);
来创建一个代表两个节点中的点的新平面。
这是我遇到麻烦的地方......我首先认为我可以简单地用新平面替换两个平面,即plane = newPlane; neighbor->plane = newPlane;
并完成(除了内存泄漏;我在真实代码中处理它们)。不幸的是,这在实践中不起作用。合并多个平面后,可能有几个不同的OctreeNode
s 指向一个Plane
,并且简单地替换this->plane
和neighbor->plane
中的指针并不会替换指向其旧平面的每个指针。
即使我第一次想出这个解决方案时,它似乎也很老套,现在它的缺陷更加明显。任何人都可以想出一种方法来解决我想出的合并方法,或者想出更好的方法吗?
谢谢
【问题讨论】:
【参考方案1】:标准修复是延迟修复节点。有一种访问方法可以查看您所指向的平面,然后查看它是否已指向其他地方。如果有,递归搜索,直到找到它所在的位置,然后将所有对象修复回当前对象,然后将正确的平面交还。
这比跟随指针要昂贵得多,但实际上这并不像您想象的那么昂贵,因为大多数时候最终对象位于您查看的第一或第二位置。
【讨论】:
【参考方案2】:VTK 有一个类似的点句柄类vtkIncrementalOctreePointLocator。我认为合并插入点的理想点。
例如:
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 );
所以我的意见是:如果类太大,重建它会更容易。
【讨论】:
以上是关于在八叉树中合并叶子的主要内容,如果未能解决你的问题,请参考以下文章