mapboxgl 互联网地图纠偏插件(一)
之前写过一个 leaflet 互联网地图纠偏插件,引用插件后一行代码都不用写,就能解决国内互联网地图瓦片的偏移问题。
最近想对 mapboxgl 也写一个这样的插件。
原因是自己发布的OSM矢量瓦片地图精度不够高,当需要放大地图查看详细信息时,就可以拿百度、高德的栅格瓦片做个补充。而使用它们的第一步就是要先纠偏。
去研究了 mapboxgl 的底层代码,发现很多都看不懂。于是去恶补了 webgl 的知识,再去看 mapboxgl 的源码,哈哈,万变不离其宗,GIS知识还是那些,只是计算机绘制图形的方式变了而已。
研究后,把目标锁定在了 transform.js 文件上,这个文件主要用来处理各种坐标转换问题,包括经纬度坐标、墨卡托坐标、屏幕坐标、webgl坐标等,还负责生成瓦片的编号。
文件中的 coveringTiles 方法就是用来计算瓦片的 x、y、z 编号的,它会返回当前比例尺和可视范围内的所有瓦片编号。

根据 x、y、z 瓦片编号请求到互联网地图瓦片后,会在 calculatePosMatrix 方法里计算瓦片显示的屏幕位置。

mapboxgl 和 leaflet 的显示原理不同,mapboxgl 是三维坐标系,使用webgl绘图,增加了一个维度后,多出了很多东西要处理,二维坐标系加载瓦片时,只需要考虑瓦片的 x、y 位置,三维坐标系在此基础上还要考虑倾斜和透视。
webgl 的坐标都是通过位置变换矩阵来表示的,这一点和leaflet的差别很大。
上面的 calculatePosMatrix 方法就是根据瓦片的 x、y、z 编号,计算出瓦片在 webgl 中显示的位置变换矩阵。这里分别将瓦片的平移矩阵、缩放矩阵和视图+投影矩阵进行了相乘,得到了最终的位置变换矩阵。
看这个方法时我有些疑惑,它是如何根据瓦片的 x、y、z 编号来计算位置变换矩阵的,去研究了xyz协议后,才明白xyz坐标和经纬度坐标是有一套互转公式的,瓦片编号转经纬度时返回的坐标是瓦片左上角的经纬度。详见:https://wiki.openstreetmap.org/wiki/Slippy_map_tilenames
关于 webgl 变换矩阵的知识可以参考这篇文章 https://www.cnblogs.com/charlee44/p/11623502.html 或 《WebGL编程指南》,我更推荐后者,因为后者讲的更系统更容易理解。
不得不说,webgl 的位置变换矩阵计算还是有一些复杂的,所以就想看看 mapboxgl 中有没有内置经纬度坐标和 webgl 坐标互转的方法,查看后发现,只有经纬度坐标、墨卡托坐标和屏幕坐标三者互转的方法,没有 webgl 的。
那就曲线救国,先将经纬度转成屏幕坐标,再自己写个方法把屏幕坐标转成 webgl 坐标。
实现思路:
- 根据瓦片编号和经纬度的互转公式,计算出瓦片左上角的经纬度
- 对瓦片左上角的经纬度进行纠偏,得到 wgs84 坐标的经纬度
- 将纠偏前、后的经纬度分别转为屏幕坐标,再将转换后的屏幕坐标相减,得出瓦片屏幕坐标的偏移量
- 将瓦片屏幕坐标的偏移量换算成 webgl 坐标的偏移量
- 在瓦片的平移矩阵中加上刚才计算出的 webgl 坐标偏移量,理论上就能实现对瓦片的纠偏
在实现过程中,将 1、2、3 步搞定以后,因为暂时还没有想好怎么实现第4步,于是就先将第 3 步的结果屏幕坐标偏移量,直接加到了第 5 步的平移矩阵中,结果很让人意外。
实现代码:

实现效果:
以天安门国旗为参照,纠偏前

纠偏后

哈哈,难道就这么搞定了?
难道平移矩阵中的数值都是按屏幕像素来计算的?
至少目前看来是的。
正当我开心的不要不要时,咦?边上为什么会有空白,瓦片没有请求过来?我接着放大地图,白边越来越大了

嗯~ 这个好解决,应该是因为 mapboxgl 只显示当前范围的瓦片,当屏幕边缘的瓦片被纠偏到屏幕中间时,边缘就会出现空隙。
只要将当前显示范围向外扩展一些就能搞定。
正当我在开心的研究如何向外扩展显示范围时,无意中把地图倾斜了一下,我的妈呀!这是什么鬼

看到这个,我当时的心情瞬间就不好了。
~~ 容我整理下心情 ~~
好了,个人猜想,原因可能是,在地图旋转时,瓦片根据 webgl 坐标的中心点计算要旋转的角度和移动的距离,现在瓦片纠偏后位置发生了偏移,但计算旋转坐标时,还是根据webgl的中心点,所以旋转时就出问题了。
具体我也没想明白呢,感觉还是对瓦片纠偏后,需要对某个中心点也需要纠偏一下。如果有技术大牛看到这篇文章也可以给留言指导一下。
总结:
- 目前搞定了垂直视角下的瓦片纠偏
- 后续需要解决纠偏后屏幕边缘出现的空白区域问题。
- 地图倾斜和旋转时瓦片会出现错位,需要继续研究。
最后,mapboxgl纠偏插件还没有完全搞定,就不放代码了,后续有新进展会再跟大家分享,等完全搞定以后再向以前一样跟大家分享插件。
原文地址:http://gisarmory.xyz/blog/index.html?blog=mapboxglMapCorrection1
关注《GIS兵器库》, 第一时间获得更多高质量GIS文章。

本文章采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。欢迎转载、使用、重新发布,但务必保留文章署名《GIS兵器库》(包含链接: http://gisarmory.xyz/blog/),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。
mapboxgl 互联网地图纠偏插件(一)的更多相关文章
- mapboxgl 互联网地图纠偏插件(二)
前段时间写的mapboxgl 互联网地图纠偏插件(一)存在地图旋转时瓦片错位的问题. 这次没有再跟 mapboxgl 的变换矩阵较劲,而是另辟蹊径使用 mapboxgl 的自定义图层,重新写了一套加载 ...
- mapboxgl 互联网地图纠偏插件(三)
先说结论,结论当然是:大功告成,喜大普奔.看效果图: 好了,接下来说一下过程 先回顾一下这个系列的第一篇和第二篇 第一篇是直接改的 mapboxgl 源码,在源码里面对瓦片的位置进行纠偏,遇到的问题是 ...
- Arcmap中加载互联网地图资源
本文转载自:http://blog.3snews.net/space.php?uid=6955280&do=blog&id=67981 前一段时间想在Arcmap中打开互联网地图中的地 ...
- [转]在Arcmap中加载互联网地图资源的4种方法
转自http://blog.3snews.net/space.php?uid=6955280&do=blog&id=67981 前一段时间想在Arcmap中打开互联网地图中的地图数据, ...
- WebGIS中自定义互联网地图局部注记的一种方案
文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/ 1. 前言 实际项目中我们经常会遇到这样一种场景:地图底图可能是互 ...
- 在Arcmap中加载互联网地图资源的4种方法
前一段时间想在Arcmap中打开互联网地图中的地图数据,如影像数据.基础地图数据等,经过简单研究目前总结了四种方法,整理下与大家分享,有些内容可能理解有误,希望大家多多指教.4种方法如下: a) ...
- 在Arcmap中加载互联网地图资源的4种方法(转载)
前一段时间想在Arcmap中打开互联网地图中的地图数据,如影像数据.基础地图数据等,经过简单研究目前总结了四种方法,整理下与大家分享,有些内容可能理解有误,希望大家多多指教.4种方法如下: a) ...
- openlayers应用“四”:百度地图纠偏续
续前一篇,上一篇提到百度地图纠偏的基本思路,经过经过一天的努力,实现了百度地图坐标偏移参数的提取,步骤以及实现效果如下: 1.数据来源:四川省的省道矢量数据 2.提取坐标偏移参数的过程如下: A.将四 ...
- openlayers应用“三”:百度地图纠偏
前两篇文章介绍了openlayers3加载百度在线和离线瓦片地图,页面上能够正常显示.地图加载后在地图上显示一条GPS轨迹,发现离实际位置相差太远,如下图所示: 轨迹形状和实际形状相同,但是位移太远, ...
随机推荐
- 【python】Leetcode每日一题-位1的个数
[python]Leetcode每日一题-位1的个数 [题目描述] 编写一个函数,输入是一个无符号整数(以二进制串的形式),返回其二进制表达式中数字位数为 '1' 的个数(也被称为汉明重量). 示例1 ...
- Sublime text3 的破解
下载sublimeText3的安装包并安装(已经安装的可以忽略) 在hosts文件中添加:127.0.0.1 license.sublimehq.com(hosts文件地址:C:\Windows\Sy ...
- Windows进程间通讯(IPC)----信号量
线程同步内核对象 操作系统进行进程间同步是利用信号量机制.对于windows系统而言,可以利用一些内核对象进行线程同步,因为这些内核对象可以命名并且属于系统内核,所以可以支持不同进程间的线程同步进而实 ...
- MSSQL·备份数据库中的单表
阅文时长 | 0.11分钟 字数统计 | 237.6字符 主要内容 | 1.引言&背景 2.声明与参考资料 『MSSQL·备份数据库中的单表』 编写人 | SCscHero 编写时间 | 20 ...
- [设计模式] 读懂UML图
类之间关系(由强到弱) realize(继承):三角+实线(指向类),继承类(SUV是一种汽车) generalization(实现):三角+虚线(指向接口),实现接口(汽车是一种车) composi ...
- linux操作系统优化系列-RAID不同阵列模式的选择
背景 笔者所在的某通信运营商某大数据项目由于应用面临瓶颈需要扩充服务器设备,当初上这个项目的时候,服务器上线前的工作(配置raid,安装操作系统,Infiniband网络调试,系统漏洞安全加固)都是我 ...
- 面试阿里P6难在哪?(面试难点)
对于很多没有学历优势的人来说,面试大厂是非常困难的,这对我而言,也是一样,出身于二本,原本以为就三点一线的生活度过一生,直到生活上的变故,才让我有了新的想法和目标,因此我这个二本渣渣也奋斗了起来,竟拿 ...
- 怎么用优启通安装win7 !!!!好好好20191020
怎么用优启通安装win7 PE技术探索在国内属于前沿梯队.相关PE工具更新的非常及时,两个月一更新,很赞. 尤其是论坛代表作之一:EasyImageX系统备份恢复镜像工具(集成在PE里面),可以说是用 ...
- reboot 就是 poweroff 然后power on
halt Shut down and halt the system poweroff Shut down and power-off the system reboot [ARG] Shut dow ...
- 搭建LNMP环境部署Wordpress博客
!!!首先要做的就是关闭系统的防火墙以及selinux: #systemctl stop firewalld #systemctl disable firewalld #sed -ri 's/^(SE ...