11. 空间关系¶
到目前为止,我们只使用了测量(ST_Area、ST_Length)、序列化(ST_GeomFromText)或反序列化(ST_AsGML)几何图形的空间函数。这些函数的共同点是它们一次只能处理一个几何图形。
空间数据库之所以强大,是因为它们不仅存储几何图形,而且还能够比较几何图形之间的关系。
诸如“哪些自行车架离公园最近?”或“地铁线路和街道的交汇点在哪里?”之类的问题只能通过比较代表自行车架、街道和地铁线路的几何图形来回答。
OGC 标准定义了以下一组方法来比较几何图形。
11.1. ST_Equals¶
ST_Equals(geometry A, geometry B) 测试两个几何图形的空间相等性。
如果两个相同类型的几何图形具有相同的 x,y 坐标值,即如果第二个形状等于(相同)第一个形状,则 ST_Equals 返回 TRUE。
首先,让我们从 nyc_subway_stations
表中检索一个点的表示形式。我们只取“Broad St”的条目。
SELECT name, geom
FROM nyc_subway_stations
WHERE name = 'Broad St';
name | geom
----------+---------------------------------------------------
Broad St | 0101000020266900000EEBD4CF27CF2141BC17D69516315141
然后,将几何图形表示形式重新插入 ST_Equals 测试中
SELECT name
FROM nyc_subway_stations
WHERE ST_Equals(
geom,
'0101000020266900000EEBD4CF27CF2141BC17D69516315141');
Broad St
注意
点的表示形式不是非常人性化可读(0101000020266900000EEBD4CF27CF2141BC17D69516315141
),但它是坐标值的精确表示形式。对于像相等性这样的测试,使用精确的坐标是必要的。
11.2. ST_Intersects、ST_Disjoint、ST_Crosses 和 ST_Overlaps¶
ST_Intersects、ST_Crosses 和 ST_Overlaps 测试几何图形的内部是否相交。
ST_Intersects(geometry A, geometry B) 如果两个形状有任何共同的空间,即如果它们的边界或内部相交,则返回 t(TRUE)。
ST_Intersects 的反面是 ST_Disjoint(geometry A , geometry B)。如果两个几何图形是不相交的,则它们不相交,反之亦然。事实上,测试“不相交”通常比测试“不相交”更有效,因为相交测试可以进行空间索引,而不相交测试则不能。
对于多点/多边形、多点/线字符串、线字符串/线字符串、线字符串/多边形和线字符串/多边形比较,ST_Crosses(geometry A, geometry B) 如果交集导致的几何图形的维数比两个源几何图形的最大维数少一,并且交集集位于两个源几何图形的内部,则返回 t(TRUE)。
ST_Overlaps(geometry A, geometry B) 用于比较两个相同维度的几何图形,如果它们的交集结果是一个与两者不同但维度相同的几何图形,则返回 TRUE。
让我们以百老汇街地铁站为例,使用 ST_Intersects 函数确定其周边区域。
SELECT name, ST_AsText(geom)
FROM nyc_subway_stations
WHERE name = 'Broad St';
POINT(583571 4506714)
SELECT name, boroname
FROM nyc_neighborhoods
WHERE ST_Intersects(geom, ST_GeomFromText('POINT(583571 4506714)',26918));
name | boroname
--------------------+-----------
Financial District | Manhattan
11.3. ST_Touches¶
ST_Touches 用于测试两个几何图形是否在边界处接触,但不在内部相交。
ST_Touches(geometry A, geometry B) 如果两个几何图形的边界相交,或者只有一个几何图形的内部与另一个几何图形的边界相交,则返回 TRUE。
11.4. ST_Within 和 ST_Contains¶
ST_Within 和 ST_Contains 用于测试一个几何图形是否完全在另一个几何图形内。
ST_Within(geometry A , geometry B) 如果第一个几何图形完全在第二个几何图形内,则返回 TRUE。ST_Within 测试的结果与 ST_Contains 正好相反。
ST_Contains(geometry A, geometry B) 如果第二个几何图形完全包含在第一个几何图形内,则返回 TRUE。
11.5. ST_Distance 和 ST_DWithin¶
一个非常常见的 GIS 问题是“找到距离这个东西 X 距离内的所有东西”。
ST_Distance(geometry A, geometry B) 计算两个几何图形之间的最短距离,并将其作为浮点数返回。这对于实际报告对象之间的距离很有用。
SELECT ST_Distance(
ST_GeometryFromText('POINT(0 5)'),
ST_GeometryFromText('LINESTRING(-2 2, 2 2)'));
3
为了测试两个对象是否在彼此的距离范围内,ST_DWithin 函数提供了一个索引加速的真/假测试。这对于诸如“有多少棵树在道路 500 米缓冲区内?”之类的问题很有用。您不必计算实际的缓冲区,只需测试距离关系即可。
再次使用我们的百老汇街地铁站,我们可以找到地铁站附近(距离地铁站 10 米以内)的街道。
SELECT name
FROM nyc_streets
WHERE ST_DWithin(
geom,
ST_GeomFromText('POINT(583571 4506714)',26918),
10
);
name
--------------
Wall St
Broad St
Nassau St
我们可以在地图上验证答案。百老汇街车站实际上位于华尔街、百老汇街和纳索街的交汇处。
11.6. 函数列表¶
ST_Contains(geometry A, geometry B): 当且仅当 B 的任何点都不在 A 的外部,并且 B 的内部至少有一个点在 A 的内部时,返回 true。
ST_Crosses(geometry A, geometry B): 如果提供的几何体有一些(但不是全部)内部点重合,则返回 TRUE。
ST_Disjoint(geometry A , geometry B): 如果几何体不“空间相交”(它们不共享任何空间),则返回 TRUE。
ST_Distance(geometry A, geometry B): 返回两个几何体在投影单位中基于空间参考的二维笛卡尔最小距离。
ST_DWithin(geometry A, geometry B, radius): 如果几何体彼此之间的距离(半径)在指定范围内,则返回 true。
ST_Equals(geometry A, geometry B): 如果给定的几何体表示相同的几何体,则返回 true。方向性被忽略。
ST_Intersects(geometry A, geometry B): 如果几何体/地理“空间相交”(共享任何空间部分),则返回 TRUE;如果它们不相交(它们是分离的),则返回 FALSE。
ST_Overlaps(geometry A, geometry B): 如果几何体共享空间,具有相同的维度,但没有完全包含在彼此内部,则返回 TRUE。
ST_Touches(geometry A, geometry B): 如果几何体至少有一个公共点,但它们的内部不交叉,则返回 TRUE。
ST_Within(geometry A , geometry B): 如果几何体 A 完全在几何体 B 内部,则返回 true。