分辨率

前面简单提到过,分辨率是屏幕坐标和世界坐标的纽带,通过它,才能知道你在屏幕上用鼠标点击的位置对应于世界地图具体的经纬度位置。 当然你不用自己来做这个计算,OpenLayers 3的ol.Map已提供了对应的方法getCoordinateFromPixel来帮助你实现坐标转换。 你可能经常使用这个函数,但却不知道背后是怎样的一个原理,本小节将理清其中的来龙去脉。

上一节说到了每一个层级,会使用不同的瓦片数来表示整个地球,那么无论是哪一个层级,所表示的实际地理空间范围都是一致的。但使用的瓦片个数却是不一样的,以Google在线地图为例,层级0使用了一个瓦片,层级1使用了4个瓦片。 通过计算可以知道层级0整个地球图像为256256256*256像素大小,层级1整个地球图像为512512512*512像素大小。 层级0和层级1表示的地球范围都是一样的经度[-180, 180],纬度[-90, 90]。 在层级0的时候,一个像素就表示360256=1.40625\frac{360}{256} = 1.40625这么长的经度范围,180256=0.703125\frac{180}{256}=0.703125这么长的纬度范围。 而这两个数字就是分辨率了,即一个像素所表达的范围是多少,这个范围可能是度,可能是米,或者其他单位,根据具体的情况而定。

墨卡托投影坐标系下的分辨率

我们知道,在WebGis中使用的在线瓦片地图是采用的墨卡托(Mercator)投影坐标系,经过投影后,整个地球是一个正方形,所能表示的地球范围为经度[-180, 180],纬度[-85, 85],单位为度。 对应的墨卡托坐标系的范围x[-20037508.3427892, 20037508.3427892],范围y同样是[-20037508.3427892, 20037508.3427892],单位为m。 或许你会好奇这个范围是怎么计算而来的,如果详细了解过它的定义,应该知道墨卡托只是简单的把地球球面剖开拉伸为一个正方形而来,由于南北极两端采用这种拉伸会严重变形,并且南北极在使用过程中很少用到,所以干脆就只投影了[-85, 85]纬度范围的地球。 而展开时,因为纬度范围有缩减,所以肯定只能以经度来展开,即在经度-180度的地方从上到下剖开地球,然后按照赤道方向来展开成一张平面,那么这个平面的长,就等于以地球赤道半径按照圆来计算的周长。 近似的按照6378137米为半径来计算,那么整个赤道周长的一半,即为

πr=3.14159266378137=20037508.0009862\pi*r=3.1415926*6378137=20037508.0009862

以上就是墨卡托投影坐标系范围的完整的计算过程,墨卡托也有很多变形,会有细微的不同,OpenLayers 3默认使用的是EPSG:3857,对于该坐标系的详细定义,可以参见epsg.io 3857

有了范围之后,要想计算分辨率,按照上面的计算过程就非常简单了,还是以Google在线瓦片地图为例,x方向上的分辨率计算公式可以归纳为:

resolution=rangeX2562level resolution = \frac{rangeX}{256*2^{level}}

rangeX表示x方向上整个范围,比如 20037508.3427892(20037508.3427892)20037508.3427892 - (-20037508.3427892),256表示的一个瓦片的宽度,单位为像素,2level2^{level}表示的在层级level下,x方向上的瓦片个数。 那么分母计算出来的结果就是在层级level下,整个地图在x方向上的宽度,单位为像素。 那么整个公式计算出来就是在x方向上一个像素所能代表的实际地理范围,即分辨率。

OpenLayers默认使用的分辨率

当前层级:分辨率:

代码如下:

<div id="map" style="width: 100%"></div>
<div><span>当前层级:</span><span id="zoom"></span><span>分辨率:</span><span id="resolution"></span></div>
<script type="text/javascript">
    var map = new ol.Map({
        layers: [
          new ol.layer.Tile({
            source: new ol.source.OSM()
          })
        ],
        target: 'map',
        view: new ol.View({
          center: ol.proj.transform(
              [104, 30], 'EPSG:4326', 'EPSG:3857'),
          zoom: 10
        })
    });

    // 监听层级变化,输出当前层级和分辨率
    map.getView().on('change:resolution', function(){
        document.getElementById('zoom').innerHTML =  this.getZoom() + ',';
        document.getElementById('resolution').innerHTML = this.getResolution();
    })

    document.getElementById('zoom').innerHTML = map.getView().getZoom() + ',';
    document.getElementById('resolution').innerHTML = + map.getView().getResolution();
</script>

缩放上面的地图,从层级0开始,用前面介绍的公式和当前地图显示的分辨率进行比较,你会发现OpenLayers默认采用的分辨率和Google在线瓦片地图一样。

注意事项

为什么我们上面一直以Google在线瓦片地图举例说明? 因为不同的在线瓦片地图可能采用不一样的分辨率,比如百度在线瓦片地图。 所以在使用在线瓦片地图或者自己制作的瓦片地图时,都需要知道使用的分辨率是多少。 如若不然,可能也会出现位置偏移。