OQ_Analysis で建物の品質チェックを行うテスト

OQ_AnalysisOSM にある建物データの品質解析を行うスクリプトで、PostGIS を組み込んだ PostgreSQL 上で動作します。

今回はジオメトリエラーの除去を行う作業のための準備としてある建物とその建物以外のオブジェクトが交差している部分を抽出するテスト行いました。なお、実験中に OQ_Analysis のリポジトリが更新され、機能が増えたみたいです。

実行した環境は VirtualBox 上の Ubuntu 19.04 でメモリは 2GB 割り当ててあります。

テストに使うためのデータは Geofabrik 社のダウンロードサービスから四国のデータをダウンロードしました。同サービスにある日本の中では最も小さいデータサイズになっていることが決め手です。

流れとしては - PBF を PostgreSQL にインポート - OQ_Analysis で交差地物の抽出 - PostGIS で交差をポイントまたはラインに変換 - ogr2ogr で結果を GeoJSON 化 みたいな感じです。

とりあえずできたのですが、課題は残っています。

パッケージインストール

PostgreSQLPostGIS は当たり前として、osmosis は pbf データを PostgreSQL にインポートするために使います。 ogr2ogr でもできますが OQ_Analysis の例では osmosis を使っていたのでそのまま使ってみることにしました。 GDAL は最後に ogr2ogr を使ってデータを GeoJSON で取り出すために入れてあります。

$ sudo apt install postgresql postgis osmosis gdal-bin git -y

データベースの初期化

ユーザーとデータベースを作って拡張を読み込みます。

$ sudo -u postgres createuser -sP zoar
$ sudo -u postgres createdb -O zoar oq_analysis

$ psql oq_analysis -c "CREATE EXTENSION postgis;"
$ psql oq_analysis -c "CREATE EXTENSION hstore;"

osmosis のスキーマを登録します。

$ psql oq_analysis \
-f /usr/share/doc/osmosis/examples/pgsnapshot_schema_0.6.sql
$ psql oq_analysis \
-f /usr/share/doc/osmosis/examples/pgsnapshot_schema_0.6_action.sql
$ psql oq_analysis \
-f /usr/share/doc/osmosis/examples/pgsnapshot_schema_0.6_bbox.sql
$ psql oq_analysis \
-f /usr/share/doc/osmosis/examples/pgsnapshot_schema_0.6_linestring.sql

OQ_Analysis のインストール

今回使いそうな部分だけをインストールします。

$ git clone https://github.com/pierzen/OQ_Analysis.git
$ cd OQ_Analysis/sql/Analysis
$ psql oq_analysis -f OQ_01_Analysis_Table_Ways_Topology.sql
$ psql oq_analysis -f OQ_01a_Building_Analysis.sql
$ psql oq_analysis -f OQ_01b_Topology_Intersect_Analysis.sql

OSM データのインポート

osmosis を使って四国のデータをインポートします。

$ cd ~
$ mkdir pbf; cd $_
$ wget http://download.geofabrik.de/asia/japan/shikoku-latest.osm.pbf 

$ osmosis --read-pbf shikoku-latest.osm.pbf \
  --write-pgsql database=oq_analysis \
  user=zoar password=%password%
$ psql oq_analysis -c "SET search_path TO public"

解析

建物と交差している地物をテーブルに保存します。

$ psql oq_analysis -c "CREATE TABLE public.intersected_buildings AS SELECT id, id_b, teval, eval FROM public.OQ_01b_Topology_Intersect_Analysis('public')"

intersected_buildings はこんな感じのテーブルになります。

カラム名 内容
id 建物ポリゴンのID
id_b 交差している地物のID
teval 建物同士ならXB,違えばXO
eval JSONBオブジェクト

eval には JSON なデータが入ります。

キー名 内容
flag "1"(意味はわからない)
grptag 建物オブジェクトの種別
grptag_b 交差した地物の種別

grptag には building、grptag_b には building, landuse, highway, other の様な値が入っています。

このテーブルにはジオメトリのデータがないのでこの後交点や重複部分などのジオメトリを作ります。その内容に加えて eval の内容を json_populate_record でカラムとして展開したいのでそのために必要な型を用意します。

$ psql oq_analysis -c "CREATE TYPE eval AS (flag text, grptag text, grptag_b text)"

ST_Intersection を使って idid_b の地物の交差オブジェクトを作成します。OSM のデータをインポートした際の ways テーブル にある linestring カラムがジオメトリデータなのでそれを取ってきて関数に渡します。
ST_Intersection で作成された交差オブジェクトに eval の内容を展開して属性にしておきます。

$ psql oq_analysis -c "CREATE VIEW public.intersected_objects AS SELECT ST_Intersection((SELECT linestring FROM ways WHERE id = r.id), (SELECT linestring FROM ways WHERE id = r.id_b)) AS geom, (json_populate_record(NULL::eval,(eval)::json)).* FROM (SELECT * FROM public.intersected_buildings) AS r"

CREATE VIEW してるだけなので一瞬です。

エクスポート

出来上がったビューを GeoJSON としてエクスポートします。

$ ogr2ogr -f GeoJSON intersection_objects.geojson \
"PG:host=localhost dbname=oq_analysis user=zoar password=%password%" \
-sql "SELECT * FROM public.intersected_objects"

ogr2ogr は取り出したテーブルの先頭に近い方のカラムから見ていってジオメトリカラムを見つけたらそれを GeoJSON のジオメトリにしてくれるみたいです。

出来上がった GeoJSON に「GeometryCollection」というちょっと想定外な地物があるのでこれをなんとかしたりしないといけません。

おわり

さて、最後にはこのデータを MapRoulette に登録できるようにしたいので MapRoulette の課題にするための JSON 形式に合わせないといけません。
ついでに MapRoulette インスタンスも立てたいのですが、まだ立てられないのでこっちもなんとかしないと…。

ついでに更新する度にこれだけコマンド打つのも面倒なので Dockerfile でも作って楽に更新したいですね。

PostGIS 使うの初めてだったけど割とできた方なんじゃない?