前言
上一节通过OSG插件的方式,成功将Potree点云数据集成至OSG渲染引擎,实现了大规模点云数据的高效加载与可视化呈现(osgPotree:基于OSG的插件,支持Potree点云读取-CSDN博客)。本节将在上节的基础上,进一步实现一个指定空间范围提取点云数据的工具。源码地址:https://gitee.com/osg_opensource/osg-potree.git
目录
- 1 点云提取器设计
- 2 测试效果
1 点云提取器设计
与OSG中的求交器做对比,我们首先分析线段求交器(LineSegmentIntersector)的特性,然后对比其与点云提取工具的区别,最后阐述点云提取器的设计思路与关键要点。
1.1 OSG中求交工具设计
OSG中求交工具的组成由访问器、求交器、读取文件回调类组成,如下图为类图关系:

整个类图的核心是 IntersectionVisitor,它继承自 osg::NodeVisitor,允许开发者通过访问者模式以非侵入方式自定义数据处理逻辑。具体求交功能由 Intersector 及其子类实现:LineSegmentIntersector 用于线段求交,IntersectorGroup 可组合多个求交器,PlaneIntersector 负责平面求交,而 PolytopeIntersector 则用于多面体求交。此外,通过 ReadCallback 类可读取瓦片数据:由于 OSG 中数据常以层级瓦片形式组织,当前场景可能未加载最精细层级,借助 ReadCallback 可在求交时动态加载所需精细瓦片参与计算,相反当为设置ReadCallback时,仅当前视口下场景图最精细的层级参与计算。
osgPotree点云不同点主要体现在两点:1)点云采用Add模式显示数据,而倾斜模型采用Replace模式显示数据;2)osgPotree点云子节点的加载依赖osgDB::Options传递点云的八叉树结构信息。对于第一点,如下图所示,以二叉树为例:
|----------------------------------------------------------------------------|
|
|
| Replace模式显示节点(红色) |
|
|
| Add模式显示节点(红色) |
Replace模式父子节点显示是一种互斥关系,及当前显示节点的父子节点都不显示,而Add模式当前显示节点的父节点都显示。这种差异会反应到重写的节点访问器中重载函数apply(osg::PagedLOD&)的写法上,后续将具体说明代码上的差异。
1.2 点云提取器设计

其中ExtractVisitor、Extractor、ReadCallback与前面提到的IntersectionVisitor、Intersector、ReadCallback组合功能类似,其中BoxExtractor是提取范围为Box的提取器、DatabaseCacheReadCallback用于在提取点云过程中加载点云最精细的层级并做缓存。区别点有两个地方:1)ExtractVisitor的设计坐标系上仅考虑到了模型空间,未考虑投影、窗口坐标系;2)如前面提到的,ExtractVisitor的具体实现需考虑到点云渲染、运算的Add模式特点。3)如前面提到的,ExtractVisitor的具体实现在加载精细级别点云时,需要将点云的八叉树结构信息通过osgDB::Options向下传递。
针对第一点,相应的apply重载函数针对osg::Camera、osg::Projection做重载,仅对简单的节点如osg::Node、osg::Drawable、osg::Geode、osg::Group、osg::LOD、osg::PagedLOD、osg::Transform做重载,对应的矩阵栈只考虑_modelStack(变量)。
第二点体现在apply(osg::PagedLOD&)重载函数的具体实现上,保证访问osg::PagedLOD最精细层级的同时,访问所有低精细层级的子节点,具体实现可参照pointCloudExtractor/ExtractVisitor.cpp · osg_opensource/osgPotree - 码云 - 开源中国中apply(osg::PagedLOD&)函数的实现。
第三点体现在ReadCallback的设计上,readNode方法新增一个osgDB::Options变量,如下所示:
cpp
struct ReadCallback : public osg::Referenced
{
virtual osg::ref_ptr<osg::Node> readNodeFile(const std::string& filename, osgDB::Options* options) = 0;
};
2 测试效果
运行如下命令:
bash
pointCloudExtractor --potree .\osg-potree\assets\PointExtractor
--cubepath .\osg-potree\assets\PointExtractor\box.txt
--outpath .\osg-potree\assets\PointExtractor\out.txt
其中pointCloudExtractor是 https://gitee.com/osg_opensource/osg-potree.git编译出来的点云提取器工具。--potree后续路径为potreeconverter( https://github.com/potree/PotreeConverter )输出结果文件夹。--cubepath为过滤器参数,有四行,第一个为起点,第二、三、四行分别为x、y、z三个轴向的向量,整体上表达了一个空间任意位置、方位的Box。--outpath后续路径为提取的点云保存路径,当前仅支持保存为txt格式,txt中第一行为点的个数,剩余行每行表示一个三维点坐标。相应的文件同步在了开源仓库
assets/PointExtractor 文件夹下,包含数据源于点云过滤器文件(box.txt)。
如下图所示,在1676毫秒内,提取了290517个点云点。
