OpenLayers学习--Layer体系(二)

在OpenLayers学习——Layer体系(一)中,绘制出整个OpenLayers的UML架构图。

这里重点讨论OpenLayers的网络瓦片地图的绘制过程,这里以XYZ图层作为样例来调试学习。

在讨论之前,首先明确一些基本概念:

分辨率(resolution):瓦片上每个像素所代表的地图距离(单位是地图单位)。

最大范围(maxExtent):地图或者图层的最大的范围。

瓦片切图原点的位置(tileOriginCorner):"tl”(左上角)、"tr”、"bl”、"br”。

行编号顺序(rowSign):不需要开发者直接调用,如果设置的tileOriginCorner为“tl”,则该值为1,代表为从上到下为行号,从左到右为列号,默认值为-1。

比率(ratio):地图分辨率与对应等级瓦片分辨率的比例。

调试代码,查看Layer绘图机制,如下图:

上图是简化的绘制出地图地图的整个过程。

(1)任何地图视图发生变化的时候都会执行map的moveTo方法,该方法中首先判断baseLayer是否存在,如果存在,则执行baseLayer的moveTo方法。

(2)在baseLayer的moveTo方法中首先会计算需要绘制的瓦片的行列号(即图中的initGridTiles),目的是为了计算该瓦片在服务器中的存放地址(url)。

计算瓦片的行列号,需要5个参数:待求瓦片的范围tileBound,地图切图的原点tileOrigin,地图的分辨率resolution,瓦片的大小tileSize,地图的切图方向。

这里假设地图切图的方向是从左到右,从上到下,则瓦片行列号的计算方法如下:

colNum = Math.Ceil((tileBound.getCenter().lon - tileOrigin.lon)/(tileSize.width*resolution));

rowNum =Math.Ceil((tileOrigin.lat - tileBound.getCenter().lat )/(tileSize.height*resolution));

(3)在initGridTiles()方法中,除了计算每一张瓦片的行列号之外还计算该瓦片在地图页面上的绘图位置(控件坐标系),目的是为了地图显示在前台页面上。

计算绘图位置的方法是,首先取到该图层在地图上左上角的地理坐标:

        var layerContainerDivLeft = this.map.layerContainerOriginPx.x;
        var layerContainerDivTop = this.map.layerContainerOriginPx.y;

然后以图层容器左上角显示的瓦片的左上角地理坐标,并调用getViewPortPxFromLonLat()来计算该点的屏幕坐标。如下图所示:

图中黑色的边框矩形代表绘图的屏幕,即map对应的div,红色边框的矩形代表瓦片数据,getViewPortPxFromLonLat()方法计算的是某一个地图坐标的值对应在map的div参考坐标系下的屏幕坐标值。即要计算每一个瓦片绘制在什么位置上,通过该步骤计算得到,此处只要统一计算容器的左上角瓦片的坐标参考(图中蓝色的点),其他的瓦片绘图位置可以根据该位置推算得到。

在initGridTiles得到一个tileData数组,包含了屏幕上需要显示的瓦片所需要的所有数据,瓦片的行列号,瓦片的地理范围坐标,瓦片的屏幕坐标。

(4)完成初始化tileData数组之后,可以开始绘图,绘图是调用的renderTile()方法,该方法中可以调用到Layer的getUrl()方法获取到瓦片数据所在的路径,然后初始化地图容器中的该瓦片所对应的div,并在该div中添加img数据,将img的SRC指向瓦片的url,完成地图的渲染。

结论:

瓦片地图数据的绘图方式都是一样,初始化一个需要绘制瓦片大小一样的DIV容器,容器中存放一个Img,Img的Src设置为tile的Url。

瓦片地图数据最关键的是计算瓦片所在的服务器路径,即重写好getURL方法。

计算瓦片的方法都是一样,根据切图原点、瓦片大小、瓦片编号方式就可以计算出某一个瓦片的行列号,关键是理解所调用TMS服务的切图协议。

时间: 2024-10-29 03:22:04

OpenLayers学习--Layer体系(二)的相关文章

OpenLayers学习--加载指定等级指定范围的高德地图数据

在使用高德地图数据的时候,我们通常不需要加载世界地图,只需要指定项目片区地图数据即可:同样,我们也不需要所有等级的数据,只需要指定等级数据即可. 按照<OpenLayers学习--Layer体系(一)>中的方法,直接使用XYZ图层类来加载,显然无法实现该功能.主要原因有以下两点: 1.没有指定地图的分辨率 OpenLayers的机制就是,当你没有给Layer指定分辨率,也没有给Map指定分辨率,则直接将地图的最大范围的左上角点作为切图原点,并且按照18级来计算切图分辨率,分辨率是以1/2向下递

IOS图层Layer学习笔记(二)—— CALayer(上)

IOS图层Layer学习笔记(二)-- CALayer(上) 简介 CALayer是所有图层的基类.主要是一些基本显示属性(位置.锚点.颜色.透明度等).层次关系(子图层和父图层).基本动画等. 接下来分别从常用属性.类方法和实例方法来介绍CALayer的使用.顺序是按头文件的排序来. 常用属性 bounds CGRect,Animatable.控制layer的大小,其中x和y无效果,默认是(0,0). position CGPoint,Animatable.控制layer锚点在父图层的位置.

cocos2dx游戏开发——微信打飞机学习笔记(二)——游戏框架

一.游戏的基本框架: WelcomeScene    ——>    GameScene   ——>   GameOverScene ||                                       ||                                    || ∨                                      ∨                                   ∨ WelcomeLayer            

cocos2dx游戏开发——别踩白块学习笔记(二)——经典模式的实现

一.创建GameScene以及GameLayer 就是简单创建一个Scene而已,在此就不多说啦~,可以参照我的打飞机的学习笔记(2). 二.添加一个开始栏 很简单,就是调用Block中的create方法就可以啦~,只是需要传入大小和颜色等等的参数即可. void GameLayer::addStartLine() { auto block = Block::createWithArgs(Color3B::YELLOW, Size(visibleSize.width,visibleSize.he

学习layer和laydate的官方文档

layer是一个Web弹窗组件,laydate是一个日期和时间组件.二者都是layui的组件.layer的官方文档:http://www.layui.com/doc/modules/layer.html/,laydate的官方文档:http://www.layui.com/doc/modules/laydate.html,layer可以独立使用,也可以通过layui模块化使用.具体使用参考layer的官方文档. 一.学习layer中常用的基础参数 一般在调用layer的open或msg方法时用到

winform学习日志(二十三)---------------socket(TCP)发送文件

一:由于在上一个随笔的基础之上拓展的所以直接上代码,客户端: using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Net.Sockets; using Sys

Unix文件系统学习笔记之二: 文件描述符、inode和打开文件表

Unix文件系统学习笔记之二: 文件描述符.inode和打开文件表 系统盘上数据的布局 文件系统无非是关于数据在磁盘上的组织以及存储空间管理的,为此,首先需要知道磁盘上数据的总体布局方式.以Unix为例,最重要的一张表如下: Unix 进程管理中和用户文件.io 最相关的数据结构:usr 数据结构 The procstructure does not record information related to file access.  However the userstructure con

C++primer学习笔记(二)——Chapter 4

4.1  Fundamentals 1.Basic Concepts (1)操作符分为一元,二元或者三元操作符: (2)复杂的表达式中含有很多操作符时: 规则一:分为不同的级别,级别高的先运行: 规则二:相同级别的操作符有执行顺序的确定: (3)操作符可以改变操作数的类型 一般将级别低的转化成级别高的 (4)重载运算符 相同的运算符在对不同类型的对象进行操作的时候,会有不同的功能: (5)Lvalue和Rvalue 显而易见:Lvalue指的是Left value,Rvalue指的是Right

Android学习路线(二十)运用Fragment构建动态UI

要在Android系统上创建一个动态或者多面板的用户界面,你需要将UI组件以及activity行为封装成模块,让它能够在你的activity中灵活地切换显示与隐藏.你可以使用Fragment类来创建这些模块,它们能够表现得有些像嵌套的activity,它们定义着自己的布局,管理自己的生命周期. 当一个fragment指定了它自己的布局,它可以在activity中和其他的fragment配置为不同的组合,这样就能够为不同的屏幕尺寸来修改你的布局配置(在小屏幕上一次展现一个fragment,而在大屏