PostGIS系列课程之空间关系

27 篇文章 8 订阅

本文将逐一介绍空间关系的定义及使用。

空间关系

PostGIS的强大功能是能够计算Geometry之间的空间关系。

通过比较代表自行车位置,街道和地铁线的Geometry 形状,可以回答诸如“距公园最近的自行车架在哪里?”或“地铁线与街道的交叉点在哪里?”之类的问题。

PostGIS提供了Open Geospatial Consortium / SQL-MM标准中定义的全套空间关系功能。这些功能允许测试空间(拓扑)关系和基于Geometry 之间的距离的关系。

大多数关系函数接受两个Geometry 作为输入,并以布尔值形式返回指定关系的值。 您可以使用以下查询尝试此操作:

SELECT ST_Intersects('POINT(1 1)', 'LINESTRING(1 1, 2 2)');

通常,布尔关系函数在SQL查询的“ WHERE”子句中使用(称为“空间过滤器”)。您将在本课程的稍后部分看到使用NYC示例数据集的示例。

它们还用于“ JOIN … ON”子句中,以指定“空间连接”。

ST_Equals

ST_Equals(geometry A,geometry B) 测试两个Geometry 的空间相等性。如果两个相同类型的Geometry 具有相同的形状,则 *返回TRUE。通常仅当它们具有相同的x,y坐标值时才如此。

ST_Equals

例如,让我们使用“ nyc_subway_stations”表中的点Geometry 。我们将查询Broad St站点的特征,并使用精确的数据表示形式(称为WKB)和更具可读性的文本格式(称为WKT)来显示它。 ):

SELECT name, geom, ST_AsText(geom) From nyc_subway_stations WHERE name = 'Broad St';
-----------------------------------
   name     |       geom                                         |      st_astext
   ----------+----------------------------------------------------+-----------------------
   Broad St | 0101000020266900000EEBD4CF27CF2141BC17D69516315141 | POINT(583571 4506714)

Geometry 值可以与“ ST_Equals”测试一起使用以检索原始记录:

SELECT name  From nyc_subway_stations  WHERE ST_Equals(geom, '0101000020266900000EEBD4CF27CF2141BC17D69516315141');
----------------------------------
Broad St

注意:点的WKB数据格式不是可读的,但是它是坐标值的精确表示。 对于相等性之类的测试,必须使用确切的值。

ST_Intersects, ST_Disjoint

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

ST_Intersects

让我们乘坐Broad Street地铁站,并使用 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_Geom FromText('POINT(583571 4506714)',26918));
------------------------------
       name        | boroname-------------------+-----------Financial District | Manhattan
ST_Disjoint

ST_Disjoint(geometry A,geometry B)ST_Intersects
相反。如果两个Geometry 不相交,则 *它们不相交,反之亦然。实际上,测试“ not_nots”通常更有效 “相交”而不是“不相交”,因为相交测试可以在空间上建立索引,而相交测试则 *不能。

ST_Disjoint

ST_Within, ST_Contains

ST_WithinST_Contains
是一对具有相关但相反含义的函数。

如果第一个Geometry 完全在第二个Geometry 内,并且它们具有至少一个共同的内部点,则 * ST_Within(geometry A,geometry B) 返回TRUE。

ST_Within

如果第一个Geometry 完全包含第二个Geometry ,并且它们具有至少一个共同的内部点,则 ST_Contains(geometry A,geometry B) 返回TRUE。

ST_Contains 测试 ST_Within 的相反关系,这意味着

  ST_Contains(A,B) = ST_Within(B, A)
ST_Covers, ST_CoveredBy

PostGIS提供了另一对用于测试密闭度的功能,即 ST_CoversT_CoveredBy

这些函数不是SQL / MM标准的一部分,但是它们解决了 ST_ContainsST_Within 的微妙之处,这有时会引起问题。ST_Contains 的标准定义有一个怪异,即多边形不包含沿其边界(在边界内)的线串。

SELECT ST_Contains('POLYGON ((0 1, 1 1, 1 0, 0 0, 0 1))'::geometry,'LINESTRING (0 0, 1 0)'::geometry );
---------------------------------
  f

定义了 ST_Covers(geometry A,geometry B) ,以便不会发生此异常,该异常通常更符合您的期望。

SELECT ST_Covers('POLYGON ((0 1, 1 1, 1 0, 0 0, 0 1))'::geometry,'LINESTRING (0 0, 1 0)'::geometry );
---------------------------------
t

ST_CoveredBy(Geometry A,Geometry B)ST_Covers 具有相反的含义,因此:

  ST_Covers(A,B) = ST_CoveredBy(B, A)
SELECT ST_CoveredBy('LINESTRING (0 0, 1 0)'::geometry,'POLYGON ((0 1, 1 1, 1 0, 0 0, 0 1))'::geometry );
---------------------------------
  t
ST_Crosses, ST_Overlaps, ST_Touches

ST_CrossesST_OverlapsST_Touches 是较少使用的函数,用于测试Geometry 之间空间关系的特定方面。

ST_Crosses(geometry A,geometry B) 测试交集是否产生尺寸小于两个源Geometry 的最大维且交集位于两个源Geometry 内部的Geometry ,仅适用于点/多边形, 点/线串,线串/线串和线串/多边形比较。

ST_Crosses

例如,这测试一条线是否穿过多边形:

SELECT ST_Crosses('POLYGON ((100 100, 100 200, 200 200, 200 100, 100 100))','LINESTRING (50 150, 150 150)');
---------------------------------
t

ST_Overlaps(Geometry A,Geometry B) 比较相同维度的两个Geometry ,如果它们的交集导致二者的年龄测量结果不同但尺寸相同,则 *返回true。

ST_Touches(Geometry A,Geometry B) 测试两个Geometry 的边界是否相交,或者仅Geometry 的一个内部与另一个Geometry 的边界相交。

ST_Relate

前几节中的空间关系函数是更通用的函数 ST_Relate 的特例。它使用维数扩展的9交点模型(DE-9IM)计算两个Geometry 之间的完整拓扑关系。 表示为文本代码,用于指定每个输入Geometry 的内部,边界和外部的交点的尺寸。由于有九种组合,因此代码具有符号,每个符号具有交集尺寸的值(012)或F(如果没有交叉点)。

例如,与多边形相交的线的交点的代码为“ 1020F1102”:

SELECT ST_Relate('POLYGON ((100 100, 100 200, 200 200, 200 100, 100 100))','LINESTRING (50 150, 150 150)');
---------------------------------
1020F1102

特定的空间关系是通过将DE-9IM代码与指定所需关系的“图案遮罩”进行比较来确定的。除DE-9IM符号外,遮罩还可以包含“ T”(表示任何尺寸的交集)和“ *”(表示一个维)。 通配符或“无关”值。例如,多边形/线格“ Crosses”的图案遮罩为“ T** T”。

对于上述情况,可以通过在掩码中使用 T_Relate 来确认这一点:

SELECT ST_Relate('POLYGON ((100 100, 100 200, 200 200, 200 100, 100 100))','LINESTRING (50 150, 150 150)','T* ***T**' );
---------------------------------
t

通常使用命名关系函数会更方便,但是在某些情况下,不需要提供关系的函数,例如GIS数据结构称为``多边形覆盖率’’(polygonal coverage *)是多边形的集合,其中没有多边形 有相交的内部。 这由矩阵模式“ F******”表示。在这种情况下,没有命名空间关系函数测试,因此必须使用“ ST_Relate”进行测试。

这是两个内部相交的多边形,因此不会形成多边形覆盖范围:

SELECT ST_Relate('POLYGON ((100 100, 100 200, 200 200, 200 100, 100 100))','POLYGON ((250 250, 250 150, 150 150, 150 250, 250 250))','F******' );
---------------------------------
f

这是两个确实形成有效多边形覆盖率的多边形:

SELECT ST_Relate('POLYGON ((100 100, 100 200, 200 200, 200 100, 100 100))','POLYGON ((300 100, 200 100, 200 200, 300 200, 300 100))','F******' );
---------------------------------
t
ST_Distance, ST_DWithin

常见的GIS问题是“在其他物料的distanceX范围内找到所有物料”。

T_Distance(geometry A,geometry B) 函数计算两个Geometry 之间的最短距离,并将其作为浮点数返回。 这对于报告对象之间的实际距离很有用。

SELECT ST_Distance(ST_Geometry FromText('POINT(0 5)'),ST_Geometry FromText('LINESTRING(-2 2, 2 2)'));
---------------------------------
    3

注意:返回的距离值以输入Geometry 的空间参考系为单位

ST_DWithin

为了测试两个物体是否在给定的距离内, T_DWithin 函数提供了索引加速的真/假测试。这对于诸如“在道路的500米缓冲区内有几棵树? ”。 您不必计算实际的缓冲区,只需要测试距离关系即可。

再次使用Broad Street地铁站,我们可以找到地铁站附近(10米以内)的街道:

SELECT name From nyc_streets WHERE ST_DWithin(geom,ST_Geom FromText('POINT(583571 4506714)',26918),10);
---------------------------------
    name
    --------------
    Wall StBroad StNassau St

我们可以在地图上验证答案。 宽街站实际上位于华尔街,宽街和拿骚街的交汇处。

Broad Street

Exercises

以下是使用NYC数据集表的其他一些查询:

  • nyc_census_blocks
    • blkid, popn_total, boroname, geom
  • nyc_streets
    • name, type, geom
  • nyc_subway_stations
    • name, geom
  • nyc_neighborhoods
    • name, boroname, geom

名为“ Atlantic Commons”的街道的Geometry 值是多少?

SELECT ST_AsText(geom) From nyc_streets WHERE name = 'Atlantic Commons';
---------------------------------
MULTILINESTRING((586781.701577724 4504202.15314339,586863.51964484 4504215.9881701))

大西洋公域位于哪个街区和自治市镇?

SELECT name, boroname From nyc_neighborhoods WHERE ST_Intersects(geom,ST_Geom FromText('LINESTRING(586782 4504202,586864 4504216)', 26918));
---------------------------------
    name    | boroname-
    -----------+----------
    Fort Green | Brooklyn

“嘿,您为什么从’MULTILINESTRING’变为’LINESTRING’?” 它们在空间上描述的形状相同,因此从单项多Geometry 到单例可以节省一些击键。

更重要的是,我们还对坐标进行了四舍五入,以使其更易于阅读,这实际上改变了结果:我们无法使用ST_Touches()谓词来确定哪些道路加入了Atlantic Commons,因为坐标不再完全相同 。

大西洋共同体与哪些街道相连?

SELECT name From nyc_streets WHERE ST_DWithin(geom,ST_Geom FromText('LINESTRING(586782 4504202,586864 4504216)', 26918),0.1);
---------------------------------
     name
     ------------------
     Cumberland StAtlantic Commons

大约有多少人生活在(大西洋公地50米以内)

SELECT Sum(popn_total) From nyc_census_blocks WHERE ST_DWithin(geom,ST_Geom FromText('LINESTRING(586782 4504202,586864 4504216)', 26918),50);
---------------------------------
1438
总结

现在,您已经了解了PostGIS如何支持全套标准空间和距离关系功能。

有关空间关系和“尺寸扩展的9交叉模型”(DE-9IM)的更多技术细节,请访问[这里](https://en.wikipedia.org/wiki/DE-9IM)。

关系函数及其定义总结如下:

空间关系函数

ST_Contains(geometry A,geometry B)
当且仅当B的点不位于A的外部且B的内部的至少一个点位于A的内部时,才返回true。

ST_CoveredBy(geometryA,geometryB)
当且仅当A的点不位于B的外部时,才返回true。换句话说,A完全位于B的内部。 T_Covers 的相反。

ST_Covers(geometryA,geometryB)
当且仅当B的点不位于A的外部时,才返回true。换句话说,B完全位于A的内部。 T_CoveredBy 的反面。

ST_Crosses(geometry A,geometry B)
如果提供的Geometry 具有一些但不是全部内部点,则 *返回true。

ST_Disjoint(geometry A,geometry B)
如果Geometry 在空间上不相交-即它们不共享任何点,则 *返回true。ST_Intersects 的反函数。

ST_Equals(geometry A,geometry B)
如果Geometry 形状完全相同,则 *返回true。不考虑方向性。

ST_Intersects(geometryA,geometryB)
如果geometry“空间相交”,即,如果它们至少有一个共同的空间点,则 *返回true。ST_Disjoint 的反函数。

ST_Overlaps(geometry A,geometry B)
如果Geometry 共享空间,具有相同尺寸但彼此之间不完全包含,则 *返回true。

ST_Touches(geometryA,geometryB)
如果geometry至少有一个公共点,但它们的内部不相交,则 *返回true。

ST_Within(geometry A,geometry B)
如果Geometry A完全在Geometry B之内,则 *返回true。 T_Contains 的反之。

相关功能

ST_Relate(Geometry A,Geometry B)
返回DE-9IM代码,指示A和B之间的完整拓扑关系。

ST_Relate(Geometry A,Geometry B,文本蒙版)
测试Geometry A和B是否具有与给定蒙版匹配的DE-9IM代码。

距离关系功能

ST_Distance(geometryA,geometryB)
返回两个geometry之间的二维笛卡尔最小距离,以空间参考系统为单位。

ST_DWithin(Geometry A,Geometry B,半径)
如果两个Geometry 在彼此的指定距离(半径)之内,则 *返回true。

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

丷丩

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值