GDAL升级到3.0之后遇到的坑
GDAL3.0变化
GDAL3.0的主要变化在于对空间参考系统进行了大规模的重构,在使用上接口发生了部分变化,同时也会遇到很多坑。最重要的是GDAL的官网不再使用doxygon生成的页面了,而且对空间参考这部分还存在部分错误,导致看官方文档也会遇到坑。 具体可以参考https://github.com/OSGeo/gdal/blob/v3.0.1/gdal/MIGRATION_GUIDE.TXT。
API变化
- SRS_WKT_WGS84宏定义被替换为SRS_WKT_WGS84_LAT_LONG;
- 空间参考类添加函数OSRSetPROJSearchPaths(), OSRExportToWktEx(), OSRGetName(), OSRIsSameEx(), OSRGetCRSInfoListFromDatabase(), OSRGetAreaOfUse(),OSRGetAxisMappingStrategy(), OSRSetAxisMappingStrategy(), OSRGetDataAxisToSRSAxisMapping();
- 坐标转换类添加函数OCTNewCoordinateTransformationOptions(), OCTCoordinateTransformationOptionsSetOperation(), OCTCoordinateTransformationOptionsSetAreaOfInterest(), OCTDestroyCoordinateTransformationOptions(), OCTNewCoordinateTransformationEx(), OCTTransform4D();
- 移除函数OSRFixupOrdering(), OSRFixup(), OSRStripCTParms(), OCTProj4Normalize(), OCTCleanupProjMutex(), OPTGetProjectionMethods(), OPTGetParameterList(), OPTGetParameterInfo()。
空间参考定义
空间参考定义由于GDAL3.0以后的版本依赖的PROJ库必须是6.0+的版本,而且是必须依赖,不像以前的版本proj库可以动态加载,在编译GDAL是不需要PROJ库也可以,但是3.0以后的版本就不行了,编译GDAL的时候必须要有PROJ6.0以上的版本才可以。 这样就会引入一个问题,由于PROJ6里面需要proj.db数据库的支持,这样的话,在GDAL库使用的话也需要proj.db的支持,否则定义空间参考时会报错。proj.db文件默认会在proj.dll所在目录的proj文件夹中找,也可以通过函数OSRSetPROJSearchPaths()来设置proj.db的所在目录。 空间参考定义部分,基本上没有发生大的变化,如果通过SRS_WKT_WGS84宏来定义WGS84椭球的话,需要改为SRS_WKT_WGS84_LAT_LONG宏来进行定义。
坐标转换
坐标转换时空间参考的定义必须使用函数SetAxisMappingStrategy来设置坐标轴对应策略,否则坐标转换会失败。下面两份代码分别是之前的版本和3.0以后的版本进行坐标转换的写法。
- GDAL2.4版本
void TestLongLat2UTM() { OGRCoordinateTransformation* poCT = nullptr; double dfCenterLong = 104.49242396000000; double dfCenterLat = 26.311051110000001; int nZone = static_cast<int>(dfCenterLong / 6 + 31); int bNorth = dfCenterLat >= 0 ? TRUE : FALSE; OGRSpatialReference oWGS84; oWGS84.SetWellKnownGeogCS("WGS84"); OGRSpatialReference oUtmSrs; oUtmSrs.SetWellKnownGeogCS("WGS84"); oUtmSrs.SetUTM(nZone, bNorth); poCT = OGRCreateCoordinateTransformation(&oWGS84, &oUtmSrs); double dx = 104.28982973166080; double dy = 26.567797593704370; double dz = 1826.8254084027094; int bTransformSuccess; poCT->Transform(1, &dx, &dy, &dz, &bTransformSuccess); OGRCoordinateTransformation::DestroyCT(poCT); }
-GDAL3.0+
void TestLongLat2UTM() { OGRCoordinateTransformation* poCT = nullptr; double dfCenterLong = 104.49242396000000; double dfCenterLat = 26.311051110000001; int nZone = static_cast<int>(dfCenterLong / 6 + 31); int bNorth = dfCenterLat >= 0 ? TRUE : FALSE; OGRSpatialReference oWGS84; oWGS84.SetWellKnownGeogCS("WGS84"); oWGS84.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER); OGRSpatialReference oUtmSrs; oUtmSrs.SetWellKnownGeogCS("WGS84"); oUtmSrs.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER); oUtmSrs.SetUTM(nZone, bNorth); poCT = OGRCreateCoordinateTransformation(&oWGS84, &oUtmSrs); double dx = 104.28982973166080; double dy = 26.567797593704370; double dz = 1826.8254084027094; int bTransformSuccess; poCT->Transform(1, &dx, &dy, &dz, &bTransformSuccess); OGRCoordinateTransformation::DestroyCT(poCT); }