osgearth学习文档
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
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<osgEarth::XXXLayer> 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<osgEarth::ImageLayer> 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<osgEarth::ImageLayer> 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<osgEarth::ElevationLayer> 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<osgEarth::ImageLayer> 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::GeoPoint
2015/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<osgViewer::View*>(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 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 );
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<Intersection> 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/22
1.坐标系统的区别
世界坐标系:
世界坐标系是一个特殊的坐标系统,它建立了描述其他坐标系所需的参考框架。
它可以用来描述其他的坐标系的位置。
它能够描述整个场景中的所有对象。
世界坐标系的位置是绝对的,它为所有对象的位置提供一个绝对的参考标准,从而避免物体之间的独立的坐标系统之间的混乱。
物体坐标系:
物体坐标是每个物体特定的坐标系,因为每个对象包含了顶点坐标以及其纹理坐标等,如果每个坐标都相对于世界坐标来进行变换将会非常困难,而且坐标的精度也不够高,如果每个对象都建立自己的物体坐标系,而只需通过物体坐标系相对于世界坐标系的变换即可描述物体的。
摄像机坐标系:
摄像机坐标系是和观察者密切相关的坐标系,摄像机坐标系和屏幕坐标系相似,差别在于摄像机坐标系处于3D空间中。
它可视为特殊的物体坐标,该物体坐标系统定义在摄像机的屏幕区域。
摄像机坐标系描述的是哪些物体应该渲染并显示在屏幕上,主要包括物体是否在摄像机坐标区域内,物体的渲染顺序和物体的遮挡渲染等。
2015/12/23
1.osgEarth::TileSource
2015/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<osgGA::GUIEventAdapter> 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/30
1.加载矢量图
如何通过EarthFile文件创建地图。
Earth File 的核心作用是指明以下3 点:
1.你创建的地图类型(geocentric 或projected)
2.可使用的图像、三面图elevation、矢量和模型数据
3.你的数据缓存在哪里
earthFile中可以加载简单的图像层,可以加载多重图像层次,将多个image元素加到earthFile 文件中。
在加载多重图像层的时候,需要指定相应的顺序,定义多个图像源时,它们在该earth 文件中指定的顺序是从在底部到顶部的。
OsgEarth中加载矢量数据,Feature Geometry OSG的几何渲染矢量数据。
<Features>元素定义了一个矢量数据源,渲染矢量特征数据的模型层要求一个特征源。
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<TileKey> rootKeys;
map->getProfile()->getRootKeys( rootKeys );
第二步是获取瓦片,弄清楚图像的尺寸大小。
ImageLayer* imageLayer = dynamic_cast<ImageLayer*>(layer);
ElevationLayer* elevationLayer = dynamic_cast<ElevationLayer*>(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文件,。