取得相交部分的最快方式
執行 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 Covers Spatial 的細微差別 一文中詳述,某筆道路中的哪個區段在一個縣中),這種細微差別將變得更為重要。
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) );