osgEarth的Rex引擎原理分析(六十一)如何提取出指定范围的高程网格

本文分析osgEarth的Rex引擎如何从DEM或IMG文件中提取指定范围的高程网格,涉及GDAL库的使用以及遥感影像的波段和波长概念。同时,列出了一系列关于osgEarth引擎内部工作原理的问题,涵盖从地球文件加载图层、地形瓦片管理到着色器和OpenGL资源的详细过程。

目标:(五十五)中的问题132

如果从dem/img等文件中提取出指定范围的高程网格,需要用到gdal库进行读取。遥感影像一般包含至少一个波段,波段对应波长,比如红、绿、蓝等,也包含透明度。

 

osgEarthDrivers/gdal/ReaderWriterGDAL.cpp
osg::HeightField* createHeightField( const TileKey&        key,
                                         ProgressCallback*     progress)
    {
        if (key.getLevelOfDetail() > _maxDataLevel)
        {
            //OE_NOTICE << "Reached maximum data resolution key=" << key.getLevelOfDetail() << " max=" << _maxDataLevel <<  std::endl;
            return NULL;
        }

        GDAL_SCOPED_LOCK;

        int tileSize = getPixelsPerTile();

        //Allocate the heightfield
        osg::ref_ptr<osg::HeightField> hf = new osg::HeightField;
        hf->allocate(tileSize, tileSize);

        if (intersects(key))
        {
            //Get the meter extents of the tile
            double xmin, ymin, xmax, ymax;
            key.getExtent().getBounds(xmin, ymin, xmax, ymax);

            // Try to find a FLOAT band
            GDALRasterBand* band = findBandByDataType(_warpedDS, GDT_Float32);
            if (band == NULL)
            {
                // Just get first band
                band = _warpedDS->GetRasterBand(1);
            }

            if (_options.interpolation() == INTERP_NEAREST)
            {
                double colMin, colMax;
                double rowMin, rowMax;
                geoToPixel( xmin, ymin, colMin, rowMax );
                geoToPixel( xmax, ymax, colMax, rowMin );
                std::vector<float> buffer(tileSize * tileSize, NO_DATA_VALUE);

                int iColMin = floor(colMin);
                int iColMax = ceil(colMax);
                int iRowMin = floor(rowMin);
                int iRowMax = ceil(rowMax);
                int iNumCols = iColMax - iColMin + 1;
                int iNumRows = iRowMax - iRowMin + 1;

                int iWinColMin = max(0, iColMin);
                int iWinColMax = min(_warpedDS->GetRasterXSize()-1, iColMax);
                int iWinRowMin = max(0, iRowMin);
                int iWinRowMax = min(_warpedDS->GetRasterYSize()-1, iRowMax);
                int iNumWinCols = iWinColMax - iWinColMin + 1;
                int iNumWinRows = iWinRowMax - iWinRowMin + 1;

                int iBufColMin = osg::round((iWinColMin - iColMin) / double(iNumCols - 1) * (tileSize - 1));
                int iBufColMax = osg::round((iWinColMax - iColMin) / double(iNumCols - 1) * (tileSize - 1));
                int iBufRowMin = osg::round((iWinRowMin - iRowMin) / double(iNumRows - 1) * (tileSize - 1));
                int iBufRowMax = osg::round((iWinRowMax - iRowMin) / double(iNumRows - 1) * (tileSize - 1));
                int iNumBufCols = iBufColMax - iBufColMin + 1;
                int iNumBufRows = iBufRowMax - iBufRowMin + 1;

   
osgEarth 中加载 EPSG:4326 坐标系时,如果地图显示范围不完整,仅显示了四分之一区域,通常与地图的 `<profile>` 配置、地形驱动器(如 Rex)以及数据源的投影范围相关。 osgEarth 在初始化 EPSG:4326 坐标系时,默认使用了完整的全球范围(-180.0, -90.0, 180.0, 90.0),如下所示: ```cpp _global_geodetic_profile = Profile::create( "epsg:4326", -180.0, -90.0, 180.0, 90.0, "", 2, 1 ); ``` 如果地图显示范围不完整,可能是由于数据源(如 GDAL 图像)或地形驱动器未正确适配 EPSG:4326 的全球范围,导致只渲染了部分区域。osgEarthRex 地形驱动器对非 Mercator 投影的支持需要额外的配置来确保完整的地理范围被正确渲染。 为了解决这一问题,可以尝试以下方法: 1. **确保地图配置文件中正确设置 `<profile>`**:在 `.earth` 配置文件中指定 EPSG:4326 的完整范围,确保 `<profile>` 元素使用了正确的边界参数。 ```xml <map name="EPSG4326Map" type="geocentric" version="2"> <options> <terrain driver="rex"/> <profile>epsg:4326</profile> </options> <image name="Global Image" driver="gdal"> <url>global_image.tif</url> </image> </map> ``` 2. **检查数据源的投影信息**:确保所使用的图像或图层数据具有正确的 EPSG:4326 投影定义。如果数据源的元数据中缺少正确的空间参考信息,GDAL 可能无法正确解析其范围,从而导致 osgEarth 仅渲染部分区域。 3. **手动设置地图范围**:在代码中通过 `osgEarth::Map` 或 `osgEarth::ImageLayer` 手动设置地图的地理范围,确保其覆盖完整的 EPSG:4326 区域。 ```cpp osg::Geode* createGlobalImageNode(osgEarth::Map* map, const std::string& imagePath) { osgEarth::ImageLayer* imageLayer = new osgEarth::ImageLayer(); imageLayer->setName("Global Image Layer"); imageLayer->setURL(imagePath); imageLayer->setProfile(map->getProfile()); map->addLayer(imageLayer); } ``` 4. **使用 `osgEarth::Profile::create` 显式定义范围**:在代码中显式定义 EPSG:4326 的全局范围,确保 osgEarth 渲染器能够正确识别并渲染完整的地理区域。 ```cpp osgEarth::Profile* geodeticProfile = osgEarth::Profile::create( "epsg:4326", -180.0, -90.0, 180.0, 90.0, "", 2, 1); ``` 5. **验证地形驱动器兼容性**:osgEarthRex 引擎在非 Mercator 投影下可能需要额外的优化配置,确保其能够处理完整的全球范围。若使用 `rex` 驱动器,需确认其支持 EPSG:4326 的渲染模式。 通过以上方法,可以解决 osgEarth 在加载 EPSG:4326 坐标系时仅显示四分之一范围的问题,确保地图能够完整渲染全球范围。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值