CoordTransform.js 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. /**
  2. * 创建者:王成
  3. * 操作系统:MAC
  4. * 创建日期:2023年1月28日
  5. * 描述:陈浩编写的坐标转换工具
  6. */
  7. /* 引入Cesium */
  8. import * as Cesium from 'cesium';
  9. const BD_FACTOR = (3.14159265358979324 * 3000.0) / 180.0
  10. const PI = 3.1415926535897932384626
  11. const RADIUS = 6378245.0
  12. const EE = 0.00669342162296594323
  13. /**
  14. * 坐标转换主类
  15. */
  16. class CoordTransform {
  17. /**
  18. * 百度坐标系转||BD-09 To GCJ-02
  19. * @param lng
  20. * @param lat
  21. * @returns {number[]}
  22. */
  23. static BD09ToGCJ02(lng, lat) {
  24. let x = +lng - 0.0065
  25. let y = +lat - 0.006
  26. let z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * BD_FACTOR)
  27. let theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * BD_FACTOR)
  28. let gg_lng = z * Math.cos(theta)
  29. let gg_lat = z * Math.sin(theta)
  30. return [gg_lng, gg_lat]
  31. }
  32. /**
  33. * GCJ-02 To BD-09
  34. * @param lng
  35. * @param lat
  36. * @returns {number[]}
  37. * @constructor
  38. */
  39. static GCJ02ToBD09(lng, lat) {
  40. lat = +lat
  41. lng = +lng
  42. let z =
  43. Math.sqrt(lng * lng + lat * lat) + 0.00002 * Math.sin(lat * BD_FACTOR)
  44. let theta = Math.atan2(lat, lng) + 0.000003 * Math.cos(lng * BD_FACTOR)
  45. let bd_lng = z * Math.cos(theta) + 0.0065
  46. let bd_lat = z * Math.sin(theta) + 0.006
  47. return [bd_lng, bd_lat]
  48. }
  49. /**
  50. * WGS-84 To GCJ-02
  51. * @param lng
  52. * @param lat
  53. * @returns {number[]}
  54. */
  55. static WGS84ToGCJ02(lng, lat) {
  56. lat = +lat
  57. lng = +lng
  58. if (this.out_of_china(lng, lat)) {
  59. return [lng, lat]
  60. } else {
  61. let d = this.delta(lng, lat)
  62. return [lng + d[0], lat + d[1]]
  63. }
  64. }
  65. /**
  66. * GCJ-02 To WGS-84
  67. * @param lng
  68. * @param lat
  69. * @returns {number[]}
  70. * @constructor
  71. */
  72. static GCJ02ToWGS84(lng, lat) {
  73. lat = +lat
  74. lng = +lng
  75. if (this.out_of_china(lng, lat)) {
  76. return [lng, lat]
  77. } else {
  78. let d = this.delta(lng, lat)
  79. let mgLng = lng + d[0]
  80. let mgLat = lat + d[1]
  81. return [lng * 2 - mgLng, lat * 2 - mgLat]
  82. }
  83. }
  84. /**
  85. *
  86. * @param lng
  87. * @param lat
  88. * @returns {number[]}
  89. */
  90. static delta(lng, lat) {
  91. let dLng = this.transformLng(lng - 105, lat - 35)
  92. let dLat = this.transformLat(lng - 105, lat - 35)
  93. const radLat = (lat / 180) * PI
  94. let magic = Math.sin(radLat)
  95. magic = 1 - EE * magic * magic
  96. const sqrtMagic = Math.sqrt(magic)
  97. dLng = (dLng * 180) / ((RADIUS / sqrtMagic) * Math.cos(radLat) * PI)
  98. dLat = (dLat * 180) / (((RADIUS * (1 - EE)) / (magic * sqrtMagic)) * PI)
  99. return [dLng, dLat]
  100. }
  101. /**
  102. *
  103. * @param lng
  104. * @param lat
  105. * @returns {number}
  106. */
  107. static transformLng(lng, lat) {
  108. lat = +lat
  109. lng = +lng
  110. let ret =
  111. 300.0 +
  112. lng +
  113. 2.0 * lat +
  114. 0.1 * lng * lng +
  115. 0.1 * lng * lat +
  116. 0.1 * Math.sqrt(Math.abs(lng))
  117. ret +=
  118. ((20.0 * Math.sin(6.0 * lng * PI) + 20.0 * Math.sin(2.0 * lng * PI)) *
  119. 2.0) /
  120. 3.0
  121. ret +=
  122. ((20.0 * Math.sin(lng * PI) + 40.0 * Math.sin((lng / 3.0) * PI)) * 2.0) /
  123. 3.0
  124. ret +=
  125. ((150.0 * Math.sin((lng / 12.0) * PI) +
  126. 300.0 * Math.sin((lng / 30.0) * PI)) *
  127. 2.0) /
  128. 3.0
  129. return ret
  130. }
  131. /**
  132. *
  133. * @param lng
  134. * @param lat
  135. * @returns {number}
  136. */
  137. static transformLat(lng, lat) {
  138. lat = +lat
  139. lng = +lng
  140. let ret = -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. * 坐标转换 84转笛卡尔
  173. * @param {Viewer} viewer - 三维场景
  174. * @param {object} position - {lng,lat,alt} 地理坐标
  175. * @param {number} alt - 高度
  176. * @returns {object} Cartesian3 笛卡尔坐标
  177. */
  178. static transformWGS84ToCartesian(viewer, position, alt) {
  179. return position ?
  180. Cesium.Cartesian3.fromDegrees(
  181. position.lng || position.lon,
  182. position.lat,
  183. (position.alt = alt || position.alt),
  184. Cesium.Ellipsoid.WGS84
  185. ) :
  186. Cesium.Cartesian3.ZERO
  187. }
  188. /**
  189. * 坐标转换 笛卡尔转84
  190. * @param {Viewer} viewer - 三维场景
  191. * @param {object} cartesian - 笛卡尔坐标
  192. * @returns {object} - {lng,lat,alt} 地理坐标
  193. */
  194. static transformCartesianToWGS84(viewer, cartesian) {
  195. let ellipsoid = Cesium.Ellipsoid.WGS84
  196. let cartographic = ellipsoid.cartesianToCartographic(cartesian)
  197. return {
  198. lng: Cesium.Math.toDegrees(cartographic.longitude),
  199. lat: Cesium.Math.toDegrees(cartographic.latitude),
  200. alt: cartographic.height
  201. }
  202. }
  203. }
  204. export default CoordTransform