找回密码
 立即注册
首页 业界区 业界 GDAL 2.X升级3.X需要注意的问题总结

GDAL 2.X升级3.X需要注意的问题总结

汪玉珂 前天 10:57
1 引言

最近终于将使用的GDAL 2.X升级到成了3.X版本,总结一下遇到的各种问题。
2 详论

2.1 数据路径

GDAL 3.X以后深度依赖PROJ库,以前只是可选构建项,现在已经是必须构建项了。最直接的体现是如果涉及到空间参考相关的内容时,除了要配置GDAL_DATA环境变量,还必须配置PROJ_DATA环境变量。GDAL_DATA和PROJ_DATA分别是GDAL和PROJ库的数据,里面存储了一些空间参考相关的参数,因此一般在使用GDAL之前,需要配置一下相关的路径:
  1. string gdalDir = shareDataDir + string("/gdal");
  2. CPLSetConfigOption("GDAL_DATA", gdalDir.c_str());
  3. std::string projDir = shareDataDir + string("/proj");
  4. CPLSetConfigOption("PROJ_DATA", projDir.c_str());
复制代码
这些数据一般在构建的时候会安装到指定的目录的share文件夹内,如下图所示:
1.png

注意以下几点:

  • 经过笔者的测试,一般设置PROJ_DATA目录就可以了。但是有的资料显示还必须继续设置GDAL_DATA目录。因为GDAL_DATA目录中可能保存的不仅仅是空间参考信息,可能保存了很多GIS相关的数据。
  • 另外,很多资料推荐直接设置操作系统的环境变量。这样做不是不行,前提是与操作系统的其他GDAL环境不冲突。如果你安装过QGIS或者PostGIS等环境就知道,这些程序也会在操作系统中设置GDAL_DATA、PROJ_DATA环境变量,那么就只能像笔者这样在程序中配置。
  • 在PROJ 9.1版本以前,PROJ数据的环境变量名为PROJ_LIB;在后续版本中优先使用PROJ_DATA,PROJ_LIB还会使用一段时间,但是最好替换成PROJ_DATA,避免后续的版本废弃。
2.2 坐标顺序

GDAL升级到3.X后另外一个问题就是坐标顺序的问题。例如如果要进行空间参考坐标转换:
  1. // CGCS2000
  2. gcs.importFromEPSG(4326);
  3. // Tm投影
  4. pcs.importFromEPSG(3857);
  5. OGRCoordinateTransformation* lonLat2XY =
  6.     OGRCreateCoordinateTransformation(&gcs, &pcs);
  7. OGRCoordinateTransformation* xy2LonLat =
  8.     OGRCreateCoordinateTransformation(&pcs, &gcs);
  9. if (!lonLat2XY || !xy2LonLat) {
  10. return 1;
  11. }
  12. double x = 113.6;
  13. double y = 38.8;
  14. printf("经纬度坐标:%.9lf\t%.9lf\n", x, y);
  15. if (!lonLat2XY->Transform(1, &x, &y)) {
  16. return 1;
  17. }
  18. printf("平面坐标:%.9lf\t%.9lf\n", x, y);
  19. if (!xy2LonLat->Transform(1, &x, &y)) {
  20. return 1;
  21. }
  22. printf("再次转换回的经纬度坐标:%.9lf\t%.9lf\n", x, y);
  23. OGRCoordinateTransformation::DestroyCT(lonLat2XY);
  24. lonLat2XY = nullptr;
  25. OGRCoordinateTransformation::DestroyCT(xy2LonLat);
  26. xy2LonLat = nullptr;
复制代码
这段代码在3.X的结果就不正确。原因是GDAL 3.X更换了坐标轴的顺序,认为y在前,x在后才是更加专业的坐标表达。不过这样就破坏了向后兼容性。解决方案是给空间参考设置轴策略为传统顺序[1]:
  1. // CGCS2000
  2. gcs.importFromEPSG(4326);
  3. // Tm投影
  4. pcs.importFromEPSG(3857);
  5. gcs.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
  6. pcs.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
  7. //...
复制代码
想这样一个一个坐标参考修改很麻烦,另一个更加合适的办法是设置全局的坐标轴策略为传统顺序[2]:
  1. // 设置全局坐标顺序为传统GIS顺序(经度,纬度)
  2. CPLSetConfigOption("OGR_CT_FORCE_TRADITIONAL_GIS_ORDER", "YES");
复制代码
3 总结

最好的办法就是在程序的最开始阶段执行一个初始化函数:
  1. void Init(const char *shareDataDir) {
  2.   GDALAllRegister();  //注册所有的格式
  3.   CPLSetConfigOption("SHAPE_ENCODING", "");  //解决中文乱码问题
  4.   string gdalDir = shareDataDir + string("/gdal");
  5.   CPLSetConfigOption("GDAL_DATA", gdalDir.c_str());
  6.   std::string projDir = shareDataDir + string("/proj");
  7.   CPLSetConfigOption("PROJ_DATA", projDir.c_str());
  8.   // 设置全局坐标顺序为传统GIS顺序(经度,纬度)
  9.   CPLSetConfigOption("OGR_CT_FORCE_TRADITIONAL_GIS_ORDER", "YES");
  10. }
复制代码


  • GDAL 3.0 Coordinate transformation (backwards compatibility (?)) ↩︎
  • Problem with GDAL >= 3.0 ↩︎

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
您需要登录后才可以回帖 登录 | 立即注册