16. 投影資料

地球不是平坦的,也沒有簡單的方式可將其繪製在平坦的紙質地圖(或電腦螢幕)上,因此人們想出各種巧妙的解決方案,各有利弊。某些投影會保留面積,讓所有物件彼此之間保持相對大小比例;其他投影會保留角度(共形),例如麥卡托投影;有些投影則嘗試找出折衷的良好混合方式,在多個參數上僅造成輕微扭曲。所有投影的共通點都是將(球狀)世界轉換到平面笛卡爾座標系統,而應選用哪一種投影則取決於你如何使用資料。

當我們 載入我們的紐約市資料 時,我們已經遇見投影。(記住那個討厭的 SRID 26918)。然而,有時你需要在空間參考系統之間轉換並重新投影。PostGIS 內建了使用 ST_Transform(geometry, srid) 函數變更資料投影的支援。為了管理幾何圖形的空間參考識別碼,PostGIS 提供了 ST_SRID(geometry)ST_SetSRID(geometry, srid) 函數。

我們可以使用 ST_SRID 函數確認我們資料的 SRID

SELECT ST_SRID(geom) FROM nyc_streets LIMIT 1;
26918

而「26918」的定義又是什麼?正如同我們在「載入資料」單元中所見,定義包含在 spatial_ref_sys 表格中。事實上,那裡有 **兩個** 定義。定義在 srtext 欄中是「已知文字」(WKT),而 proj4text 欄中則有以「proj.4」格式表示的第二個定義。

SELECT * FROM spatial_ref_sys WHERE srid = 26918;

PostGIS 重新投影引擎會嘗試從 spatial_ref_sys 表格中尋找最佳投影

  • auth_name / auth_srid 如果 proj 可以在其內部目錄中找到有效的「授權名稱」和「授權 srid」,它將使用這些資訊產生投影定義。

  • srtext 如果 proj 可以從 srtext 中解析並形成定義物件,它將會使用該物件。

  • proj4text 最後,proj 會嘗試處理 proj4text

所有這些冗餘表示只要使用有效的 srtext 字串或 proj4text 字串就能在 PostGIS 中建立新的投影。預設所有通用的權威名稱/代碼配對已載入至資料表中。

如果您在建立自訂投影時有選擇,請填寫 srtext 欄位,這是因為該欄位也會由 GeoServerQGISFME 等外部程式使用。

16.1. 比較資料

座標與 SRID 合起來定義了地球上的位置。沒有 SRID 的座標只是一個抽象概念。「笛卡兒」座標平面定義為置於地球表面的「平面」座標系統。因為 PostGIS 函數適用於此類平面,比較運算需要兩個幾何圖形以相同的 SRID 表示。

如果您輸入具有不同 SRID 的幾何圖形,只會產生錯誤

SELECT ST_Equals(
         ST_GeomFromText('POINT(0 0)', 4326),
         ST_GeomFromText('POINT(0 0)', 26918)
         );
ERROR:  ST_Equals: Operation on mixed SRID geometries (Point, 4326) != (Point, 26918)

注意

不要過度依賴使用 ST_Transform 進行動態轉換。空間索引是使用已儲存幾何圖形的 SRID 建立的。如果比較在不同的 SRID 中進行,則不會(經常)使用空間索引。最佳做法是為資料庫中的所有資料表選擇一個 SRID。僅在您讀取或寫入資料到外部應用程式時才使用轉換函數。

16.2. 轉換資料

如果我們返回 SRID 26918 的 proj4 定義,我們可以看到我們的作業投影是第 18 區的 UTM(萬用橫軸墨卡托投影),單位是公尺。

SELECT srtext FROM spatial_ref_sys WHERE srid = 26918;
PROJCS["NAD83 / UTM zone 18N",
  GEOGCS["NAD83",
    DATUM["North_American_Datum_1983",
      SPHEROID["GRS 1980",6378137,298.257222101,AUTHORITY["EPSG","7019"]],
      TOWGS84[0,0,0,0,0,0,0],
      AUTHORITY["EPSG","6269"]],
    PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],
    UNIT["degree",0.0174532925199433,AUTHORITY["EPSG","9122"]],
    AUTHORITY["EPSG","4269"]],
  PROJECTION["Transverse_Mercator"],
  PARAMETER["latitude_of_origin",0],
  PARAMETER["central_meridian",-75],
  PARAMETER["scale_factor",0.9996],
  PARAMETER["false_easting",500000],
  PARAMETER["false_northing",0],
  UNIT["metre",1,AUTHORITY["EPSG","9001"]],
  AXIS["Easting",EAST],AXIS["Northing",NORTH],
  AUTHORITY["EPSG","26918"]]

讓我們將資料從我們的作業投影轉換成地理座標(也稱為「經度/緯度」)。

要將資料從一個 SRID 轉換成另一個 SRID,您必須先驗證您的幾何圖形是否有有效的 SRID。由於我們已經確認有效的 SRID,接下來我們需要轉換成投影的 SRID。換句話說,地理座標的 SRID 是什麼?

地理座標最常見的 SRID 是 4326,對應於「WGS84 球體上的經度/緯度」。您可以在這裡看到定義

您也可以從spatial_ref_sys 資料表中提取定義

SELECT srtext FROM spatial_ref_sys WHERE srid = 4326;
GEOGCS["WGS 84",
  DATUM["WGS_1984",
    SPHEROID["WGS 84",6378137,298.257223563,AUTHORITY["EPSG","7030"]],
    AUTHORITY["EPSG","6326"]],
  PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],
  UNIT["degree",0.01745329251994328,AUTHORITY["EPSG","9122"]],
  AUTHORITY["EPSG","4326"]]

讓我們將「Broad St」地鐵站的座標轉換成地理座標

SELECT ST_AsText(ST_Transform(geom,4326))
FROM nyc_subway_stations
WHERE name = 'Broad St';
POINT(-74.01067146887341 40.70710481558761)

如果您載入資料或建立新的幾何圖形,而不指定 SRID,SRID 的值將會是 0。回想在 Geometries中,當我們建立 geometries 資料表时,並未指定 SRID。如果我們查詢我們的資料庫,我們應該預期所有 nyc_ 資料表的 SRID 為 26918,而 geometries 資料表的 SRID 預設為 0。

若要查看資料表的 SRID 指定,請查詢資料庫的 geometry_columns 資料表。

SELECT f_table_name AS name, srid
FROM geometry_columns;
        name         | srid
---------------------+-------
 nyc_census_blocks   | 26918
 nyc_homicides       | 26918
 nyc_neighborhoods   | 26918
 nyc_streets         | 26918
 nyc_subway_stations | 26918
 geometries          |     0

但是,如果您知道座標的 SRID 應該是多少,您可以使用幾何圖形的 ST_SetSRID 來事後設定。之後您將能轉換幾何圖形到其他系統。

SELECT ST_AsText(
    ST_Transform(
      ST_SetSRID(geom,26918),
      4326)
    )
  FROM geometries;

16.3. 函式清單

ST_AsText:傳回幾何圖形/地理資訊的公開文本 (WKT) 表示法,不含 SRID 的元資料。

ST_SetSRID(geometry, srid):將几何图形的 SRID 设为特定的整数。

ST_SRID(geometry):傳回在 spatial_ref_sys 資料表中定義的 ST_Geometry 的空間參考識別碼。

ST_Transform(geometry, srid):傳回一個新幾何圖形,其座標已轉換成由整數參數所參照的 SRID。