osgEarth是基于三维引擎osg开发的三维数字地球引擎库,在osg基础上实现了瓦片调度插件,可选的四叉树调度插件,更多的地理数据加载插件(包括GDAL,ogr,WMS,TMS,VPB,filesystem等),再结合一套地理投影转换插件,这样就能够实现高效处理加载调度地理数据在三维地球上的显示,实现三维虚拟地球。

想要实现一个简单的基于osgEarth的三维地球,有两种方式,这两种方式是互通的。一种基于XML标签的earth文件加载,另外一种是采用C++代码,本质是一样的,osgEarth内部支持直接解析XML标签文件,转换为代码实现,具体参考tests文件夹例子,代码则参考application下面例子。但是大多数情况下,你需要更灵活掌控性更强的代码来实现功能,因为只有一个加载了基础数据的三维地球是只能看,不能解决实际问题的,需要界面通常采用QT,更多的三维渲染和仿真业务则由osg来完成。因此学好osg是做这一切的基础。

osgEarth的特点:支持加载常见的栅格数据(影像和DEM),但是大数据必须建立金字塔,设置为地理投影,想要高效率最好处理为瓦片,这样也便于部署在服务端。矢量数据,最好尽可能的简化,因为大的矢量会十分影响渲染速度,当然也可以对矢量栅格化处理加快速度,对于模型的话,大数据量一定要做LOD或者pageLod。

osgEarth程序的常规流程:

创建osgViewer---->创建MapNode---->设置Earth操作器---->设置场景参数----->run

MapNode是继承自osg的Node,是osgEarth中地球节点,你所添加的影像,DEM,模型都包含在MapNode中,因为它们都加入到Map中,Map则类似二维中的Map可以添加各种图层。剩余的不管是模型节点Node,或者是标注Node,还是其他的都是可以直接添加到MapNode中或者另外的Group中。

Earth操作器则和其他osg操作器一样,只不过专门为三维地球浏览定制,具体参数可以设置。

场景参数则主要有自动地形裁剪,最小裁剪像素等其他优化场景的参数。

下面就简单阐述一个小例子说明:

代码功能主要实现了查询实时高程,并显示XYZ坐标的功能。

使用命令app.exe test.earth即可得到下面的效果。

//引入osg和osgEarth的头文件和命名空间
#include <osgGA/StateSetManipulator>
#include <osgGA/GUIEventHandler>
#include <osgViewer/Viewer>
#include <osgViewer/ViewerEventHandlers>
#include <osgUtil/LineSegmentIntersector>
#include <osgEarth/MapNode>
#include <osgEarth/TerrainEngineNode>
#include <osgEarth/ElevationQuery>
#include <osgEarth/StringUtils>
#include <osgEarth/Terrain>
#include <osgEarthUtil/EarthManipulator>
#include <osgEarthUtil/Controls>
#include <osgEarthUtil/LatLongFormatter>
#include <iomanip>using namespace osgEarth;
using namespace osgEarth::Util;
using namespace osgEarth::Util::Controls;static MapNode*       s_mapNode     = 0L;
static LabelControl*  s_posLabel    = 0L;
static LabelControl*  s_vdaLabel    = 0L;
static LabelControl*  s_mslLabel    = 0L;
static LabelControl*  s_haeLabel    = 0L;
static LabelControl*  s_mapLabel    = 0L;
static LabelControl*  s_resLabel    = 0L;// An event handler that will print out the elevation at the clicked point
//查询高程的一个事件回调,在场景有事件更新触发时调用,详细参考osg或者osgGA::GUIEventHandler
struct QueryElevationHandler : public osgGA::GUIEventHandler
{
//构造函数
QueryElevationHandler()
: _mouseDown( false ),
_terrain  ( s_mapNode->getTerrain() ),
_query    ( s_mapNode->getMap() )
{
_map = s_mapNode->getMap();//初始化最大查询LOD级别
_query.setMaxTilesToCache(10);_path.push_back( s_mapNode->getTerrainEngine() );
}
//更新回调,具体的内容可以参考父类,传进来的参数是屏幕坐标xy,和osgViewer
void update( float x, float y, osgViewer::View* view )
{
bool yes = false;// look under the mouse:
//采用线去对地球做碰撞检测,根据鼠标点击点去检测,得到交点,就是当前点的xyz
osg::Vec3d world;
osgUtil::LineSegmentIntersector::Intersections hits;
//判断求交结果是否为空
if ( view->computeIntersections(x, y, hits) )
{
//得到世界坐标系下面的坐标,就是osg的xyz坐标
world = hits.begin()->getWorldIntersectPoint();// convert to map coords:
//将其转换为地球的地理坐标,转换方法都照抄即可
GeoPoint mapPoint;
mapPoint.fromWorld( _terrain->getSRS(), world );// do an elevation query:
double query_resolution = 0; // 1/10th of a degree
double out_hamsl        = 0.0;
double out_resolution   = 0.0;//根据输入参数查询当前点位置的高程,需要设置分辨率,就是查询精度
bool ok = _query.getElevation(
mapPoint,
out_hamsl,
query_resolution,
&out_resolution );//如果查询成功
if ( ok )
{
// convert to geodetic to get the HAE:
mapPoint.z() = out_hamsl;
GeoPoint mapPointGeodetic( s_mapNode->getMapSRS()->getGeodeticSRS(), mapPoint );//经纬度坐标的格式化工具,也可以自己用字符串去拼接xyz数字
static LatLongFormatter s_f;//更新显示的xyz值,label是传入的控件
s_posLabel->setText( Stringify()
<< std::fixed << std::setprecision(2)
<< s_f.format(mapPointGeodetic.y())
<< ", "
<< s_f.format(mapPointGeodetic.x()) );//还可以输出分辨率,椭球体信息等
s_mslLabel->setText( Stringify() << out_hamsl );
s_haeLabel->setText( Stringify() << mapPointGeodetic.z() );
s_resLabel->setText( Stringify() << out_resolution );yes = true;
}// finally, get a normal ISECT HAE point.
GeoPoint isectPoint;
isectPoint.fromWorld( _terrain->getSRS()->getGeodeticSRS(), world );
s_mapLabel->setText( Stringify() << isectPoint.alt() );
}//如果查询不到高程的话
if (!yes)
{
s_posLabel->setText( "-" );
s_mslLabel->setText( "-" );
s_haeLabel->setText( "-" );
s_resLabel->setText( "-" );
}
}//参数一个是事件的动作,另外一个是对应的操作
bool handle( const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa )
{
//判断如果是移动鼠标事件才进行更新当前的坐标显示
if (ea.getEventType() == osgGA::GUIEventAdapter::MOVE &&
aa.asView()->getFrameStamp()->getFrameNumber() % 10 == 0)
{
osgViewer::View* view = static_cast<osgViewer::View*>(aa.asView());
update( ea.getX(), ea.getY(), view );
}return false;
}//Map对象
const Map*       _map;
//地形对象
const Terrain*   _terrain;
bool             _mouseDown;
//查询高程使用的对象
ElevationQuery   _query;
osg::NodePath    _path;
};//main函数,
int main(int argc, char** argv)
{
//这儿两个参数,第一个是命令参数的个数为,后面是字符串数组输入earth文件的路径osg::ArgumentParser arguments(&argc,argv);//osg的场景
osgViewer::Viewer viewer(arguments);
//构造MapNode,arguments里面有earth文件的路径,命令行输入
s_mapNode = MapNode::load(arguments);
//如果路径不正确或者earth文件错误,没有构造好MapNode
if ( !s_mapNode )
{
OE_WARN << "Unable to load earth file." << std::endl;
return -1;
}
//建立一个组节点
osg::Group* root = new osg::Group();
//将组节点设置为场景节点
viewer.setSceneData( root );// install the programmable manipulator.
//设置earth操作器
viewer.setCameraManipulator( new osgEarth::Util::EarthManipulator() );// The MapNode will render the Map object in the scene graph.
//将MapNode添加到组节点中去
root->addChild( s_mapNode );//下面是设置一个控件,grid的意思是用格网去布局里面的小控件
// Make the readout:
Grid* grid = new Grid();
//设置几个Label文字控件显示在场景中的第行
grid->setControl(0,0,new LabelControl("Coords (Lat, Long):"));
grid->setControl(0,1,new LabelControl("Vertical Datum:"));
grid->setControl(0,2,new LabelControl("Height (MSL):"));
grid->setControl(0,3,new LabelControl("Height (HAE):"));
grid->setControl(0,4,new LabelControl("Isect  (HAE):"));
grid->setControl(0,5,new LabelControl("Resolution:"));
//设置几个Label文字控件显示在场景中的第行
s_posLabel = grid->setControl(1,0,new LabelControl(""));
s_vdaLabel = grid->setControl(1,1,new LabelControl(""));
s_mslLabel = grid->setControl(1,2,new LabelControl(""));
s_haeLabel = grid->setControl(1,3,new LabelControl(""));
s_mapLabel = grid->setControl(1,4,new LabelControl(""));
s_resLabel = grid->setControl(1,5,new LabelControl(""));//得到空间参考,椭球面信息,并显示对应上面的label
const SpatialReference* mapSRS = s_mapNode->getMapSRS();
s_vdaLabel->setText( mapSRS->getVerticalDatum() ?
mapSRS->getVerticalDatum()->getName() :
Stringify() << "geodetic (" << mapSRS->getEllipsoid()->getName() << ")" );//控件绘制容器
ControlCanvas* canvas = new ControlCanvas();
//将要显示的控件加入到root组节点中去
root->addChild(canvas);
canvas->addControl( grid );//添加刚刚自定义的查询高程的事件回调
// An event handler that will respond to mouse clicks:
viewer.addEventHandler( new QueryElevationHandler() );
//添加状态显示,窗口改变等事件回调
// add some stock OSG handlers:
viewer.addEventHandler(new osgViewer::StatsHandler());
viewer.addEventHandler(new osgViewer::WindowSizeHandler());
viewer.addEventHandler(new osgGA::StateSetManipulator(viewer.getCamera()->getOrCreateStateSet()));//run
return viewer.run();
}

osgEarth测高程方法相关推荐

  1. cad文字提取到excel_干货!南方CASS设计土石方方格网点上提取高程方法

    想把CASS土方方格网上的设计高程批量导出(主要是横坡不是固定的坡比,且面积很大). 网上的插件难找,要不就是另装一个软件,但是只为了导一次数据,装软件太麻烦了. 其实,我们可以换一个思路.设计高程标 ...

  2. 数字测图原理与方法的实习日志_【技术】消费级无人机倾斜摄影测量1:500测图方法及精度研究...

    摘要:针对多镜头测绘级无人机价格昂贵.技术门槛较高的问题,本文提出利用消费级无人机获取的倾斜影像制作大比例尺地形图的方法.该方法运用消费级单镜头无人机,在RTK(real-timekinematic) ...

  3. matlab火焰测温源程序,一种火焰测温方法与流程

    本发明涉及一种测量火焰温度的方法. 背景技术: 火焰是气态的且正在发生剧烈氧化反应的燃料及各种中间产物及最终产物的混合物.在煤化工.化工领域,在高温.高压反应器(或气化炉)上,火焰检测器一般安装在气化 ...

  4. 网线传输速度测试_网络传输速率及测速方法

    网络传输速率概述根据国家颁布的通信行业标准,固定宽带4M/6M/12M/20M产品及3G网络21M/42M产品公布的速率均是指数据单位比特/秒(bps),而平常用户上网软件或者下载速度指的是字节/秒( ...

  5. 云计算 码率适配限速_一种基于云计算的应用于用户终端的测速方法

    一种基于云计算的应用于用户终端的测速方法 [专利摘要]本发明提供一种基于云计算的应用于用户终端的测速方法,包括:建立测速机制,定义相关参数,测速方法,输出测速结果:具体包括:建立测速机制,定义相关参数 ...

  6. 雷达测角方法(MUSIC ESPRIT)

    雷达测角方法(MUSIC ESPRIT)) MUSIC测角 圆阵MUSIC测角仿真 圆阵MUSIC解相干仿真 极化圆阵MUSIC测角 ESPRIT测角 圆阵ESPRIT测角 圆阵ESPRIT测角仿真 ...

  7. linux内核下网络驱动流程,基于Linux内核驱动的网络带宽测速方法与流程

    本发明涉及一种测速方法,尤其是一种网络带宽测速方法. 背景技术: :电信运营商为客户提供一定带宽的Internet接入:为了检验带宽是否达标,一般均由客户使用个人电脑在网页上直接测速.但是随着智能网关 ...

  8. 常用条码打印机测纸方法

    最近经常有朋友问及自己的条码打印机一开机就亮红灯,一打印就亮报错,无法进行正常打印,造成这种情况的原因是打印机感测不干胶标签所表现出的情况. 不干胶标签一般有3种类型,间隙型.连续型.黑标型,最常用的 ...

  9. 雷达测角方法(DBF测角、干涉测角(长短基线))matlab

    雷达测角方法(DBF测角.干涉测角(长短基线)) DBF测角 实验仿真 干涉测角 长短基线 相位差解模糊 实验仿真 五元均匀圆阵干涉测角(需要私,这部分实在懒得更新了) 代码私信 DBF测角 根据波束 ...

最新文章

  1. java 简单阻塞队列,制作一个简单的任务队列(使用阻塞队列)
  2. 机器学习基础(四十七)—— 统计
  3. 韩顺平--Java坦克大战
  4. 【毕业设计】基于stm32的万能红外遥控器 - 单片机 嵌入式 物联网
  5. springboot导出pdf文件(简历)
  6. PASCAL 高级编程
  7. Nvidia Jetson deepstream配置多路RTSP视频源
  8. (转)国企,私企与外企利弊通观--关键时刻给应届毕业生及时点拨5
  9. matlab失明的小猫,从小失明的小猫,手术后第一次见到猫妈妈,场面让人泪崩!...
  10. java ice开发_ice开发流程(一)
  11. 公交门户分析与统计系统
  12. 干货 | 这些年,我用的绘图工具大合集
  13. Redis集群(Cluster)
  14. 戴尔win10桌面 计算机,戴尔笔记本上win10的计算器在哪
  15. 乳腺仿体breast phantom的MATLAB实现及探讨
  16. 淘宝的ITEST框架
  17. 编程和数学基础不佳如何入门人工智能?
  18. 3D打印的各种问题及解决方案
  19. 自动取片机EMC测试,电磁兼容EMC整改,YY0505预测测试报告
  20. 科讯CMS----标签大全

热门文章

  1. 【ArcGIS微课1000例】0053:注记(水平、沿直线、跟随要素、牵引线、弯曲注记)的创建与编辑
  2. 手机短信验证码开发流程
  3. 面向对象分析与设计--遛狗玩
  4. C语言打印乘法口诀表
  5. 微星GE62 2QC-264XCN刷黑苹果详细教程亲测有效,完美双系统,双屏!
  6. 初始化之前使寄存器恢复缺省值的重要性
  7. Java图形化GUI界面
  8. OpenGL初探:二维卡通人物交互设计
  9. fluent-mybatis初体验
  10. PE、PM、PD、PR分别是什么岗位?