28. 3-D

28.1. 3D 幾何

迄今為止,我們一直在使用只有 X 和 Y 座標的 2D 幾何。但 PostGIS 支援所有幾何類型的附加維度,一個「Z」維度用於加入高度資訊,以及每個座標的「M」維度用於額外的維度資訊(一般為時間、道路里程或上游距離資訊)。

對於 3D 和 4D 幾何,額外的維度會以每個幾何中每個頂點的額外座標方式加入,並擴充幾何類型以指出如何詮釋額外的維度。加入額外的維度會為每個基本幾何產生三個額外的可能幾何類型

  • 點(2D 型別)搭配 PointZ、PointM 和 PointZM 型別。

  • 線(2D 型別)搭配 LinestringZ、LinestringM 和 LinestringZM 型別。

  • 多邊形(2D 型別)搭配 PolygonZ、PolygonM 和 PolygonZM 型別。

  • 以此類推。

對於知名文字(WKT)表示形式,高維度幾何的格式由 ISO SQL/MM 規格指定。額外的維度資訊在類型名稱後以文字字串方式加入,並在 X/Y 資訊後加入額外的座標。例如

  • POINT ZM (1 2 3 4)

  • LINESTRING M (1 1 0, 1 2 0, 1 3 1, 2 2 0)

  • POLYGON Z ((0 0 0, 0 1 0, 1 1 0, 1 0 0, 0 0 0))

處理 3D 和 4D 幾何時,ST_AsText() 函式會傳回以上的表示形式。

對於知名二進位(WKB)表示形式,高維度幾何的格式由 ISO SQL/MM 規格指定。此格式的 BNF 格式可從 https://git.osgeo.org/gitea/postgis/postgis/src/branch/master/doc/bnf-wkb.txt 取得。

除了標準型別的高維度形式以外,PostGIS 還包含一些在 3D 空間中具備意義的新型別

  • TIN 型別讓您可以將三角形網格模型建立為資料庫中的列。

  • POLYHEDRALSURFACE 讓您可以將體積物件模式設定為資料庫中的列。

由於這兩個型別都用於模擬 3D 物件,因此只有使用 Z 變異才有意義。POLYHEDRALSURFACE Z 的範例會是 1 個單位立方體

POLYHEDRALSURFACE Z (
  ((0 0 0, 0 1 0, 1 1 0, 1 0 0, 0 0 0)),
  ((0 0 0, 0 1 0, 0 1 1, 0 0 1, 0 0 0)),
  ((0 0 0, 1 0 0, 1 0 1, 0 0 1, 0 0 0)),
  ((1 1 1, 1 0 1, 0 0 1, 0 1 1, 1 1 1)),
  ((1 1 1, 1 0 1, 1 0 0, 1 1 0, 1 1 1)),
  ((1 1 1, 1 1 0, 0 1 0, 0 1 1, 1 1 1))
)

28.2. 3D 函式

有多種函數用於計算 3D 物件之間的關係

  • ST_3DClosestPoint — 傳回 g1 上最接近 g2 的 3D 點。這是 3D 最短線的第一個點。

  • ST_3DDistance — 對於幾何類型,傳回兩個幾何之間在投影單位中的 3D 卡氏座標最小距離 (根據空間參照)。

  • ST_3DDWithin — 對於 3D (z) 幾何類型,如果兩個幾何 3D 距離在一定單位範圍內,則傳回 true。

  • ST_3DDFullyWithin — 如果所有 3D 幾何都在彼此特定的距離內,則傳回 true。

  • ST_3DIntersects — 如果幾何在 3D 中「空間相交」,則傳回 TRUE - 僅限於點和線字串

  • ST_3DLongestLine — 傳回兩個幾何之間最長的 3D 線

  • ST_3DMaxDistance — 對於幾何類型,傳回兩個幾何之間在投影單位中的 3D 卡氏座標最大距離 (根據空間參照)。

  • ST_3DShortestLine — 傳回兩個幾何之間最短的 3D 線

例如,我們可以使用 ST_3DDistance 函數計算單位立方體和點之間的距離

-- This is really the distance between the top corner
-- and the point.
SELECT ST_3DDistance(
  'POLYHEDRALSURFACE Z (
    ((0 0 0, 0 1 0, 1 1 0, 1 0 0, 0 0 0)),
    ((0 0 0, 0 1 0, 0 1 1, 0 0 1, 0 0 0)),
    ((0 0 0, 1 0 0, 1 0 1, 0 0 1, 0 0 0)),
    ((1 1 1, 1 0 1, 0 0 1, 0 1 1, 1 1 1)),
    ((1 1 1, 1 0 1, 1 0 0, 1 1 0, 1 1 1)),
    ((1 1 1, 1 1 0, 0 1 0, 0 1 1, 1 1 1))
  )'::geometry,
  'POINT Z (2 2 2)'::geometry
);

-- So here's a shorter form.
SELECT ST_3DDistance(
  'POINT Z (1 1 1)'::geometry,
  'POINT Z (2 2 2)'::geometry
);

-- Both return 1.73205080756888 == sqrt(3) as expected

28.3. N 維索引

如果資料在更多維度,索引它可能很有道理。但是,在套用多維索引之前,您應該仔細考慮資料在所有維度中的分配。

只有索引允許資料庫大幅減少 WHERE 條件回傳列數時,索引才有用。多維索引要有用,資料必須涵蓋該維度的廣泛範圍,相對於您正在建構的查詢類型。

  • 一組 DEM 點可能是不適合建立 3D 索引的差勁候選,因為查詢通常會擷取點的 2D 框,並且很少嘗試選取點的 Z 切片。

  • 一組在 X/Y/T 空間中的 GPS 追蹤資料可能是建立 3D 索引的候選,如果 GPS 追蹤經常在所有維度中互相重疊 (例如,在不同時間重複行駛同一條路線),因為資料組中所有維度的變異都會很大。

您可以在資料的任何維度建立多維索引 (甚至是混合維度)。例如,要在 nyc_streets 表上建立多維索引,

CREATE INDEX nyc_streets_gix_nd ON nyc_streets
USING GIST (geom gist_geometry_ops_nd);

gist_geometry_ops_nd 參數會指示 PostGIS 使用 ND 索引,而不是標準 2D 索引。

建立索引之後,可以使用 &&& 索引運算子,透過查詢使用該索引。 &&&&& 具有相同的語意,「邊界方塊互動」;但適用這項語意於輸入幾何圖形的全部維度。尺寸不符的幾何圖形不會互動。

-- Returns true (both 3-D on the zero plane)
SELECT 'POINT Z (1 1 0)'::geometry &&&
       'POLYGON ((0 0 0, 0 2 0, 2 2 0, 2 0 0, 0 0 0))'::geometry;

-- Returns false (one 2-D one 3-D)
SELECT 'POINT Z (3 3 3)'::geometry &&&
       'POLYGON ((0 0, 0 2, 2 2, 2 0, 0 0))'::geometry;

-- Returns true (the volume around the linestring interacts with the point)
SELECT 'LINESTRING Z(0 0 0, 1 1 1)'::geometry &&&
       'POINT(0 1 1)'::geometry;

若要使用 N 維索引搜尋 nyc_streets 表格,只要使用 &&& 運算子取代一般的 && 2 維索引運算子即可。

-- N-D index operator
SELECT gid, name
FROM nyc_streets
WHERE geom &&&
      ST_SetSRID('LINESTRING(586785 4492901,587561 4493037)'::geometry,26918);

-- 2-D index operator
SELECT gid, name
FROM nyc_streets
WHERE geom &&
      ST_SetSRID('LINESTRING(586785 4492901,587561 4493037)'::geometry,26918);

結果應是相同的。整體而言,N 維索引比 2 維索引稍慢,因此僅在確定 N 維查詢將提升查詢選擇性時才使用 N 維索引。