以更快的速度获取交集
执行 ST_Intersection
的速度远低于关系检查,例如 ST_Intersects
、 ST_CoveredBy
和 ST_Within
。在许多情况下,您知道 2 个几何图形的交集,而无需实际计算交集。在这些情况下,您可以跳过代价高昂的 ST_Intersection
调用。这种情况如下
- 几何图形 a 被几何图形 b 覆盖 -> 交集是几何图形 a
- 几何 b 被几何 a 覆盖 -> 交集是几何 b
- 几何 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) );