在开源数据库中,对空间数据支持最好的是 PostgreSQL/PostGIS,postgresql 是开源数据库领域另一个著名的数据库,其支持基本的空间数据类型,如 point、line、polygon、box、path 等,由于本文主要讲解 mysql 的问题,这里就不展开了。PostGIS 是对 PostgreSQL 的空间扩展,使 PostgreSQL 对空间数据的支持能力提升到了一个更高层次:比如对空间数据对象的运算和分析。虽然 PostgreSQL/PostGIS 对空间数据的支持比较全面,但是国内使用的并不多,使用最多的还是 MySQL,因此,我们这篇文章中主要讲解 MySQL 中存储的空间数据的利用问题。
MySQL 从 4.1 开始支持空间数据类型,可能由于历史原因,或者很多技术人员并不了解 GIS,很多空间位置数据存储并没有使用专有的空间数据类型字段,而是使用了两个 float 类型存储,分别代表经度和纬度,经纬度数据一般是来自 GPS 传感器;当然还有一些数据就直接利用了 MySQL 的空间扩展,空间数据表中的 geometry 类型存储空间数据。那么这两种在 MySQL 数据库中存储的空间信息怎么利用呢?
本文结合 MapServer , OGR 和 MySQL ,对存储于 MySQL 数据库中的空间数据信息进行访问和渲染利用。
1. 服务器端渲染地图的必要性
那么当我们需要将这些存储在 MySQL 数据库中的空间数据渲染并显示到地图上时,怎么办呢?由于一般要素(非地图底图)的渲染,数据量并不是很大,因此很多做法是将经纬度字段取出,拼接成 GeoJSON 或者 KML 等空间数据交换格式,然后发送到客户端进行渲染,客户端可能是浏览器,浏览器的计算能力是有限的,这样的做法有两个瓶颈:
1. 随着数据量的增大,网络传输需要的时间变长;
2. 客户端计算能力有限,如果计算量过大,会导致浏览器假死,造成很不好的体验。
如果我们将渲染的任务交给服务器端,将渲染的图片结果传回客户端,那么以上的瓶颈就可以突破,且服务器端的计算能力可以通过增加服务器进行扩展,理论上是无限的。
如果数据库服务器软件使用 MapServer,我们可以通过 MapServer 来直接渲染 MySQL 中存储的空间数据,MapServer 对 MySQL 数据源的支持是由于得到 GDAL/OGR 的能力,MapServer 不能支持的数据往往通过 GDAL/OGR 来读取并渲染。分为两种情况:
1. 如果 MySQL 中的空间数据是存储在 geometry 字段中,那么可以直接读取;
2. 如果 MySQL 中的空间数据是通过两个字段分别代表 经纬度的形式存储的,那么需要构造虚拟图层。
2. 数据存储形式为 geometry
MySQL 对空间数据的支持是比较直观的,其空间数据类型直接对应于 OpenGIS 的规范,其能容纳空间数据的字段类型包括:GEOMETRY、POINT、LINESTRING、POLYGON、MULTIPOINT、MULTILINESTRING、MULTIPOLYGON 和 GEOMETRYCOLLECTION,它们中的一些只支持存储一个地理几何地物(GEOMETRY,POINT,LINESTRING,POLYGON),其中 GEOMETRY 可以存储 点、线 和 面,POINT,LINESTRING,POLYGON 只能存储对应的地物类型,剩下的从字面上也可以理解,可以存储多个点线面地物。
在这种存储情况下,我们可以直接配置 mapfile 读取,mapfile 示例如下(部分,完整的mapfile 配置还有 map 对象,web 对象等等,可参见我前面的文章)。
LAYER
NAME "mysql_spatial_layer"
TYPE POLYGON
STATUS DEFAULT
CONNECTIONTYPE OGR
CONNECTION "MySQL:dbname,user=root,password=mysql,port=3306"
DATA "SELECT geom_col_name,property_col_name from table_name"
LABELITEM "property_col_name"
CLASS
NAME "class_name"
STYLE
COLOR 240 240 240
OUTLINECOLOR 199 199 199
END
LABEL
COLOR 0 0 0
FONT sans
TYPE truetype
SIZE 8
POSITION AUTO
PARTIALS FALSE
OUTLINECOLOR 255 255 255
END
END
END # layer
其中需要注意的是如下几行:
CONNECTIONTYPE OGR
CONNECTION "MySQL:dbname,user=root,password=mysql,port=3306"
DATA "SELECT geom_col_name,property_col_name from table_name"
CONNECTIONTYPE的类型是OGR,这就是配置 MapServer 使用 OGR 提供的空间数据解析能力,CONNETION配置连接 MySQL 的参数,DATA指定 sql 查询语句。这样,就可通过请求 MapServer 发布的 OGC 服务,来请求存储于 MySQL 的空间数据。
3. 数据是存储形式为 x,y
默认情况下,OGR 也不能将 x,y 形式存储的坐标数据渲染,针对这种形式的数据,OGR提供了 Virtual Format,其对应的解析引擎是 OGR VRT,通俗来说是通过一个 xml 配置文件,来将关系数据库中的数据映射到 OGR 的空间数据结构。VRT 不仅可以用于将解析采用普通属性字段形式存储空间信息的表,还可以用于关联数据和坐标系统信息,将多个图层融合进一个数据源等,详细的信息可以到这里看:http://www.gdal.org/drv_vrt.html 。
针对 MySQL 中两个普通属性字段存储经纬度的信息,我们可以创建一个 Virtual File,扩展名为 .ovf,一个实例如下:
MYSQL:dbname,user=user_name,password=passwd,host=IP_addr,port=3306,tables=table_name
SELECT longitude_col_name, latitude_col_name, property_col_name FROM table_name
wkbPoint
Virtual File 根元素通常是 OGRVRTDataSource,其子元素一般是一个或者多个图层元素,图层类型包括 OGRVRTLayer ,OGRVRTWarpedLayer 或者 OGRVRTUnionLayer,后两个是在 GDAL/OGR 1.10.0 开始支持的,这里就不展开了,同时,图层元素下可以有哪些子配置元素,想了解更多的可以到这里看: http://www.gdal.org/drv_vrt.html 。这里我主要讲解该例子中涉及的参数:
SrcDataSource 配置连接 MySQL 的连接信息,SrcSQL 配置选取经纬度和属性信息的 SQL 查询语句;
GeometryType 指定表中包含的空间数据的类型,允许的类型包括:”wkbNone”, “wkbUnknown”, “wkbPoint”, “wkbLineString”, “wkbPolygon”, “wkbMultiPoint”, “wkbMultiLineString”, “wkbMultiPolygon”, 或者 “wkbGeometryCollection”,如果不指定,默认值是 “wkbUnknown”,允许任何类型的地理几何地物;
GeometryField 指定 x,y 坐标的字段名,encoding 允许的值包括 “WKT”, “WKB” 或者 “PointFromColumns”,规定坐标的来源格式。
一个将 MySQL 普通形式存储的空间信息映射到 OGR 空间数据结构的 VRT 文件就写好了,接下来要在 mapfile 配置文件中相应的图层中指定 VRT 文件,示例如下:
LAYER
NAME "layer_name"
STATUS DEFAULT
TYPE POINT
CONNECTIONTYPE OGR
CONNECTION "vrt_file_name.ovf"
DATA "vrt_layer_name"
CLASS
NAME "MyClass"
STYLE
SYMBOL 'circle'
SIZE 15
COLOR 0 255 0
END
END
END
其中,DATA 参数指定的 vrt_layer_name 需要和 VRT 文件中指定的 OGRVRTLayer 一致(),CONNECTION 参数指定 VRT 文件路径地址,注意 STYLE 中包含的 SYMBOL 值 ‘circle’ 是预先设置好的,是在 MAP 对象中设置的 SYMBOLSET 参数中指定的 symbol 文件中预先定义的样式,这里为了突出重点,进行了省略。
4. 总结
本文主要介绍了在 MySQL 中存储空间数据的两种形式,解释了在服务器端渲染空间数据的好处,并结合 MapServer 讲解了如何 结合 OGR 读取并渲染存储于 MySQL 中的空间数据。
好的,就写到这里,有什么问题,可以在文章下面留言或者给我发邮件。