結合でできた「隙間」を排除する

はじめに

ジオメトリの足し算、引き算をするの最後で、広島県内の市区町村ポリゴンを結合して広島県ポリゴンを作ったところ、不思議な「線」がまぎれてしまいました。

もう少ししっかり見ると、廿日市市のポリゴンが少しだけズレてしまっているようで、隣接する広島市佐伯区、安芸太田町、大竹市とに「隙間」ができていました。

この「隙間」を消してみましょう。

ポリゴンを外のリングだけにしてやる方針

「隙間」は、見た目は線ですが、実際は線ではなく、非常に細長い面です。また、今回は幸運にも、「隙間」は県ポリゴンの内側に留まっています。

ポリゴンは、1以上のリングから成っていて、最も外のリングで形成される領域は、内側のリングで形成される領域をカバーしますが、この「隙間」は内側のリングとして保存されています。よって、ポリゴンの外側のリングだけでポリゴンを作り直せば内側のリング=隙間を排除できます。

使用する関数

ST_ExteriorRing, ST_MakePolygon, ST_Dump, ST_Collect

ST_ExteriorRing

ポリゴンを与えると、そのポリゴンの外側のリングをラインストリングで返します。

db=# SELECT ST_AsText(  
  ST_ExteriorRing(  
    'POLYGON((0 0, 3 0, 3 3, 0 3, 0 0), (1 1, 2 1, 2 2, 1 2, 1 1))'::GEOMETRY  
  )  
);  
            st_astext              
---------------------------------  
 LINESTRING(0 0,3 0,3 3,0 3,0 0)  
(1 行)  

引数はポリゴンのみ有効です。マルチポリゴンは受け付けません。

返り値がラインストリングになっていることに注意して下さい。このままではポリゴンとは認識されません。

ST_MakePolygon

ラインストリングからポリゴンを生成するにはST_MakePolygonを使います。

db=# SELECT ST_AsText(  
  ST_MakePolygon(  
    'LINESTRING(0 0,3 0,3 3,0 3,0 0)'::GEOMETRY  
  )  
);  
           st_astext              
--------------------------------  
 POLYGON((0 0,3 0,3 3,0 3,0 0))  
(1 行)  

ただし、ラインストリングが閉じていなければなりません。言い換えると、ラインストリングの両方の端点が同じ位置でなければなりません。

ではやってみましょう

db=# CREATE TABLE tpdx (  
  gid SERIAL PRIMARY KEY,  
  geom GEOMETRY(MULTIPOLYGON, 4612)  
);  

db=# INSERT INTO tpdx(geom)  
SELECT ST_Collect(poly) FROM (  
  SELECT ST_MakePolygon(  
    ST_ExteriorRing(  
      (ST_Dump(geom)).geom  
    )  
  ) AS poly  
  FROM tp  
) AS Q;  

このクエリは若干ややこしいので、内側から見ていきましょう。

(ST_Dump(geom)).geomで、マルチポリゴンをダンプして、単一ポリゴンにしています。

ST_ExteriorRingで単一ポリゴンの外側のリングを表すラインストリングを生成します。

ST_MakePolygonでラインストリングをポリゴンにしています。

以上を言い直すと、サブクエリは、マルチポリゴンを単一ポリゴンにして、その単一ポリゴンの外側のリングを抜き出して、ポリゴンにしています。

最後に、ST_Collectを使ってポリゴンをマルチポリゴンにまとめています。

結果

南西部の「隙間」は消えました。

おわりに

結合したポリゴンに「隙間」があった場合の、「隙間」を排除する方法のひとつとして、外側のリングを残して内側のリングを消す方法を示しました。この際、ST_ExteriorRingST_MakePolygonを使いました。

今回は幸運にも「隙間」が排除できましたが、内側のリングが「隙間」以外である場合は、今回ご紹介した方法では対応できません。場合によっては、内側のリングの面積を計測する等して残すリングをフィルタリングする必要があるかもしれません。

この手の処理は、運が良ければクエリを1回実行しただけで終わりますが、トライアンドエラーをえんえんと続けなければならないこともあります。

また、さまざまなPostGIS関数を駆使していく必要もあります。役に立ちそうにない、と感じるようなものでも、ある程度はおさえておくべきでしょう。

出典

広島県ポリゴンの作成にあたっては、国土数値情報(行政区域)を使用しました。

本記事のライセンス


この記事は クリエイティブ・コモンズ 表示 4.0 国際 ライセンスの下に提供されています。