26. 維度擴展 9 交集模型

維度擴展 9 交集模型」(DE9IM) 是用於對兩個空間物件互動方式建模的架構。

首先,每個空間物件都有下列內容

  • 內部

  • 邊界

  • 外部

對於多邊形而言,內部、邊界和外部都很明顯

_images/de9im1.jpg

內部由環界定;邊界就是環本身;外部則為平面上其他所有部分。

對於線形特徵而言,內部、邊界和外部並不那麼明顯

_images/de9im2.jpg

內部由兩端界定的線段部分;邊界就是線形特徵的兩端,而外部則為平面上其他所有部分。

對於點而言,情況更為奇特:內部就是該點;邊界是空集合,而外部則為平面上其他所有部分。

使用這些內部、外部和邊界的定義,可以按照物體對內部/邊界/外部之間的九種可能交集的維度特性來描述任何空間特徵配對間的關係。

_images/de9im3.jpg

對於上述範例中的多邊形,內部的交集為 2 維度區域,因此矩陣中該部分會填入「2」。邊界只會在點相遇,為 0 維度,因此矩陣中該部分會填入 0。

如果各個組件之間沒有交集,則矩陣中的方格會填入「F」。

以下提供另一個範例,一條線段部分進入多邊形

_images/de9im4.jpg

互動的 DE9IM 矩陣如下

_images/de9im5.jpg

請注意,兩個物件的邊界實際上並未交集(線段的端點與多邊形的內部互動,而不是邊界,反之亦然),因此 B/B 儲存格會填入「F」。

採用視覺方式填入 DE9IM 矩陣很有趣,但如果電腦可以執行這項工作會更好,而這就是 ST_Relate 函數的用途。

先前的範例可以使用簡單的方塊和線段簡化,與我們的多邊形和線段具有相同的空間關係

_images/de9im6.jpg

我們可以在 SQL 中產生 DE9IM 資訊

SELECT ST_Relate(
         'LINESTRING(0 0, 2 0)',
         'POLYGON((1 -1, 1 1, 3 1, 3 -1, 1 -1))'
       );

答案 (1010F0212) 與我們視覺計算的相同,不過是傳回為 9 個字元的字串,其將表格的第一列、第二列及第三列附加在一起。

101
0F0
212

然而,DE9IM 矩陣的力量不在於產生它們,而是用它們做為配對的關鍵,找出幾何對彼此具有相當特定關係。

CREATE TABLE lakes ( id serial primary key, geom geometry );
CREATE TABLE docks ( id serial primary key, good boolean, geom geometry );

INSERT INTO lakes ( geom )
  VALUES ( 'POLYGON ((100 200, 140 230, 180 310, 280 310, 390 270, 400 210, 320 140, 215 141, 150 170, 100 200))');

INSERT INTO docks ( geom, good )
  VALUES
        ('LINESTRING (170 290, 205 272)',true),
        ('LINESTRING (120 215, 176 197)',true),
        ('LINESTRING (290 260, 340 250)',false),
        ('LINESTRING (350 300, 400 320)',false),
        ('LINESTRING (370 230, 420 240)',false),
        ('LINESTRING (370 180, 390 160)',false);

假設我們有個資料模型包含湖泊碼頭,假設碼頭必須位於湖泊內,且必須在某一端接觸到圍繞的湖泊邊界。我們能否找出資料庫中所有符合這個規則的碼頭?

_images/de9im7.jpg

我們的合法碼頭具有下列特性

  • 內部具有與湖泊內部呈線性(1D)交集

  • 邊界具有與湖泊內部呈點(0D)交集

  • 邊界具有與湖泊邊界呈點(0D)交集

  • 內部沒有與湖泊外圍(F)相交

所以其 DE9IM 矩陣如下

_images/de9im8.jpg

所以,要找出所有合法的碼頭,我們需要找出所有和湖泊相交的碼頭(用於我們聯結鍵的潛在項目的超集),然後找出具有合法關聯模式的那個集合中的所有碼頭。

SELECT docks.*
FROM docks JOIN lakes ON ST_Intersects(docks.geom, lakes.geom)
WHERE ST_Relate(docks.geom, lakes.geom, '1FF00F212');

-- Answer: our two good docks

請注意使用ST_Relate的三參數版本,如果模式匹配則傳回 True,如果不匹配則傳回 False。對於像這樣定義完整的模式,不需要使用三參數版本 – 我們只需要用字串相等運算子即可。

然而,對於較寬鬆的模式搜尋,三參數版本允許在模式字串中使用替換字元

  • “*” 表示「此儲存格中的任何值均可接受」

  • “T” 表示「任何非假值(0、1 或 2)均可接受」

因此,例如,一個我們未包含在範例圖形中的碼頭,是一個與湖泊邊界具有二維交集的碼頭

INSERT INTO docks ( geom, good )
  VALUES ('LINESTRING (140 230, 150 250, 210 230)',true);
_images/de9im9.jpg

如果我們要將此案例包含在我們的「合法」碼頭集合中,我們需要變更查詢中的關聯模式。特別是,碼頭內部與湖泊邊界的交集現在可以是 1(我們的新案例)或 F(我們原始的案例)。因此,在模式中我們使用「*」萬用字元。

_images/de9im10.jpg

SQL 如下所示

SELECT docks.*
FROM docks JOIN lakes ON ST_Intersects(docks.geom, lakes.geom)
WHERE ST_Relate(docks.geom, lakes.geom, '1*F00F212');

-- Answer: our (now) three good docks

確認先前的範例中較嚴格的 SQL 傳回新的碼頭。

26.1. 資料品質測試

TIGER 資料在製作時經過仔細的品質控管,因此我們預期資料能符合嚴格標準。例如:沒有任何普查區塊應與任何其他普查區塊重疊。我們可以對此進行測試嗎?

_images/de9im11.jpg

當然可以!

SELECT a.gid, b.gid
FROM nyc_census_blocks a, nyc_census_blocks b
WHERE ST_Intersects(a.geom, b.geom)
  AND ST_Relate(a.geom, b.geom, '2********')
  AND a.gid != b.gid
LIMIT 10;

-- Answer: 10, there's some funny business

同樣地,我們預期道路資料都已標示路徑終點。也就是說,我們預期交會僅會發生在線段的終點,而不是中點。

_images/de9im12.jpg

我們可以透過尋找會相交的街道(所以我們有一個聯結)來測試,但邊界之間的相交處並非零維(亦即端點並未接觸到)

SELECT a.gid, b.gid
FROM nyc_streets a, nyc_streets b
WHERE ST_Intersects(a.geom, b.geom)
  AND NOT ST_Relate(a.geom, b.geom, '****0****')
  AND a.gid != b.gid
LIMIT 10;

-- Answer: This happens, so the data is not end-noded.

26.1.1. 函數清單

ST_Relate(geometry A, geometry B):傳回文字字串代表幾何之間的 DE9IM 關係。