利用 OpenScales+MapServer+PostGIS 快速构建 GIS 应用

引言

随着越来越多智慧城市项目的落地实施,基于 GIS 的应用程序展现出越来越广泛的应用场景,例如大多数行业都需要对真实世界中的现有资源进行可视化的实时监控、分析、操作从而提高效率,使得利益最大化;再比如基于位置的服务也越来越在公众中普及,如此等等。正因为有着如此广泛的应用场景,如何经济、快速的搭建一个开发环境,并依托此环境构建各式各样的 GIS 应用就成了一个值得关注的话题。

本文中,作者总结了在实际项目中如何快速利用开源软件构建 GIS 开发环境的实践方法和技巧,以及在搭建和使用 GIS 开发环境中所遇到的问题的解决办法,并通过一个示例将这些经验分享给需要开发 GIS 应用程序的开发人员。

通过本文,读者可以了解到 GIS 应用程序的体系结构,并能根据自身项目的特点确定所需的开源 GIS 软件,且能够快速搭建一套 GIS 开发环境来构建 GIS 应用程序。

回页首

GIS 体系结构

一个基本的 GIS 体系结构可以按层次在逻辑上进行抽象,如下图所示,主要包括以下四个部分:

图 1. GIS 体系结构图

图 1. GIS 体系结构图

上图所列举的体系结构是一个标准的三层结构,包括了用户交互层、中间层(包括 Web 服务器和 GIS 服务器)以及数据层。

回页首

开源软件的比较和选择

在软件世界里,开源无所不在。开源 GIS 软件目前已经形成了一个比较齐全的产品线,打开 FreeGIS[2] 的网站,我们可以找到各具特色的 GIS 软件,从中可以找到很好的商用 GIS 软件的替代品。

针对不同的层次,通过比较常用开源 GIS 软件的用途和优势,并且结合自身的需求,选择如下的 GIS 开源软件。

渲染引擎 OpenScales

提到 GIS 的渲染引擎,很多开发人员首先想到的可能是 OpenLayer 这款著名的使用 JavaScript 的开源 GIS 前端,但是,从技术上来说,基于 Flex 的前台地图框架也有着很大的应用空间,所以我们选择的是一款基于 ActionScript3 和 Flex 的开源 GIS 前端产品 OpenScales。它是一个优秀的前台地图框架,提供了相对完善的功能,主要包括:

GIS 服务器 MapServer

MapServer 是利用 C 语言开发的开源 WebGIS 项目,它是一套基于胖服务器端 / 瘦客户端模式的实时地图发布系统,客户端发送数据请求时,服务器端实时的处理空间数据,并将生成的数据发送给客户端。MapServer 有如下几个关键的特性 [4]:

空间数据库 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 安装成功

图 2 MS4W 安装成功

使用 MapServer 发布地图数据,关键就是要编写一个后缀名为 map 的 Mapfile 配置文件。在官方文档中,介绍了手工编写该配置文件的方法,关于手工编写的格式和注意事项会在后面的实例中有所介绍;同样读者还可以通过其他图形化配置界面工具或者是开源桌面软件来生成 Mapfile 文件。

PostGIS 的安装和使用

安装 PostGIS 空间数据库的前提条件是有关系型的 PostgreSQL 数据库,而且值得注意的是 PostgreSQL8.3 以上的版本才支持 PostGIS 空间数据库。

这样,首先从 PostgreSQL 产品页面下载最新 Windows 版本的安装文件,接下来按照安装进度依次选择安装目录、数据目录、密码和端口,等待 PostgreSQL 安装完成之后,会出现如下界面:

图 3 PostgreSQL 安装完成

图 3 PostgreSQL 安装完成

点击完成按钮之后选择所需要的 PostGIS 版本以及下载地址后进行安装:

图 4 安装 PostGIS

图 4 安装 PostGIS

PostGIS 空间数据库安装完成后,可以做如下的验证:

图 5 导入 Shape 文件

图 5 导入 Shape 文件

图 6 验证 PostGIS 数据库和导入 Shape 文件

图 6 验证 PostGIS 数据库和导入 Shape 文件

如果能得到如上述的结果,说明 PostGIS 安装成功,并且顺利导入 Shape 格式的矢量数据。

构建 GIS 应用程序

利用上述搭建的开发环境,接下来将展示如何使用 OpenScales,并且在 MapServer 和 PostGIS 的帮助下快速构建一个 GIS 应用程序。在这个应用程序中,将展示如下几个关键内容点,包括:

准备三种数据源

为了能演示支持三种不同形式的数据,需要准备三个数据源,分别是:

编写 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 中出现的一般参数及含义如下:

同时,MAP Object 允许一些嵌套的对象:PROJECTION, QUERYMAP, REFERENCE, SCALEBAR, SYMBOL, WEB. LAYER, LEGEND。接下来将介绍在示例文件中用到的三个嵌套对象,其他对象的详细用法可以参考 MapServer 的官方文档:

下面是一段 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 文件获取数据,其中部分属性介绍如下:

这里值得注意的是,如果读者选择了 KML 格式的矢量数据,需要通过 orginfo 命令行查看该文件的 Layer 名字,如下图中的 hz2 就是该 KML 文件的 Layer 名字。

图 7. 查看 KML 文件的 Layer Name

图 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. 示例程序项目结构

图 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>

上述这段代码所描述的就是如何获取空间数据,这里有两点需要强调一下:第一,每一个 元素中所定义的 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 的应用程序。