空间数据库的 raison d'etre 是在数据库内执行通常需要桌面 GIS 功能的查询。有效地使用 PostGIS 需要了解可用的空间函数、如何在查询中使用它们以及确保适当的索引到位以提供良好的性能。
空间关系表示两个几何体如何相互作用。它们是查询几何体的基本功能。
根据 OpenGIS 简单要素实现规范 for SQL,“比较两个几何体的基本方法是对两个几何体的内部、边界和外部之间的交集进行成对测试,并根据结果“交集”矩阵中的条目对两个几何体之间的关系进行分类。”
在点集拓扑理论中,嵌入在二维空间中的几何体中的点被归类为三个集合
几何体的边界是下一维几何体的集合。对于维度为 0 的 POINT
,边界为空集。LINESTRING
的边界是两个端点。对于 POLYGON
,边界是外部和内部环的线段。
几何图形的内部是指几何图形中不属于边界的所有点。对于 POINT
,内部就是点本身。 LINESTRING
的内部是端点之间的所有点。对于 POLYGON
,内部是多边形内的面积表面。
几何图形的外部是指嵌入几何图形的空间的其余部分;换句话说,所有不在几何图形的内部或边界上的点。它是一个二维的非封闭表面。
维扩展九交集模型 (DE-9IM) 通过指定每个几何图形的上述集合之间的 9 个交集的维度来描述两个几何图形之间的空间关系。交集维度可以用 3x3 的 交集矩阵 正式表示。
对于几何图形 g,内部、边界 和 外部 分别用符号 I(g)、B(g) 和 E(g) 表示。此外,dim(s) 表示集合 s 的维度,其域为 {0,1,2,F}
0
=> 点
1
=> 线
2
=> 面积
F
=> 空集
使用此符号,两个几何图形 a 和 b 的交集矩阵为
内部 | 边界 | 外部 | |
---|---|---|---|
内部 | dim( I(a) ∩ I(b) ) | dim( I(a) ∩ B(b) ) | dim( I(a) ∩ E(b) ) |
边界 | dim( B(a) ∩ I(b) ) | dim( B(a) ∩ B(b) ) | dim( B(a) ∩ E(b) ) |
外部 | dim( E(a) ∩ I(b) ) | dim( E(a) ∩ B(b) ) | dim( E(a) ∩ E(b) ) |
直观地,对于两个重叠的多边形几何图形,它看起来像
|
从左到右,从上到下读取,交集矩阵表示为文本字符串 '212101212'。
有关更多信息,请参阅
OpenGIS 简单要素实现规范 for SQL (版本 1.1,第 2.1.13.2 节)
为了便于确定常见的空间关系,OGC SFS 定义了一组命名空间关系谓词。PostGIS 将这些谓词提供为函数 ST_Contains、ST_Crosses、ST_Disjoint、ST_Equals、ST_Intersects、ST_Overlaps、ST_Touches、ST_Within。它还定义了非标准关系谓词 ST_Covers、ST_CoveredBy 和 ST_ContainsProperly。
空间谓词通常用作 SQL WHERE
或 JOIN
子句中的条件。命名空间谓词在可用时会自动使用空间索引,因此无需使用边界框运算符 &&
。例如
SELECT city.name, state.name, city.geom FROM city JOIN state ON ST_Intersects(city.geom, state.geom);
有关更多详细信息和说明,请参阅 PostGIS 工作坊。
在某些情况下,命名空间关系不足以提供所需的空間筛选条件。
例如,考虑一个表示道路网络的线性数据集。可能需要识别所有相互交叉的道路段,但不是在一点上交叉,而是在一条线上交叉(也许是为了验证某些业务规则)。在这种情况下,ST_Crosses 不能提供必要的空间过滤器,因为对于线性要素,它只在它们在一点上交叉时返回 一个两步解决方案是首先计算道路线对的空间相交 (ST_Intersects) 的实际交点 (ST_Intersection),然后检查交点的 ST_GeometryType 是否为 ' 显然,需要一个更简单、更快的解决方案。 |
第二个例子是定位与湖泊边界在一条线上相交的码头,并且码头的一端位于岸上。换句话说,码头位于湖泊内但没有完全包含在湖泊内,与湖泊边界在一条线上相交,并且码头的一个端点正好位于湖泊边界内或边界上。可以使用空间谓词的组合来查找所需的要素
|
这些需求可以通过计算完整的 DE-9IM 交点矩阵来满足。PostGIS 提供了 ST_Relate 函数来执行此操作
SELECT ST_Relate( 'LINESTRING (1 1, 5 5)', 'POLYGON ((3 3, 3 7, 7 7, 7 3, 3 3))' ); st_relate ----------- 1010F0212
为了测试特定的空间关系,使用一个交集矩阵模式。这是矩阵表示,并添加了额外的符号{T,*}
T
=> 交集维度非空;即在{0,1,2}
中
*
=> 不关心
使用交集矩阵模式,可以更简洁地评估特定的空间关系。可以使用ST_Relate和ST_RelateMatch函数来测试交集矩阵模式。对于上面的第一个示例,指定两条线在一条线上相交的交集矩阵模式是'1*1***1**'
-- Find road segments that intersect in a line SELECT a.id FROM roads a, roads b WHERE a.id != b.id AND a.geom && b.geom AND ST_Relate(a.geom, b.geom, '1*1***1**');
对于第二个示例,指定一条线部分在多边形内,部分在多边形外的交集矩阵模式是'102101FF2'
-- Find wharves partly on a lake's shoreline SELECT a.lake_id, b.wharf_id FROM lakes a, wharfs b WHERE a.geom && b.geom AND ST_Relate(a.geom, b.geom, '102101FF2');
在构建使用空间条件的查询时,为了获得最佳性能,重要的是要确保使用空间索引(如果存在)(参见第 4.9 节,“空间索引”)。为此,必须在查询的WHERE
或ON
子句中使用空间运算符或索引感知函数。
空间运算符包括边界框运算符(其中最常用的运算符是&&;有关完整列表,请参见第 7.10.1 节,“边界框运算符”)和用于最近邻查询的距离运算符(最常见的是<->;有关完整列表,请参见第 7.10.2 节,“距离运算符”)。
索引感知函数会自动将边界框运算符添加到空间条件中。索引感知函数包括命名空间关系谓词ST_Contains、ST_ContainsProperly、ST_CoveredBy、ST_Covers、ST_Crosses、ST_Intersects、ST_Overlaps、ST_Touches、ST_Within、ST_Within和ST_3DIntersects,以及距离谓词ST_DWithin、ST_DFullyWithin、ST_3DDFullyWithin和ST_3DDWithin。
诸如ST_Distance之类的函数不使用索引来优化其操作。例如,以下查询在大型表上会非常慢
SELECT geom FROM geom_table WHERE ST_Distance( geom, 'SRID=312;POINT(100000 200000)' ) < 100
此查询选择geom_table
中所有距离点 (100000, 200000) 100 个单位内的几何图形。它会很慢,因为它正在计算表中每个点与指定点之间的距离,即为表中的每一行计算一个ST_Distance()
计算。
通过使用索引感知函数 ST_DWithin,可以大幅减少处理的行数。
SELECT geom FROM geom_table WHERE ST_DWithin( geom, 'SRID=312;POINT(100000 200000)', 100 )
此查询选择相同的几何图形,但以更有效的方式进行。这是通过 ST_DWithin()
在查询几何图形的扩展边界框上内部使用 &&
运算符来实现的。如果 geom
上存在空间索引,查询计划器将识别出它可以使用索引来减少在计算距离之前扫描的行数。空间索引允许仅检索几何图形的边界框与扩展范围重叠的记录,因此这些记录可能在所需的距离内。然后计算实际距离以确认是否将记录包含在结果集中。
有关更多信息和示例,请参阅 PostGIS Workshop。
本节中的示例使用线性道路表和多边形市政边界表。 bc_roads
表的定义为
Column | Type | Description ----------+-------------------+------------------- gid | integer | Unique ID name | character varying | Road Name geom | geometry | Location Geometry (Linestring)
bc_municipality
表的定义为
Column | Type | Description ---------+-------------------+------------------- gid | integer | Unique ID code | integer | Unique ID name | character varying | City / Town Name geom | geometry | Location Geometry (Polygon)