(数据科学学习手札60)用Python实现WGS84、火星坐标系、百度坐标系、web墨卡托四种坐标相互转换
一、简介
主流被使用的地理坐标系并不统一,常用的有WGS84、GCJ02(火星坐标系)、BD09(百度坐标系)以及百度地图中保存矢量信息的web墨卡托,本文利用Python编写相关类以实现4种坐标系统之间的互相转换。
二、代码及说明
- import math
- class LngLatTransfer():
- def __init__(self):
- self.x_pi = 3.14159265358979324 * 3000.0 / 180.0
- self.pi = math.pi # π
- self.a = 6378245.0 # 长半轴
- self.es = 0.00669342162296594323 # 偏心率平方
- pass
- def GCJ02_to_BD09(self, gcj_lng, gcj_lat):
- """
- 实现GCJ02向BD09坐标系的转换
- :param lng: GCJ02坐标系下的经度
- :param lat: GCJ02坐标系下的纬度
- :return: 转换后的BD09下经纬度
- """
- z = math.sqrt(gcj_lng * gcj_lng + gcj_lat * gcj_lat) + 0.00002 * math.sin(gcj_lat * self.x_pi)
- theta = math.atan2(gcj_lat, gcj_lng) + 0.000003 * math.cos(gcj_lng * self.x_pi)
- bd_lng = z * math.cos(theta) + 0.0065
- bd_lat = z * math.sin(theta) + 0.006
- return bd_lng, bd_lat
- def BD09_to_GCJ02(self, bd_lng, bd_lat):
- '''
- 实现BD09坐标系向GCJ02坐标系的转换
- :param bd_lng: BD09坐标系下的经度
- :param bd_lat: BD09坐标系下的纬度
- :return: 转换后的GCJ02下经纬度
- '''
- x = bd_lng - 0.0065
- y = bd_lat - 0.006
- z = math.sqrt(x * x + y * y) - 0.00002 * math.sin(y * self.x_pi)
- theta = math.atan2(y, x) - 0.000003 * math.cos(x * self.x_pi)
- gcj_lng = z * math.cos(theta)
- gcj_lat = z * math.sin(theta)
- return gcj_lng, gcj_lat
- def WGS84_to_GCJ02(self, lng, lat):
- '''
- 实现WGS84坐标系向GCJ02坐标系的转换
- :param lng: WGS84坐标系下的经度
- :param lat: WGS84坐标系下的纬度
- :return: 转换后的GCJ02下经纬度
- '''
- dlat = self._transformlat(lng - 105.0, lat - 35.0)
- dlng = self._transformlng(lng - 105.0, lat - 35.0)
- radlat = lat / 180.0 * self.pi
- magic = math.sin(radlat)
- magic = 1 - self.es * magic * magic
- sqrtmagic = math.sqrt(magic)
- dlat = (dlat * 180.0) / ((self.a * (1 - self.es)) / (magic * sqrtmagic) * self.pi)
- dlng = (dlng * 180.0) / (self.a / sqrtmagic * math.cos(radlat) * self.pi)
- gcj_lng = lat + dlat
- gcj_lat = lng + dlng
- return gcj_lng, gcj_lat
- def GCJ02_to_WGS84(self, gcj_lng, gcj_lat):
- '''
- 实现GCJ02坐标系向WGS84坐标系的转换
- :param gcj_lng: GCJ02坐标系下的经度
- :param gcj_lat: GCJ02坐标系下的纬度
- :return: 转换后的WGS84下经纬度
- '''
- dlat = self._transformlat(gcj_lng - 105.0, gcj_lat - 35.0)
- dlng = self._transformlng(gcj_lng - 105.0, gcj_lat - 35.0)
- radlat = gcj_lat / 180.0 * self.pi
- magic = math.sin(radlat)
- magic = 1 - self.es * magic * magic
- sqrtmagic = math.sqrt(magic)
- dlat = (dlat * 180.0) / ((self.a * (1 - self.es)) / (magic * sqrtmagic) * self.pi)
- dlng = (dlng * 180.0) / (self.a / sqrtmagic * math.cos(radlat) * self.pi)
- mglat = gcj_lat + dlat
- mglng = gcj_lng + dlng
- lng = gcj_lng * 2 - mglng
- lat = gcj_lat * 2 - mglat
- return lng, lat
- def BD09_to_WGS84(self, bd_lng, bd_lat):
- '''
- 实现BD09坐标系向WGS84坐标系的转换
- :param bd_lng: BD09坐标系下的经度
- :param bd_lat: BD09坐标系下的纬度
- :return: 转换后的WGS84下经纬度
- '''
- lng, lat = self.BD09_to_GCJ02(bd_lng, bd_lat)
- return self.GCJ02_to_WGS84(lng, lat)
- def WGS84_to_BD09(self, lng, lat):
- '''
- 实现WGS84坐标系向BD09坐标系的转换
- :param lng: WGS84坐标系下的经度
- :param lat: WGS84坐标系下的纬度
- :return: 转换后的BD09下经纬度
- '''
- lng, lat = self.WGS84_to_GCJ02(lng, lat)
- return self.GCJ02_to_BD09(lng, lat)
- def _transformlat(self, lng, lat):
- ret = -100.0 + 2.0 * lng + 3.0 * lat + 0.2 * lat * lat + \
- 0.1 * lng * lat + 0.2 * math.sqrt(math.fabs(lng))
- ret += (20.0 * math.sin(6.0 * lng * self.pi) + 20.0 *
- math.sin(2.0 * lng * self.pi)) * 2.0 / 3.0
- ret += (20.0 * math.sin(lat * self.pi) + 40.0 *
- math.sin(lat / 3.0 * self.pi)) * 2.0 / 3.0
- ret += (160.0 * math.sin(lat / 12.0 * self.pi) + 320 *
- math.sin(lat * self.pi / 30.0)) * 2.0 / 3.0
- return ret
- def _transformlng(self, lng, lat):
- ret = 300.0 + lng + 2.0 * lat + 0.1 * lng * lng + \
- 0.1 * lng * lat + 0.1 * math.sqrt(math.fabs(lng))
- ret += (20.0 * math.sin(6.0 * lng * self.pi) + 20.0 *
- math.sin(2.0 * lng * self.pi)) * 2.0 / 3.0
- ret += (20.0 * math.sin(lng * self.pi) + 40.0 *
- math.sin(lng / 3.0 * self.pi)) * 2.0 / 3.0
- ret += (150.0 * math.sin(lng / 12.0 * self.pi) + 300.0 *
- math.sin(lng / 30.0 * self.pi)) * 2.0 / 3.0
- return ret
- def WGS84_to_WebMercator(self, lng, lat):
- '''
- 实现WGS84向web墨卡托的转换
- :param lng: WGS84经度
- :param lat: WGS84纬度
- :return: 转换后的web墨卡托坐标
- '''
- x = lng * 20037508.342789 / 180
- y = math.log(math.tan((90 + lat) * self.pi / 360)) / (self.pi / 180)
- y = y * 20037508.34789 / 180
- return x, y
- def WebMercator_to_WGS84(self, x, y):
- '''
- 实现web墨卡托向WGS84的转换
- :param x: web墨卡托x坐标
- :param y: web墨卡托y坐标
- :return: 转换后的WGS84经纬度
- '''
- lng = x / 20037508.34 * 180
- lat = y / 20037508.34 * 180
- lat = 180 / self.pi * (2 * math.atan(math.exp(lat * self.pi / 180)) - self.pi / 2)
- return lng, lat
整个模块的使用方式可用下面的导图概括,其中每个函数都只需要传入经纬度坐标信息:
以上就是本文的全部内容,如有笔误之处望指出!
(数据科学学习手札60)用Python实现WGS84、火星坐标系、百度坐标系、web墨卡托四种坐标相互转换的更多相关文章
- (数据科学学习手札90)Python+Kepler.gl轻松制作时间轮播图
本文示例代码及数据已上传至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes 1 简介 Kepler.gl作为一款强大的开源地理信 ...
- (数据科学学习手札32)Python中re模块的详细介绍
一.简介 关于正则表达式,我在前一篇(数据科学学习手札31)中已经做了详细介绍,本篇将对Python中自带模块re的常用功能进行总结: re作为Python中专为正则表达式相关功能做出支持的模块,提供 ...
- (数据科学学习手札102)Python+Dash快速web应用开发——基础概念篇
本文示例代码与数据已上传至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes 1 简介 这是我的新系列教程Python+Dash快 ...
- (数据科学学习手札121)Python+Dash快速web应用开发——项目结构篇
本文示例代码已上传至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes 1 简介 这是我的系列教程Python+Dash快速web ...
- (数据科学学习手札05)Python与R数据读入存出方式的总结与比较
在数据分析的过程中,外部数据的导入和数据的导出是非常关键的部分,而Python和R在这方面大同小异,且针对不同的包或模块,对应着不同的函数来完成这部分功能: Python 1.TXT文件 导入: 以某 ...
- (数据科学学习手札108)Python+Dash快速web应用开发——静态部件篇(上)
本文示例代码已上传至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes 1 简介 这是我的系列教程Python+Dash快速web ...
- (数据科学学习手札109)Python+Dash快速web应用开发——静态部件篇(中)
本文示例代码已上传至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes 1 简介 这是我的系列教程Python+Dash快速web ...
- (数据科学学习手札112)Python+Dash快速web应用开发——表单控件篇(上)
本文示例代码已上传至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes 1 简介 这是我的系列教程Python+Dash快速web ...
- (数据科学学习手札115)Python+Dash快速web应用开发——交互表格篇(上)
本文示例代码已上传至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes 1 简介 这是我的系列教程Python+Dash快速web ...
随机推荐
- Cocos2d-x 发布 Android
Cocos2d-x 发布 Android 前置需求: Android NDK Android SDK OR Eclipse ADT Bundle Android AVD target installe ...
- Error(10028):Can't resolve multiple constant drivers for net “ ” at **.v
两个进程里都有同一个条件判断的话,会产生并行信号冲突的问题. 同一个信号不允许在多个进程中赋值,否则则为多驱动. 进程的并行性决定了多进程不同能对同一个对象进行赋值.
- buuctf zip伪加密
平时伪加密总是依赖osx,这道题无法直接解压,所以研究一下伪加密先放两张图(图是偷的)一般在压缩源文件数据区全局方式位标记处,真加密为 09 00,伪加密为00 00,而后面将压缩源文件目录区全局方式 ...
- CG-CTF web部分wp
bin不动了,学学webWEB1,签到1f12,得到flag2,签到2给了输入窗口和密码,但输入后却显示错误,查看源码,发现对输入长度进行了限制,改下长度,得到flag3,md5 collision给 ...
- 使用androidstudio时遇到的一些小错误
1 路径名字中不能有汉字 报如下错误:Error:(1, 0) Your project path contains non-ASCII characters. This will most lik ...
- 同域SQL server 做镜像服务器遇到1418错误
今天遇到了如题所说的错误,查了一天没有看到好的解决方案,因为作者是小白,所以对于解决方案都是代码的那种,完全理解不了. 现在,讲述一下我的解决方法.因为是同域的服务器,这个时候说网络访问不了对方,但是 ...
- readme.md常用格式的编写
md是Markdown的缩写,md是一种易读易写的文本格式(easy-to-read, easy-to-write plain text format),并且可以很方便的转换成HTML格式显示在网页中 ...
- Spring下载maven
http://maven.springframework.org/release/org/springframework/spring/
- json数据返回数字,页面显示文字处理
var obj = { 1:'你好1', 2:'你好2', 3:'你好3' } var e = obj[1]; e; //'你好1'
- String类型的时间大小比较
不多废话,上代码 (String 的CompareTo方法比较仅仅限于同位数的字符串比较,格式.位数不一样比较结果会错误,原因是CompareTo比较源码是ASCII的比较) 代码一 packag ...