思ったよりも面倒くさかったので、メモ的に残します。
承前
OSMのリレーションオブジェクトも、通常のオブジェクトと同じく、履歴を有しています。
ですので、原理的に言えば、オブジェクトのリバート(巻き戻し)は以下の手順で行なうことが可能です。
- 消されてしまったオブジェクトのID番号を特定する
- 特定したオブジェクトに加えられた変更履歴(Changeset)を特定する
- 特定した変更履歴(Changeset)を Reverterプラグインに入力して、リバート用変更セットを作成
- リバート用変更セットをOSMにアップロードして完了
ただし、リレーション本体が消去されてしまった場合、手順1である オブジェクトID特定 が困難です。
なぜならば、リレーションが消された場合は、以下の理由が組み合わさるためです。
- そのリレーションに所属しているメンバーの履歴は変更されない
メンバー側のジオメトリ、およびタグ情報は変更されていないため、メンバーの履歴にはなにも情報が残りません。
メンバーだったはずのオブジェクトをダウンロードして履歴を追っても無駄、ということです。
- リレーション単体は、OSM上で範囲指定してのダウンロードができない
リレーション自体はジオメトリを持たないため、範囲を指定してのダウンロードができません。
OverPass APIなどでは、リレーションのみを指定してダウンロードする機能がありますが 消えた データはダウンロードできません。
そのため、リレーション単体が削除された場合は、ちょっとした工夫をする必要があります。
ここでは例として、リレーションオブジェクトが消えてしまったために森林リレーションが消えてしまった場合の復旧方法をメモとして残します。
過去データの検索 - PostGIS
過去データを検索する必要があり、そのためにPostGISを利用します。
osm2pgsqlを使って、リレーションオブジェクトが存在していた頃のデータをPostGISに投入します。
過去のデータは、Geofabrikなどからダウンロードするとよいでしょう。
6ヶ月以上前のデータは残していないようなので、それ以上放置されたものについては諦めてください。
PostGISのテーブルは以下のようになっています。
リレーションに関する情報は planet_osm_rels
テーブルに格納されています。
gis=> \d
List of relations
Schema | Name | Type | Owner
--------+--------------------+-------+----------
public | geography_columns | view | postgres
public | geometry_columns | table | gis
public | planet_osm_line | table | nyampire
public | planet_osm_nodes | table | nyampire
public | planet_osm_point | table | nyampire
public | planet_osm_polygon | table | nyampire
public | planet_osm_rels | table | nyampire
public | planet_osm_roads | table | nyampire
public | planet_osm_ways | table | nyampire
public | spatial_ref_sys | table | gis
(10 rows)
gis=>
planet_osm_rels
テーブルの中身は以下のようになっています。
リレーションのオブジェクトIDが id
に格納され、リレーションに所属するメンバーのオブジェクトIDが members
に格納されています。
gis=> \d planet_osm_rels
Table "public.planet_osm_rels"
Column | Type | Modifiers
---------+----------+-----------
id | bigint | not null
way_off | smallint |
rel_off | smallint |
parts | bigint[] |
members | text[] |
tags | text[] |
pending | boolean | not null
Indexes:
"planet_osm_rels_pkey" PRIMARY KEY, btree (id)
"planet_osm_rels_idx" btree (id) WHERE pending
"planet_osm_rels_parts" gin (parts) WITH (fastupdate=off)
gis=>
本来リレーションに参加しているはずだったウェイなどのオブジェクトIDを、OSM上で調査します。そのウェイのオブジェクトIDを、 members
から調べます。
ちゃんとwhere句とか書いたほうがよいのですが、面倒なのと、日本国内程度のデータであればそんなに量がないので、ファイルに出力するなどしてもよいかな、と思います。
これで、削除されたリレーションのオブジェクトIDがわかります。(今回削除されたオブジェクトのIDは 965719 でした)
gis=> select id, members from planet_osm_rels where XXXX;
965719 | {w234503902,inner,w234503903,inner,w62133397,inner, ...etc
このオブジェクトIDの履歴をOSM.orgのウェブサイト上で調べ、削除が行われた変更セットのIDを特定させることで、リバート作業を行います。
書いた後に気が付きましたが、別にPostGISを利用しなくても、.osm形式のファイルに対して直接grepかければ同様の結果が得られるかもしれません。
ちょっとばかりデータ量が多いので処理に時間かかるかもですが、PostGISを使わなくてもできそうなのは利点です。