【地图引擎】web地图渲染奥秘

1,355 阅读7分钟

本文会从投影、比例尺、坐标转换、瓦片等方面进一步介绍百度地图等互联网地图是如何渲染到屏幕上的。

一、平面墨卡托投影

地球实际上是一个赤道略宽两极略扁的椭球体,表面是不规则的曲面,而通常我们所见的地图大都是平面地图,因此需要先进行一个投影换算将球面图变换为平面图。

为了方便计算,在投影之前需要先将地球椭球体规则化,最常采用的椭球模型是WGS84坐标体系(大地坐标系,基准面为WGS1984),坐标是经纬度,单位是度,变换所有关于距离和面积的计算都是基于WGS84椭球体上的计算。

针对不同用途的地球投影方式有很多种,而web地图最常采用的投影方式是墨卡托投影。这种投影方式是正轴等角圆柱投影,可以想象将地球放入一个圆柱面内,赤道外切于圆柱面,在球心有个光源,光源射线将球面各点投影到圆柱即可得到平面地图。

image.png

由图可见,横轴方向经度是线性变化的,纵轴方向维度是非线性变化的,这是由于Web墨卡托投影在两级是趋于无限值的,所以这种投影范围维度只能在-85.05~85.05度之间,且高纬度区域处于拉伸状态。

倘若并非去南北极探险,正负85度外的地图其实很少用得到,所以对于互联网地图这个缺点无伤大雅。

总之,至此我们已经得到了一幅平面地图~

二、瓦片、比例尺与分辨率

一整幅地图的数据量非常大,而我们使用web地图通常只是查看部分区域,所以并不需要将全部地图数据都下载下来。

因此,图像服务会提前将地图分割成若干个正方形单元块,即瓦片。当地图视口发生变化或地图进行缩放时,只需要加载所需要的瓦片即可。

目前,瓦片的组织形式是一种多分辨率的金字塔结构的层次模型,如下图所示,在表示相同地理范围情况下,从瓦片金字塔的底层到顶层,分辨率越来越低。

image.png

金字塔结构的瓦片分辨率从底层到顶层有变化,而我们使用百度地图等电子地图就会发现,在缩放地图时,不同缩放层级对应的是不同的比例尺,那么比例尺与分辨率有什么关联呢?

初中地理学过比例尺表示的是,地图上一条线段的长度与实际距离之比,即地图上一厘米代表实际多少厘米。

在web地图的渲染中,为了方便屏幕像素计算将比例尺转换为分辨率(resolution),即图上一像素代表实际多少米

比例尺与分辨率可以互相换算,举个例子:

假设当前地图的比例尺为1:125000000,表示图上1米表示实际125000000米,求该比例尺转换为分辨率,即1像素等于多少米?

假设地图的坐标单位为米,dpi为96px(dpi是屏幕分辨率的单位,表示每英寸像素数)

根据 1英寸 = 0.0254米 = 96像素,可得 1像素 = 0.0254/96米

所以,1:125000000比例尺转换为分辨率,图上1像素 = 125000000*0.0254/96 =  33072.916666667米

举个小栗子,我们就明白了比例尺和分辨率其实是一回事,两者可以相互转换。

言归正传,那么地图在不同层级下的分辨率如何求呢?

假设不同层级的瓦片数为2^n * 2^n,则地图各zoom下的分辨率计算如下,其中r为墨卡托投影选取的地球半径r = 6378137。

image.png

地图比例尺与分辨率的换算关系如下:

截屏2023-03-20 下午7.20.17.png

三、坐标变换与瓦片编号计算

至此,我们已经清楚了,可缩放的web地图是由金字塔结构的不同分辨率的瓦片组成的,那么对于不同地图视口是如何知道该加载哪些瓦片的呢?

首先,我们回顾一下前一篇文章中讲述的地理坐标系:采集车GPS采集回来的WGS84坐标系,首先需要经过加密转换为国内可用的GCJ02坐标系,百度地图会进一步加密转换为BD09坐标系,经纬度坐标再经过一次web墨卡托投影,将球面坐标转换为平面墨卡托坐标,再进一步转换为各级别的地图世界像素坐标…...

再把前一篇文章中的图片搬过来,涉及到的坐标系变化如下图所示:

image.png

接下来我们主要关注的是绿色框里的步骤,我们可以计算出当前地图视口内瓦片的世界像素坐标,那么瓦片坐标怎么计算呢?

互联网地图瓦片编号没有统一的标准,只要能获取到对应的瓦片就行,所以各家web地图对瓦片编号方式并不完全一致。

百度地图瓦片的坐标原点与墨卡托坐标原点(赤道与本初子午线的交点)一致,从原点向右上方开始编号0,0,使用x,y表示瓦片编号,此外也有以左上角为坐标原点的。

无论是以左上角为编号原点还是以赤道与本初子午线的交点为坐标原点,求瓦片编号的思路是一致的,引入一个与瓦片同单位的像素坐标系,由像素坐标除以瓦片大小得到瓦片编号。

这里分别以左上角和中心点为例看具体计算:

百度地图由于采用的是特殊的BD09坐标系,边缘瓦片需要进行裁切,所以瓦片编号是以赤道与本初子午线交点为原点。

由墨卡托转瓦片像素坐标,除了上面那种百分比乘以总像素数的方式,还可以直接通过墨卡托坐标除以各zoom下的分辨率求得,同样的再由像素坐标除以瓦片大小可以求出瓦片索引。

截屏2023-03-20 下午7.22.34.png

四、在屏幕上呈现地图

前面说的是地图通用坐标和瓦片编号计算方式,最后再看下如何在浏览器窗口上渲染地图。

大致思路是获取浏览器中地图窗口四个点的经纬度所框定范围内的瓦片,再将这些瓦片按照一定的偏移坐标放置即可。

image.png

下面提供一种通用的计算思路:

(1)地图中心点

初始化地图时需要设置中心点center和级别zoom两个必要参数,其中center就是屏幕中心点对应的经纬度,根据之前讲的坐标变换,可以求得中心点对应的平面墨卡托坐标和世界像素坐标。

(2)瓦片编号

根据中心点、当前地图级别和屏幕地图窗口大小,可以求得当前地图视野四至点的像素坐标,再由四至坐标除以瓦片大小可以求出框定范围内的行列号[fromRow, fromColumn, toRow, toColumn],然后根据行列号信息加载图像服务中的瓦片数据。

(3)瓦片偏移

由图可见屏幕范围框定了6张瓦片,但加载的瓦片范围是大于屏幕范围的,所以在铺瓦片时需要进行一些偏移。

偏移量计算,比如由每个瓦片左上角像素坐标P1与屏幕左上角像素坐标P2做差值,就可以得出css像素的偏移值。

至此,我们已经知道2D互联网地图是如何从经纬度到浏览器中显示出来啦,所涉及到的坐标转换如果有疑问可以参考前一篇坐标系文章。

如今更多场景使用到了3D地图,在2D地图的基础上增加了俯仰角等参数设置,在坐标系上增加了墨卡托坐标与三维坐标系之间的转换,对于三维坐标系转换可以参考之前的三维坐标系转换文章,具体的3D地图渲染奥秘,欢迎关注我,在之后的文章中再做详细介绍。

参考:

www.jiazhengblog.com/blog/2011/0… learn.microsoft.com/en-us/bingm…