跳到主要内容
版本:V1.0.0

空间关系函数

空间关系函数来测试两个几何值 g1g2 之间的关系,使用精确的对象形状。返回值 1 和 0 分别表示真和假,除了距离函数返回距离值。

seekdb 当前所支持的空间关系函数包括 ST_Intersects()ST_Contains()ST_Distance()ST_Distance_Sphere()ST_Within()ST_Crosses()ST_Overlaps()_ST_Touches()ST_Equals()

ST_Intersects

ST_Intersects() 函数返回 1 或 0 以指示 g1 是否在空间上与 g2 相交。语法如下:

ST_Intersects(g1, g2)

ST_Contains

ST_Contains() 函数返回 1 或 0 以指示 g1 是否完全包含 g2。语法如下:

ST_Contains(g1, g2)

ST_Distance

ST_Distance() 函数返回 g1g2 之间的距离,以几何参数的空间参考系统 (SRS) 的长度单位测量。语法如下:

ST_Distance(g1, g2 [, unit])

ST_Distance() 支持一个可选的 unit 参数,该参数指定返回距离值的线性单位。如果指定 unit 参数,则以可选 unit参数的单位测量。

如果任何参数在几何上无效,则结果可能返回任何数字,或者发生报错。如果中间或最终结果产生 NaN 或负数,则会报错 ER_GIS_INVALID_DATA。 示例如下:

SET @geo1 = ST_GeomFromText('POINT(1 1)', 4230);
Query OK, 0 rows affected (0.001 sec)

SET @geo2 = ST_GeomFromText('POINT(3 3)', 4230);
Query OK, 0 rows affected (0.001 sec)

SELECT ST_Distance(@geo1, @geo2);
+---------------------------+
| ST_Distance(@geo1, @geo2) |
+---------------------------+
| 313709.8158791322 |
+---------------------------+
1 row in set (0.001 sec)

SELECT ST_Distance(@geo1, @geo2, 'metre');
+------------------------------------+
| ST_Distance(@geo1, @geo2, 'metre') |
+------------------------------------+
| 313709.8158791322 |
+------------------------------------+
1 row in set (0.001 sec)

SELECT ST_Distance(@geo1, @geo2, 'foot');
+-----------------------------------+
| ST_Distance(@geo1, @geo2, 'foot') |
+-----------------------------------+
| 1029231.6793934782 |
+-----------------------------------+
1 row in set (0.001 sec)

ST_Distance_Sphere

ST_Distance_Sphere() 函数返回球体上 Point 或 MultiPoint 参数之间的最小球面距离,以米为单位。语法如下:

ST_Distance_Sphere(g1, g2 [, radius])

可选的 radius 参数应以米为单位。如果 radius 参数存在但不是正数,则会发生报错 ER_NONPOSITIVE_RADIUS;如果距离超出双精度数的范围,则会发生报错 ER_STD_OVERFLOW_ERROR

如果两个几何参数都是地理空间参考系统 (SRS) 中有效的 Point 或 MultiPoint 值,则返回值是球体上(半径为 radius)两个几何对象之间的最短距离。如果省略,则默认半径等于平均半径,定义为 (2a+b)/3,其中 a 是 SRS 的长半轴,b 是短半轴。

ST_Distance_Sphere() 支持的几何参数组合是 Point 和 Point, 或者 Point 和 MultiPoint(以任何参数顺序)。如果至少有一个几何对象既不是 Point 也不是 MultiPoint,并且其 SRID 为 0,则会发生报错 ER_NOT_IMPLEMENTED_FOR_CARTESIAN_SRS。如果至少有一个几何既不是 Point 或者 MultiPoint,并且其 SRID 指的是地理 SRS,则会发生报错 ER_NOT_IMPLEMENTED_FOR_GEOGRAPHIC_SRS。如果任何几何图形引用投影的 SRS,则会发生报错 ER_NOT_IMPLEMENTED_FOR_PROJECTED_SRS

示例如下:

SET @pt1 = ST_GeomFromText('POINT(0 0)');
Query OK, 0 rows affected (0.001 sec)

SET @pt2 = ST_GeomFromText('POINT(180 0)');
Query OK, 0 rows affected (0.001 sec)

SELECT ST_Distance_Sphere(@pt1, @pt2);
+--------------------------------+
| ST_Distance_Sphere(@pt1, @pt2) |
+--------------------------------+
| 20015042.813723423 |
+--------------------------------+
1 row in set (0.001 sec)

ST_IsValid

如果 ST_IsValid() 函数的参数几何有效,则返回 1;如果参数几何无效,则返回 0。几何有效性由 OGC 规范定义。语法如下:

ST_IsValid(g)

唯一有效的空几何对象以空几何对象集合值的形式表示。在这种情况下,ST_IsValid() 返回 1,不支持 GIS EMPTY 值,例如 POINT EMPTY

SET @ls_test1 = ST_GeomFromText('LINESTRING(0 0,-0.00 0,0.0 0)');
Query OK, 0 rows affected (0.001 sec)

SET @ls_test2 = ST_GeomFromText('LINESTRING(0 0, 1 1)');
Query OK, 0 rows affected (0.001 sec)

SELECT ST_IsValid(@ls_test1);
+------------------+
| ST_IsValid(@ls1) |
+------------------+
| 0 |
+------------------+
1 row in set (0.001 sec)

SELECT ST_IsValid(@ls_test2);
+------------------+
| ST_IsValid(@ls2) |
+------------------+
| 1 |
+------------------+
1 row in set (0.001 sec)

ST_Within

ST_Within() 返回 1 或 0 以指示 g1 在空间上是否在 g2 内。与 ST_Contains() 具有相反的关系。语法如下:

ST_Within(g1, g2)

ST_Crosses

ST_Crosses 函数返回 1 或 0 以指示 g1 是否在空间上与 g2 交叉。如果 g1g2 交叉,则返回 1;如果 g1 和 g2 不交叉,则返回 0。且 ST_Crosses 函数支持空间索引。

ST_Crosses(g1, g2)ST_Intersects(g1, g2) 都是空间关系函数,用于判断两个几何对象在空间上的关系,但它们的定义和用途略有不同。

  • ST_Intersects(g1, g2) 函数用于确定两个几何对象是否在空间上相交,意味着它们共享至少一个公共点(这包括边界和内部)。

    只要两个对象有任何重叠的部分,无论是点、线还是面,ST_Intersects(g1, g2) 都返回 1。

  • ST_Crosses(g1, g2) 函数用于确定两个几何对象是否“交叉”,在几何学中有特定的定义:一个对象必须部分内部穿过另一个对象的内部。

具体来说,对于两个线几何对象,当它们在两个点以上相交并在内部相交时,ST_Crosses(g1, g2) 返回 1;对于线和面几何对象,当线穿过面的内部时,ST_Crosses(g1, g2) 返回 1。

ST_Intersects(g1, g2) 不同,ST_Crosses(g1, g2) 并不考虑两个对象的完全重叠或边界触摸情况。

ST_Intersects(g1, g2) 检测两个几何对象是否有任何类型的交集,而 ST_Crosses(g1, g2) 专门检测一个对象是否穿过另一个对象。例如,如果你想知道一条路是否穿过一块土地,使用 ST_Crosses(g1, g2);如果你需要找出所有覆盖或触及该土地的路线,则使用 ST_Intersects(g1, g2)

语法如下:

ST_Crosses(g1,g2)

示例如下:

select st_crosses(st_geomfromtext('LINESTRING(1 1, 11 11)'), st_geomfromtext('POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))'));

在这个示例中,ST_Crosses 判断一个线性几何对象(在这个例子中是从点 (1,1) 到点 (11,11) 的直线)是否穿过了一个多边形几何对象(这里是一个由点 (0,0), (0,10), (10,10), (10,0) 和 (0,0) 构成的正方形)。返回结果是 1,表示线穿过了多边形。

返回结果如下:

+------------------------------------------------------------------------------------------------------------------+
| st_crosses(st_geomfromtext('LINESTRING(1 1, 11 11)'), st_geomfromtext('POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))')) |
+------------------------------------------------------------------------------------------------------------------+
| 1 |
+------------------------------------------------------------------------------------------------------------------+
1 row in set (0.001 sec)

ST_Overlaps

ST_Overlaps(g1,g2) 函数返回 1 或 0 以确定两个几何对象 g1g2 是否在空间上部分重叠,但并不完全互相包含。如果 g1g2 重叠,则返回 1;如果 g1 和 g2 不重叠或者有一个完全包含另一个,则返回 0。且 ST_Overlaps(g1,g2) 函数支持空间索引。

对于两个线几何对象而言,当它们共享一段线段,但没有一条线完全包含另一条线,ST_Overlaps(g1,g2) 返回 1。 对于面几何对象(如多边形),当两个多边形至少部分地重叠,同时每个多边形都有一部分不与另一个重叠,ST_Overlaps(g1,g2) 返回 1。

语法如下:

ST_Overlaps(g1,g2)

示例如下:

SELECT ST_OVERLAPS(ST_GEOMFROMTEXT('POLYGON((0 0,0 10,10 10,10 0,0 0,0 0),(2 2,2 4,4 4,4 2,2 2))'), ST_GEOMFROMTEXT('POLYGON((0 0,0 5,5 5,5 0,0 0))'));

在这个示例中,ST_Overlaps 函数判断两个多边形是否重叠。第一个多边形 POLYGON((0 0,0 10,10 10,10 0,0 0,0 0),(2 2,2 4,4 4,4 2,2 2)) 是一个 10 ✖️ 10 的正方形,内部有一个 2✖️2 的洞(空间内的小正方形),而第二个多边形 POLYGON((0 0,0 5,5 5,5 0,0 0)) 是一个 5✖️5 的正方形,位于第一个多边形的左下角。第二个多边形与第一个多边形的内部区域重叠但又不被完全包含,那么 ST_Overlaps 函数返回 1。

返回结果如下:

+-------------------------------------------------------------------------------------------------------------------------------------------------+
| ST_OVERLAPS(ST_GEOMFROMTEXT('POLYGON((0 0,0 10,10 10,10 0,0 0,0 0),(2 2,2 4,4 4,4 2,2 2))'), ST_GEOMFROMTEXT('POLYGON((0 0,0 5,5 5,5 0,0 0))')) |
+-------------------------------------------------------------------------------------------------------------------------------------------------+
| 1 |
+-------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.001 sec)

_ST_Touches

_ST_Touches(geometry A, geometry B) 函数用来判断两个几何对象 AB 边界是否至少有一个共同点,且内部不相交。且 _ST_Touches(geometry A, geometry B) 函数支持空间索引。

这里需要注意的是,如果两个几何对象都是点 Point 类型,那么 _ST_Touches(geometry A, geometry B) 函数将返回 0。这是因为点几何对象没有边界,所以两个点不能被认为是“接触”的;它们要么是相同的(即位置完全一致),要么是完全独立的。

语法如下:

_ST_Touches(geometry A, geometry B)

示例如下:

SELECT _ST_Touches(st_geomfromtext('LINESTRING(0 0, 1 1, 0 2)'), st_geomfromtext('POINT(0 2)'));

在这个示例中,_ST_Touches 函数用来确定一个线性几何对象(LineString)和一个点几何对象(Point)是否在空间上相接触。因为点 (0 2) 是线 (0 0, 1 1, 0 2) 的终点,返回结果 1 表明这两个对象相接触。

返回结果如下:

+------------------------------------------------------------------------------------------+
| _ST_Touches(st_geomfromtext('LINESTRING(0 0, 1 1, 0 2)'), st_geomfromtext('POINT(0 2)')) |
+------------------------------------------------------------------------------------------+
| 1 |
+------------------------------------------------------------------------------------------+
1 row in set (0.001 sec)

ST_Equals

ST_Equals(geometry A, geometry B) 函数用于判断两个几何对象 AB 在空间结构上是否相等,即这两个几何对象包含相同的点集,并且每个点在两个几何对象中的相对位置是一样的,但这个函数不要求点的顺序必须完全相同。

换句话说,如果两个几何对象占据了完全相同的空间范围,并且它们的形状和尺寸完全一致,那么 ST_Equals 会返回 1。如果两个几何对象在任何方式上都不相同(即使只是大小或形状上的微小差异),ST_Equals 函数将返回 0。

ST_Equals(geometry A, geometry B) 函数支持空间索引。

语法如下:

ST_Equals(geometry A, geometry B);

示例如下:

SELECT ST_Equals(ST_GeomFromText('LINESTRING(0 0, 10 10)'), ST_GeomFromText('LINESTRING(0 0, 5 5, 10 10)'));

在这个示例中,ST_Equals 函数用来判断两条线是否空间上相等。第一条线是由 (0 0) 直接到 (10 10) 的简单直线。第二条线也从 (0 0) 到 (10 10),但通过了一个中间点 (5 5)。尽管第二条线包含了一个额外的顶点,但因为两条线在空间上覆盖了相同的点集,ST_Equals 判断这两条线在空间结构上是相等的,返回结果 1。

返回结果如下:

+------------------------------------------------------------------------------------------------------+
| ST_Equals(ST_GeomFromText('LINESTRING(0 0, 10 10)'), ST_GeomFromText('LINESTRING(0 0, 5 5, 10 10)')) |
+------------------------------------------------------------------------------------------------------+
| 1 |
+------------------------------------------------------------------------------------------------------+
1 row in set (0.001 sec)

参数的注意事项

空间关系函数中几何参数的返回值为非 NULL,以下情况除外:

  • 如果任何参数为 NULL 或任何几何参数为空几何,则返回值为 NULL

  • 如果任何几何参数的语法格式不正确,则会报错 ER_GIS_INVALID_DATA

  • 如果任何几何参数属于未定义的空间参考系统 (SRS),则会报错 ER_SRS_NOT_FOUND

  • 对于采用多个几何参数的函数,如果这些参数不在同一个 SRS 中,则会报错 ER_GIS_DIFFERENT_SRIDS

  • 如果任何几何参数无效,则结果可能为 True 或者 False,或者发生错误。

  • 对于地理 SRS 几何参数,如果任何参数的经度或纬度超出范围(范围以度为单位,如果 SRS 使用其他单位,则范围使用其单位中的相应值),则会发生错误:

    • 如果经度值不在范围内(-180、180],则会报错 ER_GEOMETRY_PARAM_LONGITUDE_OUT_OF_RANGE

    • 如果纬度值不在 [−90, 90] 范围内,则会报错 ER_GEOMETRY_PARAM_LATITUDE_OUT_OF_RANGE

  • 空间计算的坐标精度不能超过(-9.223e18, 9.223e18),否则会报错:

    SELECT ST_CONTAINS(ST_GEOMFROMTEXT('MULTIPOLYGON(((0 1e+19,0 0,0 0,0 1e+19)))'), ST_GEOMFROMTEXT('POLYGON((0 0,0 0,0 0,0 0))'));
    ERROR 1690 (22003): coordinate value is out of range in 'st_contains'