2009年4月24日星期五

PostgreSQL+PostGIS的使用 2

三、 PostGIS中空间信息处理的实现

1. spatial_ref_sys表

在基于PostGIS模板创建的数据库的public模式下,有一个spatial_ref_sys表,它存放的是OGC规范的空间参考。我们取我们最熟悉的4326参考看一下:

它的srid存放的就是空间参考的Well-Known ID,对这个空间参考的定义主要包括两个字段,srtext存放的是以字符串描述的空间参考,proj4text存放的则是以字符串描述的PROJ.4 投影定义(PostGIS使用PROJ.4实现投影)。

4326空间参考的srtext内容:
GEOGCS["WGS 84",DATUM["WGS_1984",SPHEROID["WGS 84",6378137,298.257223563,AUTHORITY["EPSG","7030"]],TOWGS84[0,0,0,0,0,0,0],AUTHORITY["EPSG","6326"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.01745329251994328,AUTHORITY["EPSG","9122"]],AUTHORITY["EPSG","4326"]]

4326空间参考的proj4text内容:
+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs

2. geometry_columns表

geometry_columns表存放了当前数据库中所有几何字段的信息,比如我当前的库里面有两个空间表,在geometry_columns表中就可以找到这两个空间表中几何字段的定义:

其中f_table_schema字段表示的是空间表所在的模式,f_table_name字段表示的是空间表的表名,f_geometry_column字段表示的是该空间表中几何字段的名称,srid字段表示的是该空间表的空间参考。

3. 在PostGIS中创建一个空间表

在PostGIS中创建一个包含几何字段的空间表分为2步:第一步创建一个一般表,第二步给这个表添加几何字段。

以下先在test模式下创建一个名为cities的一般表:
create table test.cities (id int4, name varchar(20))

再给cities添加一个名为shape的几何字段(二维点):
select AddGeometryColumn('test', 'cities', 'shape', 4326, 'POINT', 2)

4. PostGIS对几何信息的检查

PostGIS可以检查几何信息的正确性,这主要是通过IsValid函数实现的。
以下语句分辨检查了2个几何对象的正确性,显然,(0, 0)点和(1,1)点可以构成一条线,但是(0, 0)点和(0, 0)点则不能构成,这个语句执行以后的得出的结果是TRUE,FALSE。

select IsValid('LINESTRING(0 0, 1 1)'), IsValid('LINESTRING(0 0,0 0)')
默认PostGIS并不会使用IsValid函数检查用户插入的新数据,因为这会消耗较多的CPU资源(特别是复杂的几何对象)。当你需要使用这个功能的时候,你可以使用以下语句为表新建一个约束:
ALTER TABLE cities
ADD CONSTRAINT geometry_valid
CHECK (IsValid(shape))

这时当我们往这个表试图插入一个错误的空间对象的时候,会得到一个错误:
INSERT INTO test.cities ( shape, name )
VALUES ( GeomFromText('LINESTRING(0 0,0 0)', 4326), '北京');

ERROR: new row for relation "cities" violates check constraint "geometry_valid"
SQL 状态: 23514

5. PostGIS中的空间索引

数据库对多维数据的存取有两种索引方案,R-Tree和GiST(Generalized Search Tree),在PostgreSQL中的GiST比R-Tree的健壮性更好,因此PostGIS对空间数据的索引一般采用GiST实现。

以下的语句给sde模式中的cities表添加了一个空间索引shape_index_cities,在pgAdmin中也可以通过图形界面完成相同的功能。
CREATE INDEX shape_index_cities
ON sde.cities
USING gist
(shape);

另外要注意的是,空间索引只有在进行基于边界范围的查询时才起作用,比如“&&”操作。

没有评论: