开源空间数据库入门——使用postgreSQL的拓展组件PostGIS
1空间数据库介绍
PostgreSQL空间数据库= PostgreSQL数据库+ PostGIS扩展组件
1.1 数据库PostgreSQL
PostgreSQL 是开源的对象-关系数据库服务器 (ORDBMS, object-relational database management system),是目前概念最强大、特性最丰富和最复杂的开源数据库系统之一。
它起源于伯克利(BSD)的数据库研究计划,有非常广泛的用户。PostgreSQL具有优异的跨平台性,支持各类主流的操作系统,包括linux,Windows,Macintosh等。同时支持事务、子查询、多版本并行控制、数据完整性检查等特性,并且支持多语言的开发。
PostgreSQL 从一开始就考虑到了类型扩展——在运行时添加新数据类型、函数和索引的能力。
1.2 空间拓展组件PostGIS
PostGIS是PostgreSQL的空间拓展组件,它可以在数据库中存储GIS(Geographic Information Systems)的对象。PostGIS提供空间对象、空间索引、空间操作函数和空间操作符等功能,将PostgreSQL数据库扩展成了空间数据库。
PostGIS遵循OGC的规范,支持OGC所有空间数据类型。此外,PostGIS还对数据类型进行了扩展,一是把二维数据向三维和四维扩展;二是在WKT和WKB数据类型基础上扩展出EWKT和EWKB数据类型。
PostGIS中重要的支持库
说明 | ||
GEOS (Geometry Engine – Open Source) | 空间计算几何的C/ C++的程序库 | 遵循LGPL开源协议,广泛用于“地理信息系统”软件,支持空间模型和空间函数。GEOS是PostGIS、QGIS、GDAL和Shapely的核心依赖项。 |
GDAL (Geospatial Data Abstraction Library) | 地理空间数据抽象模型的程序库 | 遵循X/MIT开源协议,用于地理空间数据的转换和处理。它利用抽象数据模型来表示所支持的各种数据格式。 |
PROJ(Cartographic Projections and Coordinate Transformations Library) | 地图投影的程序库 | 遵循X/MIT开源协议,用于坐标转换和坐标参考系统转换。 |
SFCGAL(CGAL, Computational Geometry Algorithms Library) | 围绕计算几何算法库的C++包装程序库 | 支持基于OGC标准模型的二维对象操作和三维对象操作。 |
1.3 PgAdmin数据库管理工具
PgAdmin是访问PostgreSQL数据库的图形化工具,极大提高了访问该数据库的方便性。
pgAdmin4 GUI v3.3及其以上,支持查看几何对象、地理对象,不支持查看扩展空间对象。
2空间数据库安装
2.1 安装PostgreSQL
对于windows系统,通过Stackbuilder安装稳定版本。
对于其他操作系统,较老版本提供安装包,新版本只提供源码包。建议源码编译安装。
2.2 安装PostGIS
对于windows系统,通过Stackbuilder安装PostgreSQL对应的PostGIS版本,或者下载相应安装包安装。
对于其他操作系统,源码编译安装。
2.3 安装pgAdmin4
建议安装PgAdmin4 v3.3及其以上版本。
2.4 其他注意事项
(1)安装其他依赖插件。对于windows系统,通过PostgreSQL自带的Stackbuilder软件安装即可;对于其他操作系统,源码编译安装。
(2)PostGIS 版本要与PostgreSQL版本相匹配。例如:PostGIS 3.0.3要求PostgreSQL版本在9.5以上(包含9.5)。
(3)PG库Locale的选择。Locale就是某一个地域内的人们的语言习惯和文化传统和生活习惯。安装PG库时, Locale建议选择C(除非业务需要必须使用中文字符集)。
2.5 查看安装结果
-- 查看所有数据库postgres=# \l 数据库列表 名称 | 拥有者 | 字元编码 | 校对规则 | Ctype | 存取权限 -------------------+----------+----------+----------+-------+----------------------- postgis_30_sample | postgres | UTF8 | C | C | postgis_4_sm | postgres | UTF8 | C | C | postgres | postgres | UTF8 | C | C | postgres_4_sm | postgres | UTF8 | C | C | template0 | postgres | UTF8 | C | C |=c/postgres +||||| postgres=CTc/postgres template1 | postgres | UTF8 | C | C |=c/postgres +||||| postgres=CTc/postgres (6 行记录)
-- 以PostGis创建的空间数据库为模板,创建自己的空间数据库postgis(省去为新库安装拓展组件)postgres=# CREATE DATABASE postgis TEMPLATE postgis_30_sample;
-- 再次查看所有数据库postgres=# \l 数据库列表 名称 | 拥有者 | 字元编码 | 校对规则 | Ctype | 存取权限 -------------------+----------+----------+----------+-------+----------------------- postgis | postgres | UTF8 | C | C | postgis_30_sample | postgres | UTF8 | C | C | postgis_4_sm | postgres | UTF8 | C | C | postgres | postgres | UTF8 | C | C | postgres_4_sm | postgres | UTF8 | C | C | template0 | postgres | UTF8 | C | C |=c/postgres +||||| postgres=CTc/postgres template1 | postgres | UTF8 | C | C |=c/postgres +||||| postgres=CTc/postgres (7 行记录)
-- 进入自己的空间数据库postgispostgres=# \c postgis 您现在已经连接到数据库 "postgis",用户 "postgres".
3空间对象的类型
PostGIS支持的GIS对象是开放地理空间协会(OGC, Open Geospatial Consortium)定义的“简单几何要素”的一个超集。PostGIS支持OGC“SQL的简单几何要素”规范中指定的所有对象和函数。在OGC规范的基础上,PostGIS还扩展了标准,支持3DZ、3DM和4D坐标。
OGC“SQL的简单几何要素”规范插图
3.1 几何对象(geometry)
对于几何对象,OGC规范定义了两种表示空间对象的标准方法:WKT(Well-Known Text)、WKB(Well-Known Binary), 表示对象类型和组成对象的坐标的信息。
空间对象的文本表示(WKT, Well-Known Text)
• POINT(0 0) • LINESTRING(0 0,1 1,1 2) • POLYGON((0 0,4 0,4 4,0 4,0 0),(1 1, 2 1, 2 2, 1 2,1 1)) • MULTIPOINT((0 0),(1 2)) • MULTILINESTRING((0 0,1 1,1 2),(2 3,3 2,5 4)) • MULTIPOLYGON(((0 0,4 0,4 4,0 4,0 0),(1 1,2 1,2 2,1 2,1 1)), ((-1 -1,-1 -2,-2 -2,-2 -1,-1 -1))) • GEOMETRYCOLLECTION(POINT(2 3),LINESTRING(2 3,3 4))
3.2 扩展空间对象
OGC格式只支持2D几何图形。PostGIS的EWKB/EWKT增加了3DM、3DZ、4D坐标支持和嵌入式SRID信息,但这些内容目前是OGC扩展格式的超集(每个有效的WKB/WKT都是有效的EWKB/EWKT),未来可能会有所不同。
扩展空间对象的文本表示(WKT)
• POINT(0 0 0) -- XYZ • SRID=32632;POINT(0 0) -- XY with SRID • POINTM(0 0 0) -- XYM • POINT(0 0 0 0) -- XYZM • SRID=4326;MULTIPOINTM(0 0 0,1 2 1) -- XYM with SRID • MULTILINESTRING((0 0 0,1 1 0,1 2 1),(2 3 1,3 2 1,5 4 1)) • POLYGON((0 0 0,4 0 0,4 4 0,0 4 0,0 0 0),(1 1 0,2 1 0,2 2 0,1 2 0,1 1 0)) • MULTIPOLYGON(((0 0 0,4 0 0,4 4 0,0 4 0,0 0 0),(1 1 0,2 1 0,2 2 0,1 2 0,1 1 0)),((-1 -1 0,-1 -2 0,-2 -2 0,-2 -1 0,-1 -1 0))) • GEOMETRYCOLLECTIONM( POINTM(2 3 9), LINESTRINGM(2 3 4, 3 4 5) ) • MULTICURVE( (0 0, 5 5), CIRCULARSTRING(4 0, 4 4, 8 4) ) • POLYHEDRALSURFACE( ((0 0 0, 0 0 1, 0 1 1, 0 1 0, 0 0 0)), ((0 0 0, 0 1 0, 1 1 0, 1 0 0, 0 0 0)), ((0 0 0, 1 0 0, 1 0 1, 0 0 1, 0 0 0)), ((1 1 0, 1 1 1, 1 0 1, 1 0 0, 1 1 0)), ((0 1 0, 0 1 1, 1 1 1, 1 1 0, 0 1 0)), ((0 0 1, 1 0 1, 1 1 1, 0 1 1, 0 0 1)) ) • TRIANGLE ((0 0, 0 9, 9 0, 0 0)) • TIN( ((0 0 0, 0 0 1, 0 1 0, 0 0 0)), ((0 0 0, 0 1 0, 1 1 0, 0 0 0)) )
3.3 地理对象(geography)
geography类型是基于地理坐标/大地坐标/经纬度坐标表示的空间几何对象,使用角单位(度)表示的球坐标。
3.4 几何对象和地理对象的区别
几何对象 | 地理对象 | |
基础 | 平面 | 球面 |
距离 | 平面上两点之间的最短路径是一条直线 | 球面上两点之间的最短路径是一条大圆弧 |
表示范围 | 适合小区域 | 适合大范围(全球/大陆地区) |
坐标 | 投影坐标(单位:米) | 经纬度坐标(单位:度) |
操作函数 | 空间函数多 | 空间函数少,GEOS函数不支持 |
支持格式 | 支持所有标准OGC格式 | 支持除曲线外的所有标准OGC格式 |
4空间操作函数
PostGIS提供的空间操作函数数量繁多,功能强大。
本文使用简单的点、线、面为示例数据,选取部分代表性的空间函数(如下)操作几何图形,结果仅作参考。
4.1 二维空间数据的创建
-- 创建含有单点的几何表postgis=# CREATETABLE point (name varchar, geom geometry);CREATETABLEpostgis=# INSERTINTO point VALUES('Point','POINT(0 0)');INSERT01
-- 查看点的几何表postgis=# SELECT*FROM point; name | geom -------+-------------------------------------------- Point |010100000000000000000000000000000000000000(1 行记录)
-- 创建含有单线的几何表postgis=# CREATETABLE line (name varchar, geom geometry);CREATETABLEINSERTINTO line VALUES('road','LINESTRING(0 0, 1 1, 2 1, 2 2)');INSERT01
-- 查看线的几何表postgis=# SELECT*FROM line; name | geom -------------------+--------------------------------------------------------------------- road |01020000000400000000000000000000000000000000000000000000000000F03F000000000000F03F0000000000000040000000000000F03F00000000000000400000000000000040 (1 行记录)
-- 创建含有单面的几何表postgis=# CREATETABLE polygon (name varchar, geom geometry);CREATETABLEpostgis=# INSERTINTO polygon VALUES('boundary','POLYGON((0 0, 1 0, 1 1, 0 1, 0 0))');INSERT01
-- 查看面的几何表postgis=# SELECT*FROM polygon; name | geom ----------+------------------------------------------------------------------------------ boundary |0103000000010000000500000000000000000000000000000000000000000000000000F03F0000000000000000000000000000F03F000000000000F03F0000000000000000000000000000F03F00000000000000000000000000000000 (1 行记录)
4.2 二维空间数据的预览
-- 查看点的WKT内容postgis=# SELECT ST_AsText(geom)AS wkt FROM city; wkt ------------------------------------------ POINT(116.39599544457939.8987271597721) POINT(117.21285382386739.105545834957) POINT(114.48999255957638.0400783837128)(3 行记录)
getometry 列上显示了一个眼睛图标,点击眼睛图标,自动在GeometryViewer中显示空间数据。当几何对象、地理对象的空间参考标识符SRID为4326(WGS84)的时候,PgAdmin会自动加载osm(open street map)地图作为浏览的底图。
-- 查看点的几何类型字段并在GeometryViewer中浏览postgis=# SELECT geom FROM city;
-- 查看线的几何类型字段并在GeometryViewer中浏览postgis=# SELECT geom FROM river;
-- 查看面的几何类型字段并在GeometryViewer中浏览postgis=# SELECT geom FROM province;
4.3 二维空间数据的分析
-- 查看面的空间参考标识符postgis=# SELECT ST_SRID(geom)AS srid FROM province LIMIT1; srid ------4326(1 行记录)
-- 计算线的长度postgis=# SELECT ST_Length(ST_Transform(geom,32650))AS length FROM river; length -------------------735193.7734506618(1 行记录)
-- 计算面的面积postgis=# SELECT ST_Area(ST_Transform(geom,32650))AS area FROM province WHERE provincena ='河北'; area --------------------187289489082.25452(1 行记录)
-- 计算线的最小外包矩形postgis=# SELECT ST_AsText(ST_Envelope(geom))AS wkt FROM river; wkt ----------------------------------------------------------------------------------------- POLYGON((115.75111116889339.437267438529,115.75111116889342.3688621600899,119.26902483476642.3688621600899,119.26902483476639.437267438529,115.75111116889339.437267438529))(1 行记录)
-- 查找包含点的面postgis=# SELECT p.gid, p.userid, p.provincenaFROM province p CROSS JOIN city c WHERE c.name='石家庄'AND ST_Contains(p.geom, c.geom); gid | userid | provincena -----+--------+------------2|| 河北 (1 行记录)
-- 获得点的10km缓冲区postgis=# SELECT ST_AsText(ST_Buffer(ST_Transform(geom,32650),10000))AS wkt FROM city;
4.4 三维空间数据的创建
-- 创建含有三棱柱的表postgis=# CREATETABLE triangularPyramid (name varchar, geom geometry);CREATETABLE-- 向表中插入1条记录postgis=# INSERTINTO triangularPyramid (name, geom)VALUES('beam', ST_Extrude(ST_GeomFromText('POLYGON((0 0,1 3,2 0, 0 0))'),0,0,10));INSERT01
-- 创建含有立方体的表postgis=# CREATETABLE cubeBox (name varchar, geom geometry);CREATETABLE-- 向表中插入1条记录postgis=# INSERTINTO cubeBox (name, geom)VALUES('box', ST_Extrude(ST_GeomFromText('POLYGON((0 0,2 0,2 2,0 2,0 0))'),0,0,2));INSERT01
4.5 三维空间数据的预览
-- 查询含有三棱柱的表postgis=# SELECT name, ST_AsText(geom)AS ewkt FROM triangularPyramid; name | ewkt ------+---------------------------------------------------------------------------------- beam | POLYHEDRALSURFACE Z (((000,130,200,000)),((0010,2010,1310,0010)),((000,0010,1310,130,000)),((130,1310,2010,200,130)),((200,2010,0010,000,200)))(1 行记录)
-- 查询含有立方体的表postgis=# SELECT name, ST_AsText(geom)AS ewkt FROM cubeBox; name | ewkt ------+---------------------------------------------------------------------------------- box | POLYHEDRALSURFACE Z (((000,020,220,200,000)),((002,202,222,022,002)),((000,002,022,020,000)),((020,022,222,220,020)),((220,222,202,200,220)),((200,202,002,000,200)))(1 行记录)
-- 查看三棱柱的X3D格式文本postgis=# SELECT ST_AsX3D(geom)AS x3d FROM triangularPyramid; x3d -----------------------------------------------------------------------------------------<IndexedFaceSet convex='false' coordIndex='0 1 2 -1 3 4 5 -1 6 7 8 9 -1 10 11 12 13 -1 14 15 16 17'><Coordinate point='0 0 0 1 3 0 2 0 0 0 0 10 2 0 10 1 3 10 0 0 0 0 0 10 1 3 10 1 3 0 1 3 0 1 3 10 2 0 10 2 0 0 2 0 0 2 0 10 0 0 10 0 0 0'/></IndexedFaceSet>(1 行记录)
-- 查看立方体的X3D格式文本postgis=# SELECT ST_AsX3D(geom)AS x3d FROM cubeBox; x3d -----------------------------------------------------------------------------------------<IndexedFaceSet convex='false' coordIndex='0 1 2 3 -1 4 5 6 7 -1 8 9 10 11 -1 12 13 14 15 -1 16 17 18 19 -1 20 21 22 23'><Coordinate point='0 0 0 0 2 0 2 2 0 2 0 0 0 0 2 2 0 2 2 2 2 0 2 2 0 0 0 0 0 2 0 2 2 0 2 0 0 2 0 0 2 2 2 2 2 2 2 0 2 2 0 2 2 2 2 0 2 2 0 0 2 0 0 2 0 2 0 0 2 0 0 0'/></IndexedFaceSet>(1 行记录)
4.6 三维空间数据的分析
-- 查询三棱柱和的相交部分的X3D格式文本postgis=# SELECT ST_AsX3D(ST_3DIntersection(t.geom,c.geom))AS x3d FROM triangularPyramid AS t,cubebox AS c;
-- 查询立方体的维度postgis=# SELECT ST_Dimension(geom)as dimension FROM cubeBox; dimension -----------3(1 行记录)
-- 将立方体由三维转为二维postgis=# SELECT ST_AsText(ST_Force2D(geom))as geo2d FROM cubeBox; geo2d ------------------------------------------------------------------------------------ POLYHEDRALSURFACE(((00,02,22,20,00)),((00,20,22,02,00)),((00,00,02,02,00)),((02,02,22,22,02)),((22,22,20,20,22)),((20,20,00,00,20)))(1 行记录)
-- 查询转换后的维度postgis=# SELECT ST_Dimension(ST_Force2D(geom))as dimension FROM cubeBox; dimension -----------2(1 行记录)
参考链接
[1] https://www.postgresql.org/
[2] http://postgis.net/docs/manual-3.0/