map-utils.js 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. //坐标转换
  2. //WGS84:为一种大地坐标系,也是目前广泛使用的GPS全球卫星定位系统使用的坐标系。
  3. //GCJ02:又称火星坐标系,是由中国国家测绘局制订的地理信息系统的坐标系统。由WGS84坐标系经加密后的坐标系
  4. //BD09:为百度坐标系,在GCJ02坐标系基础上再次加密。其中bd09ll表示百度经纬度坐标,bd09mc表示百度墨卡托米制(mercator)坐标。
  5. //h5在微信浏览器里、uniapp是使用 gcj02 国测局坐标系
  6. //WGS84 GCJ02 BD09
  7. const PI = 3.14159265358979324;
  8. const x_pi = 3.14159265358979324 * 3000.0 / 180.0;
  9. const delta = (lat, lon) => {
  10. // Krasovsky 1940
  11. //
  12. // a = 6378245.0, 1/f = 298.3
  13. // b = a * (1 - f)
  14. // ee = (a^2 - b^2) / a^2;
  15. var a = 6378245.0; // a: 卫星椭球坐标投影到平面地图坐标系的投影因子。
  16. var ee = 0.00669342162296594323; // ee: 椭球的偏心率。
  17. var dLat = transformLat(lon - 105.0, lat - 35.0);
  18. var dLon = transformLon(lon - 105.0, lat - 35.0);
  19. var radLat = lat / 180.0 * PI;
  20. var magic = Math.sin(radLat);
  21. magic = 1 - ee * magic * magic;
  22. var sqrtMagic = Math.sqrt(magic);
  23. dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * PI);
  24. dLon = (dLon * 180.0) / (a / sqrtMagic * Math.cos(radLat) * PI);
  25. return {
  26. 'lat': dLat,
  27. 'lon': dLon
  28. };
  29. }
  30. //WGS-84 to GCJ-02
  31. const gcj_encrypt = (wgsLat, wgsLon) => {
  32. if ( outOfChina(wgsLat, wgsLon))
  33. return {
  34. 'lat': wgsLat,
  35. 'lon': wgsLon
  36. };
  37. var d = delta(wgsLat, wgsLon);
  38. return {
  39. 'lat': wgsLat + d.lat,
  40. 'lon': wgsLon + d.lon
  41. };
  42. }
  43. //GCJ-02 to WGS-84
  44. const gcj_decrypt_To_wgs = (gcjLat, gcjLon) => {
  45. if ( outOfChina(gcjLat, gcjLon))
  46. return {
  47. 'lat': gcjLat,
  48. 'lon': gcjLon
  49. };
  50. var d = delta(gcjLat, gcjLon);
  51. return {
  52. 'lat': gcjLat - d.lat,
  53. 'lon': gcjLon - d.lon
  54. };
  55. }
  56. //GCJ-02 to WGS-84 exactly
  57. const gcj_decrypt_exact = (gcjLat, gcjLon) => {
  58. var initDelta = 0.01;
  59. var threshold = 0.000000001;
  60. var dLat = initDelta,
  61. dLon = initDelta;
  62. var mLat = gcjLat - dLat,
  63. mLon = gcjLon - dLon;
  64. var pLat = gcjLat + dLat,
  65. pLon = gcjLon + dLon;
  66. var wgsLat, wgsLon, i = 0;
  67. while (1) {
  68. wgsLat = (mLat + pLat) / 2;
  69. wgsLon = (mLon + pLon) / 2;
  70. var tmp = gcj_encrypt(wgsLat, wgsLon)
  71. dLat = tmp.lat - gcjLat;
  72. dLon = tmp.lon - gcjLon;
  73. if ((Math.abs(dLat) < threshold) && (Math.abs(dLon) < threshold))
  74. break;
  75. if (dLat > 0) pLat = wgsLat;
  76. else mLat = wgsLat;
  77. if (dLon > 0) pLon = wgsLon;
  78. else mLon = wgsLon;
  79. if (++i > 10000) break;
  80. }
  81. //console.log(i);
  82. return {
  83. 'lat': wgsLat,
  84. 'lon': wgsLon
  85. };
  86. }
  87. //GCJ-02 to BD-09
  88. const bd_encrypt = (gcjLat, gcjLon) => {
  89. var x = gcjLon,
  90. y = gcjLat;
  91. var z = Math.sqrt(x * x + y * y) + 0.00002 * Math.sin(y * x_pi);
  92. var theta = Math.atan2(y, x) + 0.000003 * Math.cos(x * x_pi);
  93. bdLon = z * Math.cos(theta) + 0.0065;
  94. bdLat = z * Math.sin(theta) + 0.006;
  95. return {
  96. 'lat': bdLat,
  97. 'lon': bdLon
  98. };
  99. }
  100. //BD-09 to GCJ-02
  101. const bd_decrypt_To_gcj = (bdLat, bdLon) => {
  102. var x = bdLon - 0.0065,
  103. y = bdLat - 0.006;
  104. var z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * x_pi);
  105. var theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * x_pi);
  106. var gcjLon = z * Math.cos(theta);
  107. var gcjLat = z * Math.sin(theta);
  108. return {
  109. 'lat': gcjLat,
  110. 'lon': gcjLon
  111. };
  112. }
  113. //WGS-84 to Web mercator
  114. //mercatorLat -> y mercatorLon -> x
  115. const mercator_encrypt = (wgsLat, wgsLon) => {
  116. var x = wgsLon * 20037508.34 / 180.;
  117. var y = Math.log(Math.tan((90. + wgsLat) * PI / 360.)) / ( PI / 180.);
  118. y = y * 20037508.34 / 180.;
  119. return {
  120. 'lat': y,
  121. 'lon': x
  122. };
  123. /*
  124. if ((Math.abs(wgsLon) > 180 || Math.abs(wgsLat) > 90))
  125. return null;
  126. var x = 6378137.0 * wgsLon * 0.017453292519943295;
  127. var a = wgsLat * 0.017453292519943295;
  128. var y = 3189068.5 * Math.log((1.0 + Math.sin(a)) / (1.0 - Math.sin(a)));
  129. return {'lat' : y, 'lon' : x};
  130. //*/
  131. }
  132. // Web mercator to WGS-84
  133. // mercatorLat -> y mercatorLon -> x
  134. const mercator_decrypt = (mercatorLat, mercatorLon) => {
  135. var x = mercatorLon / 20037508.34 * 180.;
  136. var y = mercatorLat / 20037508.34 * 180.;
  137. y = 180 / PI * (2 * Math.atan(Math.exp(y * PI / 180.)) - PI / 2);
  138. return {
  139. 'lat': y,
  140. 'lon': x
  141. };
  142. /*
  143. if (Math.abs(mercatorLon) < 180 && Math.abs(mercatorLat) < 90)
  144. return null;
  145. if ((Math.abs(mercatorLon) > 20037508.3427892) || (Math.abs(mercatorLat) > 20037508.3427892))
  146. return null;
  147. var a = mercatorLon / 6378137.0 * 57.295779513082323;
  148. var x = a - (Math.floor(((a + 180.0) / 360.0)) * 360.0);
  149. var y = (1.5707963267948966 - (2.0 * Math.atan(Math.exp((-1.0 * mercatorLat) / 6378137.0)))) * 57.295779513082323;
  150. return {'lat' : y, 'lon' : x};
  151. //*/
  152. }
  153. // two point's distance
  154. const distance = (latA, lonA, latB, lonB) => {
  155. var earthR = 6371000.;
  156. var x = Math.cos(latA * PI / 180.) * Math.cos(latB * PI / 180.) * Math.cos((lonA - lonB) * PI / 180);
  157. var y = Math.sin(latA * PI / 180.) * Math.sin(latB * PI / 180.);
  158. var s = x + y;
  159. if (s > 1) s = 1;
  160. if (s < -1) s = -1;
  161. var alpha = Math.acos(s);
  162. var distance = alpha * earthR;
  163. return distance;
  164. }
  165. const outOfChina = (lat, lon) => {
  166. if (lon < 72.004 || lon > 137.8347)
  167. return true;
  168. if (lat < 0.8293 || lat > 55.8271)
  169. return true;
  170. return false;
  171. }
  172. const transformLat = (x, y) => {
  173. 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));
  174. ret += (20.0 * Math.sin(6.0 * x * PI) + 20.0 * Math.sin(2.0 * x * PI)) * 2.0 / 3.0;
  175. ret += (20.0 * Math.sin(y * PI) + 40.0 * Math.sin(y / 3.0 * PI)) * 2.0 / 3.0;
  176. ret += (160.0 * Math.sin(y / 12.0 * PI) + 320 * Math.sin(y * PI / 30.0)) * 2.0 / 3.0;
  177. return ret;
  178. }
  179. const transformLon = (x, y) => {
  180. var ret = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1 * Math.sqrt(Math.abs(x));
  181. ret += (20.0 * Math.sin(6.0 * x * PI) + 20.0 * Math.sin(2.0 * x * PI)) * 2.0 / 3.0;
  182. ret += (20.0 * Math.sin(x * PI) + 40.0 * Math.sin(x / 3.0 * PI)) * 2.0 / 3.0;
  183. ret += (150.0 * Math.sin(x / 12.0 * PI) + 300.0 * Math.sin(x / 30.0 * PI)) * 2.0 / 3.0;
  184. return ret;
  185. }
  186. module.exports = {
  187. bd_decrypt_To_gcj : bd_decrypt_To_gcj ,
  188. gcj_decrypt_To_wgs : gcj_decrypt_To_wgs ,
  189. }