Chapter 02

ジオメトリタイプ一覧をながめる

boiledorange73
boiledorange73
2020.10.27に更新

はじめに

地理空間データは、ジオメトリ(図形)と属性(図形に付く数値や文字列といったスカラ値)の組み合わせでできています。今回はジオメトリを見てみましょう。

シンプルなジオメトリを扱うためのデータ型や関数等の仕様として、OGC 06-103r4 (ISO 19125-1:2004)が定められていて、OGCサイト内の http://www.opengeospatial.org/standards/sfa で見ることができます。ジオメトリタイプは Part 1 "Common
architecture" に記述されています。

PostGISは、OGC標準に準拠するようにしているので、この仕様がつかめれば、PostGISのジオメトリについての理解が進むと思います。

そこで、ここでは、WKT表現をもとに、ジオメトリのタイプについてみていきます。

WKT?

WKTは"Well-Known Text"の略で、形状をテキストで表現するための仕様です。WKTは上述のOGC仕様で定められています。

WKTの例は、各ジオメトリタイプでご覧頂くとして、ここでは、WKTの共通の法則のみ提示します。

  • <ジオメトリタイプ> "(" <形状(浮動小数点数の羅列)> ")" という書式です。
  • アルファベットは大文字小文字の区別がありません。
  • 位置要素の座標値は空白で区切り、要素はコンマで区切ります。
  • 座標値は、X、Yの順序です。OGC仕様では明記されていないのですが、Xは東西/左右/経度方向で、Yは南北/上下/緯度方向で使われています。

タイプ一覧

タイプは、次の通りです。

タイプ 意味
POINT 単一の点
LINESTRING 単一の折れ線
POLYGON 単一のポリゴン、リングは複数あっても良い
POLYHEDRALSURFACE 多面体サーフェス(立体)
TRIANGLE 三角形
MULTIPOINT 複数の点からなるジオメトリ
MULTILINESTRING 複数の折れ線からなるジオメトリ
MULTIPOLYGON 複数のポリゴンからなるジオメトリ
TIN 複数の三角形からなるジオメトリ
GEOMETRYCOLLECTION 上記ジオメトリの集合、要素のタイプは他の要素のタイプと異なっても良い

基本的なタイプを見る

ポイント

単純なポイントは、ひとつの位置を示すので、次のようになります。

point( x y )

ラインストリング

単純なラインストリングは、1本の折れ線です。開始位置から終了位置までの節点をコンマ区切りで記述します。1次元位置配列になります。

linestring( x1 y1, x2 y2, ... )

ポリゴン

ポリゴンは、面を形成するので、ラインストリングと同じように1次元位置配列のように思われるかも知れませんが、穴あきポリゴンを表現する必要があるので、2次元位置不規則配列とし、複数の1次元位置配列を受け入れます。
1次元位置配列は「リング」と呼びます。リングをコンマでつないで、ポリゴンが形成されます。個々のリングは、開始位置と終了位置は同じでなければなりません。
リングは閉じられていなければなりません。言い換えると、最初の点と最後の点とが同じにならなければなりません。このため、n角形を形成するためには、n+1個のノードが必要です。

polygon( (x11 y11, x12 y12, ..., x11 y11), (x21 y21, x22 y22, ..., x21 y21), ... )

リング?

ここまで「リング」という言葉をしれっと使っています。
リングは、ポリゴンを形成する境界線です。リングがひとつだけの場合は、そのリングで形成される面全体がポリゴンとされます。
ふたつある場合は、ドーナツ型を形成します。

複数のリング

次に示すポリゴンは、外側のリング一つと内側のリング二つからなっています。

内側に二つの穴を持つポリゴン

db=# SELECT ST_IsValid(
  'POLYGON(
    (0 0, 10 0, 10 10, 0 10, 0 0),
    (1 4, 1 9, 7 9, 7 4, 1 4),
    (1 1, 8 1, 8 3, 1 3, 1 1)
  )'::GEOMETRY
);
 st_isvalid 
------------
 t
(1 行)

これは、TRUEを返しています。

つまり、穴が複数あっても妥当です。もちろん穴が無くても妥当です。

内側リングのネストは禁止

では、内側のリングの中にさらにリングを置く、三重リングは妥当でしょうか?

ST_IsValid()は不正なジオメトリかどうかを判定し、不正な場合にはその理由をNOTICEとして出力したうえで、真偽値を返します。これを使って本当に妥当なポリゴンか確かめます。

db=# SELECT ST_IsValid(
  'POLYGON(
    (0 0, 10 0, 10 10, 0 10, 0 0),
    (1 1, 1 9, 9 9, 9 1, 1 1),
    (2 2, 8 2, 8 8, 2 8, 2 2)
  )'::GEOMETRY
);
NOTICE:  Holes are nested at or near point 2 2
 st_isvalid 
------------
 f
(1 行)

穴の中にさらにリングを持つ不正ポリゴン

妥当ではありませんでした。

マルチ系タイプ

マルチポイントは、複数のポイントからなります。単一ポイントごとに丸括弧で括りません。

multipoint( x1 y1, x2 y2, ... )

マルチラインストリングは、複数のラインストリングからなります。

multilinestring( (x11 y11, x12 y12, ...), (x21 y21, x22, y22, ...))

マルチポリゴンは、複数のポリゴンからなります。

multipolygon(
  ( (x111 y111, x112 y112, ..., x111 y111), (x121 y121, x122, y122, ..., x121 y121), ...),
  ( (x211 y211, x212 y112, ..., x211 y211), ...),
  ...
)

ジオメトリコレクションは、各タイプの表現をコンマで繋いだだけです。

geometrycollection( point(...), linestring(...), ...)

X,Y,Z

ここまでX,Yの2次元座標についてみていましたが、これにZ座標を加えることもできます。この場合には、タイプ名称に"z"を追加します。

point z (1 2 3)

X,Y,Z,M と X,Y,M

X,Yの2次元座標、X,Y,Zの3次元座標に、さらにM座標を追加することができます。この場合には、タイプ名称に"m"または"zm"を追加します。

次に、X,Y,MのポイントとX,Y,Z,MのポイントのWKT表現を示します。

point m (1 2 0)
point zm (1 2 3)

M座標

M座標は「measurementを表現する」もので、X,Y,Z座標と違い、空間と直接関係のない座標です。空間座標とは違うので、投影変換を行った際にZ値は変化することがありますが、M値は変化しません。

次に、JGD2000経度緯度で東経135度、北緯35度を、Webメルカトルに投影した結果を示します。Z値は0から若干鉛直下向きに移動していますが、M値は0から変化していません。

db=# SELECT ST_AsText(ST_Transform('SRID=4612;POINT Z(135 35 0)'::GEOMETRY, 3857));
                             st_astext                             
-------------------------------------------------------------------
 POINT Z (15028131.2570919 4163881.14394377 -3.44058498740196e-05)
(1 行)

db=# SELECT ST_AsText(ST_Transform('SRID=4612;POINT M(135 35 0)'::GEOMETRY, 3857));
                   st_astext                   
-----------------------------------------------
 POINT M (15028131.2570919 4163881.14394377 0)
(1 行)

M座標には、任意の意味を持たせることができます。たとえば、「時刻」という意味を持たせることで時空間ベースとすることができますし、「何らかの代表値」という意味を持たせることでジオメトリの種別分けに使うことも可能です。ただ、個人的には全く使っていませんし、シェープファイルの時代ならともかく、PostGIS等ではメリットを感じません。たぶん、あまり使われていないと思います。

多面体サーフェス

多面体の面となるジオメトリです。ポリゴンの集合で、各ポリゴンは境界線を共有します(隙間を作らない)。また、立体を構成する面では、表と裏とを区別する必要があるため、右ねじの法則に従わなければなりません。

ただし、PostGIS (少なくとも 2.1) では、境界線を共有しない多面体サーフェスを(マルチポリゴンでしかないけれども)許容しますし、右ねじの法則に従わない面があっても隙間が無ければボリュームと認識します。

ポリゴン(2次元不規則位置配列)の集合なので、3次元不規則位置配列になります。

次に三角錐の例を示します。

polyhedralsurface z(
  ((0 0 0, 1 0 0, 1 0 1, 0 0 0)),
  ((1 0 0, 1 1 0, 1 0 1, 1 0 0)),
  ((1 1 0, 0 0 0, 1 0 1, 1 1 0)),
  ((0 0 0, 1 1 0, 1 0 0, 0 0 0))
)

三角錐から底を除いた多面体サーフェスは許容されますが、ボリュームではないと認識されます。

db=# SELECT ST_IsClosed(
'POLYHEDRALSURFACE Z(
  ((0 0 0, 1 0 0, 1 0 1, 0 0 0)),
  ((1 0 0, 1 1 0, 1 0 1, 1 0 0)),
  ((1 1 0, 0 0 0, 1 0 1, 1 1 0))
)'::GEOMETRY);
 st_isclosed 
-------------
 f
(1 行)

三角形

TRIANGLE

ポリゴンの特殊形で、三角形に限定されます。リングの数は1個で、かつノードの数は4個でなければなりません。ノードが3個でなく4個なのは、ポリゴンのリングは閉じなければならないからです。

triangle((x1 y1, x2 y2, x3 y3, x1 y1))

TIN

OGCシンプルフィーチャーの定義によると「三角形パッチのみからなる多面体サーフェス」です。そのため、TRIANGLEのマルチ系ジオメトリととらえられます。よって、マルチポリゴンと同じ3次元位置配列となりますが、パッチごとに4点でなければなりません。

tin(((x11 y11, x12 y12, x13 y13, x11 y11)),((...)),...)
tin z(((x11 y11 z11, x12 y12 z12, x13 y13 z13, x11 y11 z11)),((...)),...)

おわりに

OGCのシンプルフィーチャーをWKT表現で見てみました。WKTで表現できるものとしては、これで全てです。これも全てを把握する必要があるわけではなく、ポイント、ラインストリング、ポリゴンまでおさえておけば、ほとんどのケースで大丈夫だろうと思います。

WKT表現からジオメトリを生成する際にキャストを使っていますが、これはPostGISの独自機能ですのでご注意下さい。また、OGCのWKT仕様に従わない表現も受け入れます(EWKTと呼ばれています)。