OpenLayers:
OpenLayers是一个开源的js框架,用于在您的浏览器中实现地图浏览的效果和基本的zoom,pan等功能。OpenLayers支持的地图来源包括了WMS,GoogleMap,KaMap,MSVirtualEarth等等,您也可以用简单的图片作为源,在这一方面OPenLayers提供了非常多的选择。
WMS服务:
1 OGC组织及其开放性规范
为了实现异构的地理空间信息及GIS处理功能的互操作的集成,OGC(Open GIS Consortium)一直致力于寻求一种方式,将地理信息系统技术、分布处理技术、面向对象技术、数据库设计以及实时信息处理方法有效地结合起来,实现分布式异构平台上GIS互操作[2]。OGC制定了开放地理信息互操作规范(OGIS),试图通过共同的开放地理数据模型(OGM)和OGIS参考模型(ORM)来实现互操作。其目的是希望提出一个可扩展的、基于各种标准的、能无缝集成各种在线空间处理和位置服务的框架,使得分布式空间处理系统能通过XML和HTTP技术进行交互,并为各种在线空间数据资源,来自传感器的信息、空间处理服务和位置服务和基于Web的发现、访问、整合、分析、利用和可视化提供互操作框架[3]。
OGC的中心主题是共享信息和提供服务,在OGC的抽象规范中共有17个主题,其中主题12是开放式Web Services空间信息服务框架[4,5],它包含一系列的抽象规范和实现规范。概括地来讲,OGC OpenGIS Web Services(OWS)包括三个主要的地理信息服务即Web Map Service(WMS)、Web Feature Service(WFS)和Web Coverage Service(WCS)。除此之外,还包括Simple Feature Specillcation(SFS),Geography Markup Language(GML)等。
2 WMS规范及其实现过程
2.1 WMS规范
OGC WMS属于OGC图示表达服务,它利用具有地理空间位置信息的数据制作地图。在WMS规范中将地图定义为地理数据可视的表现,WMS返回的不是地图数据,而是地图图像。WMS规范定义了三个操作[6]:
●GetCapabilities操作返回服务级元数据,它是对服务信息内容和请求参数的一种描述,元数据使用XML形式文件表示。
●GetMap操作根据客户端发出的请求参数在服务端进行检索,服务器端返回一个地图图像,其地理空间参数和大小参数是已经明确定义的,返回的地图图像可以是GIF、JPEG、PNG或SVG格式。
●GetFeaturelnfo操作根据用户所请求的X、Y坐标或感兴趣的图层,返回地图上某些特殊要素的信息,信息以HTML,GML或ASCII的格式表示。
2.2 WMS的具体实现过程
在WMS的三个操作中,GetCapabilities和GetMap是必须要实现的,而GetFeaturelnfo是可选的,下面介绍这三种操作的具体实现过程。
WMS的请求与响应是在客户端和服务器端实现的,客户端既可以是普通的浏览器,也可以是应用系统或组件。图1是一个用UML时序图描述的客户端与服务器端的交互过程。
客户端通过HTTP协议向服务器端发送请求并完成空间数据的可视化。服务器端要响应三种基于URL的请求,即GetCapablilties、GetMap和GetFeaturelnfo。客户端接收GIF,JPEG,PNG格式的图像文件或XML格式的元数据文件、GML文件。
图1 客户端与服务器端的交互过程
Fig. 1 Process of interaction between client and server
客户端在请求一个Web地图服务之前,必须了解WMS服务器所能提供地图的相关信息,这些信息包含在地图元数据文件中。在OGCWMS规范中,通过发送GetCapabilities请求获得描述服务器端所能提供服务的元数据,例如,用户可以通过浏览器发送下列请求获得XML文档:
http://localhost:8080/query Capabilities?REQU EST=GetCapabilities & VERSION=version&SERVICE=WMS。
元数据是以XML文档的形式返回的。XML文档中提供的信息包括:WMS服务器支持的所有功能接口列表;所能提供的图像格式;从服务器端传送地图数据的可用的空间参照系列表;从服务器端返回的所有异常的列表;特定与某一软件商的WMS服务器修改和控制功能的专用元数据的列表;某一WMS服务器的可用图层及可选属性的列表;该WMS是否支持可选的GetFeaturelnfo操作等。
客户端解析元数据描述文档,从中检索到需要的信息,然后发出下面格式的GetMap请求,http//localhost:8080/deegeewms? SERVIC
E=WMS&REQUEST = GetMap&LAYERS = layers&STYLES=styleS&FORMAT = format &sRS=coordinate-system&BBOX=bounding_box&WIDTH = width & HEIGHT=height
WMS服务器处理来自用户的请求,通过访问数据库或文件获得需要的数据,以图像的方式返回给用户请求的地图,格式可以为JPEG、PNG、GIF或SVG。
由于每一个GetMap请求将返回对应一个地图的一个或多个图层。多个图层在构成一个新的地图时就有可能相互覆盖,解决方法就是将它们设置成透明的。用户不仅可以请求单个WMS服务器上的多个图层,也可以向多个WMS服务器发出请求,由于每一个服务器有不同的元数据描述文件,客户端就需要向每一个WMS服务器发送Get Captilities请求获取各自不同的元数据描述文档,当用户选择的图层分别位于不同的WMS服务器上时,每一个服务器将返回一个或多个图层,这些图层有可能使用不同的坐标参照系、显示范围等参数,只有参数相同的图层才可以进行叠加。
选定地图上的某一点,通过发送GetFeaturelnfo请求可以获得该区域的更详细的信息,WMS服务器的响应将是以下三种格式的一种,GML格式、文本格式和HTML文件。由于GML是基于XML的,所以客户端可以通过编程的方式解析GML文件,转化为可以在浏览器上显示的SVG矢量格式。
3 基于WMS的体系结构及实现过程
图2 WMS应用实例体系结构框架
Fig. 2 The architecture of WMS instance
由于WMS规范从语义和语法两个角度详细定义了WMS服务器向客户程序提供的操作接口,所以它提供了规范化网络空间信息系统的能力。所有遵循该规范的服务器都可以被客户端访问。同所有基于Web的应用程序一样,OGCWMS规范可以有多种实现方式。三层或多层体系结构由于可以对显示层、业务逻辑层和数据层进行逻辑上和物理上的分离,便于系统的维护和升级,最大程度地减少了系统间的耦合,成为构建基于Web的应用系统的首选。本文设计了一个基于开源WMS服务器的三层结构的WMS应用框架,即WMS客户端、WMS服务器端和数据源端。其体系结构见图2OpenLayers调用WMS服务:
图像的加载是采用的螺旋式加载。首先从右上角开始按照顺时针方向给整个img矩阵建立一个堆栈,其实质是按照堆栈先进后出思想设计的一个数组,然后按堆栈中的位置顺序从视窗中间开始逆时针方向依次加载栅格图像。
整个img矩阵构成一个grid格网,当移动地图使得grid的范围[即bound值]不能包含视窗的bound,或者地图的显示比例发生变化时会重新向服务器请求数据,否则只会移动各个img的位置,从而使得视窗在grid之内。
客户端用于栅格图显示的img数量是由计算得到的。用户指定的用于显示的div作为视窗,视窗大小除以每张img的长宽得到一个m*n的矩阵,表示要填满整个视窗在长宽方向所需的最少的img数量,然后将Img长宽方向都缓存两个img得到一个(m+2)*(n+2)的矩阵,即为客户端img数,默认缓存为两格,当然我们也可以将缓存数作为参数传入以改变缓存默认值buffer,那么改动之后的矩阵为(m+buffer)*(n+buffer)。
在移动的时候取grid网格中左上角那个tile的左上角坐标值,即grid[0][0]为参考点,当这个点的坐标超出阈值的时候会搬动grid中各个节点的位置。
这里的img在openlayers中其实已经被封装成了Tile类,该图层有一个div作为容器。每个image都有一个div将其包装起来,tileSize是按照OpenLayers.TILE_WHITH,OpenLayers.TILE_HEIGHT常量事先就定义好了,表示每个tile实例的大小。
栅格图形显示之提供了基于标准的WMS调用的,即只要服务器端提供了标准的WMS服务,客户端就可以调用到。由于OpenLayers的螺旋加载功能是和最底下的一层分开的,因此我们可以在最底层扩展自己的栅格地图调用类,即让自己的类继承自OpenLayers.Layer.Grid,在我们自己的类中重构getURL方法。但是,这也有个弊端,那就是我们依然很大程度上继承了OpenLayers的栅格调用方法,这种方法具有很高的重用性,非常利于扩展,但是不一定会带来高的效率。
举个例子:我们需要自己的调用方式,服务器端提供的栅格图金字塔一共有17级,整个显示范围是-180,-90,180,90,第零级每张栅格图经纬度方向上的跨度都是18度,随着级数升高经纬度方向上的跨度相比前一级都减半,栅格图采用的是格网坐标,坐标原点在左上角。我们自己的调用方式有一部分和WMS栅格图调用相同。当移动或者缩放的范围超出阈值的时候会向服务器发送请求,我们根据每个Tile的经纬度范围计算得到该栅格图中心点的经纬度坐标,而根据当前经纬度可以知道该分辨率下服务器端栅格图矩阵,然后再根据该分辨率下栅格图的经纬度跨度得到Tile在服务器端提供的栅格图上所处的位置,从而取到该图。从服务器端过来的栅格图像每张大小为256*256像素。这个过程是很我重新写过的,基本继承了OpenLayers的WMS调用的核心思想,当然效率也不会有改进。
其实我们完全可以让自己的栅格显示类直接继承自OpenLayers.Layer,这样一方面利用了OpenLayers图层操作的框架,令一方面又最大程度上放弃了OpenLayers带来低效率的机制。经过本人试验,虽然做了这个改进,但是最终的效果也没有很明显的改进,原因容后续分析。
该部分主要包含4个类:
OpenLayers.Layer,OpenLayers.Layer.HTTPRequest,OpenLayers.Layer.Grid,OpenLayers.Layer.WMS,它们的继承关系如图所示: