低ズーム世界地図用OSMデータの抽出をOsmosisで実行してみた。 エリア別の osm.pbf は合計約 50GBであるが、 ダウンロードは欧米が真夜中の時間帯だと特に問題はないようだ。
その後、この巨大な osm.pbf からごく少量のデータを取り出すのが大変な仕事になる。
実行時間がかかっても、できれば osmosis のみで実現したい。 これまでは 4GB を超える osm.pbf ファイル(asia, north-america, europe)では ディスク不足やメモリ不足エラーが起きている。
メモリ不足はこれまで使っていた java が 32ビット版だったのが原因のようだ。 64bit版をインストールして、オプション指定で解決した。
ディスク容量不足は tempdir を外付けハードディスクとすることにより解決した。 osmosis の場合、巨大な一時ファイルが作成されるが、 アクセス頻度はヘビーでないため、SSD でなくても問題はない。
これで再挑戦して、無事、所期の目的を達成できた。 しかし、個人的には世界地図の必要性は少ないことから、まだ物足りない。
タグ・フィルタリングを3つに分ける。 第一は国名・都市名の point 情報である。 line(ライン) および polygon(エリア)は way および relation で表現されるので、 第二を way 、第三を relation としている。 ラインは、道路、国境・県境など、エリアは森林、湖などを描画するためのデータである。
africa は 43分で、node_temp が 7GBx2 となり、way_temp が生まれた。 一方は 82MB、もう一方は 1時間で 3.2GB となり、rel_temp(2MB) と新たな node_temp が生まれた。 node_temp は 1時間40分で 7GB となった。 ほどなくpbfファイル出力が始まり、2時間10分で終了、230MB となった。
south-america は 1時間8分で全工程を終了した。出力 osm.pbf は 376MB となった。
europe は 2時間27分で、node_temp が 27.7GBx2 となり、way_temp 作成が始まった。 一方は9分後 89MB で止まった。 もう一方は増え続け 3時間25分で 15.3GB で止まり、rel_temp(34MB) と新たな node_temp が生まれた。 node_temp は大きくなり 5時間36分 27.7GB で止まった。 約30分後 pbfファイル出力が始まり、7時間23分で全工程を終了した。 出力 osm.pbf は 1.47GB となった。
extract europe extract north-america extract asia extract africa extract antarctica extract australia-oceania extract central-america extract south-america[extract.bat]
set JAVACMD_OPTIONS=-server -Xmx3G -Djava.io.tmpdir=e:/tmp osmosis ^ --rbf e:/world_osm/%1.osm.pbf ^ --tf reject-relations ^ --tf reject-ways ^ --tf accept-nodes place=country,state,region,province,county,city ^ ^ --rbf e:/world_osm/%1.osm.pbf ^ --tf reject-relations ^ --tf accept-ways natural=wood,water,sand,desert,heath landuse=forest admin_level=2,3,4 ^ highway=motorway,trunk waterway=riverbank ^ --used-node ^ ^ --rbf e:/world_osm/%1.osm.pbf ^ --tf accept-relations natural=wood,water,sand,desert,heath landuse=forest admin_level=2,3,4 ^ highway=motorway,trunk waterway=riverbank ^ --used-way ^ --used-node ^ ^ --merge --merge ^ --wb e:/wosm4lz/%1.osm.pbf
試行錯誤のすえ、上のコマンドに落ち着いたが、これがベストとは限らない。 気が向いたときに、改良案を模索したい。
最初の二つの node tempファイルは、 多分、第二、第三ブロックの --used-node に対するもので、 次の大きい way temp ファイルは --used-way に対応するものであろう。
この憶測が当たっているとしたとき、 最初の二つの node tempファイルの内容は同じものだろうか? もしそうなら、極めて非効率である。 しかし、一つ当たりの CPU使用率は 30% 程度であるため、 node tempファイル作成時間帯の CPU負荷が高くなるだけであるから、 非効率だとしても、全体の所要時間の増加は招いていない。
第三の node temp ファイルが何に対応するかは想像がつかない。
抽出された osm.pbf ファイルのサイズは小さいので、全体を一つにすることも可能であるが、 PostgreSQL+PostGISデータベースにインポート後、更にテーブルを小さくする都合から、 europe、north_america、asia はそのままで、 その他(africa, south_america, central_america, austraria-oceania, antarctia)を south として ひとまとめにする。
--merge の個数は「マージするファイル数-1」である。
set JAVACMD_OPTIONS=-server -Xmx2G -Djava.io.tmpdir=e:/tmp cd d:/wosm4lz osmosis ^ --rbf africa.osm.pbf --rbf antarctica.osm.pbf --rbf australia-oceania.osm.pbf ^ --rbf central-america.osm.pbf --rbf south-america.osm.pbf ^ --merge --merge --merge --merge ^ --wb south.osm.pbf
europe.osm.pbf(22GB)の場合、メモリ使用量が 2GB を超えた。 正確には 2x1024x1024x1024 byte未満だったのかも知れない。 エラーは起きなかった。安全のため -Xmx2G を -Xmx3G に変更した。
巨大な node の一時ファイルが三度も作られる。 サイズから想像すると、同じものが3度も作られているのかも知れない。
これならば、別々に実行して、結果をマージするのと大差がないだろう。
asia を同時に実行した場合、node は 13分、way は1時間50分で終わった。 relationでは node, way のtemp ファイル作成後、小さい relation の temp ファイルと 再び大きな node の temp ファイルの作成が始まった。なぜ、二度も作成されるのか分からない。
relation は 3時間13分かかった。
osmosisが生まれた頃は planet.osm.pbf は小さく、問題なかったのであろうが、 巨大化した今日で、パフォーマンスに難があると言えよう。 このため、新しい o5m フォーマットが登場したものと思われる。 しかし、osmosis、pbfフォーマットほど普及していないのが問題である。
set JAVACMD_OPTIONS=-server -Xmx3G -Djava.io.tmpdir=e:/tmp osmosis ^ --rbf e:/world_osm/%1.osm.pbf ^ --tf reject-relations ^ --tf accept-ways natural=wood,water,sand,desert,heath landuse=forest admin_level=2,3,4 ^ highway=motorway,trunk waterway=riverbank ^ --used-node ^ --wb d:/wosm4lz/%1_way.osm.pbf[extractrel.bat]
set JAVACMD_OPTIONS=-server -Xmx3G -Djava.io.tmpdir=e:/tmp osmosis ^ --rbf e:/world_osm/%1.osm.pbf ^ --tf accept-relations natural=wood,water,sand,desert,heath landuse=forest admin_level=2,3,4 ^ highway=motorway,trunk waterway=riverbank ^ --used-way ^ --used-node ^ --wb d:/wosm4lz/%1_rel.osm.pbf[extractnode.bat]
set JAVACMD_OPTIONS=-server -Xmx3G -Djava.io.tmpdir=e:/tmp osmosis ^ --rbf e:/world_osm/%1.osm.pbf ^ --tf reject-relations ^ --tf reject-ways ^ --tf accept-nodes place=country,state,region,province,county,city ^ --wb d:/wosm4lz/%1_node.osm.pbf
この分割は、データベース上のテーブルとは一致しない。node は point と一致するが、 way, relation はテーブルでは双方とも line と polygon に分かれる。
このため、merge してからインポートする。asia のマージは 17分かかった。
分割した場合、2,3のジョブを並行処理できるため、世界全体の実行時間を短縮できる。
[merge.bat]set JAVACMD_OPTIONS=-server -Xmx3G -Djava.io.tmpdir=e:/tmp osmosis ^ --rbf d:/wosm4lz/%1_node.osm.pbf ^ --rbf d:/wosm4lz/%1_way.osm.pbf ^ --rbf d:/wosm4lz/%1_rel.osm.pbf ^ --merge --merge ^ --wb d:/wosm4lz/%1.osm.pbf
圧縮ファイルを解凍する。
osmosis --rbf d:/downloads/japan.osm.pbf --wx d:/osm/japan.osm
1.74GB を解凍すると 43.2GB(ディスク上のサイズ 11.0GB) となった。 今回は JOSM を使いながら実行したため 1時間15分かかったが、 単独実行であれば1時間前後だろう。
osmosis --rbf d:/downloads/kanto.osm.pbf --wx d:/osm/kanto.osm
kantoの場合、301MB を解凍すると 6.52GB(ディスク上のサイズ 1.67GB) となった(実行時間10分)。
解凍するとサイズが大きいので、パイプで受け取り処理をしたい場合がある。 stdout に出力するにはファイル名を - とすればよい。
c:\gisa>osmosis --rbf japan-latest.osm.pbf --wx file=-
マルチスレッドで実行するときは --rbf(--read-pbf-fast) workers=スレッド数 を使う。
c:\gisa>osmosis --rbf workers=2 japan-latest.osm.pbf --wx file=-
ようやく osmosis だけで所期の目的を達成できた。 滅多に更新しないため、現在の所要時間はそれほど問題ではないが、 今後、osmosis を使い慣れることにより、改善方法も見つかるであろう。
ここで得た ***.osm.pbf ファイルを osm2pqsql で PostgreSQL+PostGISデータベースに インポートすれば低ズーム世界地図がレンダリングできるが、 無駄が多い。
道路や森林などの way を構成する node の数は大幅に間引いた方がいいし、 面積の小さいエリアは実際上描画できないため、データベースから削除した方がいい。
このような操作は残念ながら osmosis ではできない。 生の osm.pbf に対してこれができるソフトは知る限りでは存在しない。
データベースに読み込んで、PostGIS を使えば、node を間引くことができる。 また、osm2pgsql、imposm でデータベースに読み込むと、 インポート時にエリアの面積が計算され、データベースのテーブルに 面積カラムが付加されるため、面積の小さい水域や森林データ(レコード)を除去できる。
osmosis の管轄ではないので、詳細は別のページに記載する。
シンプルな処理ならば、osmosis で プレーンテキスト(xml形式)化したものを パイプで受け取れば実現できる。 しかし、合計 50GB もの pbf ファイルを xml に戻すと、 テラバイト単位の巨大なものになるため、処理に時間がかかる。
一見した限りでは、pbf のファイルフォーマットは複雑なため、 これを自作プログラムでバイナリファイルとしてランダムアクセスするのは楽ではない。
しかし、それがもし可能ならば、最初に時間をかけて temp ファイルを作成しない。 最初に、抽出対象のrelationを調べ、そのメンバーである way を取り出す。 それに抽出対象の way を加える。数の多い建物、住宅内道路などは含まないので、 この数は比較的少ない。
次にこの way が参照している node の id をハッシングして、 ビットマップにセットする。対象となる node 数が比較的小さいため、 ビットマップは 128MB でもよい。
次に、先頭から node の定義を調べて、その id が ビットマップにあれば、 出力する。
要するに、巨大な node temp ファイルは作らない。
よく理解すれば、osmosis でもこのような動きをするオプションがあるかも知れない。 一番の問題はまだ osmosis に精通していないことであろう。
プログラミングが趣味であるから、 自作ソフトもいいが、osmosis もあれこれ使い込みたい。