LAS点云转OSGB
对于现如今无人机与激光雷达的应用在GIS行业中也越来越成熟,所以对于一个GISer来说,Las点云数据应该都不会陌生;
但在我们开发环境中,有时候Las数据也不能完全适用于所有的场景,这时候我们就需要将数据进行格式转换;
小编也是在工作中需要将las点云转为OSGB倾斜摄影数据;也查阅了很多资料但都没有找到一个比较好的中间件来进行转换,所以只能发挥一下自己的动手能力,自己做了一个小程序;
在这里我把程序代码给大家分享出来,完全是起个抛砖引玉的作用,还请各位大神,多多指教!
思路:
1、解析Las点云数据,并将数据散列点储存到内存中
2、对点云投影转换
3、使用OSG(OpenSceneGraph应用程序接口)创建OSGB文件
使用到的库
1、proj4
2、openscenegraph3.4
编程语言:Qt C++
在上一篇文章中小编也是将如何解析Las点云数据贴出来了,下面我们来分析下怎么样转换数据。
读取las文件到结构中,并调用转换方法
LasHelper* lhelper = new LasHelper(&lasfile);
LasInfo linfo = lhelper->getPoints();
delete lhelper;
ohelper->lasInfo2Osg(linfo, c_pt, this->oName,lasFiles.count(),pc);
初始化对象时设置度带号及投影转换参数
OsgHelper::OsgHelper(QString* clon)
: QObject()
{
double ang6num = qCeil(clon->toDouble() / 6) + (double)30;
QString SpatialL = QString("+proj=utm +zone=%0 +datum=WGS84 +units=m +no_defs ");
QString SpatialR = "+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs";
QString SpatialWGS84Lonlat = "+proj=longlat +datum=WGS84 +no_defs ";
if (!(utmProj = pj_init_plus(SpatialL.arg((int)ang6num).toLatin1())))
exit(-1); // 初始化失败,退出程序
if (!(mercatorProj = pj_init_plus(SpatialR.toLatin1())))
exit(-1);
if (!(wgs84lonlatProj = pj_init_plus(SpatialWGS84Lonlat.toLatin1())))
exit(-1);
QString SpatialWorldXY = QString("+proj=tmerc +lat_0=0 +lon_0=%0 +k=1 +x_0=45500000 +y_0=0 +ellps=GRS80 +units=m +no_defs ").arg(*clon);
//"+proj=merc +lon_0=0 +k=1 +x_0=0 +y_0=0 +datum=WGS84 +units=m +no_defs ";
//"+proj=tmerc +lat_0=0 +lon_0=105 +k=1 +x_0=500000 +y_0=0 +ellps=krass +units=m +no_defs ";
if (!(worldXY = pj_init_plus(SpatialWorldXY.toLatin1())))
exit(-1);
}
将las数据传入方法中进行投影及转换
void OsgHelper::lasInfo2Osg(LasInfo lasInfo, PointD point_min, QString outName, int tcount,int &pc)
{
QFileInfo fInfo(lasInfo.lasFilePath);
QString path = fInfo.absolutePath() + "/" + outName + "/";
QString name = fInfo.baseName();
QDir dir;
dir.mkpath(path);
baseDataPath = path;
int totalCount = tcount * 7;
for (int i = 0; i < 3; i++)
{
pc++;
double res = (double)3 / (i + 1);
osg::ref_ptr<:pagedlod> plod = getPagedLOD(lasInfo, res, i, fInfo.baseName(), point_min);
QByteArray loddata = QString("%0%1_level_%2.osgb").arg(path).arg(name).arg(i).toLocal8Bit();
string outLodPath = string(loddata);
osg::ref_ptr<:options> spOptions = new osgDB::Options;
spOptions->setPluginStringData("Compressor", "zlib");
bool succeed = osgDB::writeNodeFile(*plod.get(), outLodPath, spOptions.get());
double cpro = ((double)pc / (double)7) / (double)tcount;
emit outputSchedule(cpro);
if (i == 2)//到最后一层时进行切片,切4片
{
for (int j = 0; j < 4; j++)
{
pc++;
osg::ref_ptr<:geode> gd = getGeode(lasInfo, j, point_min);
QByteArray gddata = QString("%0%1_level_%2_%3.osgb").arg(path).arg(name).arg(i + 1).arg(j + 1).toLocal8Bit();
string outGeoPath = string(gddata);
bool succeeg = osgDB::writeNodeFile(*gd.get(), outGeoPath, spOptions.get());
double cpro = ((double)pc / (double)7) / (double)tcount;
emit outputSchedule(cpro);
}
}
}
}
获取PagedLOD分级数据
```
// 获取PagedLOD分级数据
///
/// 点云信息
/// 分辨率,用于抽稀
/// 当前生成的级别
/// 文件名
///
osg::ref_ptrOsgHelper::getPagedLOD(LasInfo lasInfo, double res, int level, QString fileName, PointD point_min)
{
// 创建顶点数组
osg::ref_ptrcoords = new osg::Vec3Array();
// 创建颜色
osg::ref_ptrcolors = new osg::UIntArray();
osg::Vec3d n_ptmin = UTMAltToWorld(point_min);
//当前这一段的范围
osg::Vec3d cpara_point_min = UTMAltToWorld({ lasInfo.rangeBound.xmin, lasInfo.rangeBound.ymin,lasInfo.rangeBound.zmin });
osg::Vec3d cpara_point_max = UTMAltToWorld({ lasInfo.rangeBound.xmax, lasInfo.rangeBound.ymax,lasInfo.rangeBound.zmax });