PCL专栏目录及须知
PCL中,往往使用八叉树的子类,而不是直接使用 pcl::octree::OctreePointCloud这个基类。
子类在6.PCL八叉树关键函数中展示。
PCL中:将三维空间等分为8份,分配空间对象。并不停地迭代,直至最大分辨率。其中,八叉树的每个结点表示一个正方体的体积元素,每一个结点最多有八个子节点。
1.构造原理
- 设定最大递归深度。
- 找出场景的最大尺寸,并以此尺寸建立第一个立方体。
- 依序将单位元素丢入能包含且没有子节点的立方体
- 若没达到最大递归深度,就进行细分八等份,再讲该立方体所装的单位元元素全部分组给八个子立方体
- 若发现子立方体所分配到的单位元元素数量不为零且跟父立方体一样,则该子立方体停止细分
- (因为根据空间分割理论,细分的空间所得到的分配必定较少,若是一样的数目,再怎么切,数目还是一样)
- 重复3,直到到达最大递归深度。
2.数据结构
八叉树这种树结构中,每个节点的子节点数量永远是8。假设原目标(点云)被一个大立方体包含,八叉树的作用就是细分该大立方体,每个结点对应一个立方体空间。其中八叉树的结点分为三类:
灰色结点:它对应的立方体部分被目标占据(非叶结点)
白色结点:它对应的立方体没有被目标占据(叶结点)
黑色结点:它对应的立方体完全被目标占据(叶结点)
对于非叶结点,数据结构以八元数法进行区分,分解为更小的子区块,每个区块有结点容量,当结点达到最大容量(八叉树最大递归深度)时结点停止分裂。
3.分割终止判定
若不对空间划分做一定的条件限制,则会对空间无限划分下去。常见的限制条件为:
(1)节点中的对象数量限制。
(2)节点的最小尺寸。
4.查询节点
从根节点开始,如果找到给定点的节点,递归搜索,然后返回true,如果遇到空节点或边界点或空点,然后返回false。
如果找到一个内部节点,返回该节点(即我们查询的结点)。
5.优缺点
优点:使用八叉树可以快速进行三维目标的集合运算,如交、并、补、差等,亦可快速进行最邻近区域或点的搜索。
缺点:存储空间消耗。
6.PCL八叉树关键函数
(1)PCL中所有pcl::octree::OctreePointCloud的子类均可调用以下方法。
常用子类为:
1)八叉树搜索类
pcl::octree::OctreePointCloudSearch<pcl::PointXYZ> octree;
pcl::octree::OctreePointCloudChangeDetector<pcl::PointXYZ> octree;
3)八叉树点云压缩类
pcl::io::OctreePointCloudCompression<pcl::PointXYZRGB> compression;
(2)子类常调用的通用函数
1)检查用户输入位置的体素块是否存在
bool
isVoxelOccupiedAtPoint(const double point_x_arg,
const double point_y_arg,
const double point_z_arg) const;
2)获取树深
inline uindex_t
getTreeDepth() const
{
return this->octree_depth_;
}
3)获取体素块中心点
uindex_t
getOccupiedVoxelCenters(AlignedPointTVector& voxel_center_list_arg) const;
4)获取与线段相交的体素中心的PointT向量
uindex_t
getApproxIntersectedVoxelCentersBySegment(const Eigen::Vector3f& origin,
const Eigen::Vector3f& end,
AlignedPointTVector& voxel_center_list,
float precision = 0.2);
5)获取八叉树的点云边界
void
getBoundingBox(double& min_x_arg,
double& min_y_arg,
double& min_z_arg,
double& max_x_arg,
double& max_y_arg,
double& max_z_arg) const;
6)计算给定树深度处体素的平方直径
double
getVoxelSquaredDiameter(uindex_t tree_depth_arg) const;
7)生成八叉树当前迭代器的边界
inline void
getVoxelBounds(const OctreeIteratorBase<OctreeT>& iterator,
Eigen::Vector3f& min_pt,
Eigen::Vector3f& max_pt) const
{
this->genVoxelBoundsFromOctreeKey(iterator.getCurrentOctreeKey(),
iterator.getCurrentOctreeDepth(),
min_pt,
max_pt);
}
7.八叉树形态示例图
下图中每个可见的方格即为八叉树中拥有点云点的子节点。