11. 空间关系

到目前为止,我们只使用了测量(ST_AreaST_Length)、序列化(ST_GeomFromText)或反序列化(ST_AsGML)几何图形的空间函数。这些函数的共同点是它们一次只能处理一个几何图形。

空间数据库之所以强大,是因为它们不仅存储几何图形,而且还能够比较几何图形之间的关系

诸如“哪些自行车架离公园最近?”或“地铁线路和街道的交汇点在哪里?”之类的问题只能通过比较代表自行车架、街道和地铁线路的几何图形来回答。

OGC 标准定义了以下一组方法来比较几何图形。

11.1. ST_Equals

ST_Equals(geometry A, geometry B) 测试两个几何图形的空间相等性。

_images/st_equals.png

如果两个相同类型的几何图形具有相同的 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_IntersectsST_CrossesST_Overlaps 测试几何图形的内部是否相交。

_images/st_intersects.png

ST_Intersects(geometry A, geometry B) 如果两个形状有任何共同的空间,即如果它们的边界或内部相交,则返回 t(TRUE)。

_images/st_disjoint.png

ST_Intersects 的反面是 ST_Disjoint(geometry A , geometry B)。如果两个几何图形是不相交的,则它们不相交,反之亦然。事实上,测试“不相交”通常比测试“不相交”更有效,因为相交测试可以进行空间索引,而不相交测试则不能。

_images/st_crosses.png

对于多点/多边形、多点/线字符串、线字符串/线字符串、线字符串/多边形和线字符串/多边形比较,ST_Crosses(geometry A, geometry B) 如果交集导致的几何图形的维数比两个源几何图形的最大维数少一,并且交集集位于两个源几何图形的内部,则返回 t(TRUE)。

_images/st_overlaps.png

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 用于测试两个几何图形是否在边界处接触,但不在内部相交。

_images/st_touches.png

ST_Touches(geometry A, geometry B) 如果两个几何图形的边界相交,或者只有一个几何图形的内部与另一个几何图形的边界相交,则返回 TRUE。

11.4. ST_Within 和 ST_Contains

ST_WithinST_Contains 用于测试一个几何图形是否完全在另一个几何图形内。

_images/st_within.png

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 米缓冲区内?”之类的问题很有用。您不必计算实际的缓冲区,只需测试距离关系即可。

_images/st_dwithin.png

再次使用我们的百老汇街地铁站,我们可以找到地铁站附近(距离地铁站 10 米以内)的街道。

SELECT name
FROM nyc_streets
WHERE ST_DWithin(
        geom,
        ST_GeomFromText('POINT(583571 4506714)',26918),
        10
      );
     name
--------------
   Wall St
   Broad St
   Nassau St

我们可以在地图上验证答案。百老汇街车站实际上位于华尔街、百老汇街和纳索街的交汇处。

_images/broad_st.jpg

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。