1. 概述

我在《OSG加载倾斜摄影数据》这篇博文中论述了如何通过OSG生成一个整体的索引文件,通过这个索引文件来正确显示ContextCapture(Smart3D)生成的倾斜摄影模型数据。这类倾斜摄影模型数据一般都会有个元数据metadata.xml,通过这个元数据,可以将其正确显示在osgEarth的数字地球上。

2. 详论

2.1. 位置

metadata.xml中的内容一般如下所示:

SRS就是空间坐标参考的意思,ENU表示是东北天站心坐标系,站心点的经纬度坐标为(108.9594, 34.2196)。这个站心点对应的应该是倾斜摄影模型的中心点,那么思路就很简单了,只需要平移旋转这个倾斜摄影模型,使模型的中心点对应于站心点。这其实是个地心坐标系于站心坐标系转换的问题:

在osgEarth中可以不用关心这个问题,其直接封装了一个类osgEarth::GeoTransform,可以直接通过这个类的接口来加载倾斜摄影模型:

std::string filePath = "D:/Data/scene/Dayanta/Data.osgb";
osg::ref_ptr<osg::Node> node = osgDB::readNodeFile(filePath); osg::ref_ptr<osgEarth::GeoTransform> xform = new osgEarth::GeoTransform();
xform->addChild(node);
xform->setTerrain(mapNode->getTerrain());
osgEarth::GeoPoint point(map->getSRS(), 108.9594, 34.2196, -410); //使用绝对高,正高
xform->setPosition(point); osg::ref_ptr<osgEarth::ModelLayer> modelLayer = new osgEarth::ModelLayer("oblic", xform);
map->addLayer(modelLayer);

给osgEarth::GeoTransform传入的osgEarth::GeoPoint就是站心点。不过这种类型的metadata.xml似乎都没有给出准确的高程值,所以需要自己调整高程来贴地。可能因为我这里试用的倾斜摄影数据都是网上找的,不太可能给出准确的地理坐标。

2.2. 着色

另外一点要注意的是直接读取加载的倾斜摄影模型是没有颜色信息的,这点和OSG还不太一样,在帮助文档里面论述了这个问题:

所以一定要记得加上着色器渲染,否则倾斜摄影模型会变成白模:

osgEarth::Registry::shaderGenerator().run(node);

2.3. 其他

有的metadata.xml里面的内容是这样的:

这个元数据的意思是这个倾斜摄影模型是根据EPSG编号为2384的空间参考坐标系下构建的。简单查了一下这个坐标系应该是xian80高斯克吕格平面投影直角坐标系,因为是用于三维数据,所以加上一个高程形成一个三维立体直角坐标系。严格意义上来讲,是需要将地球展成这个立体直角坐标系,将这个倾斜摄影模型放置到SRSOrigin的地理位置才是最准确的。但是一般的投影东向和北向的方向是不会变的,仍然可以将SRSOrigin的地理位置当成一个站心位置,只不过这个站心位置不再是经纬度而是EPSG:2384的平面坐标值(加上高程)。

所以像这种类型的数据,只需要将SRSOrigin的地理位置值转换成经纬度值,就变成2.1中描述的情况了。

3. 结果

具体的实现代码如下:

#include <Windows.h>
#include <iostream>
#include <string> #include <osgViewer/Viewer>
#include <osgDB/ReadFile> #include <osgEarth/MapNode> #include <osgEarthDrivers/gdal/GDALOptions>
#include <osgEarthDrivers/cache_filesystem/FileSystemCache>
#include <osgEarth/ImageLayer>
#include <osgEarth/Viewpoint>
#include <osgEarth/GeoTransform>
#include <osgEarth/ModelLayer>
#include <osgEarth/Registry> #include <osgEarthUtil/EarthManipulator> #include <gdal_priv.h> using namespace std; void AddModel(osg::ref_ptr<osgEarth::Map> map, osg::ref_ptr<osgEarth::MapNode> mapNode)
{
//
std::string filePath = "D:/Data/scene/Dayanta/Data.osgb";
osg::ref_ptr<osg::Node> node = osgDB::readNodeFile(filePath); osg::ref_ptr<osgEarth::GeoTransform> xform = new osgEarth::GeoTransform();
xform->addChild(node);
xform->setTerrain(mapNode->getTerrain());
osgEarth::GeoPoint point(map->getSRS(), 108.9594, 34.2196, -410); //使用绝对高,正高
xform->setPosition(point); osg::ref_ptr<osgEarth::ModelLayer> modelLayer = new osgEarth::ModelLayer("oblic", xform);
map->addLayer(modelLayer); osgEarth::Registry::shaderGenerator().run(node);
} int main()
{
CPLSetConfigOption("GDAL_DATA", "D:/Work/OSGNewBuild/OpenSceneGraph-3.6.4/3rdParty/x64/gdal-data"); //string wktString = "EPSG:3857"; //web墨卡托投影
//string wktString = "EPSG:4326"; //wgs84
osgEarth::ProfileOptions profileOpts;
//profileOpts.srsString() = wktString; //osgEarth::Bounds bs(535139, 3365107, 545139, 3375107);
//osgEarth::Bounds bs(73, 3, 135, 53);
//profileOpts.bounds() = bs; //地图配置:设置缓存目录
osgEarth::Drivers::FileSystemCacheOptions cacheOpts;
string cacheDir = "D:/Work/OSGNewBuild/tmp";
cacheOpts.rootPath() = cacheDir; //
osgEarth::MapOptions mapOpts;
mapOpts.cache() = cacheOpts;
//mapOpts.coordSysType() = osgEarth::MapOptions::CSTYPE_PROJECTED; mapOpts.profile() = profileOpts; //创建地图节点
osg::ref_ptr<osgEarth::Map> map = new osgEarth::Map(mapOpts);
osg::ref_ptr<osgEarth::MapNode> mapNode = new osgEarth::MapNode(map); osgEarth::Drivers::GDALOptions gdal;
//gdal.url() = "D:/Work/OSGNewBuild/osgearth-2.10.1/data/world.tif";
//gdal.url() = "D:/Work/SinianGIS/bin/Resource/BlueMarbleNASA.jpg";
gdal.url() = "D:/Work/SinianGIS/bin/Resource/baseMap.jpg";
osg::ref_ptr<osgEarth::ImageLayer> imgLayer = new osgEarth::ImageLayer("BlueMarble", gdal);
map->addLayer(imgLayer); AddModel(map, mapNode); osgViewer::Viewer viewer;
viewer.getCamera()->setClearColor(osg::Vec4(0, 0, 0, 0));
viewer.setSceneData(mapNode); osg::ref_ptr< osgEarth::Util::EarthManipulator> mainManipulator = new osgEarth::Util::EarthManipulator;
viewer.setCameraManipulator(mainManipulator); osgEarth::Viewpoint vp;
osgEarth::GeoPoint newPoint(map->getSRS(), 108.9594, 34.2196, 0);
vp.focalPoint() = newPoint;
vp.heading() = 0;
vp.pitch() = -90;
vp.range() = 1000;
mainManipulator->setViewpoint(vp); viewer.setUpViewInWindow(100, 100, 800, 600); return viewer.run();
}

运行结果如下:

4. 参考

  1. GNSS学习笔记-坐标转换

osgEarth使用笔记3——加载倾斜摄影数据的更多相关文章

  1. Cesium加载倾斜摄影数据

    (1)倾斜摄影数据仅支持 smart3d 格式的 osgb 组织方式, 数据目录必须有一个 “Data” 目录的总入口, “Data” 目录同级放置一个 metadata.xml 文件用来记录模型的位 ...

  2. osgEarth使用笔记4——加载矢量数据

    目录 1. 概述 2. 详论 2.1. 基本绘制 2.2. 矢量符号化 2.2.1. 可见性 2.2.2. 高度设置 2.2.3. 符号化 2.2.4. 显示标注 2.3. 其他 3. 结果 4. 问 ...

  3. OSG加载倾斜摄影数据

    目录 1. 概述 2. 实例 2.1. 代码 2.2. 解析 3. 结果 1. 概述 ContextCapture(Smart3D)生成的倾斜摄影模型数据一般都形如如下组织结构: 在Data目录下包含 ...

  4. 笔记-VUE滚动加载更多数据

    来源:https://blog.csdn.net/qq_17281881/article/details/87342403 VUE滚动加载更多数据 data() { return { loading: ...

  5. 配置vuejs加载模拟数据

    [个人笔记,非技术博客] 1.使用前确保安装axios插件,vuejs官方推荐,当然使用其他插件也可以 2.配置dev-server.js var router = express.Router(); ...

  6. geotrellis使用(二十三)动态加载时间序列数据

    目录 前言 实现方法 总结 一.前言        今天要介绍的绝对是华丽的干货.比如我们从互联网上下载到了一系列(每天或者月平均等)的MODIS数据,我们怎么能够对比同一区域不同时间的数据情况,采用 ...

  7. WPF DataGrid 性能加载大数据

    WPF(Windows Presentation Foundation)应用程序在没有图形加速设备的机器上运行速度很慢是个公开的秘密,给用户的感觉是它太吃资源了,WPF程序的性能和硬件确实有很大的关系 ...

  8. 基于zepto的H5/移动端tab切换触摸拖动加载更多数据

    以前实现移动端的滑动加载更多实现的方法是当滚动条快到页面底部时就自动加载更多的数据,在这方面很多人都用的是"西门的后花园"写的一个叫dropload的插件,这个插件用起来也很好,很 ...

  9. iOS --- UIWebView的加载本地数据的三种方式

    UIWebView是IOS内置的浏览器,可以浏览网页,打开文档  html/htm  pdf   docx  txt等格式的文件.  safari浏览器就是通过UIWebView做的. 服务器将MIM ...

  10. jQuery.ajax( options ) : 通过 HTTP 请求加载远程数据

    jQuery.ajax( options ) : 通过 HTTP 请求加载远程数据 这个是jQuery 的底层 AJAX 实现.简单易用的高层实现见 $.get, $.post 等. $.ajax() ...

随机推荐

  1. mysql语句操作

    1.从login表中选出name字段包含admin的前10条结果所有信息的sql语句 select  * from login where name like %admin% limit 0 ,10; ...

  2. 大语言模型基础-Transformer模型详解和训练

    一.Transformer概述 Transformer是由谷歌在17年提出并应用于神经机器翻译的seq2seq模型,其结构完全通过自注意力机制完成对源语言序列和目标语言序列的全局依赖建模. Trans ...

  3. 未能添加SSL证书,错误1312

    1.win+r打开运行,输入mmc 2.在控制台1[控制台根节点]->文件->添加/删除....->选择证书->添加-选择计算机账户->完成->确认 3.找到证书文 ...

  4. CF223B Two Strings 题解

    题目链接 题目分析 题目很短,只有两句话,可分析的不多,似乎难以入手,我们不妨换一个思路转化一下题意,改为:是否对于 \(s\) 中的每一个字符,总有一个等于 \(t\) 的 \(s\) 的子序列覆盖 ...

  5. MySQL简易教程

    本文是参考廖雪峰老师的,但是网站广告有点多,我就在本地抄写一份,一方面是为了加强记忆巩固基础,另一方面也是就是为了第一方面.廖雪峰老师Mysql教程直达地址:https://www.liaoxuefe ...

  6. 容器Cgroup和Namespace特性简介

    一般来说,容器技术主要包括Cgroup和Namespace这两个内核特性.Cgroup Cgroup是control group,又称为控制组,它主要是做资源控制.原理是将一组进程放在放在一个控制组里 ...

  7. Vue一些进阶知识-基于官网(笔记)

    前言 主要根据vue官网文档完成.对一些平时可能会用到的知识.组件进行收集,为的是对vue的可用性有一个大致的了解.博客中的组件介绍可能只涉及简单用法,完整用法还是以官网为准. 基础 启动过程: 主文 ...

  8. [CTF/Web] PHP 反序列化学习笔记

    Serialize & unserialize 这两个方法为 PHP 中的方法, 参见 serialize 和 unserialize 的官方文档. 以下内容中可能存在 字段, 属性, 成员 ...

  9. 基于Browscap对浏览器工具类优化

    项目背景 原有的启动平台公共组件库comm-util的浏览器工具类BrowserUtils是基于UserAgentUtils的,但是该项目最后一个版本发布于 2018/01/24,之至今日23年底,已 ...

  10. CSS(不定时更新)

    一.使用img后的高度多了4px 由于img是行内元素,默认display: inline; 它与文本的默认行为类似,下边缘是与基线(baseline)对齐,而不是紧贴容器下边缘. 将displayp ...