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;  
 }

结果

python 火星坐标系 转wgs坐标系 火星坐标系转wgs84准确_c语言