OpenLayers教程 多源数据加载之瓦片地图原理 |
您所在的位置:网站首页 › 瓦片的拼音是什么样的呀 › OpenLayers教程 多源数据加载之瓦片地图原理 |
一、瓦片地图简介
瓦片地图(也叫切片地图)源于一种大地图解决方案,就是在多个比例尺下配置地图,然后提前把每个比例尺下的地图绘制为小块图片(瓦片),保存在服务器上用于缓存的目录中。这样客户端在访问地图时,可以直接获取需要的小块图片拼接成整幅地图,而不是由服务器动态创建(实时创建)出一幅图片再发送到客户端,从而极大提高了访问速度。 瓦片地图起始于谷歌地图。在2005年前后谷歌地图已经开始将矢量图层融合为一张栅格化的大图像,大图像被切分为256像素 x 256像素的图片(瓦片)。这些图片预先生成并存储在磁盘上,以便快速分发(通过AJAX)到客户端。这样做可以同时支持成千上万个并发请求(异步-因为瓦片地图根据请求范围加载),而这对于动态地图绘制而言基本是不可能的。 瓦片地图的缺点是不能改变图层的符号,可以认为它们是一些"死图片",不能进行更新。因此,WebGIS中通常的做法是将通用的基础底图图层发布为瓦片,在其上叠加另外的包含专题信息的图层,这种图层结构可以被比喻为"图层三明治"。 如今有许多软件提供创建地图瓦片的功能,商业软件中,功能强大的ArcGIS软件系列的ArcGIS Server(价格较贵)能够进行创建瓦片地图操作,国内的超图SuperMap iServer同样也能创建瓦片地图。另外,开源的Mapnik库也可以创建地图瓦片,Mapnik库被封装在用户友好的应用程序TileMill中。 二、LODLOD是Levels of Detail(细节层级)的简写,用于根据当前的环境,渲染不同的图像,用于降低非重要内容的细节度,从而提高渲染效率,在电子游戏中经常运用,对于需要显示全球地图的GIS系统而言,更需要应用这项技术。 在不同的LOD下,自然分辨率就可能不一样,这两者是紧密结合在一起的。对于图形显示系统而言,分辨率作为屏幕坐标和世界坐标之间计算的纽带,其作用是非常重要的(例如,屏幕上两个像素点间的距离对应的现实世界的距离是多少,这就需要通过分辨率来衡量与计算——分辨率将在后面进行介绍)。 在详细讲解之前,假设给你两张A4纸,在其中一张纸上把你家整个绘制上去,在另一张纸上只把你睡的房间绘制上去。如果别人想看你家,你会给哪一张纸?如果想看你睡的房间,你会给哪一张纸?相信你不会给错,LOD就是这种根据不同需要,采用不同图的技术方案。在地图应用中,最直观的体验,就是地图放大缩小。当地图放大后,能看到更详细的地理信息,比如街道、商店等等。当地图缩小再缩小,原来能看到的街道、商店就看不见了,但是能看到更大的区域。我们的屏幕就相当于是A4纸,大小不变。 LOD这个技术方案非常棒!非常符合我们的自然习惯,所以在很多图形系统中都使用了这项技术。在GIS系统中,不断放大,就能看到更多地图细节,了解更加详细的信息。对于GIS引擎的开发者而言,需要实现这项技术,当发现用户放大地图时,就立马使用更有细节的地图图片,替换现在显示的地图图片。现在问题来了:意思是说对于同一个地点而言,需要有更多张呈现不同细节程度的图片?是的,你没有猜错。虽然在使用瓦片地图的过程中,感觉放大、缩小地图是浑然一体的,但其实就在你眼皮下发生了图片替换。不同层级使用具有不同细节的地图瓦片,这就需要为每一个层级准备图片,如果使用离线工具下载瓦片地图,会看到下载的图片是按照层级Z进行存储的。开发者不用担心数据源的处理,只需要知道这个原理就可以了。 为了便于理解GIS系统中不同层级,使用不同的图片,下面使用google在线瓦片地图进行说明。最小层级0情况下,只用了一张256*256像素的图片表示整个地球平面: 稍大一个层级1情况下,用了四张256*256像素的图片(各张图片中表示的信息更丰富了)来表示整个地球:
如果对整个地球图片进行切片,需要考虑的是整个地球图片大小,以及切片规则,切片(瓦片)大小。 对于WebGIS而言,在线地图几乎都采用Web墨卡托投影坐标系(EPSG:3857,后面会详解介绍),地球投影到平面上就是一个正方形。为了方便使用,切片时大多按照正方形的方式来进行切片,比如大小为256*256的瓦片(单位像素),一个1024*1024的地图,就可以切片4张小的256*256的瓦片。 瓦片大小几乎都是256*256,有一些则会增加到512*512(由于以前的屏幕分辨率通常比较低,所以256*256的瓦片在低分辨率的屏幕上显示效果比较好,随着屏幕分辨率的提高,瓦片大小自然就会增加到512*512。但目前主流仍是256*256大小的瓦片)。 LOD会使得不同层级下的全球地图大小不一致,结合瓦片地图技术一起,就出现了金字塔瓦片结构: 在金字塔瓦片结构中,上一层级的一张瓦片,在更大一层级中,会用4张瓦片来表示,依次类推,比如上一篇文章中看到的Google在线瓦片地图的第0级和第1级的瓦片地图就呈现这样的规律。这样做可以维持正方形的投影方式不变,同时按照2的幂次方放大(瓦片的边长),计算效率非常高。 3.2、瓦片数量计算通过上面切片的介绍,我们可以对每一层级拥有的瓦片的数量进行简单的计算: 层级0的瓦片数是 1 = 2^0 ∗ 2^0层级1的瓦片数是 4 = 2^1 * 2^1层级2的瓦片数是 16 = 2^2 * 2^2层级3的瓦片数是 64 = 2^3 * 2^3层级z的瓦片数是 2^z * 2^z 3.3、瓦片坐标系从以上的金字塔瓦片结构可以看出来,瓦片的组织方式是三维的,因此对一幅地图进行切片时,需要给每一块瓦片进行详细的编号,即需要指定每一块瓦片的行号、列号以及层级数。 这个问题就涉及到了瓦片坐标系,瓦片坐标系是瓦片地图的组织参考框架。它规定每一块瓦片的行号、列号以及层级数,另外,在瓦片坐标系中列号一般从左到右方向递增,而在瓦片坐标系中行号有可能沿着从上到下的方向递增,或者从下到上递增,所以不同的瓦片坐标系的起始点(原点)不同。 不同的在线地图服务商,可能定义不一样的瓦片坐标系,瓦片坐标系不一样,那么对应的同一个位置的瓦片的坐标也会不一样。需要引起重视。 OpenLayers提供了一个用于调试瓦片坐标系的ol.source.TileDebug类。借助这个类,我们可以清晰的看到每一个瓦片的坐标: 代码如下:
查看瓦片坐标
let osmSource = new ol.source.OSM(); var map = new ol.Map({ layers: [ // 加载Open Street Map地图 new ol.layer.Tile({ source: osmSource }), // 添加一个显示OSM地图的瓦片网格的图层 new ol.layer.Tile({ source: new ol.source.TileDebug({ projection: 'EPSG:3857', // Web墨卡托投影坐标系 tileGrid: osmSource.getTileGrid() // 获取OSM地图的瓦片坐标系 }) }) ], target: 'map', view: new ol.View({ center: ol.proj.transform([104, 30], 'EPSG:4326', 'EPSG:3857'), zoom: 10 }) }); 首先从上图可以看到地图上多了网格,每一个网格对应的就是一个瓦片。 其次网格中有三个数字,这些数字就表示当前瓦片的坐标: 第一个数字是层级z第二个数字是表示经度方向上的x(列号)第三个数字是表示纬度方向上的y(行号) 四、分辨率 4.1、分辨率简介分辨率的简单定义是屏幕上的1像素表示的现实世界的地面实际距离。 上一节说到了金字塔瓦片结构中每一个层级,会使用不同数量的瓦片来表示整个地球,那么无论是哪一个层级,所表示的实际地理空间范围都是一致的,但使用的瓦片个数却是不一样的。 以Google在线地图为例,层级0使用了一个瓦片,层级1使用了4个瓦片。通过计算可以知道层级0的整个地球图像(瓦片)为256*256像素大小,层级1整个地球图像为512*512像素大小。而层级0和层级1表示的地球范围都是一样的(经度[-180°, 180°],纬度[-90°, 90°])。在层级0的时候,一个像素在水平方向就表示360°/256 = 1.40625°这么长的经度范围(以度为单位),在竖直方向就表示180°/256 = 0.703125°这么长的纬度范围(以度为单位)。而这两个数字就是分辨率了,即一个像素所表示的现实世界的范围是多少,这个范围可能是度(在地理坐标系统中),可能是米(在投影坐标系统中),或者其他单位,根据具体的情况而定。 4.2、Web墨卡托投影坐标系中的分辨率我们知道,在WebGIS中使用的在线瓦片地图是采用的Web墨卡托(Mercator)投影坐标系(可以查看这篇文章-墨卡托投影-来了解详细内容),经过投影后,整个地球是一个正方形,所能表示的地球范围为: 经度[-180°, 180°],纬度[-85°, 85°],单位为度。 对应的Web墨卡托坐标系的范围为: x[-20037508.3427892, 20037508.3427892],范围y同样是[-20037508.3427892, 20037508.3427892],单位为米。 或许,你会好奇这个范围是怎么计算而来的,如果详细了解过它的定义,应该知道Web墨卡托投影只是简单的把地球球面剖开拉伸为一个正方形,由于南北极两端采用这种拉伸会严重变形,并且南北极在使用过程中很少用到,所以干脆就只投影了地球的[-85, 85]纬度范围。然后在经度-180度(或+180)的地方从上到下剖开地球,然后按照赤道方向来展开成一张平面,那么这个平面的边长,就等于以地球赤道半径按照圆来计算的周长。近似的按照6378137米为地球半径来计算,那么整个赤道周长的一半,即为: π∗r=3.1415926∗6378137=20037508.0009862 以上就是Web墨卡托投影坐标系范围的完整的计算过程,墨卡托投影也有很多变形,会有细微的不同,OpenLayers默认使用的就是EPSG:3857(Web墨卡托投影坐标系),对于该坐标系的详细定义,可以参见epsg.io.3867。 有了范围之后,要想计算Web墨卡托投影坐标系中的分辨率,按照上面的计算过程就非常简单了,还是以Google在线瓦片地图为例,x、y方向上的各层级瓦片地图分辨率计算公式可以归纳为: resolution = rang / (256 * 2^z) rang —— 表示x方向或y方向上的整个范围,比如20037508.3427892 * 2。256 —— 表示一个瓦片的边长,单位为像素。2^z —— 表示在层级z下,x或y方向上的瓦片个数。那么整个公式计算出来就是在x或y方向,屏幕上一个像素所能代表的实际地理范围,即分辨率。 4.3、OpenLayers默认使用的分辨率OpenLayers默认设置了加载瓦片地图时采用的分辨率,通过一个示例来看一下: 代码如下: resolution.html: OpenLayers默认使用的分辨率 当前层级:分辨率:
var map = new ol.Map({ target: 'map', layers: [ new ol.layer.Tile({ source: new ol.source.OSM() }) ], 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(); 缩放上面的地图,从层级0开始,用前面介绍的公式和当前地图显示的分辨率进行比较,你会发现OpenLayers默认采用的分辨率和Google在线瓦片地图一样。 OpenLayers瓦片地图默认分辨率表(地面比例尺):
注意事项 为什么我们上面一直以Google在线瓦片地图举例说明? 因为不同的在线瓦片地图可能采用不一样的分辨率,比如百度在线瓦片地图。所以在使用在线瓦片地图或者自己制作的瓦片地图时,都需要知道使用的分辨率是多少。如若不然,可能也会出现位置偏移。
原文地址: https://blog.csdn.net/qq_35732147/article/details/94589577 https://blog.csdn.net/qq_35732147/article/details/94595658 |
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |