トップ地図ユーティリティ > OSMデータファイルのバイナリコード化

OSMデータファイルのバイナリコード化

はじめに

本来ならば、OSM地図レンダリング用ファイルもAndroidタブレットで行いたいが、現有機ではパワー不足で難しい。 日本地図領域のOSMファイル(xmlファイル)は約40GBという大きさである。

SAXParserを使って、前処理を行い、結果をバイナリコード化して、複数のファイルに分割したい。 大きくは Node、Way、Relation に分離する。Relation は小さいが、NodeとWayは日本地図領域では、 4GB前後になる見込みのため、1~2GBのファイル数個に分割したい。

SAXParserによるXMLファイルの処理

japan.osm(日本全域 38.3GB)や kanto.osm(関東地方 9.3GB)ファイルを SAXParser で空読みした場合 (Parser.java)、 実行時間は 7.8秒、2.0秒となった。

SAXParserを使わず、自作パーサとした場合、およそ、2倍の速さとなった。

OSMデータのダウンロードからレンダリング用ファイル作成までの全工程としては最低でも2時間くらいはかかる。 実施は数か月~1年に一度であるから、5~10時間かかっても問題はない。 プログラムをスリムにしてメンテナンスしやすくしたい。

中間結果

まだ、プログラムは作成途上であるが、大雑把な見通しはついた。

c:\map>java -Dfile.encoding=UTF-8 -classpath ./class Encoder kanto
sizeStr=12158678, 実行時間: 2.76分  1.18GB

c:\map>java -Dfile.encoding=UTF-8 -classpath ./class Encoder japan
sizeStr=44096108, 実行時間: 12.25分   6.07GB
  1. name、refなど文字列を値とするタグでレンダリング上必要とするものは限られている。 辞書は使わず、バイナリレコードに文字列を含ませても、全体のファイルサイズはそれほど大きくならない。 japan.osm では文字列の総サイズは 44MB程度である。因みに、現在の words_utf16.txt は 約31MBである。

    つまり、文字列コード化の効果はファイルサイズ的には微々たるものである。 地図アプリ map4 では文字列タグのコード化はやめたい。バイナリレコードに文字列を UTF-16形式で含ませる。

  2. 現在の osm_id は5バイトで表現できるため、上位2バイト、下位4バイトとする。 このうち、上位2バイトの上位バイトはレコード種別とする。

最初のプログラムの実行結果

細部の詰めが残っているため、コードは省く。 処理時間、ファイルサイズについては大きくは変わらないと思われる。

ただし、この後の処理の都合により、仕様の変更はありうる。

c:\map>java -Dfile.encoding=UTF-8 -classpath ./class Encoder kanto
maxId=2822F0E7C, sizeStr=19761652, ファイル総サイズ=1.01GB 実行時間: 2.88分

c:\map>java -Dfile.encoding=UTF-8 -classpath ./class Encoder japan
maxId=28230265A, sizeStr=67376558, ファイル総サイズ=5.13GB 実行時間: 13.07分

各オブジェクト数を表示した。ノード数は2億を超える。このため、ノードIDを座標値に変換する処理に手がかかる。 詰め合わせれば、パソコンの場合、座標値テーブル全体をメモリにおける。これまでは、これをキャッシュに展開していた。 大幅な処理時間増がなければキャッシュ展開をやめ、バイナリサーチにした方がシンプルになる。

Androidタブレットではメモリ上の制約から座標値テーブルをファイルに置いて、メモリ上にキャッシュすることになる。

まずは、パソコンで現在よりも簡単な方法を考えたい。

c:\map>java -Dfile.encoding=UTF-8 -classpath ./class Encoder japan
maxId=28230265A, nodes=DF15625, ways=1E8A2CA, rels=1E074, sizeStr=67384394, ファイル総サイズ=5.13GB 実行時間: 12.95分

way の参照ノードIDを座標値に変換する

現プログラムは複雑なことをしているが、バイナリサーチで十分に対応できることが分かった。 全体としては時間増加は問題ない大きさであるから、座標値テーブルはフラットなものとして、 バイナリサーチでノードIDに対応する座標値を得る方法を採用する。

c:\map>java -Dfile.encoding=UTF-8 -Xmx5g -classpath ./class Encoder kanto
maxId=2822F0E7C, nodes=2A6D42B, ways=6B3661, rels=8715, sizeStr=19762866, ファイル総サイズ=1.01GB 実行時間: 3.11分

c:\map>java -Dfile.encoding=UTF-8 -Xmx5g -classpath ./class Encoder japan
maxId=28230265A, nodes=DF15625, ways=1E8A2CA, rels=1E074, sizeStr=67384394, ファイル総サイズ=5.13GB 実行時間: 14.43分

wayを構成するノードについては、ノードIDではなく、座標値を出力するように変更した。 ノードオブジェクトの出力は有効タグを持つものに限定した。ファイルサイズは大幅に減少した。

c:\map>java -Dfile.encoding=UTF-8 -Xmx5g -classpath ./class Encoder kanto
maxId=2822F0E7C, nodes=2A6D42B, ways=6B3661, rels=8715, sizeStr=19762866, 総サイズ=0.53GB 実行時間: 3.03分

c:\map>java -Dfile.encoding=UTF-8 -Xmx5g -classpath ./class Encoder japan
maxId=28230265A, nodes=DF15625, ways=1E8A2CA, rels=1E074, sizeStr=67384394, 総サイズ=2.59GB 実行時間: 13.79分

おわりに

思ったより総ファイルサイズは小さくなった。また、実行時間も速いことが分かった。

特に、ノードIDから極座標値への変換が簡単に行えることが分かったのは大きな収穫である。

後の処理やレンダリングを分かりやすくするため、仕様については、 更に、時間をかけて見直したい。

細かい詰めは行っていないが、現時点のソースプログラムを下に示す。

Encoder.java

Tag.java

リファレンス