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 ...
随机推荐
- 赞美Syscall
知道程序员在编写程序时直接和硬件打交道是一件非常麻烦的事,同时不受保障的程序直接运行在硬件上如果出错可能造成计算机宕机,于是可以编写一个应用程序驻留在计算机上管理硬件资源为上层应用提供系统调用(sys ...
- RSA算法详解及相关数学原理解析
RSA算法详解及相关数学原理解析 前言 为了记录自己学习密码学的过程,也是为了便于个人应付相关课程的考核,故写此博客. 本博客总结了怎么用C++手搓一个RSA算法,以及补补欠缺的一些数学知识和可能 ...
- Shell语言编程(炼气)
1. Shell脚本执行方式 执行方式 应用及场景 通过sh或bash 书写脚本后,最常用的方式,在其他非红帽系统中,建议使用bash运行脚本 通过.点或source 加载/生效配置文件(环境变量,别 ...
- BUUCTF---signin
题目 welcome to crypto world!! 密文:424a447b57653163306d655f74345f424a444354467d 解题 啥也没有只有一段密文,只能从密文下手了, ...
- 使用AOP技术实现接口验签
一.背景 在给第三方提供接口时,我们需要对接口进行验签.具体来说,当外部系统调用我们的接口时,请求中需要携带一个签名,我们接收到请求后,会解析数据并校验签名是否正确,以确保请求的合法性和安全性. 为了 ...
- Global.asax
转
备忘: 项目中的Global.asax文件里通常包含这5个方法: Application_Start – web 应用程序最初启动时执行 Application_End – 应用程序关闭时运行 App ...
- 终于有人把ROS机器人操作系统讲明白了
终于有人把ROS机器人操作系统讲明白了 导读:机器人是多专业知识交叉的学科,通常涉及传感器.驱动程序.多机通信.机械结构.算法等,为了更高效地进行机器人的研究和开发,选择一个通用的开发框架非常必要,R ...
- 实现Andriod的APP中文名
让程序编译后,就会自动生成中文名,以及启动界面. 1. 2.AndroidManifest.xml的修改. 如果新建project,自动生成,否则要手动 3. 4.ok了.到手机端看结果吧
- MQTT协议发布和订阅的实现,一步步带你实现发布订阅服务。
MQTT协议 MQTT协议是基于TCP传输协议之上的应用层协议,全程Message Queuing Telemetry Transport.主要用于物联网设备间的通信,在低带宽.不稳定网络环境下的优势 ...
- 成都信息工程大学天梯赛 L2-2 不要刁难我们了
赛时板子没写对,原因就是标记数组的位置放错了,放到了while外面,导致这样距离数组是不会更新的,板子还是要自己多写少看 #include <bits/stdc++.h> #define ...