进阶 postgis.net 2026-10-09 21:31:24 · 6 阅读

第6章 PostGIS 技巧:用更快的路径求几何交集

### 更快的求交方式 执行 ST_Intersection 往往比关系判断(如 ST_Intersects、ST_CoveredBy 和 ST_Within)慢得多。 在许多情况下,无需真正计算交集,就能知道两个几何体的交集结果。在这种情况下,可以跳过代价高昂的 ST_Intersection 调用。例如: - 几何体 a 被几何体 b 覆盖 -> 交集即为几何体 a - 几何体 b 被几何体 a 覆盖 -> 交集即为几何体 b - 几何体 a 与几何体 b 不相交 -> 交集为空几何体

这类问题经常出现,正如在 StackExchange 讨论“在 PostGIS 中实现 ArcGIS 速度”中所述。

### 示例 在这个练习中,我们要提取每个地块落在社区区域内的部分。 与 StackExchange 上的例子不同,这里使用 ST_CoveredBy 而非 ST_Within 进行判断。这两者构造相似,区别在于 ST_CoveredBy 允许几何体完全位于另一个几何体边界内,且计算速度通常略快于 ST_Within。 如果你正在比较线状要素(例如道路的哪部分落在县内),这种细微差别会变得更为重要,详见“OGC Covers 空间判断的细微差别”。

```sql 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 排除地块与社区仅边界相接的情况,如下所示:

```sql 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) ); ```

评论 (0)