使用js对WGS-84 ,GCJ-02与BD-09的坐标进行转换

  1.  
        

    一。在进行地图开发过程中,我们一般能接触到以下三种类型的地图坐标系:

    1.WGS-84原始坐标系,一般用国际GPS纪录仪记录下来的经纬度,通过GPS定位拿到的原始经纬度,Google和高德地图定位的的经纬度(国外)都是基于WGS-84坐标系的;但是在国内是不允许直接用WGS84坐标系标注的,必须经过加密后才能使用;

    2.GCJ-02坐标系,又名“火星坐标系”,是我国国测局独创的坐标体系,由WGS-84加密而成,在国内,必须至少使用GCJ-02坐标系,或者使用在GCJ-02加密后再进行加密的坐标系,如百度坐标系。高德和Google在国内都是使用GCJ-02坐标系,可以说,GCJ-02是国内最广泛使用的坐标系;

    3.百度坐标系:bd-09,百度坐标系是在GCJ-02坐标系的基础上再次加密偏移后形成的坐标系,只适用于百度地图。(目前百度API提供了从其它坐标系转换为百度坐标系的API,但却没有从百度坐标系转为其他坐标系的API)

    二。为什么会发生偏移?

    1.由于坐标系之间不兼容,如在百度地图上定位的经纬度拿到高德地图上直接描点就肯定会发生偏移;只考虑国内的情况,高德地图和Google地图是可以不经过转换也能够准确显示的(在国内用的都是GCJ-02坐标系);下面是收录了网上的WGS-84,GCJ-02,百度坐标系(bd-09)之间的相互转换的方法,经测试,是转换后相对准确可用的:

    作者:青檬可乐_链接:https://www.jianshu.com/p/d3dd4149bb0b來源:简书著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

  2. var GPS = {  
  3.   
  4.     PI: 3.14159265358979324,  
  5.     x_pi: 3.14159265358979324 * 3000.0 / 180.0,  
  6.     delta: function (lat, lon)  
  7.     {  
  8.         // Krasovsky 1940  
  9.         //  
  10.         // a = 6378245.0, 1/f = 298.3  
  11.         // b = a * (1 - f)  
  12.         // ee = (a^2 - b^2) / a^2;  
  13.         var a = 6378245.0; //  a: 卫星椭球坐标投影到平面地图坐标系的投影因子。  
  14.         var ee = 0.00669342162296594323; //  ee: 椭球的偏心率。  
  15.         var dLat = this.transformLat(lon - 105.0, lat - 35.0);  
  16.         var dLon = this.transformLon(lon - 105.0, lat - 35.0);  
  17.         var radLat = lat / 180.0 * this.PI;  
  18.         var magic = Math.sin(radLat);  
  19.         magic = 1 - ee * magic * magic;  
  20.         var sqrtMagic = Math.sqrt(magic);  
  21.         dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * this.PI);  
  22.         dLon = (dLon * 180.0) / (a / sqrtMagic * Math.cos(radLat) * this.PI);  
  23.         return { 'lat': dLat, 'lon': dLon };  
  24.     },  
  25.   
  26.     //WGS-84 to GCJ-02  
  27.     gcj_encrypt: function (wgsLat, wgsLon)  
  28.     {  
  29.         if (this.outOfChina(wgsLat, wgsLon))  
  30.             return { 'lat': wgsLat, 'lon': wgsLon };  
  31.   
  32.         var d = this.delta(wgsLat, wgsLon);  
  33.         return { 'lat': wgsLat + d.lat, 'lon': wgsLon + d.lon };  
  34.     },  
  35.     //GCJ-02 to WGS-84  
  36.     gcj_decrypt: function (gcjLat, gcjLon)  
  37.     {  
  38.         if (this.outOfChina(gcjLat, gcjLon))  
  39.             return { 'lat': gcjLat, 'lon': gcjLon };  
  40.   
  41.         var d = this.delta(gcjLat, gcjLon);  
  42.         return { 'lat': gcjLat - d.lat, 'lon': gcjLon - d.lon };  
  43.     },  
  44.     //GCJ-02 to WGS-84 exactly  
  45.     gcj_decrypt_exact: function (gcjLat, gcjLon)  
  46.     {  
  47.         var initDelta = 0.01;  
  48.         var threshold = 0.000000001;  
  49.         var dLat = initDelta, dLon = initDelta;  
  50.         var mLat = gcjLat - dLat, mLon = gcjLon - dLon;  
  51.         var pLat = gcjLat + dLat, pLon = gcjLon + dLon;  
  52.         var wgsLat, wgsLon, i = 0;  
  53.         while (1)  
  54.         {  
  55.             wgsLat = (mLat + pLat) / 2;  
  56.             wgsLon = (mLon + pLon) / 2;  
  57.             var tmp = this.gcj_encrypt(wgsLat, wgsLon)  
  58.             dLat = tmp.lat - gcjLat;  
  59.             dLon = tmp.lon - gcjLon;  
  60.             if ((Math.abs(dLat) < threshold) && (Math.abs(dLon) < threshold))  
  61.                 break;  
  62.   
  63.             if (dLat > 0) pLat = wgsLat; else mLat = wgsLat;  
  64.             if (dLon > 0) pLon = wgsLon; else mLon = wgsLon;  
  65.   
  66.             if (++i > 10000) break;  
  67.         }  
  68.         //console.log(i);  
  69.         return { 'lat': wgsLat, 'lon': wgsLon };  
  70.     },  
  71.     //GCJ-02 to BD-09  
  72.     bd_encrypt: function (gcjLat, gcjLon)  
  73.     {  
  74.         var x = gcjLon, y = gcjLat;  
  75.         var z = Math.sqrt(x * x + y * y) + 0.00002 * Math.sin(y * this.x_pi);  
  76.         var theta = Math.atan2(y, x) + 0.000003 * Math.cos(x * this.x_pi);  
  77.         bdLon = z * Math.cos(theta) + 0.0065;  
  78.         bdLat = z * Math.sin(theta) + 0.006;  
  79.         return { 'lat': bdLat, 'lon': bdLon };  
  80.     },  
  81.     //BD-09 to GCJ-02  
  82.     bd_decrypt: function (bdLat, bdLon)  
  83.     {  
  84.         var x = bdLon - 0.0065, y = bdLat - 0.006;  
  85.         var z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * this.x_pi);  
  86.         var theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * this.x_pi);  
  87.         var gcjLon = z * Math.cos(theta);  
  88.         var gcjLat = z * Math.sin(theta);  
  89.         return { 'lat': gcjLat, 'lon': gcjLon };  
  90.     },  
  91.     //WGS-84 to Web mercator  
  92.     //mercatorLat -> y mercatorLon -> x  
  93.     mercator_encrypt: function (wgsLat, wgsLon)  
  94.     {  
  95.         var x = wgsLon * 20037508.34 / 180.;  
  96.         var y = Math.log(Math.tan((90. + wgsLat) * this.PI / 360.)) / (this.PI / 180.);  
  97.         y = y * 20037508.34 / 180.;  
  98.         return { 'lat': y, 'lon': x };  
  99.         /* 
  100.         if ((Math.abs(wgsLon) > 180 || Math.abs(wgsLat) > 90)) 
  101.             return null; 
  102.         var x = 6378137.0 * wgsLon * 0.017453292519943295; 
  103.         var a = wgsLat * 0.017453292519943295; 
  104.         var y = 3189068.5 * Math.log((1.0 + Math.sin(a)) / (1.0 - Math.sin(a))); 
  105.         return {'lat' : y, 'lon' : x}; 
  106.         //*/  
  107.     },  
  108.     // Web mercator to WGS-84  
  109.     // mercatorLat -> y mercatorLon -> x  
  110.     mercator_decrypt: function (mercatorLat, mercatorLon)  
  111.     {  
  112.         var x = mercatorLon / 20037508.34 * 180.;  
  113.         var y = mercatorLat / 20037508.34 * 180.;  
  114.         y = 180 / this.PI * (2 * Math.atan(Math.exp(y * this.PI / 180.)) - this.PI / 2);  
  115.         return { 'lat': y, 'lon': x };  
  116.         /* 
  117.         if (Math.abs(mercatorLon) < 180 && Math.abs(mercatorLat) < 90) 
  118.             return null; 
  119.         if ((Math.abs(mercatorLon) > 20037508.3427892) || (Math.abs(mercatorLat) > 20037508.3427892)) 
  120.             return null; 
  121.         var a = mercatorLon / 6378137.0 * 57.295779513082323; 
  122.         var x = a - (Math.floor(((a + 180.0) / 360.0)) * 360.0); 
  123.         var y = (1.5707963267948966 - (2.0 * Math.atan(Math.exp((-1.0 * mercatorLat) / 6378137.0)))) * 57.295779513082323; 
  124.         return {'lat' : y, 'lon' : x}; 
  125.         //*/  
  126.     },  
  127.     // two point's distance  
  128.     distance: function (latA, lonA, latB, lonB)  
  129.     {  
  130.         var earthR = 6371000.;  
  131.         var x = Math.cos(latA * this.PI / 180.) * Math.cos(latB * this.PI / 180.) * Math.cos((lonA - lonB) * this.PI / 180);  
  132.         var y = Math.sin(latA * this.PI / 180.) * Math.sin(latB * this.PI / 180.);  
  133.         var s = x + y;  
  134.         if (s > 1) s = 1;  
  135.         if (s < -1) s = -1;  
  136.         var alpha = Math.acos(s);  
  137.         var distance = alpha * earthR;  
  138.         return distance;  
  139.     },  
  140.     outOfChina: function (lat, lon)  
  141.     {  
  142.         if (lon < 72.004 || lon > 137.8347)  
  143.             return true;  
  144.         if (lat < 0.8293 || lat > 55.8271)  
  145.             return true;  
  146.         return false;  
  147.     },  
  148.     transformLat: function (x, y)  
  149.     {  
  150.         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));  
  151.         ret += (20.0 * Math.sin(6.0 * x * this.PI) + 20.0 * Math.sin(2.0 * x * this.PI)) * 2.0 / 3.0;  
  152.         ret += (20.0 * Math.sin(y * this.PI) + 40.0 * Math.sin(y / 3.0 * this.PI)) * 2.0 / 3.0;  
  153.         ret += (160.0 * Math.sin(y / 12.0 * this.PI) + 320 * Math.sin(y * this.PI / 30.0)) * 2.0 / 3.0;  
  154.         return ret;  
  155.     },  
  156.     transformLon: function (x, y)  
  157.     {  
  158.         var ret = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1 * Math.sqrt(Math.abs(x));  
  159.         ret += (20.0 * Math.sin(6.0 * x * this.PI) + 20.0 * Math.sin(2.0 * x * this.PI)) * 2.0 / 3.0;  
  160.         ret += (20.0 * Math.sin(x * this.PI) + 40.0 * Math.sin(x / 3.0 * this.PI)) * 2.0 / 3.0;  
  161.         ret += (150.0 * Math.sin(x / 12.0 * this.PI) + 300.0 * Math.sin(x / 30.0 * this.PI)) * 2.0 / 3.0;  
  162.         return ret;  
  163.     }  
  164. };  

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值