墨卡托投影, GPS 坐标转像素, GPS 坐标转距离
Before:
1. 研究的需要, 在 google map 上爬取了一些的静态卫星地图图片,每张图片的像素为 256*256
2. 通过 photshop 将这些地图碎片手动拼成了地图, 地图只是覆盖了学校而已, 还是比较小的
3. 我通过手机采集到一些 GPS 的 trace, 希望在这个离线地图上画上这些 GPS 点
4. 最初, 我以为地图上的经纬度都是等距分布的, 比如一张图片的顶部纬度是20, 底部纬度为22, 那么图片中间的横线纬度是 21. 实际上, 并非如此, 中间横线的纬度应当是小于 21 的, 想了解具体的原因, 可搜索墨卡托投影
5. 好消息是, 经度是等距分布的, 比如图片左边经度是20, 右边是 22, 那么中间竖线经度是 21。 因此, 我们仅需搞定纬度
解决办法:
1. 古德曼函数 的输入是一个点距离赤道的“距离” y,输出是该点的纬度 lat。 我们的需求恰好相反, 已知 lat, 希望知道 y。 wiki 同时也提供了古德曼函数的反函数, 因此, 直接使用就好
2. 古德曼反函数有多种形式, wiki 的中文和英文版本至少提供了三种实现形式, 选一个就好, 都是等价的
3. 古德曼函数的一段 python 代码. 注意函数输入 longitude 不是 30, 60 这种值, 而是 (30/180 * math.pi) 这种类型的输入
def reverseGoodman(longitude):
return math.log((1 + math.sin(longitude)) / (1 - math.sin(longitude)))/2
输入 0 时,返回 0; 输入为 85.05112877980659, 返回的是 3.1415...(math.pi)
我本期待输入 [0, 85.05112877980659] 的输出应当是 [0, 1], 所以这个地方疑惑了挺久, 后来发现只需要在原始公式的基础上除以 math.pi 即可将值域锁定到 [0,1]
4. 墨卡托投影的假设是地球经度为 [-180, 180], 纬度为[-85.05112877980659,85.05112877980659], 投影出的地球是一个正方形, 长宽分别为 [-20037508.3427892,20037508.3427892]
5. 联合 (3, 4), 就能完成一般的计算了. 假如某点的纬度为 31度, 那么该点距离赤道的距离是
20037508.3427892/math.pi*reverseGoodman(31/180*math.pi)
再高级一点, 假如已知两个点的纬度, 求其在经度方向上的距离差,为此, 我写了个函数
def reverseGoodman(longitude):
return math.log((1 + math.sin(longitude)) / (1 - math.sin(longitude)))/math.pi/2 def convertGeoToMeter(lat1, lat2):
lat1 = lat1 * math.pi / 180
lat2 = lat2 * math.pi / 180 worldMapHeight = 20037508.3427892
OffsetY1 = worldMapHeight * reverseGoodman(lat1)
OffsetY2 = worldMapHeight * reverseGoodman(lat2) return OffsetY2-OffsetY1
Advanced:
假设已经获得了 GPS trace, 上面的函数也已经准备好, 现在缺少的只剩静态地图的 GPS 信息了, 有了这个信息, 就能实现离线地图标注
However, google map 的经纬度并非从 0 开始计算, 不能从 zoom level + 地图碎片的索引 获得图片某一个点(如左上角)的GPS
我依然用了比较粗糙办法: 先找一个地图碎片,已知其索引和 zoom level, 找到其一个边缘的某个点, 这个点必须比较好认, 然后打开 web google map, 同样找到这个点, 右键这里是哪, 得到 GPS 信息
得到 GPS 信息后, 需要计算这种办法的误差
1. 我爬取的地图 zoom level 为 17。 根据 google map 的原理, 在 zoom level == 17 这一层, 共有 (4^17) 个静态地图碎片。 其中, 横纵方向, 各有 (2^17) 个地图碎片
2. 每张地图碎片的属性和大家熟悉的地图相同, 支持分度值, 即横纵方向上, 每一厘米表示的实际距离是相同的
3. 手动的获得一张地图碎片上下边缘的纬度, 分别为 31.027048, 31.02940。 每张地图的长度实际为 realDis, 根据经纬度之差计算的来的与真实值之差小于 0.2 米, 准确度很高, 可以使用
realDis = 20037508.3427892/(2**16)
print convertGeoToMeter(31.027048, 31.02940)*100/realDis # 99.9327328479%
print math.fabs(convertGeoToMeter(31.027048, 31.02940) - realDis) #0.205668048242
4. 经度的误差计算更加容易, 误差依然很小
import math realLngDis = 360*1.0/(2**17)
observedLngDis = 121.429158-121.426381 print realLatDis
print observedLatDis
print math.fabs(realLatDis-observedLatDis)/realLatDis*100
#0.00274658203125
#0.00277699999999
#1.10748444425
Material:
1. 爬取的一张地图碎片

每张地图碎片含有 x, y, zoom level 三个属性
2. 地图碎片的爬取函数, python
import urllib
import os
def scheduler(a, b, c):
per = 100 * a * b / c
if per > 100:
per = 100
print "%.2f%%" %per def downloader(x, y):
for i in xrange(1,7):
for j in xrange(1,5):
url = 'https://mts2.google.com/vt/lyrs=s@139&hl=en&gl=CN&src=app&x=%i&s=&y=%i&z=17&s=' %(int(i)+ int(x), int(j) + int(y))
local = os.path.join('E:\Copy\google_map', 'x%iy%iz17.jpg' %(i+ int(x), j + int(y)) )
urllib.urlretrieve(url, local, scheduler)
#填写你需要从哪张图片开始爬取
#downloader(index_of_x, index_of_y )
代码写的比较死, 但代码量比较小, 还是非常容易修改的
墨卡托投影, GPS 坐标转像素, GPS 坐标转距离的更多相关文章
- 照片提取GPS 转成百度地图坐标
感谢: 小慧only http://www.cnblogs.com/zhaohuionly/p/3142623.html GPS转化坐标方法 大胡子青松 http://www.cnblogs.com ...
- GPS坐标转换为百度地图坐标
/** * GPS坐标转换为百度地图坐标 * 需要引入javabase64.jar 和json的一些包 * */ public class Gps2BaiDu { public static void ...
- GPS坐标转百度地图坐标
百度地图提供了相关API:BMap.Convertor.translate, 但是使用上存在部分限制:1.次数限制:2.异步回调 可以用如下方法: /** * 地图位置计算工具(将GPS坐标转换成百度 ...
- BD09坐标(百度坐标) WGS84(GPS坐标) GCJ02(国测局坐标) 的相互转换
BD09坐标(百度坐标) WGS84(GPS坐标) GCJ02(国测局坐标) 的相互转换 http://www.cnphp6.com/archives/24822 by root ⋅ Leave a ...
- WGS84、GCJ-02(火星坐标)、百度坐标,Web墨卡托坐标
GCJ-02坐标系统(火星坐标)简介:http://blog.csdn.net/giswens/article/details/8775121(存档:http://mapbd.com/cms/2012 ...
- OpenGL超级宝典总结(二)2D/3D笛卡尔坐标、坐标裁剪、纹理坐标、MVP转换等概念
如果你想把图形渲染在正确的位置上,那么坐标的设置就很重要了.在OpenGL中,与坐标相关的主要有笛卡尔坐标.坐标裁剪.纹理坐标.MVP(Model View Projection)转换. 1.笛卡尔坐 ...
- 验证坐标在某片坐标区域内 php 代码
之前碰到的这样一个需求,要将公司的服务范围在地图中显示出来,并将用户每天的访问坐标进行统计看有多少用户是在所能达到的服务范围半径内. 以下是PHP代码的实现 (仅验证坐标在某片坐标区域内) <? ...
- OpenGL屏幕二维坐标转化成三维模型坐标
我们把OpenGL里模型的三维坐标往二维坐标的转化称为投影,则屏幕上的二维坐标往三维坐标转化则可以称为反投影,下面我们来介绍一下反投影的方法. 主要是gluUnProject函数的使用,下面是代码: ...
- GPS校时器,GPS时钟装置,NTP网络时间服务器
GPS校时器,GPS时钟装置,NTP网络时间服务器 GPS校时器,GPS时钟装置,NTP网络时间服务器 GPS校时器,GPS时钟装置,NTP网络时间服务器 GPS校时器,GPS时钟装置,NTP网络时间 ...
- baidu经纬度坐标与google经纬度坐标都转换
baidu经纬度坐标与google经纬度坐标都是经过转换的.使用下面那个url可以将原始坐标或者谷歌的坐标转换成baidu的坐标http://api.map.baidu.com/ag/coord/co ...
随机推荐
- 六、从length和length()方法开始
首先你可以快速回答下面问题吗.当没有任何IDE的情况下,如何得到一个数组的长度,如何得到一个String的长度.我问这个了很对不同水平的开发者:初级的中级的.他们不能快速正确的回答这个问题.当IDE提 ...
- SQL Server FOR XML PATH 语句的应用---列转行
经常在论坛看到高手使用了 for xml path,由于是搜索一下,记录了详细的使用方法.在SQL Server中利用 FOR XML PATH 语句能够把查询的数据生成XML数据,下面是它的一些应用 ...
- JavaEE各种Javadoc的下载
刚才突然发现,很多servlet的api都不熟悉,但是又没有给eclipse导入api,就google了一下 关键字,servlet api / doc 或者java ee api / doc 注意版 ...
- BAT-SVN自动更新代码目录
1.安装“TortoiseSVN-1.7.15.25753-x64-svn-1.7.18.msi”. 2.“运行”->“cmd”->输入“svn help”->出现用说明代表正常,提 ...
- 在mac电脑上写入文件到NTFS格式的移动硬盘的解决办法
需求背景: 今天我在Mac电脑A上下载了11G的资料,想传给Mac电脑B,试用了AirPort.文件共享.远程操作等,传输速度都慢得要死,虽然是在同一个局域网下,两台电脑挨的非常的近,但是还是传得超级 ...
- C++基础学习-20120516
1.一下是使用strcpy_s与strcpy的安全性比较 char szBuf[2] = {0}; strcpy_s(szBuf, 2, "12131"); //新的CRT函数 ...
- IIS安全加固
1 删除IIS默认站点 把IIS默认安装的站点删除或禁用掉. 2 禁用不必要的Web服务扩展 打开IIS 管理器,检查是否有不必要的“Web服务扩展”,如果有则禁用掉.如下图所示: 3 IIS访问权限 ...
- QT4.8.5 QComboBox 增加选择菜单记录
QT4.8.5 QComboBox 增加选择菜单记录 因为软件需要测试多个UART ,多个LAN,当要测试多个同样功能的时候就可以使用QComboBox类实现一个菜单选择功能. 步骤如下: 1. 在U ...
- CAS (3) —— Mac下配置CAS客户端经代理访问Tomcat CAS
CAS (3) -- Mac下配置CAS客户端经代理访问Tomcat CAS tomcat版本: tomcat-8.0.29 jdk版本: jdk1.8.0_65 nginx版本: nginx-1.9 ...
- HTTP协议详解(文档)
目录引言................................................................................................ ...