Google Maps、Virtual Earth等网络地理所使用的地图投影,常被称作Web Mercator或Spherical Mercator,它与常规墨卡托投影的主要区别就是把地球模拟为球体而非椭球体。
墨卡托(Mercator)投影,又名”等角正轴圆柱投影”,荷兰地图学家墨卡托(Mercator)在1569年拟定,假设地球被围在一个中空的圆柱 里,其赤道与圆柱相接触,然后再假想地球中心有一盏灯,把球面上的图形投影到圆柱体上,再把圆柱体展开,这就是一幅标准纬线为零度(即赤道)的”墨卡托投 影”绘制出的世界地图。
墨卡托投影的”等角”特性,保证了对象的形状的不变行,正方形的物体投影后不会变为长方形。”等角”也保证了方向和相互位置的正确性,因此在航海和航空中常常应用,而Google们在计算人们查询地物的方向时不会出错。 墨卡托投影的”圆柱”特性,保证了南北(纬线)和东西(经线)都是平行直线,并且相互垂直。而且经线间隔是相同的,纬线间隔从标准纬线(此处是赤道,也可能是其他纬线)向两级逐渐增大。 但是,”等角”不可避免的带来的面积的巨大变形,特别是两极地区,明显的如格陵兰岛比实际面积扩大了N倍。
为什么是圆形球体,而非椭球体? 这说来简单,仅仅是由于实现的方便,和计算上的简单,精度理论上差别0.33%之内,特别是比例尺越大,地物更详细的时候,差别基本可以忽略。
以整个世界范围,赤道作为标准纬线,本初子午线作为中央经线,两者交点为坐标原点,向东向北为正,向西向南为负。 X轴:由于赤道半径为6378137米,则赤道周长为2*PI*r = 20037508.3427892,因此X轴的取值范围:[-20037508.3427892,20037508.3427892]。 Y轴:由墨卡托投影的公式可知,同时上图也有示意,当纬度φ接近两极,即90°时,y值趋向于无穷。这是那些”懒惰的工程师”就把Y轴的取值范围也限定在[-20037508.3427892,20037508.3427892]之间,搞个正方形。 懒人的好处,众所周知,事先切好静态图片,提高访问效率云云。俺只是告诉你为什么会是这样子。因此在投影坐标系(米)下的范围是:最小 (-20037508.3427892, -20037508.3427892 )到最大 (20037508.3427892,20037508.3427892)。
按道理,先讲地理坐标系才是,比如球体还是椭球体是地理坐标系的事情,和墨卡托投影本关联不大。简单来说,投影坐标系(PROJCS)是平面坐标系,以米 为单位;而地理坐标系(GEOGCS)是椭球面坐标系,以经纬度为单位。具体可参考《坐标系、坐标参照系、坐标变换、投影变换》。 经度:这边没问题,可取全球范围:[-180,180]。 纬度:上面已知,纬度不可能到达90°,懒人们为了正方形而取的-20037508.3427892,经过反计算,可得到纬度 85.05112877980659。因此纬度取值范围是[-85.05112877980659,85.05112877980659]。其余的地区怎 么办?没事,企鹅们不在乎。 因此,地理坐标系(经纬度)对应的范围是:最小(-180,-85.05112877980659),最大(180, 85.05112877980659)。至于其中的Datum、坐标转换等就不再多言。
关于Google Maps等的组织方式------地图瓦片金字塔,估计我在这里重复一遍这玩意,怕也是没人看了。尽管原理都一样,但具体到写不同厂商不同数据源的代码时,你会发 现,可缩放级别数不一样,最小级别不一样,编码方式不一样,比如Google的QRST,微软的四叉树,OSGeo的TMS等。 然而,你或许也不必这么麻烦,因为这些算法在网络上早已遍布朝野,你尽可从他人博客中获取,或是从开源软件里学习。这本身都不是秘密,微软自己也是公布的。 《Tiles à la Google Maps》 用交互性地方式可得到任一Tile的边界范围,各种流行编码方式等。该页面的链接都非常有价值,部分也是本文写作的重要参考。作者用python完成了下 列坐标之间转换算法:经纬度(出现在KML中的坐标,WMS的BBOX参数等),平面坐标XY(米,Web Mercator投影坐标系),金字塔的XYZ(即X轴的位置,Y轴的位置,和缩放级别ZoomLevel),每个Tile的编码Key值(QRST或 0123等)。转换时,还需要注意两个概念,Ground Resolution和Map Scale。
Ground Resolution,地面分辨率,类似Spatial Resolution(空间分辨率),我们这里主要关注用象元(pixel size)表示的形式:一个像素(pixel)代表的地面尺寸(米)。以Virtual Earth为例,Level为1时,图片大小为512*512(4个Tile),那么赤道空间分辨率为:赤道周长/512。其他纬度的空间分辨率则为纬度 圈长度/512,极端的北极则为0。Level为2时,赤道的空间分辨率为 赤道周长/1024,其他纬度为纬度圈长度1024。很明显,Ground Resolution取决于两个参数,缩放级别Level和纬度latitude ,Level决定像素的多少,latitude决定地面距离的长短。地面分辨率的公式为,单位:米/像素: ground resolution = (cos(latitude * pi/180) * 2 * pi * 6378137 meters) / (256 * 2levelpixels)
Map Scale,即地图比例尺,小学知识,图上距离比实地距离,两者单位一般都是米。在Ground Resolution的计算中,由Level可得到图片的像素大小,那么需要把其转换为以米为单位的距离,涉及到DPI(dot per inch),暂时可理解为类似的PPI(pixelper inch),即每英寸代表多少个像素。256 * 2level / DPI即得到相应的英寸inch,再把英寸inch除以0.0254转换为米。实地距离仍旧是:cos(latitude * pi/180) * 2 * pi * 6378137 meters; 因此比例尺的公式为,一般都化为1:XXX,无单位: map scale = 256 * 2level / screen dpi / 0.0254 / (cos(latitude * pi/180) * 2 * pi * 6378137) = 1 : (cos(latitude * pi/180) * 2 * pi * 6378137 * screen dpi) / (256 * 2level * 0.0254)
其实,Map Scale 和 Ground Resolution存在对应关系,毕竟都和实地距离相关联,两者关系:map scale = 1 : ground resolution * screen dpi / 0.0254 meters/inch 《Virtual Earth Tile System》列举了Virtual Earth在赤道上,Level、像素数、地面分辨率、地图比例尺的对应关系,同时本文也简单介绍了Mercator投影和上述两个概念,推荐。
花了一下午的时间终于可以计算每个缩放级别的比例尺了。上面“ground resolution = (cos(latitude * pi/180) * 2 * pi * 6378137 meters) / (256 * 2levelpixels)”计算公式是有错的,之前我一直用这个公式来验证,结果总是相距甚远。查阅相关文献之后,找出了问题的所在。
Google Map 是由分辨率大小为256*256 的图片无缝拼接而成的,称之为瓦片。在初始等级时,整个地球只投影在一张256*256 的图片上,也就是说256 个像素代表了40075016.685578488米。Google Map 中定义的比例尺与传统意义定义的比例尺不同,所定义的是单位像素所代表的距离值。在初始等级时的比例尺为:40075016.685578488/256=156543.033928041(米/像素)。地图的缩放功能是由四叉树实现的,地图放大一个级别后原来256*256 的图片将变成512*512 的图片,也就是说将原来的图片分裂成4 张256*256 的图片。这时比例尺为:
40075016.685578488/512=78271.51696402(米/像素)。
每放大一级每张图片都会分裂成四张,比例尺则减小为原来的一半。最后随着缩放等级的增大,瓦片自顶向下呈几何级数的增长,形成一个金字塔状,可参考下表。
所以,ground resolution = (cos(latitude * pi/180) * 2 * pi * 6378137 meters) / (256 * 2levelpixels)”应该更改为:
ground resolution = (cos(latitude * pi/180) * 2 * pi * 6378137) / (256 * Pow(2,level)),其中latitude表示纬度,level表示放大多少倍数,pi是3.14。