GDAL 2.X升级3.X需要注意的问题总结
1 引言
最近终于将使用的GDAL 2.X升级到成了3.X版本,总结一下遇到的各种问题。
2 详论
2.1 数据路径
GDAL 3.X以后深度依赖PROJ库,以前只是可选构建项,现在已经是必须构建项了。最直接的体现是如果涉及到空间参考相关的内容时,除了要配置GDAL_DATA环境变量,还必须配置PROJ_DATA环境变量。GDAL_DATA和PROJ_DATA分别是GDAL和PROJ库的数据,里面存储了一些空间参考相关的参数,因此一般在使用GDAL之前,需要配置一下相关的路径:
string gdalDir = shareDataDir + string("/gdal");
CPLSetConfigOption("GDAL_DATA", gdalDir.c_str());
std::string projDir = shareDataDir + string("/proj");
CPLSetConfigOption("PROJ_DATA", projDir.c_str());
这些数据一般在构建的时候会安装到指定的目录的share文件夹内,如下图所示:

注意以下几点:
- 经过笔者的测试,一般设置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后另外一个问题就是坐标顺序的问题。例如如果要进行空间参考坐标转换:
// CGCS2000
gcs.importFromEPSG(4326);
// Tm投影
pcs.importFromEPSG(3857);
OGRCoordinateTransformation* lonLat2XY =
OGRCreateCoordinateTransformation(&gcs, &pcs);
OGRCoordinateTransformation* xy2LonLat =
OGRCreateCoordinateTransformation(&pcs, &gcs);
if (!lonLat2XY || !xy2LonLat) {
return 1;
}
double x = 113.6;
double y = 38.8;
printf("经纬度坐标:%.9lf\t%.9lf\n", x, y);
if (!lonLat2XY->Transform(1, &x, &y)) {
return 1;
}
printf("平面坐标:%.9lf\t%.9lf\n", x, y);
if (!xy2LonLat->Transform(1, &x, &y)) {
return 1;
}
printf("再次转换回的经纬度坐标:%.9lf\t%.9lf\n", x, y);
OGRCoordinateTransformation::DestroyCT(lonLat2XY);
lonLat2XY = nullptr;
OGRCoordinateTransformation::DestroyCT(xy2LonLat);
xy2LonLat = nullptr;
这段代码在3.X的结果就不正确。原因是GDAL 3.X更换了坐标轴的顺序,认为y在前,x在后才是更加专业的坐标表达。不过这样就破坏了向后兼容性。解决方案是给空间参考设置轴策略为传统顺序[1]:
// CGCS2000
gcs.importFromEPSG(4326);
// Tm投影
pcs.importFromEPSG(3857);
gcs.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
pcs.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
//...
想这样一个一个坐标参考修改很麻烦,另一个更加合适的办法是设置全局的坐标轴策略为传统顺序[2]:
// 设置全局坐标顺序为传统GIS顺序(经度,纬度)
CPLSetConfigOption("OGR_CT_FORCE_TRADITIONAL_GIS_ORDER", "YES");
3 总结
最好的办法就是在程序的最开始阶段执行一个初始化函数:
void Init(const char *shareDataDir) {
GDALAllRegister(); //注册所有的格式
CPLSetConfigOption("SHAPE_ENCODING", ""); //解决中文乱码问题
string gdalDir = shareDataDir + string("/gdal");
CPLSetConfigOption("GDAL_DATA", gdalDir.c_str());
std::string projDir = shareDataDir + string("/proj");
CPLSetConfigOption("PROJ_DATA", projDir.c_str());
// 设置全局坐标顺序为传统GIS顺序(经度,纬度)
CPLSetConfigOption("OGR_CT_FORCE_TRADITIONAL_GIS_ORDER", "YES");
}
GDAL 2.X升级3.X需要注意的问题总结的更多相关文章
- VS2015下编译64位GDAL总结
使用VS2015编译最新的64位GDAL(最新gdal2.11),确实有一些问题,看来双方还是太新了,有点不兼容,特总结如下. 以前经常用的通过VisualStudio IDE进行编译的方式现在似乎不 ...
- GDAL库简介以及在Windows下编译过程
GDAL(Geospatial Data Abstraction Library,地理空间数据抽象库)是一个在X/MIT许可协议下的开源栅格空间数据转换库.官网http://www.gdal.org/ ...
- Proj.4 升级新版本5.x和6.x
目录 Proj.4 升级新版本5.x和6.x 0.缘起 1.5.x和6.x更新情况简述 PROJ 5.x 更新 PROJ 6.x 更新 2.从PROJ.4向新版本迁移 迁移到5.x版本 迁移到6.x版 ...
- Linux平台 Oracle 10gR2(10.2.0.5)RAC安装 Part3:db安装和升级
Linux平台 Oracle 10gR2(10.2.0.5)RAC安装 Part3:db安装和升级 环境:OEL 5.7 + Oracle 10.2.0.5 RAC 5.安装Database软件 5. ...
- 看完SQL Server 2014 Q/A答疑集锦:想不升级都难!
看完SQL Server 2014 Q/A答疑集锦:想不升级都难! 转载自:http://mp.weixin.qq.com/s/5rZCgnMKmJqeC7hbe4CZ_g 本期嘉宾为微软技术中心技术 ...
- Entity Framework Core 1.1 升级通告
原文地址:https://blogs.msdn.microsoft.com/dotnet/2016/11/16/announcing-entity-framework-core-1-1/ 翻译:杨晓东 ...
- ASP.NET 5 RC1 升级 ASP.NET Core 1.0 RC2 记录
升级文档: Migrating from DNX to .NET Core Migrating from ASP.NET 5 RC1 to ASP.NET Core 1.0 RC2 Migrating ...
- SQL Server2016升级前几点自检
SQL Server2016已经出来一段时间了,而且最新的SP1包也于2016年11月18日正式发布,各种新的特性推出让我们跃跃欲试.那么对于我们真实的业务环境,特别是生产环境要不要"跟风& ...
- 如何安全的将VMware vCenter Server使用的SQL Server Express数据库平滑升级到完整版
背景: 由于建设初期使用的vSphere vCenter for Windows版,其中安装自动化过程中会使用SQL Server Express的免费版数据库进行基础环境构建.而此时随着业务量的增加 ...
- Linux平台 Oracle 10gR2(10.2.0.5)RAC安装 Part2:clusterware安装和升级
Linux平台 Oracle 10gR2(10.2.0.5)RAC安装 Part2:clusterware安装和升级 环境:OEL 5.7 + Oracle 10.2.0.5 RAC 3.安装Clus ...
随机推荐
- nuclei安装使用
go环境安装 go 下载路径:https://golang.google.cn/dl/ 1.双击 go1.20.7.windows-amd64.msi 2.点击下一步 3.我同意,然后下一步. 4.选 ...
- 单词搜索 & 周赛第二道
单词搜索 描述: 给定一个二维网格和一个单词,找出该单词是否存在于网格中.单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中"相邻"单元格是那些水平相邻或垂直相邻的单元格.同 ...
- 注册全局图标ts写法
https://element-plus.gitee.io/zh-CN/component/icon.html#使用图标 仓库地址:https://github.com/Megasu/element- ...
- helm Error: INSTALLATION FAILED: cannot re-use a name that is still in use
前言 使用helm安装服务报错,修改chat后重新安装报错:安装失败:无法重复使用仍在使用的名称 解决方法 1.查找安装失败的服务 helm -n {namespace} ls -a 2.删除安装失败 ...
- [Vue warn]: Unknown custom element: did you register the component correctly?
前言 [Vue warn]: Unknown custom element: did you register the component correctly? For recursive compo ...
- 选择排序(LOW)
博客地址:https://www.cnblogs.com/zylyehuo/ # _*_coding:utf-8_*_ def select_sort(li): for i in range(len( ...
- 如何删除Docker Swarm中的Node
好吧,我又回来了...断了那么久主要是因为懒...现在有空会更新一些docker相关的知识.本文主要是总结下在工作中需要管理Docker Swarm中的Node遇到的问题:如何删除一个Swarm中的N ...
- How to grow old
An individual human existence should be like a river-small at first,narrowly contained within its ba ...
- 枚举与string之间查找与转换
利用TypInfo单元的GetEnumName和GetEnumValue可以遍历任意枚举类型 其实上面程序运行会有err,为什么?因为没有理解和掌握JSON Objects Framework[感到简 ...
- 静态批处理/动态批处理/GPU Instancing /SRP Batcher的详细剖析
静态批处理[1] 定义 标明为 Static 的静态物件,如果在使用相同材质球的条件下,在Build(项目打包)的时候Unity会自动地提取这些共享材质的静态模型的Vertex buffer和Inde ...