トップ地図アプリMap > マイ・モバイル地図の変遷
OpenStreetMapとの出会い[2015.2.17]

マイ・モバイル地図の変遷

モバイル地図開発のスタート

8年ほど前、週1日程度は出かけていたと思うが、概して暇になったので、 神奈川、東京などで散歩や軽いハイキングをすることが多くなった。 方向音痴のため、モバイル地図が欲しくなった。

当時でも通信費はそれほどかからなかったかも知れないが、 たかが地図のために通信費はもったいないという思いから、ネットなしで使える地図を目指した。

スタートから国土地理院地図と OpenStreetMap(OSM)[1] をサポートした。 国土地理院地図はダウンロードしたタイル画像地図を表示するだけなので、簡単である。

一方、OSMはxml形式のデータからタイル地図をレンダリングする必要があるため、桁違いに難しい。

全てフリーソフトで構築する方法が主流であるが[2]、自分の場合、プログラミングが好きなことと、 個人利用で、オフライン利用であるから、サーバーは要らない。

geofabrik[3] からダウンロードした japan-latest.osm.pbf ファイルを osm2pgsql を使って PostgreSQL/PostGISデータベースにインポートする。 レンダリングソフト Mapnik を使って、タイル地図画像ファイルを生成した。

Mapnikを使うに当たっては、自分にとっては初めての python の知識も必要であり、 Mapnik独自のレンダリング用のスクリプトの理解も必要であった。

また、当然、GPSデータの入力も必要であり、 そんなこんなで、最初のシステム開発には2,3か月を要したと思う。

最初の1年は10インチの Windowsタブレットを持ち歩いた。 しかし、これでは持ち運びが大変であり、1年で6インチタブレットに変更した。

スタートから3~5年目頃

今はまた osm2pgsql の Windows版があるが、数年、使えない時期があった。 そのうち Mapnik も Windows 版がサポートされなくなった。

Oracle VM VirtualBoxを導入して Ubuntu で Mapnik を使うことにした。 このとき、python を使うことをやめ C++ で Mapnik を動かすようにした。

OSM は発展を遂げており、関連フリーソフトもこれに同期して、高度化し、パフォーマンスも 向上している。

Mapnik(osm2pgsql)によるレンダリングのカスタマイズには Lua言語が使われるようになり、 しばらくの間この言語も使った。

PostgreSQL関連でもPL/pgSQLを使ったことがある。

スタートから6年目頃~2022年

プログラミングが大好き人間でも、これだけ振り回されるといい加減うんざりしてくる。

フリーソフトから徐々に離れて、極力、自前プログラムに移行した。

7年目にタブレットからスマホに移行して、ますます、その傾向を強くした。 スリムで分かりやすくハイパフォーマンスな地図アプリに向かって進んでいる。

最初のスマホ用地図アプリでは、陸地ポリゴンを描画するだけのために、 PostgreSQL/PostGIS を使っているが、新地図アプリでは、これもやめて、 Overpass APIで海岸線データを取得して、陸地ポリゴンを描画する予定である。

Overpass APIは OSM の最初の API よりも桁違いに強力である。

2023年~2024年

1年前後かけてOSMバイナリレコード作成を全面的に見直した。 パフォーマンス向上もさることながら、プログラムの分かりやすさを追求する。

  1. 陸地ポリゴンはシェイプファイル経由ではなく、 OSMデータの海岸線(natural=coastline)を繋ぎ合わせて陸地ポリゴンとする。 低ズームはノードを間引いてデータ圧縮し、高ズームは大きなポリゴンは小さく分割する。

    しばらくして、独自方式をやめた。シェイプファイルを PostgreSQL/PostGIS にインポートして、 分割ファイルと低ズーム用ファイルをそのまま使う方式に戻した。 パフォーマンスは独自方式よりやや劣るが、レンダリングした結果を再利用する方式に変えたので、 問題はない。

  2. OSMParser(OSMのxmlファイルをレンダリング用のバイナリレコードに変換する)での node(折れ線や多角形の頂点)座標値はブロック単位の配列で管理する。

    検索は二分探索(binary search)とした。近傍の値の検索が続くときは順次検索(sequential search) でよいため、パフォーマンス上は全く問題がないことが分かった。

  3. 座標値列データは可変長バイトコードにより圧縮を図るようにした。
  4. 中低ズームタイルのレンダリングには時間がかかるため、レンダリング結果を保存して、 再利用する方式に変更した。

概ね完了し、現在使用中の地図アプリより進歩した面はあるが、複雑化した面もあり、若干の不安もある。 やはり、もっとシンプルにしたいという思いがある。

パフォーマンスに拘り、複雑化したことを否定できない。 どこかでチョンボして、パフォーマンスロスが潜在している懸念もある。

再スタート(2024年5月~)

地図アプリをパソコンからスマホに移植した時、一時的に3つのアプリに分割していた。 このときは、HTTP通信を使っていた。 ほどなくして、一つのアプリに統合した。

今度は地図表示アプリと地図サーバーアプリに二分してみる。タイル画像ファイルの作成はサーバー、 読み込みは地図表示アプリとなるが、リクエストとレスポンス(タイル画像作成完了通知)は broadcast を使う。

国土地理院地図のタイル画像のダウンロードは取りあえず、地図表示アプリで行う。 補助的使用のため、当面、先行ダウンロードは行わない。先行ダウンロードも行う場合には、 ダウンロードを地図サーバーに移す方がよいと思われる。

可変長バイトコードは有効かどうか再考したい。3.3GBから2.6GBへ2割以上縮小しているが、 プログラムは複雑化している。

可変長バイトコード自体では3、4割の圧縮効果があるが、空間検索高速化のために、 管理データが必要となった。以前の差分コードでも2割前後の圧縮効果はある。

OSMバイナリレコード形式も課題となる。タグの追加で enum を変更すると、 一からデータの作り直しになるのもできれば避けたい。

現在の OSMのタグ仕様を全面的にチェックして、全タグを盛り込むのも楽ではない。 最初のフェーズ Encoder では、enum によるコード化は行わない案もある。 タグ部のサイズは数倍の大きさになるとしても、全体の大きさは2倍にはならないだろう。

way_area や中心座標をレコード形式の表に出すか、tag部に含めるかも悩ましい。 tag部に含めた方が見かけはシンプルで、tag部のどこにあってもよい。 表にだすと、有無を表すフラグがいる。

可変長バイトコードはやめる。name:en、name:ja もやめ、文字列コードは utf-16 に戻して、 バイナリレコードは short配列に戻した方がよいだろう。あるいは、タグ部を4バイトの倍数に調整して、 レコードをメモリ上はint配列とした方がいいだろう。

元々、簡単化を目指したが、そうはなっていないので、再度、仕切り直しである。

リファレンス

[1] JA:OpenStreetMap について
[2] OpenStreetMapのタイルサーバを構築する (CentOS7)
[3] Download OpenStreetMap data for this region: Japan
[4] JA:Overpass API
[5] 第 40章PL/pgSQL - SQL手続き言語