• GDAL坐标转换


    一、引言

    最近研究了一下GIS、测绘学的坐标转换的问题,感觉大部分资料专业性太强,上来就是一通专业性论述;但感觉对于相关从业者来说,其实不必了解那么多背景知识的;就通过GDAL这个工具,来简单总结下坐标转换相关的问题。
    GDAL坐标转换其实也是调用proj4来实现,但是proj4有个特别麻烦的地方,就是坐标系描述的部分特别繁复,需要对专业知识有一定的了解。使用GDAL则相对简单很多。

    二、地理坐标系

    地理坐标系就是常说的经纬度坐标系,比如用GPS直接获取的坐标就是在地理坐标系下获取的。一个真实坐标无论怎么变换,一定会有地理坐标系作为基准,也一定有可以转换出来的经纬度坐标。以国内的情况来说,常用到的地理坐标系有WGS84,beijing54,xian80,CGCS2000这四种。
    GDAL可以像proj4那样自定义坐标系,也可以仅通过字符串定义一些常用的坐标系,但本文认为最方便的还是通过EPSG数据库定义的代码来定义一个地理坐标系统;毕竟很多时候需要兼容的地理坐标系很多,全部一个个自定义坐标系太麻烦。

    OGRSpatialReference spatialReference;
    //spatialReference.importFromEPSG(4326);//WGS84
    //spatialReference.importFromEPSG(4214);//BeiJing54
    spatialReference.importFromEPSG(4610);//XIAN80
    //spatialReference.importFromEPSG(4490);//CGCS2000
    
    char *pszWKT = nullptr;
    spatialReference.exportToPrettyWkt(&pszWKT);
    cout << pszWKT << endl;
    CPLFree(pszWKT);
    pszWKT = nullptr;
    

    如上演示了GDAL定义地理坐标系并输出坐标系的信息。四种不同的坐标系只需要改变相应的代码编号,用起来十分方便。最终打印输出了的xian80坐标系信息:
    1
    在这里一定要注意,使用这种方式定义地理坐标系一定要通过配置GDAL_DATA路径,否则控制台会输出错误信息:

    CPLSetConfigOption("GDAL_DATA", "gdaldata");
    

    “gdaldata”表示一个路径(这里用的是相对路径,当然也可以设置成绝对路径),是GDAL编译完成后会生成的一个目录,里面记录了各种坐标系的参数文件。例如进入这个文件夹,用Excel打开pcs.csv这个文件,就可以看到各种坐标系的参数了。
    2
    除了这种方法,也可以在环境变量中设置GDAL_DATA变量来实现。

    三、投影平面坐标系

    经纬度坐标是曲面上的坐标,曲面上的坐标投影到平面,不同的投影方式就会产生不同的平面坐标;即使是同一种投影方式,不同的参数得到的平面坐标也会不同。也就是说,地理坐标系下的经纬度坐标与投影坐标系下的平面坐标,是一对多的关系而不是一对一的关系。以国内的情况来说,经常用到的投影有横轴墨卡托投影,高斯-克吕格投影和UTM投影。
    在Global Mapper中三种投影设置方式如下:
    3
    4
    5
    可以看出,高斯-克吕格投影和UTM投影其实都是横轴墨卡托投影,两者都是通过设置带号(Zone)来实现设置横轴墨卡托投影的具体参数(Parameters)。在GDAL里面,高斯-克吕格投影就是通过设置横轴墨卡托投影来实现的。如下演示了一个xian80坐标系,3度带带号38的横轴墨卡托投影。

    OGRSpatialReference spatialReference;
    spatialReference.importFromEPSG(4610);			//XIAN80
    spatialReference.SetTM(0, 114, 1.0, 38500000, 0);
    

    设置横轴墨卡托投影的函数SetTM()有六个参数:

    参数 设置
    dfCenterLat 一般为0
    dfCenterLong 中央经线,决定了是哪一投影带
    dfScale 一般为1.0,UTM设置为0.9996
    dfFalseEasting 一般为500000,高斯-克吕格前面加上带号
    dfFalseNorthing 一般为0

    用之前方法得到坐标系信息并输出,信息如下:
    6

    四、坐标转换

    定义好坐标系之后,就可以进行坐标转换了。如下为xian80地理坐标系下某点(113.6,38.8)用高斯-克吕格投影到带平面坐标系:

    OGRSpatialReference* pLonLat = spatialReference.CloneGeogCS();
    OGRCoordinateTransformation* LonLat2XY = OGRCreateCoordinateTransformation(pLonLat, &spatialReference);
    if (!LonLat2XY)
    {		
    	return 1;
    }
    	
    double x = 113.6;
    double y = 38.8;
    printf("经纬度坐标:%.9lf	%.9lf
    ", x, y);
    if (!LonLat2XY->Transform(1, &x, &y))
    {
    	return 1;
    }
    printf("平面坐标:%.9lf	%.9lf
    ", x, y);
    
    OGRCoordinateTransformation::DestroyCT(LonLat2XY);
    LonLat2XY = nullptr;
    

    这里通过复制之前定义的高斯-克吕格投影平面坐标系得到相同的地理坐标系(当然也可以自定义新坐标系),然后使用OGRCoordinateTransformation::Transform()方法来进行坐标转换。最后的输出结果为:
    7
    通过Global Mapper的坐标转换工具来验证结果是否正确:
    8
    9
    比较可以发现两者转换的结果基本一致。除此之外,将平面坐标逆投影到地理坐标也是可以的,只需要在OGRCreateCoordinateTransformation()的时候颠倒下顺序即可。

    五、其他

    1.GDAL默认不编译proj.4,使用的时候需要添加proj.4的支持。
    2.同一地理坐标系的投影转换是严密的,但不同地理坐标系之间需要先转换到地心立体坐标系,然后通过七参数转换。
    3.可以根据坐标值选择正确的分带,使用这个分带的上下几个分带进行投影问题也不是很大。但是分带差距太大可能有问题,因为投影公式只能在一定范围内有效;即不同的软件对的时候结果比较一致,错的时候结果可能不同。
    以上三个问题有时间再做进一步的研究和总结。

    六、参考文献

    1.GDAL源码剖析(十一)之OGR投影说明
    2.墨卡托投影、高斯-克吕格投影、UTM投影及我国分带方法
    3.GDAL库学习笔记(五):坐标系之间的转化
    4.GIS坐标转换库Proj.4的使用
    5.GDAL影像投影转换

  • 相关阅读:
    Hufman编码实现运用1 (原理不描述)
    E
    1178: [Apio2009]CONVENTION会议中心
    1071: [SCOI2007]组队
    #333. 【NOIP2017】宝藏
    CF 96 D. Volleyball
    CF 987 D. Fair
    qbxt的题:运
    qbxt的题:找一个三元环
    4361: isn
  • 原文地址:https://www.cnblogs.com/charlee44/p/6919412.html
Copyright © 2020-2023  润新知