一、简介

  主流被使用的地理坐标系并不统一,常用的有WGS84、GCJ02(火星坐标系)、BD09(百度坐标系)以及百度地图中保存矢量信息的web墨卡托,本文利用Python编写相关类以实现4种坐标系统之间的互相转换。

二、代码及说明

  1. import math
  2.  
  3. class LngLatTransfer():
  4.  
  5. def __init__(self):
  6. self.x_pi = 3.14159265358979324 * 3000.0 / 180.0
  7. self.pi = math.pi # π
  8. self.a = 6378245.0 # 长半轴
  9. self.es = 0.00669342162296594323 # 偏心率平方
  10. pass
  11.  
  12. def GCJ02_to_BD09(self, gcj_lng, gcj_lat):
  13. """
  14. 实现GCJ02向BD09坐标系的转换
  15. :param lng: GCJ02坐标系下的经度
  16. :param lat: GCJ02坐标系下的纬度
  17. :return: 转换后的BD09下经纬度
  18. """
  19. z = math.sqrt(gcj_lng * gcj_lng + gcj_lat * gcj_lat) + 0.00002 * math.sin(gcj_lat * self.x_pi)
  20. theta = math.atan2(gcj_lat, gcj_lng) + 0.000003 * math.cos(gcj_lng * self.x_pi)
  21. bd_lng = z * math.cos(theta) + 0.0065
  22. bd_lat = z * math.sin(theta) + 0.006
  23. return bd_lng, bd_lat
  24.  
  25. def BD09_to_GCJ02(self, bd_lng, bd_lat):
  26. '''
  27. 实现BD09坐标系向GCJ02坐标系的转换
  28. :param bd_lng: BD09坐标系下的经度
  29. :param bd_lat: BD09坐标系下的纬度
  30. :return: 转换后的GCJ02下经纬度
  31. '''
  32. x = bd_lng - 0.0065
  33. y = bd_lat - 0.006
  34. z = math.sqrt(x * x + y * y) - 0.00002 * math.sin(y * self.x_pi)
  35. theta = math.atan2(y, x) - 0.000003 * math.cos(x * self.x_pi)
  36. gcj_lng = z * math.cos(theta)
  37. gcj_lat = z * math.sin(theta)
  38. return gcj_lng, gcj_lat
  39.  
  40. def WGS84_to_GCJ02(self, lng, lat):
  41. '''
  42. 实现WGS84坐标系向GCJ02坐标系的转换
  43. :param lng: WGS84坐标系下的经度
  44. :param lat: WGS84坐标系下的纬度
  45. :return: 转换后的GCJ02下经纬度
  46. '''
  47. dlat = self._transformlat(lng - 105.0, lat - 35.0)
  48. dlng = self._transformlng(lng - 105.0, lat - 35.0)
  49. radlat = lat / 180.0 * self.pi
  50. magic = math.sin(radlat)
  51. magic = 1 - self.es * magic * magic
  52. sqrtmagic = math.sqrt(magic)
  53. dlat = (dlat * 180.0) / ((self.a * (1 - self.es)) / (magic * sqrtmagic) * self.pi)
  54. dlng = (dlng * 180.0) / (self.a / sqrtmagic * math.cos(radlat) * self.pi)
  55. gcj_lng = lat + dlat
  56. gcj_lat = lng + dlng
  57. return gcj_lng, gcj_lat
  58.  
  59. def GCJ02_to_WGS84(self, gcj_lng, gcj_lat):
  60. '''
  61. 实现GCJ02坐标系向WGS84坐标系的转换
  62. :param gcj_lng: GCJ02坐标系下的经度
  63. :param gcj_lat: GCJ02坐标系下的纬度
  64. :return: 转换后的WGS84下经纬度
  65. '''
  66. dlat = self._transformlat(gcj_lng - 105.0, gcj_lat - 35.0)
  67. dlng = self._transformlng(gcj_lng - 105.0, gcj_lat - 35.0)
  68. radlat = gcj_lat / 180.0 * self.pi
  69. magic = math.sin(radlat)
  70. magic = 1 - self.es * magic * magic
  71. sqrtmagic = math.sqrt(magic)
  72. dlat = (dlat * 180.0) / ((self.a * (1 - self.es)) / (magic * sqrtmagic) * self.pi)
  73. dlng = (dlng * 180.0) / (self.a / sqrtmagic * math.cos(radlat) * self.pi)
  74. mglat = gcj_lat + dlat
  75. mglng = gcj_lng + dlng
  76. lng = gcj_lng * 2 - mglng
  77. lat = gcj_lat * 2 - mglat
  78. return lng, lat
  79.  
  80. def BD09_to_WGS84(self, bd_lng, bd_lat):
  81. '''
  82. 实现BD09坐标系向WGS84坐标系的转换
  83. :param bd_lng: BD09坐标系下的经度
  84. :param bd_lat: BD09坐标系下的纬度
  85. :return: 转换后的WGS84下经纬度
  86. '''
  87. lng, lat = self.BD09_to_GCJ02(bd_lng, bd_lat)
  88. return self.GCJ02_to_WGS84(lng, lat)
  89.  
  90. def WGS84_to_BD09(self, lng, lat):
  91. '''
  92. 实现WGS84坐标系向BD09坐标系的转换
  93. :param lng: WGS84坐标系下的经度
  94. :param lat: WGS84坐标系下的纬度
  95. :return: 转换后的BD09下经纬度
  96. '''
  97. lng, lat = self.WGS84_to_GCJ02(lng, lat)
  98. return self.GCJ02_to_BD09(lng, lat)
  99.  
  100. def _transformlat(self, lng, lat):
  101. ret = -100.0 + 2.0 * lng + 3.0 * lat + 0.2 * lat * lat + \
  102. 0.1 * lng * lat + 0.2 * math.sqrt(math.fabs(lng))
  103. ret += (20.0 * math.sin(6.0 * lng * self.pi) + 20.0 *
  104. math.sin(2.0 * lng * self.pi)) * 2.0 / 3.0
  105. ret += (20.0 * math.sin(lat * self.pi) + 40.0 *
  106. math.sin(lat / 3.0 * self.pi)) * 2.0 / 3.0
  107. ret += (160.0 * math.sin(lat / 12.0 * self.pi) + 320 *
  108. math.sin(lat * self.pi / 30.0)) * 2.0 / 3.0
  109. return ret
  110.  
  111. def _transformlng(self, lng, lat):
  112. ret = 300.0 + lng + 2.0 * lat + 0.1 * lng * lng + \
  113. 0.1 * lng * lat + 0.1 * math.sqrt(math.fabs(lng))
  114. ret += (20.0 * math.sin(6.0 * lng * self.pi) + 20.0 *
  115. math.sin(2.0 * lng * self.pi)) * 2.0 / 3.0
  116. ret += (20.0 * math.sin(lng * self.pi) + 40.0 *
  117. math.sin(lng / 3.0 * self.pi)) * 2.0 / 3.0
  118. ret += (150.0 * math.sin(lng / 12.0 * self.pi) + 300.0 *
  119. math.sin(lng / 30.0 * self.pi)) * 2.0 / 3.0
  120. return ret
  121.  
  122. def WGS84_to_WebMercator(self, lng, lat):
  123. '''
  124. 实现WGS84向web墨卡托的转换
  125. :param lng: WGS84经度
  126. :param lat: WGS84纬度
  127. :return: 转换后的web墨卡托坐标
  128. '''
  129. x = lng * 20037508.342789 / 180
  130. y = math.log(math.tan((90 + lat) * self.pi / 360)) / (self.pi / 180)
  131. y = y * 20037508.34789 / 180
  132. return x, y
  133.  
  134. def WebMercator_to_WGS84(self, x, y):
  135. '''
  136. 实现web墨卡托向WGS84的转换
  137. :param x: web墨卡托x坐标
  138. :param y: web墨卡托y坐标
  139. :return: 转换后的WGS84经纬度
  140. '''
  141. lng = x / 20037508.34 * 180
  142. lat = y / 20037508.34 * 180
  143. lat = 180 / self.pi * (2 * math.atan(math.exp(lat * self.pi / 180)) - self.pi / 2)
  144. return lng, lat

  整个模块的使用方式可用下面的导图概括,其中每个函数都只需要传入经纬度坐标信息:

  以上就是本文的全部内容,如有笔误之处望指出!

(数据科学学习手札60)用Python实现WGS84、火星坐标系、百度坐标系、web墨卡托四种坐标相互转换的更多相关文章

  1. (数据科学学习手札90)Python+Kepler.gl轻松制作时间轮播图

    本文示例代码及数据已上传至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes 1 简介 Kepler.gl作为一款强大的开源地理信 ...

  2. (数据科学学习手札32)Python中re模块的详细介绍

    一.简介 关于正则表达式,我在前一篇(数据科学学习手札31)中已经做了详细介绍,本篇将对Python中自带模块re的常用功能进行总结: re作为Python中专为正则表达式相关功能做出支持的模块,提供 ...

  3. (数据科学学习手札102)Python+Dash快速web应用开发——基础概念篇

    本文示例代码与数据已上传至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes 1 简介 这是我的新系列教程Python+Dash快 ...

  4. (数据科学学习手札121)Python+Dash快速web应用开发——项目结构篇

    本文示例代码已上传至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes 1 简介 这是我的系列教程Python+Dash快速web ...

  5. (数据科学学习手札05)Python与R数据读入存出方式的总结与比较

    在数据分析的过程中,外部数据的导入和数据的导出是非常关键的部分,而Python和R在这方面大同小异,且针对不同的包或模块,对应着不同的函数来完成这部分功能: Python 1.TXT文件 导入: 以某 ...

  6. (数据科学学习手札108)Python+Dash快速web应用开发——静态部件篇(上)

    本文示例代码已上传至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes 1 简介 这是我的系列教程Python+Dash快速web ...

  7. (数据科学学习手札109)Python+Dash快速web应用开发——静态部件篇(中)

    本文示例代码已上传至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes 1 简介 这是我的系列教程Python+Dash快速web ...

  8. (数据科学学习手札112)Python+Dash快速web应用开发——表单控件篇(上)

    本文示例代码已上传至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes 1 简介 这是我的系列教程Python+Dash快速web ...

  9. (数据科学学习手札115)Python+Dash快速web应用开发——交互表格篇(上)

    本文示例代码已上传至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes 1 简介 这是我的系列教程Python+Dash快速web ...

随机推荐

  1. Cocos2d-x 发布 Android

    Cocos2d-x 发布 Android 前置需求: Android NDK Android SDK OR Eclipse ADT Bundle Android AVD target installe ...

  2. Error(10028):Can't resolve multiple constant drivers for net “ ” at **.v

    两个进程里都有同一个条件判断的话,会产生并行信号冲突的问题. 同一个信号不允许在多个进程中赋值,否则则为多驱动. 进程的并行性决定了多进程不同能对同一个对象进行赋值.

  3. buuctf zip伪加密

    平时伪加密总是依赖osx,这道题无法直接解压,所以研究一下伪加密先放两张图(图是偷的)一般在压缩源文件数据区全局方式位标记处,真加密为 09 00,伪加密为00 00,而后面将压缩源文件目录区全局方式 ...

  4. CG-CTF web部分wp

    bin不动了,学学webWEB1,签到1f12,得到flag2,签到2给了输入窗口和密码,但输入后却显示错误,查看源码,发现对输入长度进行了限制,改下长度,得到flag3,md5 collision给 ...

  5. 使用androidstudio时遇到的一些小错误

    1 路径名字中不能有汉字  报如下错误:Error:(1, 0) Your project path contains non-ASCII characters. This will most lik ...

  6. 同域SQL server 做镜像服务器遇到1418错误

    今天遇到了如题所说的错误,查了一天没有看到好的解决方案,因为作者是小白,所以对于解决方案都是代码的那种,完全理解不了. 现在,讲述一下我的解决方法.因为是同域的服务器,这个时候说网络访问不了对方,但是 ...

  7. readme.md常用格式的编写

    md是Markdown的缩写,md是一种易读易写的文本格式(easy-to-read, easy-to-write plain text format),并且可以很方便的转换成HTML格式显示在网页中 ...

  8. Spring下载maven

    http://maven.springframework.org/release/org/springframework/spring/

  9. json数据返回数字,页面显示文字处理

    var obj = { 1:'你好1', 2:'你好2', 3:'你好3' } var e = obj[1]; e; //'你好1'

  10. String类型的时间大小比较

    不多废话,上代码   (String 的CompareTo方法比较仅仅限于同位数的字符串比较,格式.位数不一样比较结果会错误,原因是CompareTo比较源码是ASCII的比较) 代码一 packag ...