【地图开发】MapServer+TileCache+OpenLayers
去年写的一篇关于MapServer开发的文章,迟迟没有写后续,主要是因为真的忘了,现在补上去。我知道现在网上关于MapServer的开源地图引擎的资料特别少,并且也都是国外文献,晦涩难懂。之前毕业论文因为做这个,所以当时也研究了很长一段时间。最后实现的地图基于了MapServer开源地图引擎+TileCache切片缓存+OpenLayers前端js操作框架。我不知道现在做这方面研究的人还多不多,但是或多或少还是有人需要了解这方面的开发技能吧。
下面基本是从我的论文里摘出来的,有基础知识讲解、地图环境搭建和各种配置,以及地图应用的完整开发流程和代码注释,参照着就能自己构建出一个完整的地图应用。反正我自己是实现了。
温馨提醒,下文篇幅很长,应该是现在网上很全的一篇讲述MapServer开发的文章了,别闲太长看不下去,如果连这点的耐心都没有,技术研发也就不用提了。
注:因为涉及很多原创内容,如转载请注明出处,文章仅供非商业的学习用途。
第1章 MapServer
1.1 MapServer简述
MapServer,它是美国明尼苏达大学 (University of Minnesota, 简称 UMN)在二十世纪90 年代利用 C语言开发的开源 WebGIS项目。
MapServer是一套基于胖服务器端/瘦客户端模式的实时地图发布系统,客户端发送数据请求时,服务器端实时处理空间数据,并将生成的数据发送给客户端。MapServer 的核心部分是C语言编写的地图操作模块,它本身许多功能的实现依赖一些开源或免费的库。
MapServer 基于C 语言,利用GEOS、OGR/GDAL 对多种矢量和栅格数据的支持,通过Proj.4共享库实时的进行投影变换。同时,还集合PostGIS 和开源数据库PostgreSQL 对地理空间数据进行存储和SQL 查询操作,基于ka-map 、MapLab 、Cartoweb 、OpenLayers和Chameleon 等一系列客户端JavaScript API来支持对地理空间数据的传输与表达,并且遵守OGC制定的WMS、WFS、WCS、WMC、SLD、GML 和Filter Encoding 等一系列规范。
1.2 MapServer绘图机制
MapServer 的绘图机制:首先,MapServer 引擎对各种类型的空间数据进行读取,并转换成 WKT(Well Know Text)的格式。继而,它读取 WKT 中的各种要素,按照 MapFile 文件中指定的排列顺序和排列渲染方式使用 GD 函数数据库,生成对应格式的图像,最后输出。因此,MapFile 文件是 MapServer 对空间地图数据进行配置管理发布的最重要的配置文件。
MapServer 对输入数据格式支持广泛,包含支持常用的矢量数据格式 shapefiles、PostGIS、ArcSDE、geometries、Arc/Info coverages、OpenDAP 和 Census TIGER files 等和通过添加 GDAL 包支持 20 多种格式的位图数据格式(包括 JPEG、GIF、BitMAP 等)。
此外,对栅格格式的两种数据可以直接读取:EPPL7 和 GeoTIFF。同时,MapServer 提供了多种不同的输出格式,用以不同需求:包括 BMP、JPEG、GIF、GeoTIFF、PDF、FLASH、SWF、SVG 等。MapServer 优秀的数据格式支持能力,是通过内在绑定其他函数库的依赖实现的。例如,MapServer使用了 FrankWarmerdam 开发的 ShapeLIB 库,来对 ESRI 的 ShapeFile类型进行支持。
图 1-1 MapServer的绘图机制
1.3 MapFile结构
MapFile是MapServer 配置地图排列和样式的核心。MapFile通过对图像集合进行定义,对地图之间的各种要素有机组织成预定层次结构的整体。而这个层次和对象,决定了地图在浏览器显示的外观样式和对应行为。即使是对应同样的空间数据文件,但是MapFile 的配置不一样,依然可以产生出完全不同的地图。而用户的交互行为以及对 OGC协议的支持,也会在 MapFile 中进行定义。
图 1-2 MapFile 的层次结构
1.3.1 Map Object
Map 对象是 MapFile 的根对象,以此为延伸出其他对象作为 Map 对象的子孙节点。它的属性可以用于定义地图应用程序的大部分整体参数,例如地图边界,输出大小,使用的投影,背景色,分辨率,渲染质量等等。
1.3.2 Web Object
Web对象定义了一个WEB借口运行时的参数,通过指定对应参数决定和Web有关的URL的链接,以及可以灵活使用模板存储键值。
1.3.3 Layer Object
Layer 对象,是 MapFile 中最重要的对象,一个MapFile允许有50个。通过Layer 的属性决定了其绘制内容和对应的样式。一个 Layer包含了绘制一个地图图层相关要素的集合,最终通过特定的比例尺和渲染方式绘制出对应的地图投影。 Layer 关键的字对象包括 Class、Data、Feature、Label 等,用来灵活指定 Layer 绘制的内容和形式。
Layer 使用 Type对象表示空间数据的图形类型,对数据解释成点、线、面、标签、遮掩物等。例如,Point 以独立点来进行空间数据绘制,Line 用来绘制一系列和顺序相关的点,Polygon是首结点和尾结点相互重合的线构成的,它具有面积及填充等属性,Raster层用以表示图像空间与真实空间的参考影像,使矢量数据与真实世界关联,作为对比。Annotation用作要素标志,在特定的位置对特定的图形符号进行标注绘制。Query 是用作鼠标点击的空间数据集查询的,通过鼠标定位,坐标定位,正则表达式和要素索引等办法实现各种不同的查询。
1.3.4 Label Object
Label Object用于定义注释特征的文本标签,或者通过使用TrueType 作为symbols用。Label一般可以为图层添加文字说明标注。本文实现的地图建筑物或道路中文标注名称其实用的就是Label的属性——先给地图数据源文件里Table表中的字段赋值,用MapFile里的LABELITEM属性定位到该字段的值,用Label读取出来就行了。
1.3.5 Class Object
Class Object定义一个给定Layer的类别,每个图层至少有一个类别。任何的 Layer层都必须具有一个默认的主题类,该 Class 不对要素的条件进行选择限制,直接绘制其中的数据集的所有要素。在 Class 中,我们通过定义 Label、Style、Color 等对象,为空间数据的样式给予特定渲染。
1.3.6 Symbology Reference
Symbol 定义可以包含在MapFile中,更普遍的是在独立文件中,并通过在Map Object中使用SYMBOLSET 引用。
1.4 MapServer CGI模块
MapServer可以看作是两个独立模块的统称:MapServer CGI模块和MapScript模块。在服务器端可以使用任一模块,编写WebGIS程序。
利用MapServerCGI模块进行开发,只需编写WEB显示页面,向CGI程序传递特定的参数,从而得到相应的渲染好的地图数据。CGI是一组定义了Web服务器与在同一台机器上的其他软件相互通信的规则。Web服务器可利用CGI程序实现动态交互功能(Server-side)。通常CGI程序是运行在服务器端的小程序,被Web服务器调用,处理从Web服务器获得的数据(如对表单数据处理,查询数据库等),将处理结果返回给Web服务器:
图 1-3 MapServer CGI处理流程图
CGI程序可以使用任何语言编写,只要遵循CGI通信规则。编译语言:C、C++等;脚本语言:Perl、Python、Bourne shell、Java等。
MapServer CGI模块是用C语言编写的CGI程序,非常小。MapServer CGI模块的核心mapserv.exe不过36KB。当浏览器通过URL告知Web Server调用MapServer CGI模块时,Web Server就为CGI模块创建一个进程,CGI模块运行并加载URL指定的MapFile文件,读取MapFile文件中的TEMPLATE文件(HTML文件),并将TEMPLATE文件中CGI 变量的替换变量(template substitutions)替换成具体的值;处理TEMPLATE文件后,CGI模块将TEMPLATE文件处理结果(HTML文件)返回给Web Server,Web Server在将HTML文件输出到用户浏览器上。这时TEMPLATE文件(HTML文件)就作为用户的交互界面。
而另一种模块MapScript是一系列功能完善、可以对Mapfile进行各种操作的API,开发人员可以利用这些API编写自己的WEB服务器程序,从而取代MapServerCGI模块。目前MapServer提供给了Java、Python等地图API。
第2章 TileCache
2.1 TileCache简述
TileCache源自于FOSS4G 2006大会上的一个决议,即后来OGC的一个推荐标准WMS Tiling Client Recommendation。MetaCarta Labs后来开发了TileCache,用来缓存地图,配合OpenLayers使地图显示更快。它可以看作一个中间件,WMS服务器不用自己缓存地图,TileCache可以帮他完成。TileCache支持多种服务器和多种OGC服务标准,以及支持多种请求方式和格式。
所谓TileCache,就是因为普通的WMS服务器在接收客户端的请求后要读取数据、生成图片,效率过低,那么对于那些一成不变的地图服务,可以在WMS前端封装一个TMS(Tiled Map Service)。TileCache首先缓存一些WMS地图图片,提供一个伪WMS,仅在适当的时候和后台的WMS服务器交互。这个标准的实现是由OpenLayers的后台MetaCarta提供的,名字就叫做TileCache。TileCache以今年最流行的Python实现,可以通过cgi方式部署和运行在Apache和IIS以及Python的WSGI上。
2.2 TileCache缓存策略
TileCache是使用Python开发的一个开源工具,是居于GIS服务器之前,可以将任何WMS服务的据进行Cache处理,以产生瓦片式WebGIS效果。Web服务器接收客户端用户的请求后,首先根据相应缩放比例下的图片切片是否在TileCache缓存池中存在,若没有从WMS服务器获取地图切片并保存,返回地图切片。
Tilecache 是一个地图瓦片缓存器,只有当请求的地图不在tiles之列时,才与WMS等其他服务交互请求地图,这样一来大大提高了客户端访问地图的响应速度,减少资源的消耗。
图 2-1 TileCache系统流程图
2.3 TileCache切片结构
与ARCIMS的缓存相比较,TileCache中缓存的切片编码就有所不同,TileCache中图片文件夹共用六层,除了第一层,每层的编码是3位数的十进制来表示,它也是根据四叉树切分的,按逻辑网层来算幅数也是按2的指数增加的,根据行列号可以反算出相应的TileCache图片的位置,反之,也可以根据图片的位置反算出行列号,再根据行列号反算出相应的经纬度。其公式为:
X=Mathround((Xmin—MaxExtentXmin)/BlockSize x)
Y=Mathround((Ymin—MaxExtentYmin)/BlockSizeY)
Z=zoom
其中X,Y表示行列号,blockSizeX,blockSizeY分别为分块的大小。
图 3-2 TileCache切片的结构图
TileCache提供了一个基于PythonTile的WMS.C/TMS服务器,同时具有开可插入的缓存和后台渲染机制。在最简单的应用中,只要求TileCache可以访问磁盘可以运行Python的CGI脚本,同时可以连接需要缓存的WMS服务。TileCache需要配合OpenLayers的前端才能更好地处理地图切片,异步加载,所以TileCache的使用方法要结合在OpenLayers的使用中,这个在下文会详细说明。
第3章 OpenLayers
3.1 OpenLayers简述
OpenLayers 是由MetaCarta公司开发的,是一个应用于WebGIS客户端的 JavaScript包。OpenLayers实现访问地理空间数据的方法符合行业标准。OpenLayers 支持Open GIS 协会制定的WMS(Web Mapping Service)和WFS(Web Feature Service)等网络服务规范,可以通过远程服务的方式,将以OGC 服务形式发布的地图数据加载到基于浏览器的OpenLayers 客户端中进行显示。
OpenLayers采用面向对象方式开发,从2.2版本以后,OpenLayers已经将所用到的Prototype.js组件整合到了自身当中,并不断在Prototype.js的基础上完善面向对象的开发,Rico用到地方不多,只是在OpenLayers.Popup.AnchoredBubble类中圆角化DIV。OpenLayers2.4版本以后提供了矢量画图功能,方便动态地展现“点、线和面”这样的地理数据。
在操作方面,OpenLayers 除了可以在浏览器中帮助开发者实现地图浏览的基本效果,比如放大(Zoom In)、缩小(Zoom Out)、平移(Pan)等常用操作之外,还可以进行选取面、选取线、要素选择、图层叠加等不同的操作,甚至可以对已有的OpenLayers 操作和数据支持类型进行扩充,为其赋予更多的功能。例如,它可以为OpenLayers 添加网络处理服务WPS 的操作接口,从而利用已有的空间分析处理服务来对加载的地理空间数据进行计算。同时,在OpenLayers提供的类库当中,它还使用了类库Prototype.js 和Rico 中的部分组件,为地图浏览操作客户端增加Ajax 效果。
采用OpenLayers作为客户端不存在浏览器依赖性。由于OpenLayers采用JavaScript语言实现,而应用于Web浏览器中的DOM(文档对象模型)由JavaScript实现,同时,Web浏览器(比如IE,FF等)都支持DOM 。
OpenLayers APIs采用动态类型脚本语言JavaScript编写,实现了类似与Ajax功能的无刷新更新页面,能够带给用户丰富的桌面体验(它本身就有一个Ajax类,用于实现Ajax功能)。
目前,OpenLayers所能够支持的Format有:XML、GML、 GeoJSON、GeoRSS、JSON、KML、WFS、WKT(Well-Known Text)。在OPenlayers.Format名称空间下的各个类里,实现了具体读/写这些Format的解析器。
OpenLayers 支持的地图来源包括Google Maps、Yahoo、 Map、微软Virtual Earth 等,用户还可以用简单的图片地图作为背景图,与其他的图层在OpenLayers 中进行叠加,在这一方面OpenLayers提供了非常多的选择。本文通过OpenLayers调用MapServer的WMS服务实现对地图的显示、控制和操作。
3.2 OpenLayers的层次结构
图 3-1 OpenLayers文档层次结构图
(1) OpenLayers:它为整个项目实现提供名称空间(JavaScript语言没有名称空间一说,但是它确实有自己的机制实现类似的功能,后面会说明),它直接拥有一常量 VERSION_NUMBER,以标识版本。
(2)Ajax:用于实现Ajax功能,其中用到了Prototype.js框架里的一些东西。同时,设计的时候也考虑了跨浏览器的问题。
(3) BaseTypes:这里定制了OpenLayers中用到的string,number 和 function。
(4) Console:OpenLayers.Console,此名称空间用于调试和把错误等输出到“控制台”上,需要结合使用../Firebug/firebug.js。
(5) Control:OpenLayers的控件类,它提供各种各样的控件,比如上节中说的图层开关LayerSwitcher,编辑工具条EditingToolbar等等。
(6) Events:实现OpenLayers的事件机制。OpenLayers中的事件分为两种,一种是浏览器事件,例如mouseup、mousedown之类的;另外一种是自定义的,如addLayer之类的。
(7) Feature:Feature是geography 和attributes的集合。在OpenLayers中,特别地OpenLayers.Feature 类由一个marker 和一个lonlat组成。
(8) Format:此类用于读/写各种格式的数据,它的子类都分别创建了各个格式的解析器。这些格式有:XML、GML、GeoJSON、GeoRSS、JSON、KML、WFS、WKT等等。
(9) Geometry:对地理对象的描述。它的子类有Collection、Curve、LinearRing、LineString、MultiLineString、MultiPoint、MultiPolygon、Point、Polygon、Rectangle、Surface,正是这些类的实例,构成了我们看到的地图。
(10)Handler:用于处理序列事件,可被激活和取消。同时,它也有命名类似于浏览器事件的方法。当一个handler 被激活,处理事件的方法就会被注册到浏览器监听器listener ,以响应相应的事件;当一个handler被取消,这些方法在事件监听器中也会相应的被取消注册。Handler通过控件control被创建,而control通过icon表现。
(11)Icon:在计算机屏幕上以图标的形式呈现,有url、尺寸size和位置position的3个属性。一般情况,它与 OpenLayers.Marker结合应用,表现为一个Marker。
(12)Layer:图层。
(13)Map:动态地图的容器,可向里面添加图层Layer和控件Control。实际上,单个Map是毫无意义的,正是Layer和Control成就了它。
(14)Marker:它的实例是OpenLayers.LonLat 和OpenLayers.Icon的集合。
(15)Popup:地图上一个弹出窗口。
(16)Renderer:渲染类。在OpenLayers中,渲染功能是作为矢量图层的一个属性存在的,我们称之为渲染器,矢量图层就是通过这个渲染器提供的方法将矢量数据显示出来。
(17)Tile:设计这个类用于指明单个“瓦片”Tile,或者更小的分辨率。Tiles存储它们自身的信息,比如url和size等。
(18)Util:其他工具类。
第4章 MapServer开发
本文使用开源地图引擎MapServer作为发布地图信息的服务器,提供标准的WMS地图服务,通过加载已经制作完成的MapFile文件,实现在浏览器上实时绘制出地图。MapServer开发需要先进行系统环境搭建、测试和启动地图服务、MapFile地图配置文件的编写。
4.1 MapServer开发
4.1.1 MapServer环境搭建
1、 Windows下配置MapServer
(1) 官网(http://mapserver.org/)下载ms4w环境包(Windows下的已编译安装包)
(2) 解压ms4w(mapserver的库)到任意目录,此处解压到D:\ms4w
(3) 配置mapserver的环境变量(本文涉及到的MapServer环境解压均在系统D盘),按如下新建或设置系统变量:
Path:D:\ms4w\Apache\cgi-bin;%PATH%
PROJ_LIB:D:\ms4w\proj\nad
CLASSPATH:D:\ms4w\Apache\cgi-bin\mapscript\java\mapscript.jar;%CLASSPATH%
2、 Linux下配置MapServer
(1) 命令行下载FGS(MapServer在Linux下的安装环境)
$ wget http://dl.maptools.org/dl/fgs/releases/1.0/1.0.0/self-installers/
fgs-mapserver_5.0.2-fgs_1.0.0-linux-i386.bin
$ sh fgs-mapserver_5.0.2-fgs_1.0.0-linux-i386.bin
(2) 按ENTER开始安装,输入你想安装的路径
(3) 指定你想使用的端口号,一般设置端口号为80
(4) 完成安装,使用浏览器访问下面网址,按照自己安装时的参数修改
http://yourserver:port/cgi-bin/mapserv/
如果出现以下提示,则MapServer环境配置成功!
*you should see the following message displayed:
“No query information to decode. QUERY_STRING is set, but empty”.
(5) 命令行安装其他需要的模块(可选择)
$ fgs install module-name:version from-where
4.1.2 MapServer地图服务
1、 由于系统要用到MapServer的WMS服务,需检查当前MS4W是否支持OGC WMS服务。
(1) 用DOS命令(cmd命令)进入MS4W的安装路径(D:\ms4w\Apache\cgi-bin),执行mapserv –v。
图 4-1 检查MapServer是否支持OGC WMS服务
(2) 若出现下图类似字符信息,则表明当前环境支持OGC WMS服务。
图 4-2 支持OGC WMS服务时显示的信息
2、 安装或启动MapServer服务器。
(1) 进入ms4w根目录,双击“apache-install.bat”批处理文件,或用命令行执行“D:\ms4w>apache-install”启动。
(2) 示例中的“D:\ms4w\Apache\htdocs”为服务器根目录。默认服务器网络路径为“http://127.0.0.1”。若http://127.0.0.1被占用,则找到D:\ms4w\Apache\conf目录下的httpd.conf,按下图修改并重新启动Apache。
图 4-3 修改httpd.conf文件
3、 打开浏览器输入如下网址,测试MapServer服务器是否解析地图成功。
图 4-4 地图服务测试地址
URL中部分参数说明:
(1) LAYERS=road_region #——mapfile文件中的一个图层(显示在浏览器中)
(2) MAP=D:/map/htdocs/test.map #——需加载的mapfile文件路径,自定义
(3) FORMAT=gif #——MapServer输出图片类型,PNG、GIF等
(4) SERVICE=WMS #——需要用的一种地图服务Web地图服务(Web map service)
(5) VERSION=1.1.1 #——调用mapserver自带的WMS的版本号,此处无需设置
(6) BBOX=-76.562804,19.642376,521.800149,309.243476 #——BBOX与mapfile文件中设置的EXTENT范围需一致,否则浏览器中会显示空白,而不是地图图层
(7) WIDTH和HEIGHT #——输出地图图片宽和高
4、 下图为MapServer载入简单MapFile文件绘制地图效果。(使用的MapFile文件需要自己编写)。测试错误时请检查mapfile配置文件是否编写错误或者Apache是否开启。
图 4-5 MapServer加载简单MapFile文件显示的地图
4.1.3 MapFile文件编写
MapServer使用自己定义的独特的Mapfile对地图进行配置,所有地图上的元素都以通过Mapfile来配置。本章的重点就是介绍MapFile文件,以及使用CGI模块开发WebGIS程序的方法。
4.1.3.1 Map地图文件的目录结构
1、 下面所示的目录结构为一般性结构,可以自由调整,但在MapFile文件中的路径必须正确,否则会造成文件找不到的错误。
<Map>——根目录
|-data——地图数据目录
| |-.dbf
| |-.shp
| |-.shx
| |-.prj
|-etc——符号使用的图片集合、地图字体、符号配置文件存放目录
| |-image
| |-fonts.txt
| |-symbols.sym
| |-.ttf
|-htdocs——mapfile文件存放目录
| |-TrainStation.map
2、 相关文件配置格式解析:
(1) font.txt字体文件配置格式:
字体名称 + 字体文件的相对或绝对路径
如“sans SIMSUN.TTC”
(2) symbols.sym符号文件配置格式
SYMBOLSET #——新版本的MapServer必须以此关键字为开头
Symbol #——新定义一个符号
Name ‘tent’ #——符号别名,在Class中使用
Type VECTOR #——符号渲染类型:
Vector:一个简单的用户定义符号
Ellipse:XY方向的半径值。
Pixmap:(Bitmap Symbols),支持GIF和PNG图片
TrueType:可以在FONTSET中定义
取值:[vector|ellipse|hatch|cartoline|pixmap|true]
Filled TRUE #——设置填充色,取值[True|False],Class中自定义颜色
Points #——定义矢量符号的起始点或椭圆的XY方向,以END
0 1 结束定义。坐标的单位为像素,使用之前请先定义
.5 0 其默认值。你可以在适当位置插入一些非负的坐标
1 1 创建一个非临近的路径。对椭圆形符号你应该提供
.75 1 XY方向的半径,如果X与Y相等那就是一个圆。
.5 .5 取值:[x y] [x y] … END
.25 1
0 1
END
END
4.1.3.2 MapFile文件编写
地图模块使用广州火车站交通枢纽地图,MapFile文件如下,后面是相关参数的注释。
MAP #——MapFile开始标记
NAME “TrainStation” #——地图别名
STATUS ON #——设置地图状态是否被激活
SIZE 800 600 #——输出图像大小
PROJECTION #——设置图像的投影
“init=epsg:4326”
END
EXTENT -1418.920 -1420.011 1937.376 1088.331 #——地图边界
UNITS DD #——地图坐标的单位。取值:[feet|inches|kilometers|meters|miles|dd]
IMAGECOLOR 255 255 255 #——设置地图背景颜色。RGB分别为红、绿、蓝
IMAGETYPE png #——输出图像的类型,png,gif等
SHAPEPATH “../data/” #——指定地图文件.shp的路径
FONTSET “../etc/fonts.txt” #——指定使用字体文件的文件列表
WEB #——定义如何处理web接口
MINSCALE 1 #——绘制该图层的最小比例
MAXSCALE 13 #——绘制该图层的最大比例
IMAGEPATH ‘/ms4w/tmp/ms_tmp’ #——存储临时文件和图像的路径。根据操作系统不同以”\””/”结尾
IMAGEURL ‘/ms_tmp/’ #——配置IMAGEPATH的URL访问路径。该URL 将引导浏览器从IMAGEPATH中获取输出图像
METADATA #——可以加入任何说明。用于定义OGC WMS的要素
“wms_title” “TrainStation”
“wms_srs” “EPSG:4326”
“wms_enable_request” “GetMap GetFeatureInfo” #——设置WMS请求类型
END
END
LAYER #——Layer Object图层对象与使用的每个图层相对应
NAME chengyu_region #——Layer别名
TYPE POLYGON #——指明数据怎样绘制。无须与shapefile 文件类型一致,取值为[point|line|polygon|circle|annotation|raster|query]
STATUS ON #——设置该图层的状态
DATA “城域_region.shp” #——设置该图层使用的地图源文件相对data路径
LABELITEM “城域” #——使用LABEL对应来定义一个标签,标签用来对图层的某个特征进行说明,需与地图文件创建时设置的字段名一样
CLASS
NAME “chengyu_region” #——设置Class别名
LABEL #——设置该图层的标签属性,读取字段值
COLOR 255 255 255 #——设置字体的颜色
OUTLINECOLOR 255 255 255 #——文本边界的颜色
FONT “sans” #——此处sans对应宋体SIMSUN.TTC
TYPE truetype #——使用的字体类型,bitmap比truetype效率高,但truetype类型的字体更新比较方便。取值:[bitmap|truetype]
SIZE 12 #——设置字体的大小
ANTIALIAS FALSE #——是否使用抗锯齿(平滑)。
取值:[true | false]
POSITION CC #——POSITION:Label的位置。首字母是“Y”位置,第二个为“X”位置。取值:[ul|uc|ur|cl|cc|cr|ll|lc|lr|auto],对于垂直的话是C=中间 U=上面 L=下面,对于水品的话是C=中间 L=左面 R=右面
PARTIALS FALSE #——是否显示不完整的LABEL,默认为不显示部分坐标。
ANTIALIAS TRUE #——字体是否平滑
MINDISTANCE 300 #——复制一个label 产生的label 与被复制的label 之间的最小距离。单位pixels。
BUFFER 400 #——在LABEL周围填充相应的颜色,可以提高文本的可读性,默认为0
ENCODING GBK #——此处为文字编码,如果不设置该值,中文将不能正确显示。对于中文Windows系统,操作系统的默认编码为GBK。
END
STYLE #——该图层填充颜色
COLOR 102 102 255
END
END
END
END #——Map File END
4.2 TileCache开发
TileCache负责对地图进行切片处理,缓存瓦片数据,避免MapServer重复读取数据和生成图片造成的效率过低。客户端请求时先在tile队列里查找对应地图数据,若没有才由MapServer生成。
4.2.1 TileCache的配置
1、安装Apache服务器,MapServer已经自带Apache服务器。忽略。
2、 安装Python环境。
下载版本python-2.5.4.msi或以下版本并安装(Windows环境下),本文的示例安装在C盘根目录(例如C:\Python25)。若安装到其他盘,则需要修改下面第6步和第8步python相关变量的路径。
3、 安装TileCache。
到官网(http://tilecache.org/)下载TileCache压缩包,示例解压到D:\ms4w\Apache\htdocs。
4、 安装mod_python,此模块的作用是让Apache支持python。
在http://archive.apache.org/dist/httpd/modpython/win/3.3.1/ 下载对应的版本,由于MapServer自带的Apache版本为2.2,Python版本为2.5,所以应选择如下版本的模块:mod_python-3.3.1.win32-py2.5-Apache2.2.exe。TileCache需要python环境支持,安装完后,在Apache\modules目录下会生成mod_python.so文件(注意安装快结束时会提示选择mod_python.so的生成路径,即Apache的目录)。
5、 打开Apache下的conf\httpd.conf文件的如下位置添加下图红线标注的代码。
图 4-6 为httpd.conf添加mod_python.so模块
图 4-7 为httpd.conf添加调用TileCache模块
上述修改中的部分参数解释:
(1) D:/ms4w/Apache/htdocs/tilecache-2.11 #——tilecache的安装目录
(2) D:/ms4w/Apache/htdocs/tilecache-2.11/tilecache.cfg #——tilecache的配置文件
6、 将TileCache目录下的tilecache.cgi文件名改为tilecache.py,打开文件并修改第一行。下图中C:/Python25/python.exe为本地实际安装目录。
图 4-8 修改python.exe路径
7、 修改 TileCache目录下的tilecache.cfg文件。
(1) 找到[cache](未被#号注释掉的那个), 做如下修改。 Base的值为瓦片数据缓存的文件夹目录路径,可以自定义文件夹路径。
图 4-9 修改切片缓存的路径
(2) 在文件的最后增加实际需要加载的mapfile图层信息,图层名要和mapfile里面定义的图层的名字一一对应,此处加载图层background和chengyu_region。
图 4-10 配置TileCache使用图层的信息
8、 修改python的环境变量。
(1) 修改注册表中PythonPath的路径。
依次点击系统”开始”,”运行”,输入”Regedit”,打开注册表编辑器,在注册表的[HKEY_LOCAL_MACHINE\SOFTWARE\Python\PythonCore\2.5 \PythonPath]位置下的修改第一项的键值,在后面加入TileCache的位置路径:”D:\ms4w\Apache\htdocs\tilecache-2.11″,用分号与前面参数隔开。为了保险起见,新建一个字符串值,并将数值数据也写为:D:\ms4w\Apache\htdocs\tilecache-2.11
图 4-11 配置PythonPath注册表信息
(2) 修改PythonPath环境变量路径。
点击”我的电脑”–“属性”–“高级”,在”环境变量”中找到或添加变量PythonPath,这里的路径值设为:D:\ms4w\Apache\htdocs\tilecache-2.11;C:\Python25(一个是tilecache的目录,一个是python的安装目录,前后同样用分号隔开)。
(3) 测试切片服务是否成功应用。
若地图显示成功并且在D:/ms4w/Apache/htdocs/tilecache(本文示例cache的路径)目录下生成瓦片数据图片,则表示成功。TileCache服务需要结合OpenLayers进行,此处后文再讲。大致出现的瓦片效果如下:
图 4-12 TileCache生成切片数据的文件夹
图 4-13 TileCache生成的切片
4.3 OpenLayers开发
OpenLayers负责结合MapServer的WMS服务和TileCache服务,使用JS控制地图,实现常见的地图操作,如地图浏览、拖动、放大缩小、鹰眼、选择性加载图层,添加标注,点击弹窗等功能。并通过Ajax技术进行异步交互,与后台的数据连接,实现实时性的地图模型。
4.3.1 OpenLayers引入
OpenLayers是一个JavaScript包,包含了地图操作的各类API,所以在MapServer中使用它只需要在HTML页面上引入JS文件即可。具体代码是:
<script src =”OpenLayers.js” type =”text/javascript”></script>
4.3.2 OpenLayers开发方式
4.3.2.1 定义地图容器对象Map
// 将渲染后的地图填充到ID为“map”的div中
var map = new OpenLayers.Map({
div: “map”, // 定义HTML中地图放置的div容器
// 下面很重要,如果不设置,每个图片都按照默认BBOX:-180,-90,90-270这样的经纬度去找,对于用meters来做的mapfile是找不到图的,显示为白屏
// 定义边界范围
maxExtent: new OpenLayers.Bounds(-1418.920,-1420.011,1937.376,1088.331),
maxResolution: 100, // 定义最大分辨率
units: “dd”, // 定义坐标单位,与mapfile必须一致
projection: “EPSG:4326” // 定义坐标投影
});
4.3.2.2 定义图层对象Layer
利用OpenLayers.Layer.WMS类加载mapserver的WMS地图服务,创建图层对象。
var layer1 = new OpenLayers.Layer.WMS(
“background”,
” http://127.0.0.1/tilecache-2.11/tilecache.py”,
{layers: “background”, transparent: “true”,imagetype: “PNG”},
{isBaseLayer: true, visibility: true, buffer: 0}
);
(1) background:对应MapFile文件中欲加载的图层名称。
(2) http://127.0.0.1/tilecache-2.11/tilecache.py:地图解析服务器URL,加入了TileCache。
(3) {layers: “background”, transparent: “true”,imagetype: “PNG”}:加载图层名称,设置背景为透明,输出图片类型为PNG。
(4) {isBaseLayer: true, visibility: true, buffer: 0} 是否是基层图,是否可见,设置缓存。
(5) map.addLayers([layer1,layer2,layer3,layer4,layer5,layer6,layer7,layer8,layer9,layer10]); 添加图层序列,顺序为从基本图层(底图)到最上层图层。
4.3.2.3 定义标注层Markers、弹窗对象Popup
(1) 在地图上添加标注物函数
// 定义一个标注层对象
mapserver.markers = new OpenLayers.Layer.Markers(“Markers”);
// 定义弹窗对象
mapserver.pop = new OpenLayers.Popup();
// 自定义添加标注物的函数,从左到右参数依此是地图容器对象、经纬度对象(OpenLayers.LonLat)、弹窗尺寸(OpenLayers.Size)、标注物图标尺寸(icon_size)、标注物图标路径(icon_url)、自定义站台LED传递参数stationId(车站ID)和platformId(站台ID)、请求读取后台数据的路径(post_url)
mapserver.autoAddMarker =
function (map,LonLat,popup_size,icon_size,icon_url,stationId,platformId,post_url){
// 标注物图标信息
var offset = new OpenLayers.Pixel(-icon_size.w+12, -icon_size.h+18);
var icon = new OpenLayers.Icon(icon_url, icon_size, offset);
// 定义标注物
var marker = new OpenLayers.Marker(LonLat,icon);
// 定义标注物弹窗
var popup = new OpenLayers.Popup(marker,LonLat,popup_size,””,true);
popup.setBackgroundColor(“#F0F0F0”);
popup.setOpacity(0.8);
popup.setBorder(“2px solid #C2C2C2”);
// 添加标注物鼠标移动事件,移上标注物则打开弹窗,移开则关闭弹窗
marker.events.register(‘click’,this,function(){
var url = post_url; // 服务器URL
var params = { // 传递参数
stationId:stationId,
platformId:platformId
};
// 发送Ajax请求,进行LED面板的公车数据更新,使用JQuery库
$.ajax({
type: “post”,
data: params,
url: url,
beforeSend: function(XMLHttpRequest){
popup.setContentHTML(“Loading……”);
map.addPopup(popup,true);
mapserver.pop = popup;
popup.show(); },
// 请求成功时执行
success: function(data, textStatus){
// 将服务器返回的数据填充到弹窗中
popup.setContentHTML(data);
},
// 请求失败时执行
error: function(){
popup.setContentHTML(“访问数据失败!”);
}
});
});
mapserver.markers.addMarker(marker);
}
(2) 调用加入标注物的函数
// 加入第一个标注
mapserver.autoAddMarker(map,
new OpenLayers.LonLat(0.7207592,0.6733901),
new OpenLayers.Size(200,120),
new OpenLayers.Size(30,30),
“openlayers/img/LED.png”,
11,
1,
url1);
4.3.2.4 添加地图常用操作
// 设置地图中心经纬度和初始放大倍数
map.setCenter(new OpenLayers.LonLat(0.52784228515611, 0.12131738281255), 15);
// 加入地图控件,注:地图相关控件可在OpenLayers的开发文档中查找
map.addControl(new OpenLayers.Control.LayerSwitcher()); // 图层控件
map.addControl(new OpenLayers.Control.OverviewMap()); // 鹰眼控件
// 地图中心显示
if (!map.getCenter()) {
map.zoomToMaxExtent();
}
4.4 地图模块展示
最终实现的效果图(基础地图是我自己绘制的,可以实现比如地图以切片形式载入和缓存在服务器、放大缩小、选择图层加载、鹰眼、标志物、弹窗信息视频展示等等基础操作功能,源码的话可以部分公开,如果你需要的话):
哈哈,看到这里的人辛苦了,推荐点相关的软件做福利吧:
1、地图绘制可以用MapInfo软件,上手快,做出来的地图文件能直接就用到MapServer,文件另存为.shp(会产生另外的.dbf和.shx)
2、MapFile的一些学习资料:Mapfile配置说明
3、我自己做的一个小的map地图,供参考 map地图示例