小白学osgEarth之路:添加ImageLayer和ModelLayer并定位至该图层

由于项目需要,从今年5份从零osg和零osgEarth基础的情况下,开始学习使用osgEarth,仅仅从配置环境就花了一周的时间(大神了偷摸笑~),废话不多说,切入正题,有不妥的地方希望各位道友批评指正。

1、环境配置(osg3.4+osgEarth2.8+VS2010);

2、在球上添加TIFF影像

osgEarth添加影像的方式主要有两种:(1)第一种是直接读取earth文件的方式,直接将earth文件读入作为osg场景中的一个节点。如下所示

//定义
osgViewer::Viewer*				mViewer;
osg::ref_ptr<osg::Group>			mRoot;

//实现
mRoot = new osg::Group;
mViewer = new osgViewer::Viewer;
osg::ref_ptr<osg::Node> mp = osgDB::readNodeFile("../../earthfile/china-simple.earth");
mRoot->addChild(mp);

(2)第二种方式就是通过osgEarth的API添加,一般地,添加影像所使用的驱动类型为GDAL,其类为osgEarth::Drivers::GDALOptions,接口为void osgEarth::Map::addImageLayer(osgEarth::ImageLayer* layer);其添加代码如下:

//变量定义及初始化
osg::ref_ptr<osgEarth::MapNode>		        mMapNode;
osgEarth::Map*				mMapPtr;   
mMapNode = dynamic_cast<osgEarth::MapNode*>(mRoot->getChild(0));
mMapPtr = mMapNode->getMap();

osgEarth::Drivers::GDALOptions imageryGDAL;
imageryGDAL.url() = IMAGERY_URL;
osgEarth::Drivers::ImageLayer* tempImageLayer = new osgEarth::Drivers::ImageLayer( osgEarth::Drivers::ImageLayerOptions(layerName, imageryGDAL));
mMapPtr->addImageLayer(tempImageLayer);

上述两种情况均可以将TIFF影像添加到场景中,但是第一种方法需要用户修改编写earth文件,可实际操作性不强;第二种方式虽然可以将影像添加进去,但是同样存在一个问题,就是将影像加载进去后视点无法定位到该影像,当影像图幅较大的时候人眼可以分辨,当加载的影像图幅较小的时候,便很难辨认了,因此视点定位还是很有必要的,笔者在网上查阅了资料几乎没有发现这样的解决方案,于是自己找接口尝试了,终于找到了,特与道友分享一下。

3、获取影像边界范围

这个东西其实在osg里面就有,该类为 osg::BoundingBoxImpl,osgEarth公有继承了该类,osgEarth::Bounds : public osg::BoundingBoxImpl<osg::Vec3d>,其描述为“这是一个‘匿名’的边界范围”,为什么说是匿名呢,这是由于该类所计算得到的边界范围是不包含地理参考信息的。具体感兴趣的道友们可以去查阅源码看看。

那么如何获取影像边界呢?这里可能会有些误区,为什么呢?

tempImageLayer->getProfile()->getExtent().bounds();

这是第一种获取bounds的方法,但是这里是通过图层的getProfile()方法获取的,通过该方法是无法获取到影像图层的地理信息的,有道友已经尝试过了,如下图所示:

这里我们应该采用另外一个方法获取:

//loc to ImageLayer
osgEarth::Bounds bound = tempImageLayer->getTileSource()->getDataExtents().data()->bounds();

说实话,这种方法使得bounds藏的很深,我反正是找了好久才找到。道行不太够,具体原因也说不上,使用这种方式可以试试,可以获取得到影像的中心坐标,具体代码如下:

//loc to ImageLayer
osgEarth::Bounds bound = tempImageLayer->getTileSource()->getDataExtents().data()->bounds();
double x = bound.center2d().x();
double y = bound.center2d().y();
osgEarth::Viewpoint vp("",x,y,0.0, 0, -90.0,2000);
mEM->setViewpoint(vp,8);

至于添加三维模型,也是同样的道理,此处不做过多的说明了~

要对图层设置 `osgEarth::GeoExtent`,你需要使用 `osgEarth::Config` 对象来构建地理范围的配置数据,并将其传递给 `osgEarth::LayerOptions` 对象。然后,将 `LayerOptions` 传递给 `osgEarth::Map` 对象中的 `addLayer` 方法,以便将其添加到地图中。下面是一个示例代码: ```cpp #include <osgEarth/GeoExtent> #include <osgEarth/Layer> #include <osgEarth/Map> #include <osgEarth/Config> // 创建地理范围对象 osgEarth::GeoExtent extent(osgEarth::SpatialReference::create("epsg:4326"), -180.0, -90.0, 180.0, 90.0); // 构建地理范围的配置数据 osgEarth::Config conf; conf.add("type", "xyz"); // 图层类型 conf.add("url", "http://tile.openstreetmap.org/{z}/{x}/{y}.png"); // 图层数据源 conf.add("profile", "global-geodetic"); // 投影方式 conf.add("min_level", 0); // 最小级别 conf.add("max_level", 18); // 最大级别 conf.add("extent", extent.getConfig()); // 设置地理范围 // 创建图层选项对象 osgEarth::LayerOptions layerOptions("OpenStreetMap", conf); // 创建地图对象并添加图层 osgEarth::Map map; map.addLayer(new osgEarth::Layer(layerOptions)); ``` 在上面的代码中,我们首先创建了一个地理范围对象 `extent`,然后使用 `osgEarth::Config` 构建了一个包含图层配置信息的 `conf` 对象。接下来,我们创建了一个 `osgEarth::LayerOptions` 对象 `layerOptions`,并将 `conf` 作为参数传递给它。最后,我们通过调用 `map.addLayer` 方法向地图添加了一个新的图层。 注意,上面的示例代码只是一个简单的示例,实际应用中可能需要根据具体的需求进行更改。
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值