2010年6月26日土曜日

GoogleMapのデータモデルの妄想

GoogleMapsは皆さんご存知の事と思います。
タイルの格納の仕方だとか、スケール問題がどうとか、
そういう話は見た事があるのですが、
このタイルをどうやって生成しているのか、
地図をどうモデル化しているのかはあまり公開されていません。

解っているのは、PostGIS的何かをHadoop的何かで
やたらスケールできるように作り直したDBのようなデータを、
多言語対応したMapServer的何かを使って
庶民には想像もつかないレベルのCPUパワーで
タイル生成を行っている、という事ぐらいです。

そこで生成されたタイルから、少し考えてみようというのが今日のお題です。

GoogleMapsと一言で言っても、少なくともMapとSatelliteの
2種類のデータを使っているのはご存知の通りです。
しかし簡単な操作で、それだけではない事が解ります。

本好きなら行かずにおれない古本屋街小川町駅付近のGoogleMapsです。



これをMapモードにするとこうなります。


もうひとつ、Satelliteのまま、ラベル表示を消すとこうなります。


この、Satelliteの状態+ラベル表示は、OpenLayersを上げるまでもなく
地図表示のレイヤーにラベルのレイヤーを重ねて表示が実現されています。
重ねているレイヤーだけ取り出すとこうなります。



見やすいように背景を透明からグレーにしてみました。
実際にはこれが透過PNGになっていて、衛星画像のjpgに重ねて表示する事で
衛星+地図となっています。
当たり前すぎることですがMapで表示しているものとは明らかに異なります。


衛星画像に重ねている地図画像を、Mapsの地図と比べてみると、
地図画像は歩道など一つ一つのディティールが角度まで書かれているのに対して、
重ねている道路レイヤーは道路が始点と終点、太さのみで書かれていて
おそらくは道路地図のベクタから生成されている物と考えられます。

これより、GoogleMapsでは
* 衛星画像のラスタレイヤ
* 地図画像のラスタレイヤ
* 道路と、鉄道と、地名表示用のベクタレイヤ
をそれぞれ持っている事が何となくわかります。

次に、地図を縮小してみます。地図表示にして、

zoom=19では


*細かい建物名の表示 + 地図記号(銀行など)

zoom=18では
*バス停表示
*大きな建物名表示
*小さな建物の輪郭

zoom=17
*中くらいの建物の輪郭

zoom=16



* 大きな建物表示

などなど、段階があるのはわざわざ見ないでもご存知と思いますが
大切なのは、ズームレベルごとに見える物が変わっていくという事は
それぞれの地物は別々の地物としてshapeを持っていて
決して一枚のラスター画像を縮小コピーしているのではない、というところです。
それぞれの地物は表示すべきズームレベルをあらかじめ持たせていて、
タイル生成の際に
zoom=16なら中くらいの建物もレンダリング、
zoom=17ならバス停もレンダリング、
zoom=18なら小さな建物名もレンダリング、

というように、タイルに書くべき物を選択していると考えるのが自然です。


同じ建物でも、zoomレベルによって表示するもの、しない物があったり、
道路もzoom5〜zoom17まで
各レベルで書くもの書かない物を細かく調整しており、
少なくとも12段階の表示レベル的指標を各道路が持っているようです。
ラスタも、ラスタではなくベクタかラスタ集合で持っていて
差分更新的何かで更新していっている物と考えられます。


...すいません、元気なくなってきました。
早足でまとめると、

現状、どのズームレベルでレンダリングすべきか、は
Mapserverやosmarender、mapnickが決定していて
タグなど(highway=primary)で決定されますが
そういった論理的なタグと、レンダリングすべきレベルは別に持っているらしい点が一つ。

もうひとつ、論理的な道路の開始/終了と、その経路のベクタと、
各交差点の形状などのラスタは別のレイヤにあるということ。
は見習うべきだと思いました。
どちらも現状ではOSMのデータも、論理構造に終止するPostGISにもなさげです。

きれいにまとまってませんが、今日はこの辺で。