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
にあります。事実 二つの 定義があります。"Well-Known Text" (WKT) 定義は srtext
カラムにあり、二つ目の "proj.4" フォーマットの定義は proj4text
カラムにあります。
SELECT * FROM spatial_ref_sys WHERE srid = 26918;
PostGIS の投影変換エンジンは最適な投影を spatial_ref_sys
テーブルから発見しようと試みます:
auth_name / auth_srid proj が内部カタログから妥当な "authority name" と "authority srid" を見つけられる場合には、投影の定義を生成するために、これを使います。
srtext 定義オブジェクトを
srtext
から読み込め、かつ形成できる場合には、これを使います。proj4text proj は最後に
proj4text
を処理しようとします。
このように冗長になっていて、PostGIS 内での新しい投影法生成に必要なものは、妥当な srtext
文字列または proj4text
文字列のいずれかになります。一般的なオーソリティ名/コードのペアは既にテーブルにロードされています。
カスタム投影法を生成する時に、できれば srtext
カラムを入れて下さい。GeoServer, QGIS, FME などで使われるためです。
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 を選ぶのが最善策です。変換関数は、外部アプリケーションとのデータの読み書きだけで使って下さい。
16.2. データの変換¶
SRID 26918 の proj4 定義に戻ると、現在の投影座標系が UTM (Universal Transverse Mercator) のゾーン 18 で、計測単位はメートルであることが分かります。
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 は 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
テーブルを生成した時に、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: ジオメトリ/ジオグラフィの SRID メタデータを持たない Well-Known Text (WKT) 表現を返します。
ST_SetSRID(geometry, srid): ジオメトリに指定した整数値の SRID を設定します。
ST_SRID: ST_Geometry の、spatial_ref_sys テーブルで定義されている空間参照系識別子を返します。
ST_Transform(geometry, srid): 整数パラメータで指定される SRID に座標変換した新しいジオメトリを返します。