OGC的WKB和WKT格式


OGC定义了两种描述几何对象的格式,分别是WKB(Well-Known Binary)和WKT(Well-Known Text)。


在SQL语句中,用以下的方式可以使用WKT格式定义几何对象:


几何要素 WKT格式


点 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))


多线 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)))


以下语句可以使用WKT格式插入一个点要素到一个表中,其中用到的GeomFromText等函数在后面会有详细介绍:


INSERT INTO table (SHAPE,NAME)


VALUES (GeomFromText('POINT(116.39 39.9)', 4326), '北京');


EWKT、EWKB和Canonical格式


EWKT和EWKB相比OGC WKT和WKB格式主要的扩展有3DZ、3DM、4D坐标和内嵌空间参考支持。


以下以EWKT语句定义了一些几何对象:


几何类型 格式


3D点 POINT(0 0 0)


内嵌空间参考的点 SRID=32632;POINT(0 0)


带M值的点 POINTM(0 0 0)


带M值的3D点 POINT(0 0 0 0)


内嵌空间参考的带M值的多点 SRID=4326;MULTIPOINTM(0 0 0,1 2 1)


以下语句可以使用EWKT格式插入一个点要素到一个表中:


INSERT INTO table (SHAPE, NAME)


VALUES(GeomFromEWKT('SRID=4326;POINTM(116.39 39.9 10)'), '北京')


Canonical格式是16进制编码的几何对象,直接用SQL语句查询出来的就是这种格式。


SQL-MM格式


SQL-MM格式定义了一些插值曲线,这些插值曲线和EWKT有点类似,也支持3DZ、3DM、4D坐标,但是不支持嵌入空间参考。


以下以SQL-MM语句定义了一些插值几何对象:


几何类型 格式


插值圆弧 CIRCULARSTRING(0 0, 1 1, 1 0)


插值复合曲线 COMPOUNDCURVE(CIRCULARSTRING(0 0, 1 1, 1 0),(1 0, 0 1))


曲线多边形 CURVEPOLYGON(CIRCULARSTRING(0 0, 4 0, 4 4, 0 4, 0 0),(1 1, 3 3, 3 1, 1 1))


多曲线 MULTICURVE((0 0, 5 5),CIRCULARSTRING(4 0, 4 4, 8 4))


多曲面 MULTISURFACE(CURVEPOLYGON(CIRCULARSTRING(0 0, 4 0, 4 4, 0 4, 0 0),(1 1, 3 3, 3 1, 1 1)),((10 10, 14 12, 11 10, 10 10),(11 11, 11.5 11, 11 11.5, 11 11)))


PostGIS中空间信息处理的实现


spatial_ref_sys表


在基于PostGIS模板创建的数据库的public模式下,有一个spatial_ref_sys表,它存放的是OGC规范的空间参考。


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


geometry_columns表


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


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


在PostGIS中创建一个空间表


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


以下先在test模式下创建一个名为cities的一般表:


create table test.cities (id int4, name varchar(20))


再给cities添加一个名为shape的几何字段(二维点):


select AddGeometryColumn('test', 'cities', 'shape', 4326, 'POINT', 2)


PostGIS对几何信息的检查


PostGIS可以检查几何信息的正确性,这主要是通过IsValid函数实现的。


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


?


1


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


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);


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