osgEarth::Drivers::TMSOptions Class Reference通过程序加载数据
赶紧进⼊正题,程序加载各种数据,⾸先介绍⼀下总体的⽅式
/*这⾥XXXOptions 是根据不同的数据类型选择不同驱动,⽐如加载本地数据可以使⽤GDALOptions ,加载TMS数据可以使⽤TMSOptions(注意TMSOptions可以加载本地也可以加载⽹上数据),WMSOptions可以加载⽹上数据(注意这个options主要加载影像和图⽚数据),ArcGISOptions加载ArcGIS Server发布数据。*/osgEarth::Drivers::XXXOptions XXXLayer;
/*这⾥就是加载的数据路径,如果加载的本地数据就是本地数据的路径,如果加载是⽹上数据就是相应的⽹址*/XXXLayer.url()=osgEarth::URI(\".................................\");
/*加载的数据是分层管理,每加载进来⼀个数据在earth上就是⼀个数据层,这⾥给数据层付个名字。*/std::string LayerName=\"earth\";
/*osgearth⾥layer主要有三种类型ImageLayer、ElevationLayer和ModleLayer ,前两个⼤家从字⾯就可以知道第⼀个是加载影像和第⼆个是加载⾼程数据的,第三个是主要⽤来加载shp数据,⾄少我是这样⽤的,不知道还能否加载其他数据类型。确定加载⽤的驱动、数据源位置(路径)、数据层名和初始化了数据层,接下来就是把数据层加到地球中如下所⽰。*/osg::ref_ptr layer =new osgEarth::XXXLayer(osgEarth::XXXLayerOptions(LayerName,XXXLayer));m_pMap->addImageLayer(layer.get());(1)加载本地数据
a 本地影像数据,数据类型为tif
osgEarth::Drivers::GDALOptions imagelayerOpt;//选择GDALOptions
imagelayerOpt.url() = osgEarth::URI(\"E:\\\\vs2010Progam Files\\\\osgVR74\\\\osgVR74\\\\world.tif\");//影像数据路径std::string imagelayerName = \"worldimage\"; //影像数据层名
osg::ref_ptr imageLayer = new osgEarth::ImageLayer(osgEarth::ImageLayerOptions(imagelayerName ,imagelayerOpt));//初始数据层
m_pMap->addImageLayer(imageLayer .get());b 本地⾼程数据,数据类型为tif
osgEarth::Drivers::GDALOptions demlayerOpt;//使⽤还是GDALOptions
demlayerOpt.url() = osgEarth::URI(\"E:\\\\vs2010Progam Files\\\\osgVR74\\\\osgVR74\\\\worlddem.tif\");//⾼程数据路径std::string demlayerName = \"worlddem\";//⾼程数据层名
osg::ref_ptr demLayer = new osgEarth::ImageLayer(osgEarth::ImageLayerOptions(demlayerName,demlayerOpt));//初始数据层
m_pMap->addImageLayer(demLayer.get());
加载本地经过package 切⽚的数据还可以⽤TMSOptions,osgEarth::Drivers::TMSOptions tmsOpt;////选择TMSOptions 驱动tmsOpt.url()=osgEarth::URI(\"//Edvis_-1/Layer_0/tms.xml\");//package切⽚⽣成⾦字塔⽂件下的xml
std::stringDemtmslayerName=\"TmsDem\";//图层名
osgEarth::ElevationLayerOptionstmslayerOpt(DemtmslayerName,tmsOpt);osg::ref_ptr TmsDemLayer = new osgEarth::ElevationLayer(tmslayerOpt);m_pMap->addElevationLayer(TmsDemLayer.get());//初始化图层并加⼊到地球中(2)加载⽹上数据
a 加载ArcGIS Server 发布的数据加载⽅式与上⾯提到的类似osgEarth::Drivers::ArcGISOptions MapImageLayer;
MapImageLayer.url()=osgEarth::URI(\"http://xxx.xxx.xxx.xxx.:xxxx/arcgis/rest/services/world/ma p003/MapServer\");std::string CdlayerName=\"worldimage\";
osg::ref_ptr cdlayer =new osgEarth::ImageLayer(osgEarth::ImageLayerOptions(CdlayerName,MapImageLayer));m_pMap->addImageLayer(cdlayer.get());
//这⾥注意,当osgearth访问ArcGIS Server 发布数据的时候有些问题很奇怪,⽤上⾯的⽅式访问ArcGIS Server 国外发布的数据没问题,但是访问⾃⼰发布的数据就会有问题,经过试验投影要设成3857才能正常访问。b 加载⽹上数据还可以⽤WMSOptions 加载⽅式同上。2015/12/14
1.osgEarth::Util::MapNodeHelper.解析内部的命令⾏参数。
⾮静态成员变量不能使⽤类名直接访问。例如:osgEarth::Util::MapNodeHelper:: load()这样的形式是错误的。
osg::Group * load (osg::ArgumentParser &args, osgViewer::View *view, Control *userControl=0L) const函数是载⼊map⽂件,解析所有的内部命令⾏参数与外部的XML⽂件。2. osgEarth::MapNode。建⽴OsgEarth的根节点。
3. osgEarth::Util::Controls::Grid. 此类是⽗类Container按照栅格形式组织⼦类。4. osgEarth::Util::Controls::LabelControl.表⽰⼀个字符串的控件。2015/12/15
1.void osgViewer::View::setCameraManipulator ( osgGA::CameraManipulator * manipulator, bool resetPosition = true )设置相机操作器。
OsgViewer::Viewer的继承关系如下图所⽰。
视图-View;视景器-Viewer。osgViewer::View类别
2015/12/17
1.osgGA::GUIEventHandler为GUI事件提供⼀个基本的接⼝。
2.osgEarth::Map map是mapNode所渲染的主要的数据模型,包括所有的层对象。3. osgEarth::Terrain 是为地形图的接⼝服务的
4 .osgEarth::ElevationQuery 查询地图上任意点的⾼程数据5. osgEarth::GeoPoint2015/12/20
1. osg::ArgumentParser 解析参数的类。
2. osgEarth::Annotation::ModelNode。从URI传递⼀个3D模型(注释节点)然后放置在⼀个地理节点。2015/12/21
动态显⽰经纬度坐标以及⾼程⽅法
1. osgEarth::SpatialReference Class.保留描述参考椭球体和地理空间数据的投影的相关数据。2.osgEarth::MapNode Class 中的函数const SpatialReference * MapNode::getMapSRS()const.得到地图的地理空间参考系统。
3.osgEarth::Util::Controls:: ControlCanvas Class。将控件与OSG视景相关联。
4. osgGA::GUIEventHandler 为GUI事件提供⼀个基本的接⼝。在这个类的基础上,派⽣了其他的类,⽐如在⾼程与经纬度查询的osgViewer::StatsHandler类(为了增加屏幕状态到视景体的事件句柄),osgViewer::WindowSizeHandler类(改变窗⼝模式的屏幕分辨率和开关全屏模式和窗⼝模式的事件句柄),osgGA::StateSetManipulator类(实验类,不能被观察⼀段时间,但是能够返回到某个点)。5.动态显⽰经纬度和⾼程经纬度查询的机制。
主要是利⽤碰撞检测机制,⿏标点在⼆维的屏幕上的坐标,然后利⽤碰撞检测求得世界坐标X,Y,Z,然后再将世界坐标转换成与地理相关的三维坐标,然后再将此地理三维坐标转换成与经纬度有关的坐标。重写handle函数。
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(aa.asView());update( ea.getX(), ea.getY(), view );}
return false;}
其中的osgGA::GUIEventAdapter类是存储键盘,⿏标和窗⼝事件。osgGA::GUIActionAdapter 是抽象基类,它定义了GUIEventHandlers事件句柄将要访问GUI的接⼝。然后调⽤相应的更新函数update();
void update( float x, float y, osgViewer::View* view ){
bool yes = false;// look under the mouse:osg::Vec3d world;
osgUtil::LineSegmentIntersector::Intersections hits;if ( view->computeIntersections(x, y, hits) ){
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 degreedouble 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 );static LatLongFormatter s_f;s_posLabel->setText( Stringify()<< std::fixed << std::setprecision(2)<< s_f.format(mapPointGeodetic.y(), true)<< \
<< s_f.format(mapPointGeodetic.x(), false) );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( \"-\" );}}
其中的osgUtil::LineSegmentIntersector是直线与场景图交点的实体类。
⽽其中的hits是多集。因为typedef std::multiset
osgUtil::LineSegmentIntersector::Intersections,osgUtil::LineSegmentIntersector::Intersections hits。
然后计算交点的三维坐标值:view->computeIntersections(x, y, hits)。将此交点转换成世界坐标X,Y,Z:world = hits.begin()->getWorldIntersectPoint(),再将世界坐标转换成地理相关的三维坐标:GeoPoint mapPoint; mapPoint.fromWorld( _terrain->getSRS(), world );然后进⾏⾼程的查询:
bool ok = _query.getElevation( mapPoint,out_hamsl,query_resolution,&out_resolution );然后再重新构建地理坐标:
GeoPoint mapPointGeodetic( s_mapNode->getMapSRS()->getGeodeticSRS(), mapPoint );此处对getSRS,getMapSRS以及getGeodeticSRS进⾏区别。
getSRS():得到与地形相关的地图的空间参照系。它是osgEarth::Terrain 类的成员函数。此类表⽰与现场地形图的交互服务。它跟Map model(地图模型)不同,地图代表了地形参数的数据⽀持,⽽Terrian代表了内存中实际的⼏何图形。通过getSRS()得到的空间参考系是以单元组织的地图坐标值。
getMapSRS():得到地图的空间参照系。它是osgEarth::MapNode类的成员函数。此类主要是利⽤osg中的node建⽴osgearth中map的根节点。
getGeodeticSRS():得到当前空间参照系的地理空间参照系。它是osgEarth::SpatialReference 类的成员函数。osgEarth::SpatialReference类是SpatialReference持有描述参考椭球体/数据的信息和地理空间数据的投影。然后将得到的地理三维坐标转换成经纬度:
static LatLongFormatter s_f; s_f.format(mapPointGeodetic.y(), true);s_f.format(mapPointGeodetic.x(), false)。最好得到相应的法线与椭球体的交点:GeoPoint isectPoint;
isectPoint.fromWorld( _terrain->getSRS()->getGeodeticSRS(), world );2015/12/221.坐标系统的区别世界坐标系:
世界坐标系是⼀个特殊的坐标系统,它建⽴了描述其他坐标系所需的参考框架。它可以⽤来描述其他的坐标系的位置。它能够
描述整个场景中的所有对象。世界坐标系的位置是绝对的,它为所有对象的位置提供⼀个绝对的参考标准,从⽽避免物体之间的独⽴的坐标系统之间的混乱。物体坐标系:
物体坐标是每个物体特定的坐标系,因为每个对象包含了顶点坐标以及其纹理坐标等,如果每个坐标都相对于世界坐标来进⾏变换将会⾮常困难,⽽且坐标的精度也不够⾼,如果每个对象都建⽴⾃⼰的物体坐标系,⽽只需通过物体坐标系相对于世界坐标系的变换即可描述物体的。摄像机坐标系:
摄像机坐标系是和观察者密切相关的坐标系,摄像机坐标系和屏幕坐标系相似,差别在于摄像机坐标系处于3D空间中。它可视为特殊的物体坐标,该物体坐标系统定义在摄像机的屏幕区域。摄像机坐标系描述的是哪些物体应该渲染并显⽰在屏幕上,主要包括物体是否在摄像机坐标区域内,物体的渲染顺序和物体的遮挡渲染等。2015/12/23
1.osgEarth::TileSource2015/12/24
1.osgEarth::ProgressCallback 是⼀个通⽤接⼝类,针对函数进⾏进程的报告。2. osg::Image Class。封装存储的纹理图像数据。
3. osgEarth::TileKey类.相对于轮廓,唯⼀的标识地图上的⽡⽚数据。轮廓从左上⾓的0,0点开始4. osgEarth::Symbology::GeometryRasterizer。使⽤软件渲染路径将⼏何图形绘制到画布上。5. osgEarth::ImageLayerOptions 。初始化图像层的选项2015/12/25
1.osgEarth::HTTPClient Class 。⼯具类的HTTP访问
2. osgDB::Registry。注册表是⼀个单例的⼯⼚模式,存储运⾏时读取的⾮内部⽂件。3. osgEarth::Bounds Class 。表⽰匿名的边界。2015/12/27
1. osgEarth::Drivers::OGRFeatureOptions 。2. osgEarth::Features::FeatureSource。2015/12/29
1. osgEarth::Util::EarthManipulator Class。可编程的操作器,适⽤于使⽤地理地形2.
解读osgViewer/ViewerBase.cpp中的osgViewer::ViewerBase::frame()。在这个函数中主要有5个过程:
1)、如果这是仿真系统启动后的第⼀帧,则执⾏viewerInit();此时如果还没有执⾏realize()函数,则执⾏它。2)、执⾏advance 函数。
3)、执⾏eventTraversal 函数,顾名思义,这个函数将负责处理系统产⽣的各种事件,诸
如⿏标的移动,点击,键盘的响应,窗⼝的关闭等等,以及摄像机与场景图形的事件回调(EventCallback)。
4)、执⾏updateTraversal 函数,这个函数负责遍历所有的更新回(UpdateCallback);除此之外,它的另⼀个重要任务就是负责更新DatabasePager 与ImagePager 这两个重要的分页数据处理组件。
5)、执⾏renderingTraversals 函数,这⾥将使⽤较为复杂的线程处理⽅法,完成场景的筛
下⾯对viewerInit()这个函数进⾏解读。它就是调⽤View::init()函数。View::init 函数中出现了两个重要的类成员变量:_eventQueue和_cameraManipulator,并且还将⼀个osgGA::GUIEventAdapter 的实例传⼊后者的初始化函数。
代码如下:
osg::ref_ptr initEvent = _eventQueue->createEvent();initEvent->setEventType(osgGA::GUIEventAdapter::FRAME);if (_cameraManipulator.valid()){
_cameraManipulator->init(*initEvent, *this);}
_eventQueue是存储该视景器的事件队列。OSG中代表事件的类是
osgGA::GUIEventAdapter,它可以⽤于表达各种类型的⿏标、键盘、触压笔和窗⼝事件。重写handle函数的⽅法,获取实时的⿏标/键盘输⼊,并进⽽实现相应的⽤户代码。_cameraManipulator就是视景器中所⽤的场景漫游器的实例。⼀般的情况下是通过setCameraManipulator来进⾏场景漫游器的设置,⽽如果要⾃定义相应的场景漫游器,我们通过覆写并使⽤osgGA::MatrixManipulator::init 就可以灵活地初始化⾃定义漫游器的功能。
因此在viewerInit()函数中的调⽤关系如下图所⽰:osgViewer::Viewer::viewerInit函数调⽤osgViewer::View::init,在init函数中调⽤osgGA::EventQueue::createEvent来创建事件的列表,同时通过osgGA::MatrixManipulator::init来对场景的漫游器进⾏操作。
2015/12/301.加载⽮量图
如何通过EarthFile⽂件创建地图。Earth File 的核⼼作⽤是指明以下3 点:1.你创建的地图类型(geocentric 或projected)2.可使⽤的图像、三⾯图elevation、⽮量和模型数据3.你的数据缓存在哪⾥
earthFile中可以加载简单的图像层,可以加载多重图像层次,将多个image元素加到earthFile ⽂件中。在加载多重图像层的时候,需要指定相应的顺序,定义多个图像源时,它们在该earth ⽂件中指定的顺序是从在底部到顶部的。OsgEarth中加载⽮量数据,Feature Geometry OSG的⼏何渲染⽮量数据。
元素定义了⼀个⽮量数据源,渲染⽮量特征数据的模型层要求⼀个特征源。name可读的特征数据源名称。如果您使⽤全局样式设置所要渲染的特征数据的外观,那么这个名字,样式将要使⽤到。driver 读取特征数据的驱动插件名称。2016/1/4
1.Osgearth_package 打包输出数据
1>OsgDB中的std::string concatPaths(const std::string& left, const std::string& right);这个函数的作⽤是将两个路径连接起来。
2>osgEarth::ImageLayer Class。表⽰包含位图数据的地图地形层。它的继承关系如下图:
3>osgEarth::ElevationLayer Class.表⽰包含⾼程⽹格的地图地形层。继承关系如下:
4>osgEarth::Util::TMSPackager Class。此类的作⽤是从imageLayer和elevationLayer中读取⽡⽚数据,然后基于磁盘⽡⽚资源库将⽡⽚数据存储起来。
此类中的函数void TMSPackager::run( TerrainLayer* layer, Map* map )起着⾄关重要的作⽤。下⾯对这个函数进⾏详细的分析。
void TMSPackager::run( TerrainLayer* layer, Map* map )
此函数主要是从基本的TileKey获得图像数据。此函数的主要过程如下所⽰:第⼀步是获取所有的root TileKey.std::vector rootKeys;
map->getProfile()->getRootKeys( rootKeys );第⼆步是获取⽡⽚,弄清楚图像的尺⼨⼤⼩。ImageLayer* imageLayer = dynamic_cast(layer);ElevationLayer* elevationLayer = dynamic_cast(layer);
这⾥是利⽤dynamic_cast进⾏基类的指针转换到⼦类的指针,转换过程中进⾏动态类型检查,⽐static_cast向下转换更加安全。
第三步是如果层的名字存在则直接读取,否则设置⼀个默认的名字。
其中分别就imageLayer和elevationLayer来进⾏判断,得到相应的⽂件的后缀名,来设置⽡⽚的⼤⼩。最后⼀步是设置TMS处理器handler。在初始化时⽤到了类:
osgEarth::Util::WriteTMSTileHandler Class。此类是TMS处理器,按照TMS格式从层中输出⽡⽚数据,并按照TMS结构封装⽡⽚数据。此类的继承关系如下图所⽰:
_handler = new WriteTMSTileHandler(layer, map, this);构造了handler之后就是初始化TileVisitor。
osgEarth::TileVisitor Class。此类是⼯具类,它遍历概要⽂件且发出基于扩展名和层级⼤⼩的TileKey.
5>osgEarth::Drivers::TMSOptions Class。⽗类osgEarth::TileSourceOptions是构建⽡⽚源驱动的选项。它被其他的
osgEarth::Drivers::xxxOption继承。此处的TMSOption的作⽤是获取与设置TMS相应的选项。附:TMS(Tile Map Service)是⼀种地理栅格数据组织⽅式,适⽤于⾦字塔状组织⽅式。
6>osgEarth::ImageLayerOptions Class。此类是初始化影像层的Option,它能够设置ImageLayerOptions相应的属性。⽐如透明度,可视范围,透明颜⾊,LOD混合等。
7>osgEarth::ElevationLayerOptions Class。此类是初始化ElevationLayer的属性和选项。此类的继承关系如下图:
8>osgEarth::MapNodeOptions Class。此类是构建运⾏时的map节点。它的继承关系如下图所⽰。
最终是输出earth⽂件,
因篇幅问题不能全部显示,请点此查看更多更全内容
Copyright © 2019- gamedaodao.net 版权所有 湘ICP备2024080961号-6
违法及侵权请联系:TEL:199 18 7713 E-MAIL:2724546146@qq.com
本站由北京市万商天勤律师事务所王兴未律师提供法律服务