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) を CREATE して、ポイント、ライン、ポリゴン、穴付きポリゴン、コレクションの 5個のジオメトリを INSERT します。最後に、挿入した行を SELECT して、Output ペインに表示します。

9.2. メタデータテーブル

PostGIS は、Simple Features for SQL (SFSQL) 仕様に準拠して、与えられたデータベースで使用可能なジオメトリタイプに関する追跡と報告のための二つのテーブルを提供します。

  • 一つ目は spatial_ref_sys で、データベースに認識されるべき空間参照系の全てを定義しています。後でたっぷり詳細説明します。

  • 二つ目のテーブルは geometry_columns で、「地物」 (ジオメトリ属性を持つオブジェクトとして定義されています) の全ての一覧と、これらの地物の基本的な詳細説明を提供しています。

_images/table01.png

データベース内の geometry_columns テーブルを見てみましょう。先ほどと同じように、このコマンドを Query Tool にペーストします:

SELECT * FROM geometry_columns;
_images/start08.png
  • f_table_catalog, f_table_schema, f_table_name は、与えられたジオメトリを含む地物テーブルの完全修飾名を提供します。PostgreSQL はカタログを使わないので、f_table_catalog は空になります。

  • f_geometry_column はジオメトリのカラム名です。複数のジオメトリカラムを持つ地物テーブルについては、それぞれの一つのレコードがあります。

  • coord_dimensionsrid はジオメトリの次元 (2, 3, 4次元) と "spatial_ref_sys" テーブルを参照する空間参照系識別子を定義しています。

  • type カラムは次に示す通り、ジオメトリのタイプを定義しています。今のところ、ポイントとラインストリングのタイプを見てきました。

このテーブルのクエリによって、GISクライアントとライブラリはデータ検索時に何を期待すべきかを判定できますし、個々のジオメトリを検査することなく、必要な投影、処理、描画を実行できます。

注釈

nyc テーブルの一部または全ては srid 26918 を持っていないでしょうか? テーブルを更新することにより簡単に修正できます。

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

9.3. 現実世界のオブジェクトの表現

PostGIS 開発の元々のガイドとなる標準である Simple Features for SQL (SFSQL) 仕様は、現実世界のオブジェクトがどのように表現されるかを定義しています。継続的な形状を取得して、固定解像度でデジタル化を行うことによって、オブジェクトの受け渡し可能な表現を実現します。SFSQL は 2次元表現だけを処理しました。PostGIS は、3次元、4次元を四方源を取り込むための拡張がなされています。最近の SQL-Multimedia Part 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

**ラインストリング**は位置間の順路です。順序の付いた 2以上のポイントの形式を取ります。道路や河川は通常はラインストリングで表現されます。始端と終端が同じ位置の場合にはラインストリングは**閉じている**と言われます。自分にクロスも接触もしない (閉じている場合の始端と終端は除く) 場合にはラインストリングは**単純**と言われます。ラインストリングは**閉じている**かつ**単純**になりえます。

ニューヨークのストリート網 (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" 演算子を使います。"LIKE" 演算子でシステムにワイルドカードを使った文字列照合を行う場合、**パターンマッチングのワイルドカードに "*" 記号に慣れているかもしれませんが、SQL では "%" 記号を使います **

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. コレクション

四つのコレクションタイプがありますが、単純ジオメトリをグループ化したものです。

  • MULTIPOINT ポイントのコレクション

  • MULTILINESTRING ラインストリングのコレクション

  • MULTIPOLYGON ポリゴンのコレクション

  • GEOMETRYCOLLECTION 任意のジオメトリ (他のコレクションも含む) の異種コレクション

コレクションは、一般的なグラフィックス ソフトウェアよりも GIS ソフトウェアに多く現れる別の概念です。これらは、現実世界のオブジェクトを空間オブジェクトとして直接モデル化するのに役立ちます。たとえば、公道用地で分割された土地区画をモデル化するにはどうするでしょう?**MULTIPOLYGON**として、公道用地の両側に土地区画の部分を置きます。

_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 は多数のフォーマットの入出力に対応しています:

  • Well-Known Text (WKT)

    • ST_GeomFromText(text, srid)geometry を返します

    • ST_AsText(geometry)text を返します

    • ST_AsEWKT(geometry)text を返します

  • Well-Known Binary (WKB)

    • ST_GeomFromWKB(bytea)geometry を返します

    • ST_AsBinary(geometry)bytea` を返します

    • ST_AsEWKB(geometry)bytea を返します

  • Geographic Mark-up Language (GML)

    • ST_GeomFromGML(text)geometry を返します

    • ST_AsGML(geometry)text を返します

  • Keyhole Mark-up Language (KML)

    • ST_GeomFromKML(text)geometry を返します

    • ST_AsKML(geometry)text を返します

  • GeoJSON

    • ST_AsGeoJSON(geometry)text を返します

  • Scalable Vector Graphics (SVG)

    • ST_AsSVG(geometry)text を返します

コンストラクタの最も一般的な利用は、ジオメトリの文字列表現を内部表現に変換することです:

ジオメトリ表現の文字パラメータに加えて、ジオメトリの SRID を提供する数値パラメータもあることに注意して下さい。

次の SQL クエリは WKB 表現の例を示します (encode() はバイナリ出力を印字のために ASCII 形式に変換するために必要です):

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

このワークショップの目的のために、表示しているジオメトリを読んで理解することができるように、WKT を引き続き使います。しかしながら、GIS アプリケーションにデータを表示したり、データをウェブサービスに転送したり、データをリモートで処理したりするような、実際的な処理のほとんどでは、WKB が最適なフォーマットです。

WKT と WKB は SFSQL 仕様で定義されていたため、3次元4次元のジオメトリは処理しませんでした。こういった場合のために PostGIS は Extended Well Known Text (EWKT) と Extended Well Known Binary (EWKB) のフォーマットを定義しました。これらは、WKT と WKB に次元を追加したフォーマット能力を持っています。

WKT の 3次元ラインストリングの例を示します:

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 の文字列入力ルーチンでは入力が自由であるためです。出力は次のものが対象です

  • 16進数エンコードされた EWKB,

  • 拡張 Well-Known Text および

  • ISO標準 Well-Known Text。

出力について、ST_AsText 関数は保守的で、ISO標準の Well-Known Text いか出力しません。

ST_GeometryFromText 関数に加えて、Well-Known Text や類似フォーマットの入力からジオメトリを生成する方法がほかにも多数あります:

-- 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 には、4件の入力フォーマット (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 文字列は「文字列」型であり、ST_GeomFromText() のような PostGIS 関数を使って「ジオメトリ」型に変換していました。

PostgreSQL にはある型から別の型に変換するのに、キャスト構文という oldata::newtype のように短い形式の構文があります。たとえば、次の SQL は倍精度浮動小数点数を文字列に変換します。

SELECT 0.9::text;

より重要なのは、この SQL は WKT 文字列をジオメトリに変換します:

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

ジオメトリを生成するためのキャストの使用での注意点: SRID を指定しない場合には、SRID 不明のジオメトリが得られます。「拡張」Well-Known Text 形式を使うと、先頭に SRID ブロックを取り込めるので、SRID を指定することができます:

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

「ジオメトリ」と「ジオグラフィ」 (ジオグラフィ 参照) のカラムと同じように WKT を使うときにキャスト標記を使つかうのは非常に一般的です。

9.6. 関数リスト

ST_Area: ポリゴン化マルチポリゴンの場合には、表面の面積を返します。ジオメトリ型では SRID の単位です。ジオグラフィ型では平方メートル単位です。

ST_AsText: ジオメトリ/ジオグラフィの SRID メタデータを持たない Well-Known Text (WKT) 表現を返します。

ST_AsBinary: ジオメトリ/ジオグラフィの SRID メタデータを持たない Well-Known Binary (WKB) 表現を返します。

ST_EndPoint: LINESTRING ジオメトリの最後のポイントを POINT として返します。

ST_AsEWKB: ジオメトリの SRID メタデータを持つ Well-Known Binary (WKB) 表現を返します。

ST_AsEWKT: ジオメトリの SRID メタデータを持つ Well-Known Text (WKT) 表現を返します。

ST_AsGeoJSON: ジオメトリを GeoJSON 要素として返します。

ST_AsGML: ジオメトリを GML バージョン 2 または 3 として返します。

ST_AsKML: ジオメトリを KML 要素として返します。いくつかの形式があり、デフォルトバージョンは 2 で、デフォルト精度は 15 です。

ST_AsSVG: ジオメトリまたはジオグラフィを与えるとジオメトリを SVG path データで返します。

ST_ExteriorRing: POLYGON ジオメトリの外側リングを表現するラインストリングを返します。ジオメトリがポリゴンでない場合には NULL を返します。MULTIPOLYGON では動作しません

ST_GeometryN: ジオメトリが GEOMETRYCOLLECTION, MULTIPOINT, MULTILINESTRING, MULTICURVE, MULTIPOLYGON の場合には、1 始まりで N 番目のジオメトリを返します。他のタイプでは NULL を返します。

ST_GeomFromGML: 入力としてジオメトリの GML 表現を取って、PostGIS ジオメトリオブジェクトを出力します。

ST_GeomFromKML: 入力としてジオメトリを表現する KML を取り、PostGIS ジオメトリを出力します

ST_GeomFromText: Well-Known Text (WKT) 表現から、指定した ST_Geometry 値を返します。

ST_GeomFromWKB: Well-Known Binary (WKB) 表現と任意引数 SRID からジオメトリを生成します。

ST_GeometryType: ST_Geometry 値のジオメトリタイプを返します。

ST_InteriorRingN: ポリゴンジオメトリの N 番目の内部リングであるラインストリングを返します。ジオメトリがポリゴンでなく、N 番目が範囲外である場合には NULL を返します。

ST_Length: ジオメトリが LINESTRING または MULTILINETRING である場合には、2次元長を返します。返り値の単位は、ジオメトリでは空間参照系の単位で、ジオグラフィではメートルです (回転楕円体がデフォルト)

ST_NDims: ジオメトリの座標次元を smallint で返します。値は 2, 3, 4 のいずれかです。

ST_NPoints: ジオメトリのポイント (頂点) 数を返します。

ST_NRings: ジオメトリがポリゴンまたはマルチポリゴンである場合に、リング数を返します。

ST_NumGeometries: ジオメトリが GEOMETRYCOLLECTION (またはマルチ系) の場合にはジオメトリ数を返します。その他の場合には NULL を返します。

ST_Perimeter: ST_Surface 値または ST_MultiSurface 値 の境界の長さの測定値を返します (POLYGON, MULTIPOLYGON)

ST_SRID: ST_Geometry の、spatial_ref_sys テーブルで定義されている空間参照系識別子を返します。

ST_StartPoint: LINESTRING jにお目取りの最初のポイントを POINT として返します。

ST_X: POINT の X座標値を返します。有効でないなら NULL を返します。入力はポイントでなければなりません。

ST_Y: POINT の Y座標値を返します。有効でないなら NULL を返します。入力はポイントでなければなりません。