openlayers中比例尺的计算原理


比例尺=图上距离与实际距离的比。本文主要侧重于电子地图(或者web地图)的计算

一、概述

比例尺,作为地图三要素(比例尺、图例、注记)之一,是地图不可或缺的组成部分。从传统的纸质地图到现在的电子地图,如天地图、百度地图、高德地图、腾讯地图、谷歌地图、Bing地图等,都能看到其身影。
在一张传统的纸质地图中、地图的长宽是固定的,对应的地理长度也是固定的,因此比例尺也是固定的,且容易计算,即地图一段距离:实际对应的地理长度。而现在的电子地图、随着地图的缩放,一定屏幕宽度(像素)对应的实际距离不同,因此随着地图的缩放级别不一样,比例尺也发生相应的改变。但实质还是没变,只是添加了缩放级别、分辨率和屏幕像素等。
缩放级别、分辨率、和像素的相关知识有很多,这里就不进行详细描述。
举个例子:以全球墨卡托地图为例
缩放级别为0,对应1张图片,
像素宽度为256,实际距离为2πearth.radius(6378137m)=40075016.68557849
0级下的分辨率为40075016.68557849/256=156543.03392804097(像素/米)
0级下的比例尺:1:591658710.9091312(将分辨率的像素转换为米即可得到)

1英寸=0.0254米=96像素
1像素=0.0254/96 米

二、查看源码

在openlayer的scaleline.js(https://github.com/openlayers/openlayers/blob/v4.6.5/src/ol/control/scaleline.js)中。
第一步、构造ol.control.ScaleLine对象,
动态创建页面元素,如

<div class="ol-scale-line ol-unselectable">
   <div class="ol-scale-line-inner" style="width: 66px;">10000 km</div>
</div>

设置默认的页面比例尺最小长度:64px
地图渲染、监听、单位等设置

第二步、设置原型方法,这里着重理解方法ol.control.ScaleLine.prototype.updateElement_

  1. 获取视图信息this.viewState_,包括中心点、坐标系、单位、分辨率对应的单位
var viewState = this.viewState_;
……
var center = viewState.center;
var projection = viewState.projection;
var units = this.getUnits();
var pointResolutionUnits = units == ol.control.ScaleLineUnits.DEGREES ?
    ol.proj.Units.DEGREES :
    ol.proj.Units.METERS;
  1. 计算中心点的分辨率pointResolution
var pointResolution =
     ol.proj.getPointResolution(projection, viewState.resolution, center, pointResolutionUnits);

补充:在epsg3857.js文件中,定义了getPointResolution方法。
墨卡托投影,纬度越高,变形越大,不能以赤道的分辨率为准,二是以该纬度的分辨率为准,即纬度周长(2πearth.radiuscos(latπ180))/256,(lat单位为度,需转化为弧度)
公式为:(默认对应0级)
赤道分辨率:resolution =2
πearth.radius/256
某一纬度分辨率:resolution * cos(lat
π*180)

保证单位的统一,需要经纬度坐标和墨卡托的坐标的转化
var mercator.y = ol.proj.EPSG3857.RADIUS Math.log(Math.tan(Math.PI * (lat + 90) / 360));
var lat= mercator.y/ ol.proj.EPSG3857.RADIUS
lat=180/Math.PI
(2atan(exp(mercator.yMath.PI/180))-Math.PI/2);

转化后:resolution / ol.math.cosh(lat / ol.proj.EPSG3857.RADIUS);

//resolution:分辨率,即我们通常计算的以赤道为标准的分辨率
//point:以米为单位
//返回值:某一纬度的分辨率,resolution /*cos(lat*π*180)
getPointResolution: function(resolution, point) {  
     return resolution / ol.math.cosh(point[1] / ol.proj.EPSG3857.RADIUS);
}

此处省略了其他坐标系的点分辨率的求法,可自行查看、推算。

  1. 根据分辨率求比例尺
//默认minWidth_=64px;
var nominalCount = this.minWidth_ * pointResolution;
//后面根据分辨率单位,对比例尺进行单位转化
……

三、总结

在openlayers中,比例尺的计算,主要是通过视图中心点的分辨率来得到。因此,重点及难点是在不同的坐标系,赤道以外的点的分辨率的计算。

在墨卡托坐标系下,[x,y]的分辨率=resolution / ol.math.cosh(y / ol.proj.EPSG3857.RADIUS);

转载自:https://blog.csdn.net/u013240519/article/details/84136793

You may also like...