1,墨卡托投影
使用经纬度表示位置的大地坐标系虽然可以描述地球上点的位置,但是对于地图地理数据在二维平面内展示的场景,需要通过投影的方式将三维空间中的点映射到二维空间中。地图投影需要建立地球表面点与投影平面点的一一对应关系,在互联网地图中常使用墨卡托投影。墨卡托投影是荷兰地理学家墨卡托于1569年提出的一种地球投影方法,该方法是圆柱投影的一种。
墨卡托投影如下:
2,瓦片切割和瓦片坐标
对于经过墨卡托投影为平面的世界地图,在不同的地图分辨率(整个世界地图的像素大小)下,通过切割的方式将世界地图划分为地图单元,划分成的每一块地图单元称为地图瓦片。
地图瓦片具有以下特点:
--具有唯一的瓦片等级(Level)和瓦片坐标编号(X, Y)。
--瓦片分辨率为256*256。
--最小的地图等级是0,此时世界地图只由一张瓦片组成。
--瓦片等级越高,组成世界地图的瓦片数越多,可以展示的地图越详细。
--某一瓦片等级地图的瓦片是由低一级的各瓦片切割成的4个瓦片组成,形成了瓦片金字塔。
3,高德地图瓦片坐标与坐标系定义
高德地图瓦片坐标与Google Map、Open Street Map相同。高德地图的墨卡托投影截取了纬度(约85.05ºS, 约85.05ºN)之间部分的地球,使得投影后的平面地图水平方向和垂直方向长度相等。将墨卡托投影地图的左上角作为瓦片坐标系起点,往左方向为X轴,X轴与北纬85.05º重合且方向向左;往下方向为Y轴,Y轴与东经180º(亦为西经180º)重合且方向向下。瓦片坐标最小等级为0级,此时平面地图是一个像素为256*256的瓦片。在某一瓦片层级Level下,瓦片坐标的X轴和Y轴各有2^Level个瓦片编号,瓦片地图上的瓦片总数为2^Level*2^Level。
高德地图Level=2的瓦片坐标编号情况:
4,通过经纬度计算瓦片坐标
公式:(参考:Slippy map tilenames)
经纬度坐标(lon, lat)转瓦片坐标(x, y),z为瓦片层级:
java代码实现:
/** 功能描述: <br> * 〈高德地图,Google Map、Open Street Map 经纬度 转 瓦片坐标〉 * @Param: [lon(经度), lat(维度), level(瓦片层级)] * @return: int[] * @author: zl * @date: 2021/12/23 14:18 */ public static int[] getTileNumber(double lon, double lat, int level) { int xtile = (int)Math.floor( (lon + 180) / 360 * (1<<level) ) ; double ln = Math.log( Math.tan(lat*Math.PI/180) + (1 / Math.cos(lat*Math.PI/180)) ); int pow = (1<<(level-1)); int ytile = (int)Math.floor( (1 - ln/Math.PI) *pow ); if (xtile < 0) { xtile=0; } if (xtile >= (1<<level)) { xtile=((1<<level)-1); } if (ytile < 0) { ytile=0; } if (ytile >= (1<<level)) { ytile=((1<<level)-1); } return new int[]{xtile,ytile}; }
5,百度地图瓦片坐标与坐标系定义
百度地图的瓦片坐标系定义与高德地图并不相同,其墨卡托投影的参数也不同。百度地图瓦片坐标以墨卡托投影地图中赤道与0º经线相交位置为原点,沿着赤道往左方向为X轴,沿着0º经线向上方向为Y轴。
百度瓦片坐标定义了另一种二维坐标系,称为百度平面坐标系。百度平面坐标系的坐标原点与百度瓦片坐标原点相同,以瓦片等级18级为基准,规定18级时百度平面坐标的一个单位等于屏幕上的一个像素。平面坐标与地图所展示的级别没有关系,也就是说在1级和18级下,同一个经纬度坐标的百度平面坐标都是一致的。
百度地图Level=2的瓦片坐标编号情况:
此时X方向和Y方向各有4个瓦片编号,但是外围的某些瓦片只有部分区域有地图或完全没有地图。没有地图的区域也可以认为其瓦片是无效的,即百度地图中X方向或Y方向的有效瓦片不一定达到2^{Level}个。
中国大概位于百度瓦片坐标的(0,0)中。
百度经纬度坐标与百度平面坐标的相互转换,并没有公开的公式,需要通过百度地图的API实现。
参考链接(这里)
6,其他投影模型和坐标系定义(天地图)
天地图的切片规则是这样的,l=1时,整幅地图(全球地图)被切为两片,如图(l=1):
当l=2即以后,每个瓦片将被切位4片,如图(l=2):
天地图经纬度计算瓦片坐标java实现:
/** 功能描述: <br> * 〈天地图 经纬度 转 瓦片坐标〉 * @Param: [rectPts(左上角经纬度rectPts[0],rectPts[1] 和 左下角经纬度rectPts[2],rectPts[3])也就是两个点, level(瓦片层级)] * @return: double[] * @author: zl * @date: 2021/12/23 14:18 */ public static double[] getTileNumber2(double[] rectPts, int level) { //瓦片的级别分辨率(1-18) double[] resolution = {5.36441802978515E-06, 1.07288360595703E-05, 2.1457672119140625E-05, 4.29153442382814E-05, 8.58306884765629E-05, 0.000171661376953125, 0.00034332275390625, 0.0006866455078125, 0.001373291015625, 0.00274658203125, 0.0054931640625, 0.010986328125, 0.02197265625, 0.0439453125, 0.087890625, 0.17578125, 0.3515625, 0.703125}; double startX = Math.floor((rectPts[0] + 180.0) / (resolution[18 - level] * 256)); double startY = Math.floor((90.0 - rectPts[1]) / (resolution[18 - level] * 256)); double endX = Math.ceil((rectPts[2] + 180.0) / (resolution[18 - level] * 256)); double endY = Math.ceil((90.0 - rectPts[3]) / (resolution[18 - level] * 256)); //左上角瓦片坐标和左下角瓦片坐标 double[] result = new double[]{startX, startY, endX, endY}; return result; }
7:,注意
- 虽然最小的瓦片等级是0,但是部分地图并不提供0级或其他较小瓦片等级的地图,因为此时的世界地图将会很小,不能铺满用户设备窗口。
-
墨卡托投影并不是一种坐标系,而是为了在二维平面上展示三维地球而进行的一种空间映射。所以在GIS地图和互联网地图中,虽然用户看到的地图经过了墨卡托投影,但依然使用经纬度坐标来表示地球上点的位置。在地图绘制和地图可视化时,就需要将地图数据使用投影的方式来呈现。
8,参考链接