You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

CoordTransform.js 4.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. /**
  2. * @Author: Caven
  3. * @Date: 2021-01-31 20:40:25
  4. */
  5. const BD_FACTOR = (3.14159265358979324 * 3000.0) / 180.0
  6. const PI = 3.1415926535897932384626
  7. const RADIUS = 6378245.0
  8. const EE = 0.00669342162296594323
  9. class CoordTransform {
  10. /**
  11. * BD-09 To GCJ-02
  12. * @param lng
  13. * @param lat
  14. * @returns {number[]}
  15. */
  16. static BD09ToGCJ02(lng, lat) {
  17. let x = +lng - 0.0065
  18. let y = +lat - 0.006
  19. let z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * BD_FACTOR)
  20. let theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * BD_FACTOR)
  21. let gg_lng = z * Math.cos(theta)
  22. let gg_lat = z * Math.sin(theta)
  23. return [gg_lng, gg_lat]
  24. }
  25. /**
  26. * GCJ-02 To BD-09
  27. * @param lng
  28. * @param lat
  29. * @returns {number[]}
  30. * @constructor
  31. */
  32. static GCJ02ToBD09(lng, lat) {
  33. lat = +lat
  34. lng = +lng
  35. let z =
  36. Math.sqrt(lng * lng + lat * lat) + 0.00002 * Math.sin(lat * BD_FACTOR)
  37. let theta = Math.atan2(lat, lng) + 0.000003 * Math.cos(lng * BD_FACTOR)
  38. let bd_lng = z * Math.cos(theta) + 0.0065
  39. let bd_lat = z * Math.sin(theta) + 0.006
  40. return [bd_lng, bd_lat]
  41. }
  42. /**
  43. * WGS-84 To GCJ-02
  44. * @param lng
  45. * @param lat
  46. * @returns {number[]}
  47. */
  48. static WGS84ToGCJ02(lng, lat) {
  49. lat = +lat
  50. lng = +lng
  51. if (this.out_of_china(lng, lat)) {
  52. return [lng, lat]
  53. } else {
  54. let d = this.delta(lng, lat)
  55. return [lng + d[0], lat + d[1]]
  56. }
  57. }
  58. /**
  59. * GCJ-02 To WGS-84
  60. * @param lng
  61. * @param lat
  62. * @returns {number[]}
  63. * @constructor
  64. */
  65. static GCJ02ToWGS84(lng, lat) {
  66. lat = +lat
  67. lng = +lng
  68. if (this.out_of_china(lng, lat)) {
  69. return [lng, lat]
  70. } else {
  71. let out = [lng, lat]
  72. let gcj02_point = this.WGS84ToGCJ02(lng, lat)
  73. let dlng = gcj02_point[0] - lng
  74. let dlat = gcj02_point[1] - lat
  75. do {
  76. gcj02_point = this.WGS84ToGCJ02((out[0] -= dlng), (out[1] -= dlat))
  77. dlng = gcj02_point[0] - lng
  78. dlat = gcj02_point[1] - lat
  79. } while (Math.abs(dlng) > 1e-7 || Math.abs(dlat) > 1e-7)
  80. return out
  81. }
  82. }
  83. /**
  84. *
  85. * @param lng
  86. * @param lat
  87. * @returns {number[]}
  88. */
  89. static delta(lng, lat) {
  90. let dLng = this.transformLng(lng - 105, lat - 35)
  91. let dLat = this.transformLat(lng - 105, lat - 35)
  92. const radLat = (lat / 180) * PI
  93. let magic = Math.sin(radLat)
  94. magic = 1 - EE * magic * magic
  95. const sqrtMagic = Math.sqrt(magic)
  96. dLng = (dLng * 180) / ((RADIUS / sqrtMagic) * Math.cos(radLat) * PI)
  97. dLat = (dLat * 180) / (((RADIUS * (1 - EE)) / (magic * sqrtMagic)) * PI)
  98. return [dLng, dLat]
  99. }
  100. /**
  101. *
  102. * @param lng
  103. * @param lat
  104. * @returns {number}
  105. */
  106. static transformLng(lng, lat) {
  107. lat = +lat
  108. lng = +lng
  109. let ret =
  110. 300.0 +
  111. lng +
  112. 2.0 * lat +
  113. 0.1 * lng * lng +
  114. 0.1 * lng * lat +
  115. 0.1 * Math.sqrt(Math.abs(lng))
  116. ret +=
  117. ((20.0 * Math.sin(6.0 * lng * PI) + 20.0 * Math.sin(2.0 * lng * PI)) *
  118. 2.0) /
  119. 3.0
  120. ret +=
  121. ((20.0 * Math.sin(lng * PI) + 40.0 * Math.sin((lng / 3.0) * PI)) * 2.0) /
  122. 3.0
  123. ret +=
  124. ((150.0 * Math.sin((lng / 12.0) * PI) +
  125. 300.0 * Math.sin((lng / 30.0) * PI)) *
  126. 2.0) /
  127. 3.0
  128. return ret
  129. }
  130. /**
  131. *
  132. * @param lng
  133. * @param lat
  134. * @returns {number}
  135. */
  136. static transformLat(lng, lat) {
  137. lat = +lat
  138. lng = +lng
  139. let ret =
  140. -100.0 +
  141. 2.0 * lng +
  142. 3.0 * lat +
  143. 0.2 * lat * lat +
  144. 0.1 * lng * lat +
  145. 0.2 * Math.sqrt(Math.abs(lng))
  146. ret +=
  147. ((20.0 * Math.sin(6.0 * lng * PI) + 20.0 * Math.sin(2.0 * lng * PI)) *
  148. 2.0) /
  149. 3.0
  150. ret +=
  151. ((20.0 * Math.sin(lat * PI) + 40.0 * Math.sin((lat / 3.0) * PI)) * 2.0) /
  152. 3.0
  153. ret +=
  154. ((160.0 * Math.sin((lat / 12.0) * PI) +
  155. 320 * Math.sin((lat * PI) / 30.0)) *
  156. 2.0) /
  157. 3.0
  158. return ret
  159. }
  160. /**
  161. *
  162. * @param lng
  163. * @param lat
  164. * @returns {boolean}
  165. */
  166. static out_of_china(lng, lat) {
  167. lat = +lat
  168. lng = +lng
  169. return !(lng > 73.66 && lng < 135.05 && lat > 3.86 && lat < 53.55)
  170. }
  171. }
  172. export default CoordTransform