intersection is geometry a geometry b is covered by geometry a -> intersection is geometry b geometry a does not intersect geometry b -> intersection is empty geometry This kind of question comes up a lot: As discussed in stackexchange Acquiring ArcGIS speed in PostGIS"> 更快速地获取交点 | PostGIS - PostGIS 空间数据库 intersection is geometry a geometry b is covered by geometry a -> intersection is geometry b geometry a does not intersect geometry b -> intersection is empty geometry This kind of question comes up a lot: As discussed in stackexchange Acquiring ArcGIS speed in PostGIS"> intersection is geometry a geometry b is covered by geometry a -> intersection is geometry b geometry a does not intersect geometry b -> intersection is empty geometry This kind of question comes up a lot: As discussed in stackexchange Acquiring ArcGIS speed in PostGIS">
PostGIS
切换深色/浅色/自动模式 - PostGIS 空间数据库 切换深色/浅色/自动模式 - PostGIS 空间数据库 切换深色/浅色/自动模式 - PostGIS 空间数据库 返回主页 - PostGIS 空间数据库

以更快的速度获取交集

执行 ST_Intersection 的速度远低于关系检查,例如 ST_IntersectsST_CoveredByST_Within 。在许多情况下,您知道 2 个几何图形的交集,而无需实际计算交集。在这些情况下,您可以跳过代价高昂的 ST_Intersection 调用。这种情况如下

  1. 几何图形 a 被几何图形 b 覆盖 -> 交集是几何图形 a
  2. 几何 b 被几何 a 覆盖 -> 交集是几何 b
  3. 几何 a 不与几何 b 相交 -> 交集是空几何

这类问题经常出现:正如 stackexchange 中所讨论的 在 PostGIS 中获得 ArcGIS 般的速度

示例

对于此练习,我们将获取属于某个社区的每个地块的部分。与 stack exchange 不同,我们将使用 ST_CoveredBy 而不是 ST_Within 检查。这两个构造类似,但 ST_CoveredBy 允许几何完全位于另一个几何的边界内,并且计算速度往往比 ST_Within 快一些。如果您正在比较线串,例如道路的哪一部分属于某个县,则这种细微差别变得更加重要,如 OGC 覆盖空间的细微差别 中所述。

SELECT p.parcel_id, n.nei_name
 , CASE
   WHEN ST_CoveredBy(p.geom, n.geom)
   THEN p.geom
   ELSE
    ST_Multi(
      ST_Intersection(p.geom,n.geom)
      ) END As geom
 FROM parcels As p
   INNER JOIN neighborhoods As n
    ON ST_Intersects(p.geom, n.geom);

在此特定情况下,我们可能希望排除地块仅与社区接壤的情况(在空间中表示为 touches)。我们不会真正认为接壤的地块在社区中占有任何部分,尽管它与社区相交。因此,一个稍微复杂但更准确的说法是使用 ST_Touches 排除地块与社区接壤的情况。

SELECT p.parcel_id, n.nei_name
 , CASE
   WHEN ST_CoveredBy(p.geom, n.geom)
   THEN p.geom
   ELSE
    ST_Multi(
      ST_Intersection(p.geom,n.geom)
      ) END As geom
 FROM parcels As p
   INNER JOIN neighborhoods As n
    ON (ST_Intersects(p.geom, n.geom)
      AND Not ST_Touches(p.geom, n.geom) );