GCJ-02火星坐标系

GCJ-02火星坐标系

sf2gis@163.com

2015年7月7日

 

1  目标:将准确的坐标信息加入随机误差,从而隐藏真实坐标。

参考:http://kongxz.com/2013/10/wgs-cgj/

2 原理:利用各种数学计算方法,将坐标进行映射。

3 方法:GCJ-02火星坐标系。

国家测绘局发布的GCJ-02加密算法,加密真实坐标,称为火星坐标系。

规定所有发布的地图系统,必须至少使用GCJ-02进行一次加密。

国内偏移量并不一致,一般在几百米范围。

谷歌地图的ditu域名进行了一次加密,其它(如卫星图,map域名)是真实数据。

国内地图厂商一般会进入二次加密(如百度),偏移量在100m左右(少量测试)。

高德使用GCJ-02(参见:http://lbs.amap.com/home/faq/%E5%9D%90%E6%A0%87%E4%BD%93%E7%B3%BB/)。

4 方法:火星坐标与真实坐标转换,GCJ-02与WGS84互转

所有的地图厂商都提供将真实坐标转换为其使用的地图坐标系统的方法,但没有反向转换功能。

4.1 通用方法:eviltransform(推荐)

来源:https://github.com/googollee/eviltransform

开源项目,提供GCJ-02与WGS84的相互转换功能。提供C,JavaScript,Java,go,php等各种语言版本。

(看名字就知道了,这转换真是挺……)

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

eviltransform.wgs2gcj(wgsLat,wgsLng) // javascript

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

快速转换:精度1m~2m。

eviltransform.gcj2wgs(gcjLat,gcjLng) // javascript

准确转换:精度<0.5m。

eviltransform.gcj2wgs_exact(gcjLat,gcjLng) // javascript

4.1.3转换源代码:c

//transform.h

#ifndefTRANSFORM_HEADER

#define TRANSFORM_HEADER

 

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;

      double magic = sin(radLat);

      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;

      var magic = Math.sin(radLat);

      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

高德使用GCJ-02坐标系统,所以可以直接使用其坐标转换API。其Web服务使用无限制,注册后可以批量转换。

注册key之后,使用http请求。

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

返回结果

参考:

http://lbsbbs.amap.com/forum.php?mod=viewthread&tid=724&highlight=%E5%9D%90%E6%A0%87%E8%BD%AC%E6%8D%A2

4.3 百度:WGS84、GCJ02-》百度坐标(2B坐标)

百度地图使用GCJ-02基础上进行二次加密的百度坐标系统,称为2B坐标,只能提供从其它坐标转换为百度坐标的功能。

参考:http://developer.baidu.com/map/index.php?title=jspopular/guide/introduction

 

GCJ-02火星坐标系

sf2gis@163.com

2015年7月7日

 

1  目标:将准确的坐标信息加入随机误差,从而隐藏真实坐标。

参考:http://kongxz.com/2013/10/wgs-cgj/

2 原理:利用各种数学计算方法,将坐标进行映射。

3 方法:GCJ-02火星坐标系。

国家测绘局发布的GCJ-02加密算法,加密真实坐标,称为火星坐标系。

规定所有发布的地图系统,必须至少使用GCJ-02进行一次加密。

国内偏移量并不一致,一般在几百米范围。

谷歌地图的ditu域名进行了一次加密,其它(如卫星图,map域名)是真实数据。

国内地图厂商一般会进入二次加密(如百度),偏移量在100m左右(少量测试)。

高德使用GCJ-02(参见:http://lbs.amap.com/home/faq/%E5%9D%90%E6%A0%87%E4%BD%93%E7%B3%BB/)。

4 方法:火星坐标与真实坐标转换,GCJ-02与WGS84互转

所有的地图厂商都提供将真实坐标转换为其使用的地图坐标系统的方法,但没有反向转换功能。

4.1 通用方法:eviltransform(推荐)

来源:https://github.com/googollee/eviltransform

开源项目,提供GCJ-02与WGS84的相互转换功能。提供C,JavaScript,Java,go,php等各种语言版本。

(看名字就知道了,这转换真是挺……)

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

eviltransform.wgs2gcj(wgsLat,wgsLng) // javascript

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

快速转换:精度1m~2m。

eviltransform.gcj2wgs(gcjLat,gcjLng) // javascript

准确转换:精度<0.5m。

eviltransform.gcj2wgs_exact(gcjLat,gcjLng) // javascript

4.1.3转换源代码:c

//transform.h

#ifndefTRANSFORM_HEADER

#define TRANSFORM_HEADER

 

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;

      double magic = sin(radLat);

      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;

      var magic = Math.sin(radLat);

      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

高德使用GCJ-02坐标系统,所以可以直接使用其坐标转换API。其Web服务使用无限制,注册后可以批量转换。

注册key之后,使用http请求。

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

返回结果

参考:

http://lbsbbs.amap.com/forum.php?mod=viewthread&tid=724&highlight=%E5%9D%90%E6%A0%87%E8%BD%AC%E6%8D%A2

4.3 百度:WGS84、GCJ02-》百度坐标(2B坐标)

百度地图使用GCJ-02基础上进行二次加密的百度坐标系统,称为2B坐标,只能提供从其它坐标转换为百度坐标的功能。

参考:http://developer.baidu.com/map/index.php?title=jspopular/guide/introduction

 

转载自:https://blog.csdn.net/sf2gis2/article/details/46940147

You may also like...