読者です 読者をやめる 読者になる 読者になる

ちずぶらりHackers

オープンデータ化も進んでいる古地図、絵地図を扱うiOSアプリ、ちずぶらりをハックし倒します。iOS / Androidでのクローンアプリの開発も予定しています。

回転/連続ズームも扱えるiOS FOSS4G地図ライブラリ「RouteMe」の紹介

当エントリは、 FOSS4G Advent Calendar 2011 の12月23日分として投稿したものです。ぜひ他の方のエントリも御覧下さい。

京都と奈良の県境でiOS向け古地図アプリを開発しているこちずふぁんというものです。
はじめまして。以後お見知りおきを。*1
12月19日分を書いた@monomotiは同僚です。*2

iOSでのFOSS4G開発というと、最近はXcodeのバージョンが上がってコンパイラGCCからLLVMに変わり、GEOSのコンパイルLLVMで通らねー!俺の知識じゃどうにもならねー!といったあたりの苦労もあるのですが、今回のネタはそれではありません。
でも枕で少し触れたので、これからiOSでGEOS使おうという方が使えるよう、旧XcodeコンパイルしたlibGeos.a 直置いときますね。*3
GEOSバージョンは3.2.2、armv6/7、i386ユニバーサルバイナリになってますが、今のところ新しくコンパイルできないので他のアーキテクチャが出てくるとうちのプロダクトは破滅です。

連続ズームとはなんぞや?

さて、今回の主題ですが、我々の古地図アプリ上で使っているiOS向けFOSS4G地図エンジンRouteMeを紹介すると共に、そのRouteMeが扱える連続ズーム機能や回転機能を紹介し、私の連続ズームLOVE分を発散させていただこうという形になっております。

連続ズームというのは聞き慣れない言葉かもしれません。
どのようなものかを知ってもらうには、まず対立概念でありより一般的である、離散(非連続)ズームについて知ってもらうのがいいと思います。

ピンチイン/アウトしても指を離したところで地図が止まらずに、少し戻ったり或いは進んだりして、決まった縮尺にしかなれないのが判りますでしょうか?
これが離散ズームという奴で、ズームレベル*4が整数値しか取れない地図エンジンであるがためにこのようになっております。

これに対して連続ズームは、中間値である小数ズームレベルを許容してくれるため、ピンチイン/ピンチアウトしてもきっちり指を離した時のサイズで止まってくれます。これはなかなか気持ちいい。

iOSの標準地図*5がこれですね。このヌルヌル感に惚れ込んだ人も多いと思います。

連続ズームを完璧に扱えるのはRouteMeだけ!(多分…)

サンプルでお見せしたようにiOSの標準地図、及びそのSDKであるMapKitは連続ズームを扱えるのですが、実は完璧ではありません。
ユーザのピンチイン/ピンチアウト操作による小数ズーム値は取れるのですが、プログラムロジックの方からズームを制御しようと思うと、途端に整数ズーム値しか扱えなくなるのです。
正確には、MapKitは直接ズームレベル値を扱えないので表示したい経緯度範囲で指定するのですが、端から端までぴったりの範囲で地図を描画したいと思って範囲を指定しても、その範囲を全て含みつつ最小の整数ズームレベルに勝手に正規化されてしまい、指定した範囲より少し広い範囲が表示されてしまいます。

実はAPIで普通に小数ズーム値を指定でき、完璧に連続ズームを扱える地図ライブラリが、iOSには存在します。
それが、今回紹介したいFOSS4Gライブラリ、RouteMeです。

連続ズームを扱えると何が嬉しいのか

RouteMeの動作サンプル動画をお見せする前に、連続ズームを扱えると何が嬉しいのかということを説明したいと思います。
まず第一には当然ながら、ユーザ操作の気持ち良さですね。タッチデバイスでのヌルヌル感を一度味わってしまうと、連続的に扱えない離散ズームには戻れなくなる。
でもそれだけならばMapKitと同様、ユーザ操作の時だけ連続ズーム、API経由では離散ズームでも問題ありません。

API側の連続ズームができれば何ができるかというと、ロジックで今画面に表示されている地図範囲を「完全に」把握/制御できるようになります。
それはすなわち、いろいろな用途のために様々な縮尺で作られた地図に対して、コストをかけて同じ縮尺にコンテンツを作り直さなくとも、ロジック側でむりやり表示範囲を制御し標準地図と同一縮尺の地図として、ぴったり重ね合わせる事ができるという事です。*6
実際にそのような事例を見ていただきましょう。

標準のMapKitの地図表示範囲に対して、全く異なる縮尺で作られた様々な古地図を(元地図の歪みで生じる誤差を無視すれば)ぴったり重ね合わせて切り替える事ができています。
これは、古地図表示側に使っているRouteMeライブラリが、API側から制御できる連続ズーム機能と、もう一つは地図の回転機能を持っているが故に実現できる事です。

このような異なる地図を重ね合わせるアプリを作る場合、それをぴったり重ね合わせられるか否かで、与えられるユーザ体験が異なるのは明らかです。

もしこの機能を持ったRouteMeライブラリと出会わなければ、私が今作っている古地図アプリも実現できなかったかもしれません。

RouteMeは決して新しいライブラリではなくむしろ古いライブラリで、確か使い始めた頃に読んだ記事だと、iOS上で標準地図SDKのMapKitが提供される前から開発が始まっていたライブラリです。
が、開発のかなり初期の段階から既にこのような連続ズームや回転機能への対応は含まれていて、その先進性はこれまで使った事のある地図エンジンの中でも随一です。
サンプルも充実していますし、またOSM、Bing Map、WMS等、FOSS4G界隈御用達のマップソースに対応したタイルソースクラスはあらかじめ用意されているので、比較的抵抗も少なく使い始められます。
ピンの配置やライン/ポリゴンの配置等、地図エンジンに必要な機能も十分です*7

これまで離散ズームしか扱ってこなかった方々も、是非RouteMeで気持ちのよい連続ズームの世界に足を踏み入れ、その奥深さに触れられてはいかがでしょうか。

Androidでの連続ズームの世界

さて、実はFOSS4G関係はここまでですw。
この後は連続ズーム繋がりでネタを続けさせてもらいます。

iOSではここまで採り上げた通り、標準地図やMapKitではユーザ操作による連続ズームまで、RouteMeでは完全な連続ズームに対応しています。
Androidの事情はどうでしょうか。

Androidの標準地図は、実はiOS以上に進んでいます。
地図ソースがラスタ画像からベクタデータに進化しているので、地図が連続ズームや回転に対応しているだけでなく、地図上の表記が中間ズームでにじんだり回転して表示される事もなく、完全に正位置を保って表記されます。
が、悲しいかな、2011年12月現在、この最強地図機能はSDK化されておらず、まだ開発者には公開されていません。
開発者がGoogle地図を扱う場合は、前世代の離散ズームで回転もできない地図エンジンを使うしかありません。
その意味で、今のところiOSAndroidの標準地図事情は一長一短というところ。
早く最新版地図のSDKを提供してくれ、Googleさん!

標準地図以外のライブラリでは、オープンソースではOSMAndOSMDroidといった地図エンジンがありますが、私の知る限り連続ズームに対応しているライブラリはありません。
が、オープンソース/フリーでなくてよければ、Nutiteq社というところが現在開発中で、来春3月あたりに発売予定のAndroid向けSDKが、この連続ズームと回転機能を完全に備えています。
うちの古地図のタイルを使ったサンプルを先方に作ってもらったので、動画で紹介します。*8

OpenGL(だったかな?)とかのグラフィックAPIを使ってるそうで、動画で動かしているのはAndroid3.2ですが、Android2.1くらいでも普通にヌルヌル動きます。
最終的にはAndroid1.6での動作まで保証したいとの事。
単に連続ズームと回転機能だけではなく、ベクタデータへの対応機能も持っているので、データソースさえあればGoogle標準地図のように常時正位置の地図表記もできますし、面白いところでは2本指で手前に引いたり奥に押したりする事で、斜め上から見たような簡易鳥瞰図表示させる事も可能です。
ライセンスは現在検討中という事ですが、旧ライセンスは年間6000ユーロの商用ライセンスと、GPLでのデュアルライセンス制ですので、新SDKももしかしたらフリーのライセンスも期待できるのではないかと思います(判りませんが)。


以上、FOSS4Gと言いながら最後には商用ライブラリの宣伝まで入ってしまった看板に偽りありの記事になってしまいましたが、こんな感じでもよかったのでしょうか… > @waigania13
明日はクリスマスイブ、フィンランドの地から@usuyuの提供です!

*1:元の人などいない!

*2:くそ、コードサンプルなんか書いてハードル上げやがって…うちの記事にはコードサンプルはないよ!コードサンプルが目的ならとっとと帰ってくんな!

*3:というか、今回のエントリはFOSS4Gネタの名を借りた連続ズームLOVEネタなので、FOSS4G分少ないやんけ!というツッコミを恐れてこの位はやっとこうと

*4:ズームレベルとは、世界全図を256x256ピクセルで表した地図をズームレベル0とし、1辺256x2^1の512ピクセルで表すのをズームレベル1、256x2^2の1024ピクセルを2…256x2^nピクセルをズームレベルn、として表した縮尺の表し方です

*5:サンプル画像自体そうですが

*6:実際には、重ね合わせるには表示範囲制御だけではなく方角を制御する回転機能も必要ですが、RouteMeはそちらにも対応しています

*7:回転機能を持っているライブラリらしく、ピン等は地図の回転に合わせて一緒に回転するか、それとも飽くまで正位置のまま表示し続けるか、といった事まで選択可能です

*8:Nutiteq社の許可をいただいています

© TileMapJp/歴史国土/地図タイル工法協会