9. 幾何圖形

9.1. 簡介

在之前的 單元 中,我們載入各種資料。在開始玩我們的資料之前,讓我們來看看一些更簡單的範例。回到 pgAdmin,再次選取nyc 資料庫,並開啟 SQL 查詢工具。將此 SQL 範例程式碼貼到 pgAdmin SQL 編輯器視窗中(移除預設文字),然後執行。

CREATE TABLE geometries (name varchar, geom geometry);

INSERT INTO geometries VALUES
  ('Point', 'POINT(0 0)'),
  ('Linestring', 'LINESTRING(0 0, 1 1, 2 1, 2 2)'),
  ('Polygon', 'POLYGON((0 0, 1 0, 1 1, 0 1, 0 0))'),
  ('PolygonWithHole', 'POLYGON((0 0, 10 0, 10 10, 0 10, 0 0),(1 1, 1 2, 2 2, 2 1, 1 1))'),
  ('Collection', 'GEOMETRYCOLLECTION(POINT(2 0),POLYGON((0 0, 1 0, 1 1, 0 1, 0 0)))');

SELECT name, ST_AsText(geom) FROM geometries;
_images/start01.png

上面的範例建立一個資料表 (geometries),並插入五個幾何圖形:一個點、一個線、一個多邊形、一個帶洞的多邊形,以及一個集合。最後,插入的列會被選取並顯示在「輸出」窗格中。

9.2. 後設資料表

配合 SFSQL(SQL 簡易特徵)規格,PostGIS 提供兩個資料表來追蹤和回報給定資料庫中的幾何圖形類型。

  • 第一個資料表 spatial_ref_sys 定義資料庫已知的空間參照系統,稍後將更詳細地說明。

  • 第二個資料表(事實上,是一個視圖) geometry_columns 提供所有「特徵」(定義為具有幾何屬性的物件)的清單,以及這些特徵的基本詳細資料。

_images/table01.png

讓我們看看在我們的資料庫中的 geometry_columns 資料表。和以前一樣把這個指令貼到查詢工具中

SELECT * FROM geometry_columns;
_images/start08.png
  • f_table_catalogf_table_schemaf_table_name 提供包含給定幾何圖形的特徵資料表的完全限定名稱。由於 PostgreSQL 不使用目錄,f_table_catalog 通常會是空的。

  • f_geometry_column 是包含幾何圖形的資料表的資料行名稱 - 對於具有多個幾何圖形資料行的特徵資料表,將會有一筆記錄。

  • coord_dimensionsrid 分別定義幾何的維度(2、3 或 4 維度)和空間參考系統識別碼,指向 spatial_ref_sys 表格。

  • type 欄位定義幾何類型,如下所述。截至目前,我們已看過點狀和線段類型。

藉由查詢該表格,GIS 用戶端和程式庫可以確定在擷取資料時應期待什麼,而且可以在不需要檢查各個幾何的情況下執行任何必要的投影、處理或繪製。

注意事項

您的某些 nyc 表格是否有 26918 以外的 srid?這很容易可藉由更新表格來修復。

ALTER TABLE nyc_neighborhoods
  ALTER COLUMN geom
  TYPE Geometry(MultiPolygon, 26918)
  USING ST_SetSRID(geom, 26918);

9.3. 表示真實世界物件

用於 SQL(SFSQL)的簡單特徵,PostGIS 開發的原始指導標準,定義如何表示真實世界的物件。藉由採用連續形狀並在固定解析度進行數位化,我們可以獲得物件的通用手冊表述。SFSQL 只處理 2 維表述。PostGIS 已將其擴充,以包含 3 維和 4 維表述;較新的 SQL 多媒體第 3 號(SQL/MM)規格已正式定義自己的表述。

我們的範例表格包含不同幾何類型的組合。我們可以使用讀取幾何資料的函式來收集各個物件的一般資訊。

  • ST_GeometryType(geometry) 傳回幾何類型

  • ST_NDims(geometry) 傳回幾何的維度數目

  • ST_SRID(geometry) 傳回幾何的空間參考識別號碼

SELECT name, ST_GeometryType(geom), ST_NDims(geom), ST_SRID(geom)
  FROM geometries;
      name       |    st_geometrytype    | st_ndims | st_srid
-----------------+-----------------------+----------+---------
 Point           | ST_Point              |        2 |       0
 Polygon         | ST_Polygon            |        2 |       0
 PolygonWithHole | ST_Polygon            |        2 |       0
 Collection      | ST_GeometryCollection |        2 |       0
 Linestring      | ST_LineString         |        2 |       0

9.3.1.

_images/points.png

空間表示地球上單一位置。該點由單一座標(包括 2、3 或 4 個維度)表示。點用於表示物件,當精確的細節(例如形狀和大小)在目標比例尺上不重要時。例如,地圖上的城市可以描述為點,而單一州的地圖則可以將城市表示為多邊形。

SELECT ST_AsText(geom)
  FROM geometries
  WHERE name = 'Point';
POINT(0 0)

以下是針對點執行的特定空間函式

  • ST_X(geometry) 傳回 X 座標

  • ST_Y(geometry) 傳回 Y 座標

因此,我們可以讀取點座標,如下所示

SELECT ST_X(geom), ST_Y(geom)
  FROM geometries
  WHERE name = 'Point';

紐約地鐵站 (nyc_subway_stations) 資料表是表示為點的資料集。下列 SQL 查詢會傳回與一個點相關的幾何 (在 ST_AsText 欄位中)。

SELECT name, ST_AsText(geom)
  FROM nyc_subway_stations
  LIMIT 1;

9.3.2. 線串

_images/lines.png

線串是位置之間的一條路徑。它採取兩個或更多點的有序系列的形式。道路和河流通常表示為線串。如果線串在同一點開始和結束,則稱為封閉線串。如果它沒有交叉或觸及它自己 (除了在它封閉時在它的端點處),則稱為單純線串。一個線串可以同時是封閉單純線串。

紐約的街道網路 (nyc_streets) 在工作坊中已於先前時候載入。此資料集包含名稱和類型等詳細資料。一個真實世界的街道可能包含許多線串,每個線串都表示一段具有不同屬性的道路。

下列 SQL 查詢會傳回與一個線串相關的幾何 (在 ST_AsText 欄位中)。

SELECT ST_AsText(geom)
  FROM geometries
  WHERE name = 'Linestring';
LINESTRING(0 0, 1 1, 2 1, 2 2)

以下是處理線串的一些特定空間函數

  • ST_Length(geometry) 傳回線串的長度

  • ST_StartPoint(geometry) 傳回第一組坐標作為點

  • ST_EndPoint(geometry) 傳回最後一組坐標作為點

  • ST_NPoints(geometry) 傳回線串中的坐標數目

因此,我們的線串的長度為

SELECT ST_Length(geom)
  FROM geometries
  WHERE name = 'Linestring';
3.41421356237309

9.3.3. 多邊形

_images/polygons.png

多邊形是區域的表示。多邊形的外界線以環形表示。此環形是符合上述定義的封閉且單純線串。多邊形內部的洞也以環形表示。

多邊形用於表示其大小和形狀很重要的物件。當比例夠高可以看到其面積時,城市界線、公園、建築物足跡或水體通常都以多邊形表示。道路和河流有時也可以表示為多邊形。

下列 SQL 查詢會傳回與一個多邊形相關的幾何 (在 ST_AsText 欄位中)。

SELECT ST_AsText(geom)
  FROM geometries
  WHERE name LIKE 'Polygon%';

注意事項

我們在 WHERE 子句中使用 LIKE 算符執行字串比對作業,而不是使用等於 = 符號。**你可能習慣於將「*」符號用作模式比對的「glob」,但在 SQL 中使用「%``」符號**,並與 LIKE 算符一起使用來告訴系統執行 glob 比對。

POLYGON((0 0, 1 0, 1 1, 0 1, 0 0))
POLYGON((0 0, 10 0, 10 10, 0 10, 0 0),(1 1, 1 2, 2 2, 2 1, 1 1))

第一個多邊形只有一個環。第二個有一個內部「洞」。大多數圖形系統都包含一個「多邊形」的概念,但 GIS 系統比較特殊,允許多邊形明確地有洞。

_images/polygons1.png

以下是與多邊形搭配使用的一些特定空間功能

  • ST_Area(geometry) 傳回多邊形的面積

  • ST_NRings(geometry) 傳回環的數量(通常為 1,如果有洞則更多)

  • ST_ExteriorRing(geometry) 傳回外環,做為線條

  • ST_InteriorRingN(geometry,n) 傳回指定內環,做為線條

  • ST_Perimeter(geometry) 傳回所有環的長度

我們可以使用面積函數計算多邊形的面積

SELECT name, ST_Area(geom)
  FROM geometries
  WHERE name LIKE 'Polygon%';
Polygon            1
PolygonWithHole    99

請注意,有洞的多邊形的面積是外殼(10x10 方形)的面積減去洞(1x1 方形)的面積。

9.3.4. 集合

有四種集合類型,可將多個簡單的幾何圖形分組成集合。

  • 多點,點的集合

  • 多線條字串,線條字串的集合

  • 多邊形,多邊形的集合

  • 幾何集合,任何幾何圖形(包括其他集合)的異質集合

集合是另一個在 GIS 軟體中出現的觀念,而不是在一般圖形軟體中。它們可用於直接將真實世界的物件建模為空間物件。例如,要如何建模一個被通行權分離的地段?做為多邊形,通行權兩側各有一部分。

_images/collection2.png

我們的範例集合包含一個多邊形和一個點

SELECT name, ST_AsText(geom)
  FROM geometries
  WHERE name = 'Collection';
GEOMETRYCOLLECTION(POINT(2 0),POLYGON((0 0, 1 0, 1 1, 0 1, 0 0)))
_images/collection.png

以下是與集合搭配使用的一些特定空間功能

  • ST_NumGeometries(geometry) 傳回集合中區段的數量

  • ST_GeometryN(geometry,n) 傳回指定的區段

  • ST_Area(geometry) 傳回所有多邊形區段的總面積

  • ST_Length(geometry) 傳回所有線性區段的總長度

9.4. 幾何輸入和輸出

在資料庫中,幾何圖形會儲存在磁碟上的格式,而該格式只能由 PostGIS 程式使用。為了讓外部程式插入和擷取有用的幾何圖形,它們需要轉換成其他應用程式可以理解的格式。很幸運地,PostGIS 支援以大量的格式傳遞和使用幾何圖形

  • 知名文字 (WKT)

    • ST_GeomFromText(text, srid) 傳回 geometry

    • ST_AsText(geometry) 傳回 text

    • ST_AsEWKT(geometry) 傳回 text

  • 已知二進位格式 (WKB)

    • ST_GeomFromWKB(bytea) 傳回 geometry

    • ST_AsBinary(geometry) 傳回 bytea

    • ST_AsEWKB(geometry) 傳回 bytea

  • 地理標記語言 (GML)

    • ST_GeomFromGML(text) 傳回 geometry

    • ST_AsGML(geometry) 傳回 text

  • Keyhole 標記語言 (KML)

    • ST_GeomFromKML(text) 傳回 geometry

    • ST_AsKML(geometry) 傳回 text

  • GeoJSON

    • ST_AsGeoJSON(geometry) 傳回 text

  • 可擴充向量圖形 (SVG)

    • ST_AsSVG(geometry) 回傳 text

建構函數最常見的用途是將幾何圖形文字表示轉換為內部表示。

請注意,除了帶有幾何表示的文字參數之外,我們還有一個提供幾何 SRID 的數字參數。

下列 SQL 查詢顯示 WKB 表示的一個範例 (呼叫 encode() 是將二進位輸出轉換為 ASCII 形式以進行列印的要求)

SELECT encode(
  ST_AsBinary(ST_GeometryFromText('LINESTRING(0 0,1 0)')),
  'hex');
01020000000200000000000000000000000000000000000000000000000000f03f0000000000000000

在本次工作坊中,我們將繼續使用 WKT,以確保您可以觀看並瞭解我們正在瀏覽的幾何圖形。然而,多數實際程序 (例如瀏覽地理資訊系統應用程式中的資料、將資料傳輸到網路服務或遙遠處理資料),WKB 都是首選格式。

由於 WKT 和 WKB 是在 SFSQL 規範中定義的,因此它們並未處理 3 或 4 維幾何圖形。對於這些情況,PostGIS 定義了擴展已知文字 (EWKT) 和擴展已知二進位格式 (EWKB) 格式。這些格式提供 WKT 和 WKB 相同的格式功能,並增加了次元。

這是一個 WKT 中 3D 線字串的範例

SELECT ST_AsText(ST_GeometryFromText('LINESTRING(0 0 0,1 0 0,1 1 2)'));
LINESTRING Z (0 0 0,1 0 0,1 1 2)

請注意該文字表示法會變更!這是因為 PostGIS 的文字輸入程式在消耗時很寬鬆。它會使用

  • 十六進位編碼的 EWKB、

  • 延伸的 Well-Known 文字,以及

  • ISO 標準的 Well-Known 文字。

在輸出方面,ST_AsText 函式比較保守,而且只會發出 ISO 標準的 Well-Known 文字。

除了 ST_GeometryFromText 函式外,還有許多其他的方法可以透過 Well-Known 文字或類似的格式化輸入來建立形狀

-- Using ST_GeomFromText with the SRID parameter
SELECT ST_GeomFromText('POINT(2 2)',4326);

-- Using ST_GeomFromText without the SRID parameter
SELECT ST_SetSRID(ST_GeomFromText('POINT(2 2)'),4326);

-- Using a ST_Make* function
SELECT ST_SetSRID(ST_MakePoint(2, 2), 4326);

-- Using PostgreSQL casting syntax and ISO WKT
SELECT ST_SetSRID('POINT(2 2)'::geometry, 4326);

-- Using PostgreSQL casting syntax and extended WKT
SELECT 'SRID=4326;POINT(2 2)'::geometry;

除了一般格式 (WKT、WKB、GML、KML、JSON、SVG) 的發送器外,PostGIS 也有四種格式 (WKT、WKB、GML、KML) 的接收器。大部分應用程式使用 WKT 或 WKB 形狀建立函式,但其他功能也能使用。這是一個使用 GML 並輸出 JSON 的範例

SELECT ST_AsGeoJSON(ST_GeomFromGML('<gml:Point><gml:coordinates>1,1</gml:coordinates></gml:Point>'));
_images/represent-07.png

9.5. 將文字轉型

我們到目前為止看到的 WKT 字串都是「文字」類型,並且我們一直使用 PostGIS 函式 (例如 ST_GeomFromText()) 將其轉換為「形狀」類型。

PostgreSQL 包含一個簡短形式的語法,可將資料從一種類型轉換為另一種類型,亦即轉型語法 oldata::newtype。例如,此 SQL 會將一個雙精度浮點數值轉換為文字字串。

SELECT 0.9::text;

更不重要的部份是,這個 SQL 會將一個 WKT 字串轉換成一個形狀

SELECT 'POINT(0 0)'::geometry;

使用轉型來建立形狀請注意一件事:除非您指定 SRID,否則您將會得到一個具有未知 SRID 的形狀。您可以使用「延伸」的 Well-Known 文字格式指定 SRID,該格式在前面包含了一個 SRID 區塊

SELECT 'SRID=4326;POINT(0 0)'::geometry;

在處理 WKTgeometrygeography 欄位時,使用轉型符號是很常見的 (請參閱 Geography)。

9.6. 函式清單

ST_Area:傳回曲面的面積,如果它是一個多邊形或多重多邊形。對於「geometry」類型,面積以 SRID 單位為單位。對於「geography」類型,面積以平方公尺為單位。

ST_AsText:傳回幾何/地理資料的 Well-Known Text (WKT) 表示法,不含 SRID 元資料。

ST_AsBinary:傳回幾何/地理資料的 Well-Known Binary (WKB) 表示法,不含 SRID 元資料。

ST_EndPoint:傳回 LINESTRING 幾何資料的最後一點作為 POINT。

ST_AsEWKB:傳回幾何資料的 Well-Known Binary (WKB) 表示法,包含 SRID 元資料。

ST_AsEWKT:傳回幾何圖形的已知文字 (WKT) 表示,具有 SRID 元資料。

ST_AsGeoJSON:傳回幾何圖形作為 GeoJSON 元素。

ST_AsGML:傳回幾何圖形作為 GML 版本 2 或 3 元素。

ST_AsKML:傳回幾何圖形作為 KML 元素。有數種衍生變形。預設版本為 2,預設精確度為 15。

ST_AsSVG:根據幾何圖形或地理物件,傳回 SVG 路徑資料中的幾何圖形。

ST_ExteriorRing:傳回一條線串,代表多邊形幾何圖形的外部環。如果幾何圖形不是多邊形,則傳回 NULL。無法用於多重多邊形。

ST_GeometryN:如果幾何圖形是 GEOMETRYCOLLECTION、多點、多線串、多曲線或多重多邊形,則傳回第 N 個基於 1 的幾何圖形。否則,傳回 NULL。

ST_GeomFromGML:輸入幾何圖形的 GML 表示,並輸出 PostGIS 幾何圖形物件。

ST_GeomFromKML:輸入幾何圖形的 KML 表示,並輸出 PostGIS 幾何圖形物件

ST_GeomFromText:根據已知文字表示 (WKT) 傳回指定的 ST_Geometry 值。

ST_GeomFromWKB:根據已知二進位幾何圖形表示 (WKB) 建立幾何圖形實例,以及選用的 SRID。

ST_GeometryType:傳回 ST_Geometry 值的幾何圖形類型。

ST_InteriorRingN:傳回多邊形幾何圖形的第 N 個內部線串環。如果幾何圖形不是多邊形,或給定 N 超過範圍,則傳回 NULL。

ST_Length:如果線串或多線串為 2d,則傳回幾何圖形的 2d 長度。幾何圖形會以空間參考單位表示,而地理則會以公尺表示(預設球體)

ST_NDims:傳回幾何圖形的座標維度,表示為小整數。值為:2、3 或 4。

ST_NPoints:傳回幾何圖形中的點(頂點)數量。

ST_NRings:如果幾何圖形是多邊形或多重多邊形,則傳回環的數量。

ST_NumGeometries:如果幾何圖形是 GEOMETRYCOLLECTION(或 MULTI*),傳回幾何圖形數量,否則傳回 NULL。

ST_Perimeter:傳回 ST_Surface 或 ST_MultiSurface 值邊界的長度測量。(多邊形、多重多邊形)

ST_SRID:傳回 ST_Geometry 的空間參考識別碼,如 spatial_ref_sys 表格中定義。

ST_StartPoint:將 LINESTRING 幾何的第一個點傳回為點 (POINT)。

ST_X:傳回點的 X 座標,或如果無法取得,則傳回 NULL。輸入必須是點。

ST_Y:傳回點的 Y 座標,或如果無法取得,則傳回 NULL。輸入必須是點。