利用OpenScales+MapServer+PostGIS快速构建GIS应用
目录
引言
随着越来越多智慧城市项目的落地实施,基于 GIS 的应用程序展现出越来越广泛的应用场景,例如大多数行业都需要对真实世界中的现有资源进行可视化的实时监控、分析、操作从而提高效率,使得利益最大化;再比如基于位置的服务也越来越在公众中普及,如此等等。正因为有着如此广泛的应用场景,如何经济、快速的搭建一个开发环境,并依托此环境构建各式各样的 GIS 应用就成了一个值得关注的话题。
本文中,作者总结了在实际项目中如何快速利用开源软件构建 GIS 开发环境的实践方法和技巧,以及在搭建和使用 GIS 开发环境中所遇到的问题的解决办法,并通过一个示例将这些经验分享给需要开发 GIS 应用程序的开发人员。
通过本文,读者可以了解到 GIS 应用程序的体系结构,并能根据自身项目的特点确定所需的开源 GIS 软件,且能够快速搭建一套 GIS 开发环境来构建 GIS 应用程序。
GIS 体系结构
一个基本的 GIS 体系结构可以按层次在逻辑上进行抽象,如下图所示,主要包括以下四个部分:
- 客户端 – 这里所说的客户端是多样化的,可以是 Web 客户端,移动设备或者是通过 HTTP 连接到 Internet 服务或连接到 GIS Server 的桌面应用程序。
- Web 服务器 – Web 服务器包含 Web 应用的部署,以及 Web 服务,它们均使用 GIS Server 上的服务资源。
- GIS 服务器 – GIS 服务器主要是提供了地理信息可视化、空间数据管理及分析等一系列服务
- GIS 渲染引擎– GIS 渲染引擎能够将地图相关数据可视化,并且提供给用户可交互的平台。
- 空间数据存储库 – 空间数据存储库可以是不同的数据形式,包括空间数据库、矢量数据文件和光栅数据文件。
图 1. GIS 体系结构图
上图所列举的体系结构是一个标准的三层结构,包括了用户交互层、中间层(包括 Web 服务器和 GIS 服务器)以及数据层。
开源软件的比较和选择
在软件世界里,开源无所不在。开源 GIS 软件目前已经形成了一个比较齐全的产品线,打开 FreeGIS[2] 的网站,我们可以找到各具特色的 GIS 软件,从中可以找到很好的商用 GIS 软件的替代品。
针对不同的层次,通过比较常用开源 GIS 软件的用途和优势,并且结合自身的需求,选择如下的 GIS 开源软件。
渲染引擎 OpenScales
提到 GIS 的渲染引擎,很多开发人员首先想到的可能是 OpenLayer 这款著名的使用 JavaScript 的开源 GIS 前端,但是,从技术上来说,基于 Flex 的前台地图框架也有着很大的应用空间,所以我们选择的是一款基于 ActionScript3 和 Flex 的开源 GIS 前端产品 OpenScales。它是一个优秀的前台地图框架,提供了相对完善的功能,主要包括:
- 能够支持各种标准的地图服务,比如 WMS、WFS 等;
- 能够快速描绘矢量数据,支持的矢量数据格式有:点、线、面、多点、多线等,这一功能可以用来支持地图编辑功能,后面章节会介绍我们是如何实现地图的编辑功能;
- 提供一系列内置的地图控件,常用的有地图缩放、拖拽、比例标尺等;
- 支持多平台,由于 OpenScales 是基于 FlashPlayer 的,因此 OpenScales 可以运行在各个浏览器,桌面程序乃至移动设备上。
GIS 服务器 MapServer
MapServer 是利用 C 语言开发的开源 WebGIS 项目,它是一套基于胖服务器端 / 瘦客户端模式的实时地图发布系统,客户端发送数据请求时,服务器端实时的处理空间数据,并将生成的数据发送给客户端。MapServer 有如下几个关键的特性 [4]:
- 支持多种矢量、栅格数据和 PostGIS 空间数据库,并借助 ArcSDE 支持商业空间数据库;
- 支持 Windows、Linux 等操作系统;
- 提供两种工作方式,CGI 方式(适用于 CGI、Ajax、Flex 开发人员)和 MapScript 方式(适用于 Php、Java、C# 开发人员),以原生 CGI 方式效率最高;
- MapFile 是 MapServer 的核心,它将各种地图要素组织成具有层次关系的对象系统;并定义数据来源,使用的数据格式,用户交互以及对 OGC 协议的支持。
空间数据库 PostGIS
PostGIS 在对象关系型数据库 PostgreSQL 上增加了存储管理空间数据的能力,是最著名的开源 GIS 数据库。
搭建开发环境
MapServer 的安装和使用
从 MapServer 产品页面下载最新版本。尽管官方文档对 Unix 和 Window 平台下的源代码安装步骤给出了详细的说明,但是笔者通过实践可以发现,在 Win32 平台下,从源代码编译安装 MapServer 是一个复杂的任务,所以推荐使用 MapServer 给出的已编译安装包 MS4W,从而能快速搭建开发环境。
将下载的 MS4W 解压到硬盘指定的目录,然后在命令提示符窗口切换到 MS4W 所在的目录,运行 apache-install,如果结果如下图所示则表示安装成功,或者使用浏览器访问 http://127.0.0.1/cgi-bin/mapserv.exe,验证 MapServer 返回的提示信息。
图 2 MS4W 安装成功
使用 MapServer 发布地图数据,关键就是要编写一个后缀名为 map 的 Mapfile 配置文件。在官方文档中,介绍了手工编写该配置文件的方法,关于手工编写的格式和注意事项会在后面的实例中有所介绍;同样读者还可以通过其他图形化配置界面工具或者是开源桌面软件来生成 Mapfile 文件。
PostGIS 的安装和使用
安装 PostGIS 空间数据库的前提条件是有关系型的 PostgreSQL 数据库,而且值得注意的是 PostgreSQL8.3 以上的版本才支持 PostGIS 空间数据库。
这样,首先从 PostgreSQL 产品页面下载最新 Windows 版本的安装文件,接下来按照安装进度依次选择安装目录、数据目录、密码和端口,等待 PostgreSQL 安装完成之后,会出现如下界面:
图 3 PostgreSQL 安装完成
点击完成按钮之后选择所需要的 PostGIS 版本以及下载地址后进行安装:
图 4 安装 PostGIS
PostGIS 空间数据库安装完成后,可以做如下的验证:
- 利用 PostGIS 提供的 Shape 文件和 DBF 文件图形化加载工具,将一个 Shape 文件导入到空间数据库中。打开”PostGIS 1.5 for PostgreSQL 9.0 -> PostGIS Shapefile and DBF Loader”,如下图所示导入 PostGIS 中
图 5 导入 Shape 文件
- 在 SQL 命令行(psql)或者图形化管理工具中验证上述文件是否导入到 PostGIS 中,打开”PostgreSQL 9.0 -> SQL Shell(psql)”,做如下验证:
图 6 验证 PostGIS 数据库和导入 Shape 文件
如果能得到如上述的结果,说明 PostGIS 安装成功,并且顺利导入 Shape 格式的矢量数据。
构建 GIS 应用程序
利用上述搭建的开发环境,接下来将展示如何使用 OpenScales,并且在 MapServer 和 PostGIS 的帮助下快速构建一个 GIS 应用程序。在这个应用程序中,将展示如下几个关键内容点,包括:
- 编写 Mapfile 文件,利用 MapServer 搭建的开源 GIS 引擎
- 支持三种数据源,分别是 PostGIS 空间数据库、Shape 和 KML 格式的矢量数据和图片格式的光栅数据;
- 使用 OpenScales 来完成前端展示以及用户交互响应。
准备三种数据源
为了能演示支持三种不同形式的数据,需要准备三个数据源,分别是:
- 数据库数据 – 已导入到 PostGIS 数据库中的数据
- 矢量数据 – Shape 格式或者 KML 格式的文件
- 光栅数据 – GIF、PNG 或者 JPEG 格式的文件
编写 Mapfile 文件
准备好数据之后,接下来要利用 MapServer 搭建的 GIS 引擎来获得上述的数据,完成这一步最最为关键的就是编写 Mapfile 文件了。在这里,为了方便介绍细节,我们采用手工编写 Mapfile 文件的方式。以下是一个示例的 Mapfile 文件。
MAP Object 是 Mapfile 的根对象,它包含了一系列的属性,结合下面的示例文件,介绍 MAP Object 的结构和部分常用属性。
清单 1. Mapfile 文件示例 – MAP Object
1 MAP 2 NAME "china" 3 SIZE 400 300 4 IMAGECOLOR 255 255 255 5 IMAGETYPE JPEG 6 SHAPEPATH "data" 7 EXTENT 73.447 3.408 135.086 53.558 8 9 PROJECTION 10 "init=epsg:4326" 11 END 12 13 WEB 14 TEMPLATE "/ms4w/apps/testshapefile/index.html" 15 IMAGEPATH "/ms4w/tmp/ms_tmp/" 16 IMAGEURL "/ms_tmp/" 17 END 18 19 LAYER 20 ……
代码 1 中出现的一般参数及含义如下:
- EXTENT 是从空间上指定要创建的地图文件的大小;
- SIZE 是从图片像素上指定输出 Map 的宽和高;
- IMAGECOLOR 指定默认的图片背景颜色;
- IMAGETYPE 指定当前的输出格式;
- SHAPEPATH 指定 shape 文件或瓦片所在的文件目录,绝对路径和相对于当前 Mapfile 文件的路径均可。
同时,MAP Object 允许一些嵌套的对象:PROJECTION, QUERYMAP, REFERENCE, SCALEBAR, SYMBOL, WEB. LAYER, LEGEND。接下来将介绍在示例文件中用到的三个嵌套对象,其他对象的详细用法可以参考 MapServer 的官方文档:
- PROJECTION Object 设置投影,有两种投影对象可以定义,一种是在 Map Object 中用于说明输出图像投影,另一种是在各个图层中定义;
- WEB Object 定义如何处理 Web 接口,比如 TEMPLATE 指明用于展示查询结果并和用户交互的文件或 URL 地址,IMAGEPATH 存储临时文件和图像的路径,IMAGEURL 配置 IMAGEPATH 的 URL 访问路径;
- LAYER Object 定义所使用的全部图层信息,一个 Mapfile 允许多个图层,且可以通过修改源码的方式改变。在 Mapfile 文件中首先定义的 LAYER 处在地图底层,最后定义的地图顶层。
下面是一段 LAYER Object 的示例代码,分别介绍了如何展示从空间数据库,Shape 文件(矢量数据)和 GIF 文件(光栅数据)导入的地理数据。
清单 2. Mapfile 文件示例 – LAYER Object
1 LAYER 2 NAME "chinalayer" 3 STATUS ON 4 TYPE line 5 CONNECTIONTYPE postgis 6 CONNECTION "host=** port=* dbname=postgis user=postgres password=passw0rd" 7 DATA "the_geom from bou2_4l" 8 9 CLASS 10 STYLE 11 COLOR 255 0 0 12 END 13 14 LABEL 15 COLOR 255 0 0 16 SIZE SMALL 17 END 18 END 19 END 20 21 LAYER 22 NAME "chinalayer2" 23 STATUS default 24 TYPE line 25 DATA "BOUNT_line" 26 27 CLASS 28 STYLE 29 COLOR 0 0 0 30 END 31 32 LABEL 33 COLOR 0 0 0 34 SIZE SMALL 35 END 36 END 37 END 38 39 LAYER 40 NAME "chinalayer3" 41 DATA "test_gif.gif" 42 STATUS ON 43 TYPE RASTER 44 #PROCESSING "SCALE=-10,10" 45 PROCESSING "SCALE_BUCKETS=2" 46 47 CLASS 48 STYLE 49 COLOR 0 0 0 50 END 51 52 LABEL 53 COLOR 0 0 0 54 SIZE TINY 55 END 56 END 57 END
从代码 2 中可以发现,从第 1 行到第 19 行配置的是从空间数据库中获取数据,从第 21 行到第 37 行配置的是从 Shape 文件获取数据,从第 39 行到 57 行是从 GIF 文件获取数据,其中部分属性介绍如下:
- NAME 用来指定图层的名称,它允许有 20 个字符并且作为标识来连接 mapfile 文件和 web interfaces,一般情况下它是唯一的;
- STATUS 用来设置图层的当前状态。缺省是 ON;
- TYPE 用来指明如何绘制数据,指定的类型并不要求与 shape 文件类型一致;
- CONNECTIONTYPE 指定连接的类型,缺省是本地;
- CONNECTION 配置远程数据连接,可以是 SDE,PostGIS,Oracle;
- DATA 指定使用的空间数据文件,不要求一定要 shape 文件格式,例如 PostGIS 图层的参数格式:”<columnname> from <tablename>”,其中”columnname” 是含有 geometry objects 的列;
- PROCESSING 表示向图层发送的处理指令,不同的图层类型支持不同的指令,例如光栅数据支持 SCALE,BANDS 指令。
这里值得注意的是,如果读者选择了 KML 格式的矢量数据,需要通过 orginfo 命令行查看该文件的 Layer 名字,如下图中的 hz2 就是该 KML 文件的 Layer 名字。
图 7. 查看 KML 文件的 Layer Name
从 KML 文件加载数据的 Mapfile 配置文件片段如下:
清单 3. Mapfile 文件示例 – 从 KML 文件加载数据
1 LAYER 2 NAME "chinalayer2" 3 STATUS DEFAULT 4 TYPE POINT 5 CONNECTIONTYPE OGR 6 CONNECTION "kml/fountains-hotel.kml" 7 DATA "fountains-hotel" 8 9 CLASS 10 ……
构建应用程序
准备好 GIS 服务器和所需的空间数据后,下面将展示如何构建基于 GIS 的 Flex 示例程序,该示例程序将用于展示不同数据源的空间数据,并提供基本的用户交互能力。接下来将逐步介绍构建 Flex 示例程序的过程。
首先,在 Flex Builder 中创建 Flex 工程,导入开源 GIS 渲染引擎 OpenScales 包,项目结构如下图所示:
图 8. 示例程序项目结构
其中,需要导入引用 4 个 swc 文件;在 src 目录下,最重要的是 osclient.mxml 文件,接下来会重点讲解,另外 ImageMarker.as 文件定义了在地图上显示用的图标类型,icons 文件加下放的是各式不同的图片
在 osclient.mxml 文件中主要完成了两件事情:第一,展示从不同数据源来的空间数据;第二,定义页面布局及一系列交互功能。
清单 4. 展示从不同数据源来的空间数据
<os:Map id="fxmap" width="100%" height="100%" zoom="3" centerLonLat="105.02831248205241,35.17319551790936" cornerRadius="7"> <os:WMS id="file_data" url="http://localhost/cgi-bin/mapserv.exe?map=/ms4w/apps/testshapefile/first.map" layers="chinalayer2" isBaseLayer="true" transparent="true" projection="EPSG:4326"/> <os:WMS id="shape_file" url="http://localhost/cgi-bin/mapserv.exe?map=/ms4w/apps/testshapefile/first.map" layers="chinalayer" isBaseLayer="true" transparent="true" projection="EPSG:4326" /> <os:MousePosition x="10" y="{height-20}" displayProjection="EPSG:900913"/> <os:Spinner id="spinner" x="{this.width / 2}" y="{this.height / 2}"/> <os:LayerSwitcher/> <os:DragHandler/> <os:ClickHandler/> <os:WheelHandler/> <os:SelectFeaturesHandler active="true" enableClickSelection="false" enableBoxSelection="false" enableOverSelection="true" /> </os:Map>
上述这段代码所描述的就是如何获取空间数据,这里有两点需要强调一下:第一,每一个 <os:WMS> 元素中所定义的 layers 的值必需和前面所配置的 Mapfile 文件中的 LAYER Object 的 NAME 匹配;第二,OpenScales 默认的投影 EPSG 值是 900913,需要转换成 EPSG:4326 的投影值才能得到我们所常用的经纬度数值(经度从 -180 到 180,纬度从 -90 到 90)。
同样,我们可以做如下配置,从而能够使用 OpenStreetMap 数据:
<os:Mapnik name="mapnik" isBaseLayer="true"proxy="http://openscales.org/proxy.php?url="/>
清单 5. 定义页面布局及一些交互功能
<os:ControlPanel x="10" y="10" width="140" title="Navigation"> <os:PanComponent map="{_map}"/> <mx:HBox width="100%" paddingLeft="5" paddingRight="5"> <os:ZoomComponent map="{_map}"/> <mx:Spacer width="100%"/> <os:ZoomBoxComponent map="{_map}" width="32" height="32"/> </mx:HBox> </os:ControlPanel> <os:ControlPanel title="Drawing Tools" x="150" y="10"> <os:FeatureDrawingComponent map="{_map}" /> </os:ControlPanel>
上述这段代码定义了两个组件,一个用于显示包含缩放比例尺的导航,另外一个用于显示包含一些 OpenScales 自定义的画图工具,在接下来的 GIS 应用展示中会看到这两个组件。
构建应用程序所需要的完整代码可以在下载资源中找到。
结束语
至此,通过介绍 GIS 体系结构以及相应的常用开源软件,并且通过实例应用程序具体介绍了如何搭建和使用 GIS 开发环境并构建应用程序,相信读者能够充分认识到这一套开源开发环境具有很强的易用性、相对完善的功能性、支持个性化应用场景的可扩展性,并且能够按照本文中介绍的步骤和方法,快速构建基于 GIS 的应用程序。
转载请注明出处。GIS帝国网站报道中出现的商标及图像版权属于其合法持有人,只供传递信息之用,非商务用途。