各种坐标之间的转换

谁践踏了优雅 2022-04-23 15:58 401阅读 0赞
  1. # -*- coding: utf-8 -*-
  2. import json
  3. import urllib
  4. import math
  5. x_pi = 3.14159265358979324 * 3000.0 / 180.0
  6. pi = 3.1415926535897932384626 # π
  7. a = 6378245.0 # 长半轴
  8. ee = 0.00669342162296594323 # 偏心率平方
  9. class Geocoding:
  10. def __init__(self, api_key):
  11. self.api_key = api_key
  12. def geocode(self, address):
  13. """
  14. 利用高德geocoding服务解析地址获取位置坐标
  15. :param address:需要解析的地址
  16. :return:
  17. """
  18. geocoding = {'s': 'rsv3',
  19. 'key': self.api_key,
  20. 'city': '全国',
  21. 'address': address}
  22. geocoding = urllib.urlencode(geocoding)
  23. ret = urllib.urlopen("%s?%s" % ("http://restapi.amap.com/v3/geocode/geo", geocoding))
  24. if ret.getcode() == 200:
  25. res = ret.read()
  26. json_obj = json.loads(res)
  27. if json_obj['status'] == '1' and int(json_obj['count']) >= 1:
  28. geocodes = json_obj['geocodes'][0]
  29. lng = float(geocodes.get('location').split(',')[0])
  30. lat = float(geocodes.get('location').split(',')[1])
  31. return [lng, lat]
  32. else:
  33. return None
  34. else:
  35. return None
  36. def gcj02_to_bd09(lng, lat):
  37. """
  38. 火星坐标系(GCJ-02)转百度坐标系(BD-09)
  39. 谷歌、高德——>百度
  40. :param lng:火星坐标经度
  41. :param lat:火星坐标纬度
  42. :return:
  43. """
  44. z = math.sqrt(lng * lng + lat * lat) + 0.00002 * math.sin(lat * x_pi)
  45. theta = math.atan2(lat, lng) + 0.000003 * math.cos(lng * x_pi)
  46. bd_lng = z * math.cos(theta) + 0.0065
  47. bd_lat = z * math.sin(theta) + 0.006
  48. return [bd_lng, bd_lat]
  49. def bd09_to_gcj02(bd_lon, bd_lat):
  50. """
  51. 百度坐标系(BD-09)转火星坐标系(GCJ-02)
  52. 百度——>谷歌、高德
  53. :param bd_lat:百度坐标纬度
  54. :param bd_lon:百度坐标经度
  55. :return:转换后的坐标列表形式
  56. """
  57. x = bd_lon - 0.0065
  58. y = bd_lat - 0.006
  59. z = math.sqrt(x * x + y * y) - 0.00002 * math.sin(y * x_pi)
  60. theta = math.atan2(y, x) - 0.000003 * math.cos(x * x_pi)
  61. gg_lng = z * math.cos(theta)
  62. gg_lat = z * math.sin(theta)
  63. return [gg_lng, gg_lat]
  64. def wgs84_to_gcj02(lng, lat):
  65. """
  66. WGS84转GCJ02(火星坐标系)
  67. :param lng:WGS84坐标系的经度
  68. :param lat:WGS84坐标系的纬度
  69. :return:
  70. """
  71. if out_of_china(lng, lat): # 判断是否在国内
  72. return [lng, lat]
  73. dlat = _transformlat(lng - 105.0, lat - 35.0)
  74. dlng = _transformlng(lng - 105.0, lat - 35.0)
  75. radlat = lat / 180.0 * pi
  76. magic = math.sin(radlat)
  77. magic = 1 - ee * magic * magic
  78. sqrtmagic = math.sqrt(magic)
  79. dlat = (dlat * 180.0) / ((a * (1 - ee)) / (magic * sqrtmagic) * pi)
  80. dlng = (dlng * 180.0) / (a / sqrtmagic * math.cos(radlat) * pi)
  81. mglat = lat + dlat
  82. mglng = lng + dlng
  83. return [mglng, mglat]
  84. def gcj02_to_wgs84(lng, lat):
  85. """
  86. GCJ02(火星坐标系)转GPS84
  87. :param lng:火星坐标系的经度
  88. :param lat:火星坐标系纬度
  89. :return:
  90. """
  91. if out_of_china(lng, lat):
  92. return [lng, lat]
  93. dlat = _transformlat(lng - 105.0, lat - 35.0)
  94. dlng = _transformlng(lng - 105.0, lat - 35.0)
  95. radlat = lat / 180.0 * pi
  96. magic = math.sin(radlat)
  97. magic = 1 - ee * magic * magic
  98. sqrtmagic = math.sqrt(magic)
  99. dlat = (dlat * 180.0) / ((a * (1 - ee)) / (magic * sqrtmagic) * pi)
  100. dlng = (dlng * 180.0) / (a / sqrtmagic * math.cos(radlat) * pi)
  101. mglat = lat + dlat
  102. mglng = lng + dlng
  103. return [lng * 2 - mglng, lat * 2 - mglat]
  104. def bd09_to_wgs84(bd_lon, bd_lat):
  105. lon, lat = bd09_to_gcj02(bd_lon, bd_lat)
  106. return gcj02_to_wgs84(lon, lat)
  107. def wgs84_to_bd09(lon, lat):
  108. lon, lat = wgs84_to_gcj02(lon, lat)
  109. return gcj02_to_bd09(lon, lat)
  110. def _transformlat(lng, lat):
  111. ret = -100.0 + 2.0 * lng + 3.0 * lat + 0.2 * lat * lat + \
  112. 0.1 * lng * lat + 0.2 * math.sqrt(math.fabs(lng))
  113. ret += (20.0 * math.sin(6.0 * lng * pi) + 20.0 *
  114. math.sin(2.0 * lng * pi)) * 2.0 / 3.0
  115. ret += (20.0 * math.sin(lat * pi) + 40.0 *
  116. math.sin(lat / 3.0 * pi)) * 2.0 / 3.0
  117. ret += (160.0 * math.sin(lat / 12.0 * pi) + 320 *
  118. math.sin(lat * pi / 30.0)) * 2.0 / 3.0
  119. return ret
  120. def _transformlng(lng, lat):
  121. ret = 300.0 + lng + 2.0 * lat + 0.1 * lng * lng + \
  122. 0.1 * lng * lat + 0.1 * math.sqrt(math.fabs(lng))
  123. ret += (20.0 * math.sin(6.0 * lng * pi) + 20.0 *
  124. math.sin(2.0 * lng * pi)) * 2.0 / 3.0
  125. ret += (20.0 * math.sin(lng * pi) + 40.0 *
  126. math.sin(lng / 3.0 * pi)) * 2.0 / 3.0
  127. ret += (150.0 * math.sin(lng / 12.0 * pi) + 300.0 *
  128. math.sin(lng / 30.0 * pi)) * 2.0 / 3.0
  129. return ret
  130. # wgs84-WebMercator
  131. def wgs84toWebMercator(lon, lat):
  132. x = lon * 20037508.342789 / 180
  133. y = math.log(math.tan((90 + lat) * math.pi / 360)) / (math.pi / 180)
  134. y = y * 20037508.34789 / 180
  135. return x, y
  136. # WebMercator-wgs84
  137. def webMercator2wgs84(x, y):
  138. lon = x / 20037508.34 * 180
  139. lat = y / 20037508.34 * 180
  140. lat = 180 / math.pi * (2 * math.atan(math.exp(lat * math.pi / 180)) - math.pi / 2)
  141. return lon, lat
  142. def out_of_china(lng, lat):
  143. """
  144. 判断是否在国内,不在国内不做偏移
  145. :param lng:
  146. :param lat:
  147. :return:
  148. """
  149. return not (lng > 73.66 and lng < 135.05 and lat > 3.86 and lat < 53.55)
  150. if __name__ == '__main__':
  151. lng =12945569.87#12945500.55004295# 12951862.38736606 # 128.543
  152. lat =4832576.84#4833565.8750497345 # 4837023.139194939 # 37.065
  153. lon, lat = webMercator2wgs84(lng, lat)
  154. # result1 = gcj02_to_bd09(lng, lat) # 火星坐标系->百度坐标系
  155. # result2 = bd09_to_gcj02(lng, lat) # 百度坐标系->火星坐标系
  156. # result3 = wgs84_to_gcj02(lng, lat) # WGS84坐标系->火星坐标系
  157. # result4 = gcj02_to_wgs84(lng, lat) # 火星坐标系->WGS84坐标系
  158. # result5 = bd09_to_wgs84(lng, lat) # 百度坐标系->WGS84坐标系
  159. # result6 = wgs84_to_bd09(lng, lat) # WGS84坐标系->百度坐标系
  160. # 中文地址到火星坐标系,需要高德地图API Key
  161. # g = Geocoding('API_KEY') # 这里填写你的高德Api_Key
  162. # result7 = g.geocode('北京市朝阳区朝阳公园')
  163. print(lon, lat)

发表评论

表情:
评论列表 (有 0 条评论,401人围观)

还没有评论,来说两句吧...

相关阅读

    相关 经纬度坐标和投影坐标转换

    昨天,有朋友要我帮忙看看一个将经纬度坐标转换成墨卡托投影(墨卡托投影有很多变种,我也不知道他说的是哪一种)的程序,他说转换以后的坐标精度太差。当时,他的程序没怎么看懂,然后研究

    相关 各种文件之间转换

    一、把PPT转WORD形式的方法  1.利用"大纲"视图  打开PPT演示文稿,单击"大纲",在左侧"幻灯片/大纲”任务窗格的“大纲”选项卡里单击一下鼠标,按"Ctrl+A