las点云数据转3dtiles实现(c++)

 一、需求

        将las格式的点云数据转换为cesium能加载渲染的3dtiles格式(pnts)。

二、具体实现步骤

2.1 依赖开源库

gdal库:点云数据多为投影坐标系,cesium渲染需要的是地理坐标系,所以需要gdal库进行坐标转换。

LASzip库:读写las的库。

Qt 、osg等库不是必须,可以不用。我的代码其他地方需要这两个库,所以就用上了。

2.2点云读取

        使用LASzip库读取点云到内存。这里在具体程序实现的时候,需要注意分块策略,因为有些点云数据动则几十个G,如果不进行分块处理,对硬件压力太大了。具体的分块思路应该是现对点云数据构建索引,我代码中用的四叉树构建的点云索引;然后根据点云数量及范围对点云进行分块,每次处理的时候针对某一块进行处理。而且分块后方便后续并行加速处理。

2.3 lod构建

第一步:根据2.2中的分块结果,读取其中的某一块点云数据,统计其点个数和外界包围盒。

第二步:判断统计的点云数据个数是否大于指定的阈值(该值是3dtiles中每个pnts文件的最大点数量)。如果小于指定阈值,则该块不需要进行分块,将该块中的全部点写入pnts。如果小于指定阈值,则以该块外界包围盒(矩形)中心为分界点,创建四个子节点块,该块则被称为根节点。

第三步:针对第二步中得到的根节点块和子节点块,继续按照步骤二中的规则对四个子节点进行分块。具体是否分块还是按照节点中的点云数与指定阈值的大小来决定。以此循环,直到所有的节点都不能再分块为止。这样就完成了整个点云的lod构建。

上述方法描述起来比较拗口,其实用程序实现的时候,只需要进行递归调用即可实现,部分实现代码如下:

QSharedPointer<scially::OSGIndexNode> Build3dtiles(const std::vector<PointCI>* pointSet,
	std::vector<unsigned int>& pointIndex, osg::BoundingBox boundingBox,
	osg::BoundingBox boundingBoxLevel0, const std::string& saveFilePath,
	const std::string& strBlock, unsigned int level,
	unsigned int childNo, ExportMode exportMode,
	const scially::SpatialTransform& transform,
	const scially::TileStorage& storage)
{
	// filename of self, left, right
	std::string saveFileName, pageName1, pageName2, pageName3, pageName4;
	if (level == 0)
	{
		saveFileName = strBlock;
	}
	else
	{
		char tmpSaveFileName[100];
		sprintf(tmpSaveFileName, "%s%s%d%s%d", strBlock.c_str(), "_L", level, "_", childNo);
		saveFileName.assign(tmpSaveFileName);
		saveFileName = /*saveFilePath + "/" +*/ saveFileName;
	}
	//********** 1 2 **********
	//********** 3 4 **********
	char tmpPageName1[100], tmpPageName2[100], tmpPageName3[100], tmpPageName4[100];
	sprintf(tmpPageName1, "%s%s%d%s%d", strBlock.c_str(), "_L", level + 1, "_", childNo * 4);
	pageName1.assign(tmpPageName1);
	sprintf(tmpPageName2, "%s%s%d%s%d", strBlock.c_str(), "_L", level + 1, "_", childNo * 4 + 1);
	pageName2.assign(tmpPageName2);
	sprintf(tmpPageName3, "%s%s%d%s%d", strBlock.c_str(), "_L", level + 1, "_", childNo * 4 + 2);
	pageName3.assign(tmpPageName3);
	sprintf(tmpPageName4, "%s%s%d%s%d", strBlock.c_str(), "_L", level + 1, "_", childNo * 4 + 3);
	pageName4.assign(tmpPageName4);

	// handle le
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

nab111

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值