Coords transform


国内各地图使用的坐标系标准及距离计算公式及相互转换方法

1.坐标系标准

坐标系的国际标准是 GPS 使用的 WGS84,以经纬度表示地球表面上的一个点。 但是在我国,政府了出于安全考虑,国内的所有导航电子地图必须使用国家测绘局制定的加密坐标系统,也就是将一个真实的经纬度加密成一个不正确的经纬度坐标,国际标准我们称为地球坐标,中国标准我们称为火星坐标。

  • 国际标准: WGS-84
  • 中国标准: GCJ-02

2.国内各地图使用的坐标系

国内常见地图,如google中国地图、搜搜地图等使用的是中国标准 GCJ-02,百度在GCJ-02的基础上又进行了二次加密,形成了BD-09坐标系。 其它地图同百度类似,都是在GCJ-02进行加密处理,参考下表:

API 坐标系 坐标类型
百度地图API 百度坐标
腾讯搜搜地图API 火星坐标
搜狐搜狗地图API 搜狗坐标*
阿里云地图API 火星坐标
图吧MapBar地图API 图吧坐标
高德MapABC地图API 火星坐标
灵图51ditu地图API 火星坐标

3.坐标系转换工具

python lib: https://github.com/zxteloiv/pycoordtrans

./coordtrans gcj02 bd09ll 116.306411 39.981839

将坐标从中国标准转换成百度坐标

./coordtrans bd09ll gcj02 112.406411 39.781839

将坐标从百度坐标转换成中国标准 要和 WGS-84 转换,只需要将参数换成 wgs84 即可,该工具是 python 包,可导入python脚本直接使用

4.距离计算公式

各种坐标系都可使用同一公式计算球面距离,误差非常小,只要坐标系相同即可。

#define PI  3.14159265
#define EARTH_RADIUS  6378137
#define RAD  (PI/180.0)
int get_distance(
    double lat1, 
    double lng1, 
    double lat2, 
    double lng2) 
{
        double radLat1 = lat1 * RAD;
        double radLat2 = lat2 * RAD;
        double a = radLat1 - radLat2;
        double b = (lng1 - lng2) * RAD;
        double s = 2  * asin(  sqrt( pow(sin(a / 2), 2) + cos(radLat1) * cos(radLat2) * pow(sin(b / 2), 2))); 
        s = s * EARTH_RADIUS;
        return static_cast<int>(s);
}

//另一种优化后的公式:

#define EARTH_RADIUS_IN_METERS  6378137.0
#define RATIO_0 0.9970707597894937
#define RATIO_1 0.0004532759255277588
#define RATIO_2  -0.00017587656744607181
#define RATIO_3 0.0000005028600490023173
double radian(double d)
{
    return d * PI / 180.0; 
}

double get_distance_lbs(
    double lat1, 
    double lng1, 
    double lat2, 
    double lng2)
{
    //1) 
    double dx = lng1 - lng2; 
    double dy = lat1 - lat2; 
    double b = (lat1 + lat2) / 2.0; 

    //2) 
    double Lx = (RATIO_3 * b * b * b + RATIO_2 * b * b  + RATIO_1 * b + RATIO_0 ) * radian(dx) *EARTH_RADIUS_IN_METERS; 
    double Ly = EARTH_RADIUS_IN_METERS * radian(dy);

    //3)
    return sqrt(Lx * Lx + Ly * Ly);
}

 Catalogue