Bing地图切片系统
Bing地图提供了一个可以直接平移和缩放的世界地图。为了让地图操作更加平滑和及时响应,我们选择提前渲染地图不同层级的细节,并把每个层级的地图切割成为瓦片以便快速的还原展示。这篇文档描述了,投影,坐标系统和地图瓦片编码的方案,这些统称为Bing地图的切片系统。
地图投影
为了确保地图中来自不同航拍影像的排版没有缝隙,我们不得不对整个地球进行投影,我们选择使用墨卡托投影,如下图所示:
尽管墨卡托投影极大的扭曲了地图比例和面积(特别是在极点附近),但它具有两个重要特征,这两个重要特征超过了它的比例失真带来的问题。
- 他是一个保持形状的投影,这意味着它保留了相对较小物体的形状。这在我们展示航拍影像的时候尤为重要,我们希望避免航拍影像中建筑物的形状不被扭曲,建筑物的形状应该是方形,而不是矩形。
- 他是一个圆柱投影,这意味着南北方向总是直上直下,东西总是左右延伸。
因为墨卡托投影在极点方向无穷大的特性,所以它没有真正展示整个世界。用一个方形宽高比来讲,最大唯独约为85.05度。
为了简化计算,我们使用球形来进行这种投影的,而不用椭球形式。由于投影仅用来显示地图,而不用来显示数字坐标,因此我们不需要对椭球投影带来的额外精度。球形投影在Y方向上大约会引起0.33%的比例失真,这在视觉上不明显。
地图分辨率和地图比例尺
除了地图投影外,在渲染地图之前地图分辨率和地图比例尺必须指定。在最低的地图层级(Level1),地图是512X512像素,在各个连续的地图层级,地图的宽度和高度以2的level次方形式增长,Level2 是1024X1024像素,Level3是2048X2048像素,等等。总之地图的宽度和高度可以通过以下方式计算:
1 地图 width = 地图 height = 256 * 2level 像素
地图分辨率表示地图上一像素代表的实际距离,例如,地图分辨率为10m/pixel,表示地图上没像素代表真实距离10米。地图分辨率是通过地图层级(Level)和纬度来计算的。使用地球半径6378137米,地图的分辨率可以通过如下方式计算:
地图 resolution = cos(latitude * pi/180) * 地球周长 / map width =(cos(latitude * pi/180) * 2 * pi * 6378137 meters) / (256 * 2level 像素)
地图的比例尺表示了在同一个单位体系下地图上距离和地面距离的比值。举个例子,地图比例尺1::100000每英寸表示,地图上一英寸表示实际距离100000英寸。类似地图分辨率,地图比例尺也是通过地图层级和纬度确定的。通过给定了屏幕分辨率(通常96dpi),则可以根据地图分辨率计算得出:
scale = 1 : resolution * screen dpi / 0.0254 meters/inch = 1 : (cos(latitude * pi/180) * 2 * pi * 6378137 * screen dpi) / (256 * 2level * 0.0254)
以下表格展示了从赤道出计算的每个层级上面的具体地图长宽、分辨率和比例尺信息。
层级 |
地图高度和宽度 (pixels) |
地图分辨率(meters / pixel) |
地图比例尺(at 96 dpi) |
1 |
512 |
78,271.5170 |
1 : 295,829,355.45 |
2 |
1,024 |
39,135.7585 |
1 : 147,914,677.73 |
3 |
2,048 |
19,567.8792 |
1 : 73,957,338.86 |
4 |
4,096 |
9,783.9396 |
1 : 36,978,669.43 |
5 |
8,192 |
4,891.9698 |
1 : 18,489,334.72 |
6 |
16,384 |
2,445.9849 |
1 : 9,244,667.36 |
7 |
32,768 |
1,222.9925 |
1 : 4,622,333.68 |
8 |
65,536 |
611.4962 |
1 : 2,311,166.84 |
9 |
131,072 |
305.7481 |
1 : 1,155,583.42 |
10 |
262,144 |
152.8741 |
1 : 577,791.71 |
11 |
524,288 |
76.4370 |
1 : 288,895.85 |
12 |
1,048,576 |
38.2185 |
1 : 144,447.93 |
13 |
2,097,152 |
19.1093 |
1 : 72,223.96 |
14 |
4,194,304 |
9.5546 |
1 : 36,111.98 |
15 |
8,388,608 |
4.7773 |
1 : 18,055.99 |
16 |
16,777,216 |
2.3887 |
1 : 9,028.00 |
17 |
33,554,432 |
1.1943 |
1 : 4,514.00 |
18 |
67,108,864 |
0.5972 |
1 : 2,257.00 |
19 |
134,217,728 |
0.2986 |
1 : 1,128.50 |
20 |
268,435,456 |
0.1493 |
1 : 564.25 |
21 |
536,870,912 |
0.0746 |
1 : 282.12 |
22 |
1,073,741,824 |
0.0373 |
1 : 141.06 |
23 |
2,147,483,648 |
0.0187 |
1 : 70.53 |
像素坐标
再通过使用地图层级确定分辨率和比例尺后,我们可以将地理坐标转换成为像素坐标。由于地图的高度和宽度在不同地图层级不一样,所以像素坐标也是如此。像素坐标在左上角总是(0,0),地图右上角为(width-1,height-1),或者参考之前的计算公式为:(256X2level-1,256X2level-1),举个例子,如果地图级别为3,则像素坐标从(0,0),到(2047,2047),如下:
给定经度纬度和地图缩放级别,像素坐标可以通过以下方式进行计算:
sinLatitude = sin(latitude * pi/180)
pixelX = ((longitude + 180) / 360) * 256 * 2level
pixelY = (0.5 – log((1 + sinLatitude) / (1 – sinLatitude)) / (4 * pi)) * 256 * 2level
其中经度纬度假设是在WGS84参考系统下的。即使Bing地图使用的是球形投影,将所有地理坐标转换为常用的椭球坐标也很重要,这里我们选择WGS84椭球坐标。我们假设经度范围从-180到+180度,纬度必须限制在-85.05112878到+85.05112878之间。这避免了投影到极点的严重变形,并且使得投影能是正方形。、
切片坐标和Quadkeys
为了优化地图检索和显示性能,每个层级渲染的地图都被切割成若干个256X256像素的瓦片。由于每个地图级别的像素数量不相同,因此切片的数量也是不同;
map width = map height = 2level tiles
所有切片给定了XY坐标,从左上角的(0,0)到右下角的(2level-1,2level-1)。例如,Level3切片坐标从(0,0)到(7,7),如图:
给定一个像素坐标,你可以根据以下公式很快的计算出包含该坐标的瓦片的XY坐标。
tileX = floor(pixelX / 256)
tileY = floor(pixelY / 256)
为了优化瓦片的所有和存储,二位瓦片坐标被组合成为四叉树的以为字符串,简称为“QuadKeys”。每个quadkey以特定的地图级别来唯一表示一个瓦片。并且可以将其用作常用的数据库B-tree索引中的键。为了将瓦片坐标转换成为quadkey,y和x坐标转换成二进制(补齐位数为最长结果二进制位数),然后依次从y到x的二进制位数由高到底组合成一个新的二进制数字。然后将其转为四进制字符串,过程如下:
tileX = 3 =011(二进制) tileY = 5 =101(二进制) quadKey = 100111(二进制) = 213(四进制) = “231”
quadKey有一些很有趣的特性:
第一:quadKey的长度(组成quadKey的数字的个数)等于相应瓦片所对应的地图级别。
第二:任何一个瓦片的quadKey的前面几位都是他所在父瓦片(上一级别中包含该瓦片的瓦片)的前几位。
如下所示:瓦片2 瓦片20到23的父瓦片,瓦片13 是瓦片130到133的父瓦片。
最后,quadkeys提供了一个可以保留xy空间中所在切片位置的一维索引的关键字,换句话说,也就是,具有连接x,y坐标的两个瓦片通常具有相对靠近在一起的四个秘钥,这对于优化数据库性能非常重要,因为通常辉耀组的形式请求相邻的瓦片,并且希望将这些瓦片保留在想通的磁盘上,以尽量减少磁盘的读取次数。
Sample Code
略
文章翻译自:Bing Maps Tile System