GCJ-02火星坐标系

sf2gis@163.com

2015年7月7日

# 4 方法：火星坐标与真实坐标转换，GCJ-02与WGS84互转

## 4.1 通用方法：eviltransform（推荐）

（看名字就知道了，这转换真是挺……）

### 4.1.1真实坐标转换为火星坐标：WGS84-》GCJ-02

eviltransform.wgs2gcj(wgsLat,wgsLng) // javascript

### 4.1.2火星坐标转换为真实坐标：GCJ-02-》WGS84

eviltransform.gcj2wgs(gcjLat,gcjLng) // javascript

eviltransform.gcj2wgs_exact(gcjLat,gcjLng) // javascript

### 4.1.3转换源代码：c

//transform.h

voidwgs2gcj(double wgsLat, double wgsLng, double *gcjLat, double *gcjLng);

voidgcj2wgs(double gcjLat, double gcjLng, double *wgsLat, double *wgsLnt);

voidgcj2wgs_exact(double gcjLat, double gcjLng, double *wgsLat, double *wgsLnt);

doubledistance(double latA, double lngA, double latB, double lngB);

#endif

//transform.c

#include<math.h>

#include<stdlib.h>

#include"transform.h"

intoutOfChina(double lat, double lng) {

if (lng < 72.004 || lng > 137.8347){

return 1;

}

if (lat < 0.8293 || lat > 55.8271) {

return 1;

}

return 0;

}

voidtransform(double x, double y, double *lat, double *lng) {

double xy = x * y;

double absX = sqrt(fabs(x));

double d = (20.0*sin(6.0*x*M_PI) +20.0*sin(2.0*x*M_PI)) * 2.0 / 3.0;

*lat = -100.0 + 2.0*x + 3.0*y + 0.2*y*y +0.1*xy + 0.2*absX;

*lng = 300.0 + x + 2.0*y + 0.1*x*x +0.1*xy + 0.1*absX;

*lat += d;

*lng += d;

*lat += (20.0*sin(y*M_PI) +40.0*sin(y/3.0*M_PI)) * 2.0 / 3.0;

*lng += (20.0*sin(x*M_PI) +40.0*sin(x/3.0*M_PI)) * 2.0 / 3.0;

*lat += (160.0*sin(y/12.0*M_PI) +320*sin(y/30.0*M_PI)) * 2.0 / 3.0;

*lng += (150.0*sin(x/12.0*M_PI) +300.0*sin(x/30.0*M_PI)) * 2.0 / 3.0;

}

void delta(doublelat, double lng, double *dLat, double *dLng) {

if ((dLat == NULL) || (dLng == NULL)) {

return;

}

const double a = 6378245.0;

const double ee = 0.00669342162296594323;

transform(lng-105.0, lat-35.0, dLat,dLng);

double radLat = lat / 180.0 * M_PI;

magic = 1 - ee*magic*magic;

double sqrtMagic = sqrt(magic);

*dLat = (*dLat * 180.0) / ((a * (1 - ee))/ (magic * sqrtMagic) * M_PI);

*dLng = (*dLng * 180.0) / (a / sqrtMagic *cos(radLat) * M_PI);

}

voidwgs2gcj(double wgsLat, double wgsLng, double *gcjLat, double *gcjLng) {

if ((gcjLat == NULL) || (gcjLng == NULL)){

return;

}

if (outOfChina(wgsLat, wgsLng)) {

*gcjLat = wgsLat;

*gcjLng = wgsLng;

return;

}

double dLat, dLng;

delta(wgsLat, wgsLng, &dLat,&dLng);

*gcjLat = wgsLat + dLat;

*gcjLng = wgsLng + dLng;

}

voidgcj2wgs(double gcjLat, double gcjLng, double *wgsLat, double *wgsLng) {

if ((wgsLat == NULL) || (wgsLng == NULL)){

return;

}

if (outOfChina(gcjLat, gcjLng)) {

*wgsLat = gcjLat;

*wgsLng = gcjLng;

return;

}

double dLat, dLng;

delta(gcjLat, gcjLng, &dLat,&dLng);

*wgsLat = gcjLat - dLat;

*wgsLng = gcjLng - dLng;

}

voidgcj2wgs_exact(double gcjLat, double gcjLng, double *wgsLat, double *wgsLng) {

double dLat, dLng;

// n_iter=2: centimeter precision,n_iter=5: double precision

const int n_iter = 2;

int i;

if ((wgsLat == NULL) || (wgsLng == NULL)){

return;

}

*wgsLat = gcjLat;

*wgsLng = gcjLng;

if (outOfChina(gcjLat, gcjLng)) {

return;

}

for (i = 0; i < n_iter; i++) {

delta(*wgsLat, *wgsLng, &dLat,&dLng);

*wgsLat = gcjLat - dLat;

*wgsLng = gcjLng - dLng;

}

}

// 1 - cos(x) == 2sin^2(x/2)

doubleoneMinusCos(double x)

{

double s = sin(x/2);

return s*s*2;

}

doubledistance(double latA, double lngA, double latB, double lngB) {

const double earthR = 6371000;

latA *= M_PI/180;

latB *= M_PI/180;

lngA *= M_PI/180;

lngB *= M_PI/180;

return2*earthR*asin(sqrt(oneMinusCos(latA-latB) +cos(latA)*cos(latB)*(oneMinusCos(lngA - lngB)))/M_SQRT2);

}

### 4.1.4转换源代码：transform.js

var exports

if (typeof module=== "object" && exports) {

exports = module.exports

} else if (typeofwindow !== "undefined") {

exports =window["eviltransform"] = {}

}

functionoutOfChina(lat, lng) {

if ((lng < 72.004) || (lng >137.8347)) {

return true;

}

if ((lat < 0.8293) || (lat >55.8271)) {

return true;

}

return false;

}

functiontransformLat(x, y) {

var ret = -100.0 + 2.0*x + 3.0*y + 0.2*y*y+ 0.1*x*y + 0.2*Math.sqrt(Math.abs(x));

ret += (20.0*Math.sin(6.0*x*Math.PI) +20.0*Math.sin(2.0*x*Math.PI)) * 2.0 / 3.0;

ret += (20.0*Math.sin(y*Math.PI) +40.0*Math.sin(y/3.0*Math.PI)) * 2.0 / 3.0;

ret += (160.0*Math.sin(y/12.0*Math.PI) +320*Math.sin(y*Math.PI/30.0)) * 2.0 / 3.0;

return ret;

}

functiontransformLon(x, y) {

var ret = 300.0 + x + 2.0*y + 0.1*x*x +0.1*x*y + 0.1*Math.sqrt(Math.abs(x));

ret += (20.0*Math.sin(6.0*x*Math.PI) +20.0*Math.sin(2.0*x*Math.PI)) * 2.0 / 3.0;

ret += (20.0*Math.sin(x*Math.PI) +40.0*Math.sin(x/3.0*Math.PI)) * 2.0 / 3.0;

ret += (150.0*Math.sin(x/12.0*Math.PI) +300.0*Math.sin(x/30.0*Math.PI)) * 2.0 / 3.0;

return ret;

}

functiondelta(lat, lng) {

var a = 6378245.0;

var ee = 0.00669342162296594323;

var dLat = transformLat(lng-105.0,lat-35.0);

var dLng = transformLon(lng-105.0,lat-35.0);

var radLat = lat / 180.0 * Math.PI;

magic = 1 - ee*magic*magic;

var sqrtMagic = Math.sqrt(magic);

dLat = (dLat * 180.0) / ((a * (1 - ee)) /(magic * sqrtMagic) * Math.PI);

dLng = (dLng * 180.0) / (a / sqrtMagic *Math.cos(radLat) * Math.PI);

return {"lat": dLat,"lng": dLng};

}

functionwgs2gcj(wgsLat, wgsLng) {

if (outOfChina(wgsLat, wgsLng)) {

return {"lat": wgsLat,"lng": wgsLng};

}

var d = delta(wgsLat, wgsLng);

return {"lat": wgsLat + d.lat,"lng": wgsLng + d.lng};

}

exports.wgs2gcj =wgs2gcj;

functiongcj2wgs(gcjLat, gcjLng) {

if (outOfChina(gcjLat, gcjLng)) {

return {"lat": gcjLat,"lng": gcjLng};

}

var d = delta(gcjLat, gcjLng);

return {"lat": gcjLat - d.lat,"lng": gcjLng - d.lng};

}

exports.gcj2wgs =gcj2wgs;

functiongcj2wgs_exact(gcjLat, gcjLng) {

var initDelta = 0.01;

var threshold = 0.000001;

var dLat = initDelta, dLng = initDelta;

var mLat = gcjLat-dLat, mLng =gcjLng-dLng;

var pLat = gcjLat+dLat, pLng =gcjLng+dLng;

var wgsLat, wgsLng;

for (var i = 0; i < 30; i++) {

wgsLat = (mLat+pLat)/2;

wgsLng = (mLng+pLng)/2;

var tmp = wgs2gcj(wgsLat, wgsLng)

dLat = tmp.lat-gcjLat;

dLng = tmp.lng-gcjLng;

if ((Math.abs(dLat) < threshold)&& (Math.abs(dLng) < threshold)) {

return {"lat":wgsLat, "lng": wgsLng};

}

if (dLat > 0) {

pLat = wgsLat;

} else {

mLat = wgsLat;

}

if (dLng > 0) {

pLng = wgsLng;

} else {

mLng = wgsLng;

}

}

return {"lat": wgsLat,"lng": wgsLng};

}

exports.gcj2wgs_exact= gcj2wgs_exact;

functiondistance(latA, lngA, latB, lngB) {

var earthR = 6371000;

var x = Math.cos(latA*Math.PI/180) *Math.cos(latB*Math.PI/180) * Math.cos((lngA-lngB)*Math.PI/180);

var y = Math.sin(latA*Math.PI/180) *Math.sin(latB*Math.PI/180);

var s = x + y;

if (s > 1) {

s = 1;

}

if (s < -1) {

s = -1;

}

var alpha = Math.acos(s);

var distance = alpha * earthR;

return distance;

}

exports.distance =distance;

functiongcj2bd(gcjLat, gcjLng) {

if (outOfChina(gcjLat, gcjLng)) {

return {"lat": gcjLat,"lng": gcjLng};

}

var x = gcjLng, y = gcjLat;

var z = Math.sqrt(x * x + y * y) + 0.00002* Math.sin(y * Math.PI);

var theta = Math.atan2(y, x) + 0.000003 *Math.cos(x * Math.PI);

var bdLng = z * Math.cos(theta) + 0.0065;

var bgLat = z * Math.sin(theta) + 0.006;

return {"lat": bdLat,"lng": bdLng};

}

exports.gcj2bd =gcj2bd;

functionbd2gcj(bdLat, bdLng) {

if (outOfChina(bdLat, bdLng)) {

return {"lat": bgLat,"lng": bdLng};

}

var x = bdLng - 0.0065, y = bdLat - 0.006;

var z = Math.sqrt(x * x + y * y) - 0.00002* Math.sin(y * Math.PI);

var theta = Math.atan2(y, x) - 0.000003 *Math.cos(x * Math.PI);

var gcjLng = z * Math.cos(theta);

var gcjLat = z * Math.sin(theta);

return {"lat": gcjLat,"lng": gcjLng};

}

exports.bd2gcj =bd2gcj;

functionwgs2bd(wgsLat, wgsLng) {

var gcj = wgs2gcj(wgsLat, wgsLng)

return gcj2bd(gcj.lat, gcj.lng)

}

exports.wgs2bd =wgs2bd;

functionbd2wgs(bdLat, bdLng) {

var gcj = bd2gcj(bdLat, bdLng)

return gcj2wgs(gcj.lat, gcj.lng)

}

exports.bd2wgs =bd2wgs;

## 4.2 高德：WGS84-》GCJ-02

http://restapi.amap.com/v3/assistant/coordinate/convert?locations=116.481499,39.990475&coordsys=gps&output=xml&key=c67d73f88613f4f574df092a93602c43

GCJ-02火星坐标系

sf2gis@163.com

2015年7月7日

# 4 方法：火星坐标与真实坐标转换，GCJ-02与WGS84互转

## 4.1 通用方法：eviltransform（推荐）

（看名字就知道了，这转换真是挺……）

### 4.1.1真实坐标转换为火星坐标：WGS84-》GCJ-02

eviltransform.wgs2gcj(wgsLat,wgsLng) // javascript

### 4.1.2火星坐标转换为真实坐标：GCJ-02-》WGS84

eviltransform.gcj2wgs(gcjLat,gcjLng) // javascript

eviltransform.gcj2wgs_exact(gcjLat,gcjLng) // javascript

### 4.1.3转换源代码：c

//transform.h

voidwgs2gcj(double wgsLat, double wgsLng, double *gcjLat, double *gcjLng);

voidgcj2wgs(double gcjLat, double gcjLng, double *wgsLat, double *wgsLnt);

voidgcj2wgs_exact(double gcjLat, double gcjLng, double *wgsLat, double *wgsLnt);

doubledistance(double latA, double lngA, double latB, double lngB);

#endif

//transform.c

#include<math.h>

#include<stdlib.h>

#include"transform.h"

intoutOfChina(double lat, double lng) {

if (lng < 72.004 || lng > 137.8347){

return 1;

}

if (lat < 0.8293 || lat > 55.8271) {

return 1;

}

return 0;

}

voidtransform(double x, double y, double *lat, double *lng) {

double xy = x * y;

double absX = sqrt(fabs(x));

double d = (20.0*sin(6.0*x*M_PI) +20.0*sin(2.0*x*M_PI)) * 2.0 / 3.0;

*lat = -100.0 + 2.0*x + 3.0*y + 0.2*y*y +0.1*xy + 0.2*absX;

*lng = 300.0 + x + 2.0*y + 0.1*x*x +0.1*xy + 0.1*absX;

*lat += d;

*lng += d;

*lat += (20.0*sin(y*M_PI) +40.0*sin(y/3.0*M_PI)) * 2.0 / 3.0;

*lng += (20.0*sin(x*M_PI) +40.0*sin(x/3.0*M_PI)) * 2.0 / 3.0;

*lat += (160.0*sin(y/12.0*M_PI) +320*sin(y/30.0*M_PI)) * 2.0 / 3.0;

*lng += (150.0*sin(x/12.0*M_PI) +300.0*sin(x/30.0*M_PI)) * 2.0 / 3.0;

}

void delta(doublelat, double lng, double *dLat, double *dLng) {

if ((dLat == NULL) || (dLng == NULL)) {

return;

}

const double a = 6378245.0;

const double ee = 0.00669342162296594323;

transform(lng-105.0, lat-35.0, dLat,dLng);

double radLat = lat / 180.0 * M_PI;

magic = 1 - ee*magic*magic;

double sqrtMagic = sqrt(magic);

*dLat = (*dLat * 180.0) / ((a * (1 - ee))/ (magic * sqrtMagic) * M_PI);

*dLng = (*dLng * 180.0) / (a / sqrtMagic *cos(radLat) * M_PI);

}

voidwgs2gcj(double wgsLat, double wgsLng, double *gcjLat, double *gcjLng) {

if ((gcjLat == NULL) || (gcjLng == NULL)){

return;

}

if (outOfChina(wgsLat, wgsLng)) {

*gcjLat = wgsLat;

*gcjLng = wgsLng;

return;

}

double dLat, dLng;

delta(wgsLat, wgsLng, &dLat,&dLng);

*gcjLat = wgsLat + dLat;

*gcjLng = wgsLng + dLng;

}

voidgcj2wgs(double gcjLat, double gcjLng, double *wgsLat, double *wgsLng) {

if ((wgsLat == NULL) || (wgsLng == NULL)){

return;

}

if (outOfChina(gcjLat, gcjLng)) {

*wgsLat = gcjLat;

*wgsLng = gcjLng;

return;

}

double dLat, dLng;

delta(gcjLat, gcjLng, &dLat,&dLng);

*wgsLat = gcjLat - dLat;

*wgsLng = gcjLng - dLng;

}

voidgcj2wgs_exact(double gcjLat, double gcjLng, double *wgsLat, double *wgsLng) {

double dLat, dLng;

// n_iter=2: centimeter precision,n_iter=5: double precision

const int n_iter = 2;

int i;

if ((wgsLat == NULL) || (wgsLng == NULL)){

return;

}

*wgsLat = gcjLat;

*wgsLng = gcjLng;

if (outOfChina(gcjLat, gcjLng)) {

return;

}

for (i = 0; i < n_iter; i++) {

delta(*wgsLat, *wgsLng, &dLat,&dLng);

*wgsLat = gcjLat - dLat;

*wgsLng = gcjLng - dLng;

}

}

// 1 - cos(x) == 2sin^2(x/2)

doubleoneMinusCos(double x)

{

double s = sin(x/2);

return s*s*2;

}

doubledistance(double latA, double lngA, double latB, double lngB) {

const double earthR = 6371000;

latA *= M_PI/180;

latB *= M_PI/180;

lngA *= M_PI/180;

lngB *= M_PI/180;

return2*earthR*asin(sqrt(oneMinusCos(latA-latB) +cos(latA)*cos(latB)*(oneMinusCos(lngA - lngB)))/M_SQRT2);

}

### 4.1.4转换源代码：transform.js

var exports

if (typeof module=== "object" && exports) {

exports = module.exports

} else if (typeofwindow !== "undefined") {

exports =window["eviltransform"] = {}

}

functionoutOfChina(lat, lng) {

if ((lng < 72.004) || (lng >137.8347)) {

return true;

}

if ((lat < 0.8293) || (lat >55.8271)) {

return true;

}

return false;

}

functiontransformLat(x, y) {

var ret = -100.0 + 2.0*x + 3.0*y + 0.2*y*y+ 0.1*x*y + 0.2*Math.sqrt(Math.abs(x));

ret += (20.0*Math.sin(6.0*x*Math.PI) +20.0*Math.sin(2.0*x*Math.PI)) * 2.0 / 3.0;

ret += (20.0*Math.sin(y*Math.PI) +40.0*Math.sin(y/3.0*Math.PI)) * 2.0 / 3.0;

ret += (160.0*Math.sin(y/12.0*Math.PI) +320*Math.sin(y*Math.PI/30.0)) * 2.0 / 3.0;

return ret;

}

functiontransformLon(x, y) {

var ret = 300.0 + x + 2.0*y + 0.1*x*x +0.1*x*y + 0.1*Math.sqrt(Math.abs(x));

ret += (20.0*Math.sin(6.0*x*Math.PI) +20.0*Math.sin(2.0*x*Math.PI)) * 2.0 / 3.0;

ret += (20.0*Math.sin(x*Math.PI) +40.0*Math.sin(x/3.0*Math.PI)) * 2.0 / 3.0;

ret += (150.0*Math.sin(x/12.0*Math.PI) +300.0*Math.sin(x/30.0*Math.PI)) * 2.0 / 3.0;

return ret;

}

functiondelta(lat, lng) {

var a = 6378245.0;

var ee = 0.00669342162296594323;

var dLat = transformLat(lng-105.0,lat-35.0);

var dLng = transformLon(lng-105.0,lat-35.0);

var radLat = lat / 180.0 * Math.PI;

magic = 1 - ee*magic*magic;

var sqrtMagic = Math.sqrt(magic);

dLat = (dLat * 180.0) / ((a * (1 - ee)) /(magic * sqrtMagic) * Math.PI);

dLng = (dLng * 180.0) / (a / sqrtMagic *Math.cos(radLat) * Math.PI);

return {"lat": dLat,"lng": dLng};

}

functionwgs2gcj(wgsLat, wgsLng) {

if (outOfChina(wgsLat, wgsLng)) {

return {"lat": wgsLat,"lng": wgsLng};

}

var d = delta(wgsLat, wgsLng);

return {"lat": wgsLat + d.lat,"lng": wgsLng + d.lng};

}

exports.wgs2gcj =wgs2gcj;

functiongcj2wgs(gcjLat, gcjLng) {

if (outOfChina(gcjLat, gcjLng)) {

return {"lat": gcjLat,"lng": gcjLng};

}

var d = delta(gcjLat, gcjLng);

return {"lat": gcjLat - d.lat,"lng": gcjLng - d.lng};

}

exports.gcj2wgs =gcj2wgs;

functiongcj2wgs_exact(gcjLat, gcjLng) {

var initDelta = 0.01;

var threshold = 0.000001;

var dLat = initDelta, dLng = initDelta;

var mLat = gcjLat-dLat, mLng =gcjLng-dLng;

var pLat = gcjLat+dLat, pLng =gcjLng+dLng;

var wgsLat, wgsLng;

for (var i = 0; i < 30; i++) {

wgsLat = (mLat+pLat)/2;

wgsLng = (mLng+pLng)/2;

var tmp = wgs2gcj(wgsLat, wgsLng)

dLat = tmp.lat-gcjLat;

dLng = tmp.lng-gcjLng;

if ((Math.abs(dLat) < threshold)&& (Math.abs(dLng) < threshold)) {

return {"lat":wgsLat, "lng": wgsLng};

}

if (dLat > 0) {

pLat = wgsLat;

} else {

mLat = wgsLat;

}

if (dLng > 0) {

pLng = wgsLng;

} else {

mLng = wgsLng;

}

}

return {"lat": wgsLat,"lng": wgsLng};

}

exports.gcj2wgs_exact= gcj2wgs_exact;

functiondistance(latA, lngA, latB, lngB) {

var earthR = 6371000;

var x = Math.cos(latA*Math.PI/180) *Math.cos(latB*Math.PI/180) * Math.cos((lngA-lngB)*Math.PI/180);

var y = Math.sin(latA*Math.PI/180) *Math.sin(latB*Math.PI/180);

var s = x + y;

if (s > 1) {

s = 1;

}

if (s < -1) {

s = -1;

}

var alpha = Math.acos(s);

var distance = alpha * earthR;

return distance;

}

exports.distance =distance;

functiongcj2bd(gcjLat, gcjLng) {

if (outOfChina(gcjLat, gcjLng)) {

return {"lat": gcjLat,"lng": gcjLng};

}

var x = gcjLng, y = gcjLat;

var z = Math.sqrt(x * x + y * y) + 0.00002* Math.sin(y * Math.PI);

var theta = Math.atan2(y, x) + 0.000003 *Math.cos(x * Math.PI);

var bdLng = z * Math.cos(theta) + 0.0065;

var bgLat = z * Math.sin(theta) + 0.006;

return {"lat": bdLat,"lng": bdLng};

}

exports.gcj2bd =gcj2bd;

functionbd2gcj(bdLat, bdLng) {

if (outOfChina(bdLat, bdLng)) {

return {"lat": bgLat,"lng": bdLng};

}

var x = bdLng - 0.0065, y = bdLat - 0.006;

var z = Math.sqrt(x * x + y * y) - 0.00002* Math.sin(y * Math.PI);

var theta = Math.atan2(y, x) - 0.000003 *Math.cos(x * Math.PI);

var gcjLng = z * Math.cos(theta);

var gcjLat = z * Math.sin(theta);

return {"lat": gcjLat,"lng": gcjLng};

}

exports.bd2gcj =bd2gcj;

functionwgs2bd(wgsLat, wgsLng) {

var gcj = wgs2gcj(wgsLat, wgsLng)

return gcj2bd(gcj.lat, gcj.lng)

}

exports.wgs2bd =wgs2bd;

functionbd2wgs(bdLat, bdLng) {

var gcj = bd2gcj(bdLat, bdLng)

return gcj2wgs(gcj.lat, gcj.lng)

}

exports.bd2wgs =bd2wgs;

## 4.2 高德：WGS84-》GCJ-02

http://restapi.amap.com/v3/assistant/coordinate/convert?locations=116.481499,39.990475&coordsys=gps&output=xml&key=c67d73f88613f4f574df092a93602c43

• 广告
• 抄袭
• 版权
• 政治
• 色情
• 无意义
• 其他

120