GPS坐标系转换(标准坐标系WGS84转GCJ-02火星坐标系)

  • 坐标系简介
  • WGS-84 标准坐标系
  • GCJ-02 – 国测局坐标
  • BD-09 – 百度坐标系
  • 干货前的说明
  • WGS84转GCJ-02代码
  • GCJ-02转WGS84代码
  • 结果

坐标系简介

通常用经纬度来表示一个地理位置,但是由于一些原因,我们从不同渠道得到的经纬度信息可能并不是在同一个坐标系下。

高德地图、腾讯地图以及谷歌中国区地图使用的是GCJ-02坐标系
百度地图使用的是BD-09坐标系
底层接口(HTML5 Geolocation或ios、安卓API)通过GPS设备获取的坐标使用的是WGS-84坐标系
不同的坐标系之间可能有几十到几百米的偏移,所以在开发基于地图的产品,或者做地理数据可视化时,我们需要修正不同坐标系之间的偏差。

WGS-84 标准坐标系

WGS-84(World Geodetic System, WGS)是使用最广泛的坐标系,也是世界通用的坐标系,GPS设备得到的经纬度就是在WGS84坐标系下的经纬度。通常通过底层接口得到的定位信息都是WGS84坐标系。

GCJ-02 – 国测局坐标

GCJ-02(G-Guojia国家,C-Cehui测绘,J-Ju局),又被称为火星坐标系,是一种基于WGS-84制定的大地测量系统,由中国国测局制定。此坐标系所采用的混淆算法会在经纬度中加入随机的偏移。

国家规定,中国大陆所有公开地理数据都需要至少用GCJ-02进行加密,也就是说我们从国内公司的产品中得到的数据,一定是经过了加密的。绝大部分国内互联网地图提供商都是使用GCJ-02坐标系,包括高德地图,谷歌地图中国区等。

BD-09 – 百度坐标系

BD-09(Baidu, BD)是百度地图使用的地理坐标系,其在GCJ-02上多增加了一次变换,用来保护用户隐私。从百度产品中得到的坐标都是BD-09坐标系。

干货前的说明

其实可以这么理解,火星坐标系是在标准坐标系的基础上进行了一次加密,加密也就是加了一次位置的偏移量,而百度坐标系是进行了两次加密

WGS84转GCJ-02代码

#include <stdio.h>
#include <math.h>double lng_r,lat_r,tran_lng,tran_lat;
double dlat,dlng,radlat,magic,sqrtmagic;
double mglat,mglng,lngtitude,lattitude;double lng_w = 120.13372381819;  //标准坐标系 
double lat_w = 30.181981289109;double PI = 3.1415926535897932384626;
double ee = 0.00669342162296594323;
int a = 6378245;//标准坐标系WGS84转GCJ-02火星坐标系
void WG_to_GCJ(float lng,float lat)
{lng_r = lng - 105.0;lat_r = lat - 35.0;//经度转换 tran_lng= 300.0 + lng_r + 2.0 * lat_r + 0.1 * lng_r * lng_r + 0.1 * lng_r * lat_r + 0.1 * sqrt(abs(lng_r));tran_lng = tran_lng + (20.0 * sin(6.0 * lng_r * PI) + 20.0 * sin(2.0 * lng_r * PI)) * 2.0 / 3.0;tran_lng = tran_lng + (20.0 * sin(lng_r * PI) + 40.0 * sin(lng_r / 3.0 * PI)) * 2.0 / 3.0;tran_lng = tran_lng + (150.0 * sin(lng_r / 12.0 * PI) + 300.0 * sin(lng_r / 30.0 * PI)) * 2.0 / 3.0;//转换纬度tran_lat = -100.0 + 2.0 * lng_r + 3.0 * lat_r + 0.2 * lat_r * lat_r + 0.1 * lng_r * lat_r + 0.2 * sqrt(abs(lng_r));tran_lat = tran_lat+(20.0 * sin(6.0 * lng_r * PI) + 20.0 * sin(2.0 * lng_r * PI)) * 2.0 / 3.0;tran_lat = tran_lat+(20.0 * sin(lat_r * PI) + 40.0 * sin(lat_r / 3.0 * PI)) * 2.0 / 3.0;tran_lat = tran_lat+(160.0 * sin(lat_r / 12.0 * PI) + 320 * sin(lat_r * PI / 30.0)) * 2.0 / 3.0;dlat = tran_lat;dlng = tran_lng;radlat = lat/180.0 * PI;magic = sin(radlat);magic = 1- ee * magic * magic;sqrtmagic = sqrt(magic);dlat = (dlat * 180.0)/((a * (1-ee))/(magic * sqrtmagic)*PI);dlng = (dlng * 180.0)/(a / sqrtmagic * cos(radlat) * PI);mglat = lat + dlat;mglng = lng + dlng;printf("%lf,%lf\r\n",mglat,mglng);} int main(void){WG_to_GCJ(lng_w,lat_w);return 0;  }

GCJ-02转WGS84代码


double lng_r,lat_r,tran_lng,tran_lat;
double dlat,dlng,radlat,magic,sqrtmagic;
double mglat,mglng,lngtitude,lattitude;double lng_G = 120.13845564;  //火星坐标系 
double lat_G = 30.17967337889;double PI = 3.1415926535897932384626;
double ee = 0.00669342162296594323;
int a = 6378245;void GCJ_to_WG(float lng,float lat)
{lng_r = lng - 105.0;lat_r = lat - 35.0;//转换经度 tran_lng= 300.0 + lng_r + 2.0 * lat_r + 0.1 * lng_r * lng_r + 0.1 * lng_r * lat_r + 0.1 * sqrt(abs(lng_r));tran_lng = tran_lng + (20.0 * sin(6.0 * lng_r * PI) + 20.0 * sin(2.0 * lng_r * PI)) * 2.0 / 3.0;tran_lng = tran_lng + (20.0 * sin(lng_r * PI) + 40.0 * sin(lng_r / 3.0 * PI)) * 2.0 / 3.0;tran_lng = tran_lng + (150.0 * sin(lng_r / 12.0 * PI) + 300.0 * sin(lng_r / 30.0 * PI)) * 2.0 / 3.0;//转换纬度tran_lat = -100.0 + 2.0 * lng_r + 3.0 * lat_r + 0.2 * lat_r * lat_r + 0.1 * lng_r * lat_r + 0.2 * sqrt(abs(lng_r));tran_lat = tran_lat+(20.0 * sin(6.0 * lng_r * PI) + 20.0 * sin(2.0 * lng_r * PI)) * 2.0 / 3.0;tran_lat = tran_lat+(20.0 * sin(lat_r * PI) + 40.0 * sin(lat_r / 3.0 * PI)) * 2.0 / 3.0;tran_lat = tran_lat+(160.0 * sin(lat_r / 12.0 * PI) + 320 * sin(lat_r * PI / 30.0)) * 2.0 / 3.0;dlat = tran_lat;dlng = tran_lng;radlat = lat/180.0 * PI;magic = sin(radlat);magic = 1- ee * magic * magic;sqrtmagic = sqrt(magic);dlat = (dlat * 180.0)/((a * (1-ee))/(magic * sqrtmagic)*PI);dlng = (dlng * 180.0)/(a / sqrtmagic * cos(radlat) * PI);mglat = lat + dlat;mglng = lng + dlng;lngtitude = lng * 2 - mglng;lattitude = lat * 2 - mglat;printf("%f,%f\r\n",lattitude,lngtitude);
}int main(void){GCJ_to_WG(lng_G,lat_G);return 0;  }

结果

GPS坐标系转换(标准坐标系WGS84转GCJ-02火星坐标系)-编程之家