我以前写过一个leaflet互联网地图修改插件。 引用插件后,一行代码也不用写,就能解决国内网络地图瓷砖的偏移问题。
我最近也想在mapboxgl上写这样的插件。
原因是自己发布的OSM矢量瓷砖地图精度不够高,需要放大地图查看详细信息时,可以用百度、高德的网格瓷砖进行补充。 使用它们的第一步是首先纠正。
虽然去研究了mapboxgl的基础代码,但是不知道的地方很多。 于是我去补充了webgl的知识,然后去看了mapboxgl的源代码。 哈哈,即使万变也不会离开那个宗教。 GIS的知识还是那些,只是计算机画图形的方法变了而已。
研究之后,将目标固定在transform.js文件中。 该文件主要用于处理纬度经度坐标、卡托坐标、屏幕坐标、webgl坐标等各种坐标转换问题,还负责生成瓷砖的编号。
文件中的coveringTiles方法用于计算平铺的x、y和z编号,并返回当前比例尺和可见范围内的所有平铺编号。
基于x、y和z平铺编号请求internet地图平铺时,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 _ tile names
有关webgl变换矩阵的知识,请参见本文https://www.cn blogs.com/charlee 44/p/11623502.html或《WebGL编程指南》。 后者更容易理解系统,所以推荐后者。
不得不说webgl的位置变换矩阵的计算还有很复杂的东西,所以我想看看mapboxgl中是否内置了经纬度坐标和webgl坐标的相互旋转方法。 经过调查,发现只有经纬度坐标、卡托坐标和屏幕坐标三者是相互旋转的方法,没有webgl的东西。
那么在曲线救国,先把经纬度转换成屏幕坐标,然后自己写方法把屏幕坐标转换成webgl坐标。
实现想法:
根据瓷砖编号和经纬度的相互旋转式,计算瓷砖左上角的经纬度,校正瓷砖左上角的经纬度,得到wgs84坐标的经纬度将校正前、校正后的经纬度分别转换为屏幕坐标,减去转换后的屏幕坐标, 将求出瓷砖屏幕坐标的偏移量的瓷砖屏幕坐标的偏移量换算为webgl坐标的偏移量,并将之前计算出的webgl坐标的偏移量与瓷砖的平移矩阵相加,理论上能够实现瓷砖的偏斜校正。 在实现过程中完成1、2、3步骤后,还没有考虑如何实现步骤4,所以将步骤3的结果屏幕坐标的偏移量直接加到了步骤5的平移矩阵上,结果出乎意料。
实现代码:
实现效果:
参考天安门国旗,在修改之前
偏斜校正后
哈哈,这就结束了吗?
平移矩阵的数值都是用屏幕像素计算的吗?
至少目前是这样。
我不需要开心
不要时,咦?边上为什么会有空白,瓦片没有请求过来?我接着放大地图,白边越来越大了嗯~ 这个好解决,应该是因为 mapboxgl 只显示当前范围的瓦片,当屏幕边缘的瓦片被纠偏到屏幕中间时,边缘就会出现空隙。
只要将当前显示范围向外扩展一些就能搞定。
正当我在开心的研究如何向外扩展显示范围时,无意中把地图倾斜了一下,我的妈呀!这是什么鬼
看到这个,我当时的心情瞬间就不好了。
~~ 容我整理下心情 ~~
好了,个人猜想,原因可能是,在地图旋转时,瓦片根据 webgl 坐标的中心点计算要旋转的角度和移动的距离,现在瓦片纠偏后位置发生了偏移,但计算旋转坐标时,还是根据webgl的中心点,所以旋转时就出问题了。
具体我也没想明白呢,感觉还是对瓦片纠偏后,需要对某个中心点也需要纠偏一下。如果有技术lcdxmg看到这篇文章也可以给留言指导一下。
总结:
目前搞定了垂直视角下的瓦片纠偏后续需要解决纠偏后屏幕边缘出现的空白区域问题。地图倾斜和旋转时瓦片会出现错位,需要继续研究。最后,mapboxgl纠偏插件还没有完全搞定,就不放代码了,后续有新进展会再跟大家分享,等完全搞定以后再向以前一样跟大家分享插件。
原文地址:http://gisarmory.xyz/blog/index.html?blog=mapboxglMapCorrection1
关注《GIS兵器库》, 第一时间获得更多高质量GIS文章。
本文章采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。欢迎转载、使用、重新发布,但务必保留文章署名《GIS兵器库》(包含链接: http://gisarmory.xyz/blog/),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。