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

ちずぶらりHackers

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

来るべき?MapStoreの時代、最適な地図のリコメンデーションを提供する技術案

AppleiOS地図でやらかして以来、地図の多様性に世間の目が向き、多様な地図の中から自分に合った物を選択する、さらにはTPOや状況に応じて地図を使い分けると言う発想も、以前よりは市民権を得てきているように感じています。
また、そこから一歩進んで、ユーザが使うアプリの機能は同一ながら、地図だけを差し替えるAPIと地図の分離や、ユーザがお金を払ってでも使いたいと思う地図*1を個別購入できるMapStoreという考え方も、一部ではメジャーになってきているのではないかと感じます*2

もしMapStoreのようなものが実現できれば、そこで流通の対象となるのはGoogle MapsOpenStreetMapクラス、或いはY!地図やMapion電子国土クラスのような、全世界地図や日本全国地図レベルのユニバーサル地図だけではない、と私は考えています。
もっとカジュアルに、いろんなクリエイターが自分の街の楽しい地図を出したり、或いは古地図や地域のハザードマップ、主題図のようなものまで、いろんなスケールの地図が乱立するようになるのが面白いと思います。

が、ここで問題が発生します。
そのように様々な範囲を含む地図が提供される場合、地図の存在を地図で検索するインタフェースが欲しいわけですが、その際、どのような優先度、或いはフィルタで多様なサイズの地図をリコメンドするか、です。


地図によって地図を検索する方法は、

  • 検索される地図の提供範囲が検索地図UIの表示範囲に含まれるか否かで探す
    (UIの見せ方としては、検索地図UIの上に検索される地図の存在を示すポリゴンの表示、等)
  • 検索地図UIの中心経緯度が検索される地図の提供範囲に含まれるか否かで探す
    (UIの見せ方としては、検索地図UIとは別の場所にリスト表示がされ、地図の移動に合わせてその表示がパラパラ切り替える、等)

等が考えられます。
前者については、以前所属した会社で私が開発した絵地図ソリューション「ちずぶらり」において、一部導入したので、例を引用します。


現在の中心点を含む地図が、リストとして下端に表示されています。東都下谷絵図とは、現在の上野公園あたりの古地図です。
(c) ATR Creative


リストをスクロールすれば、小さな公園サイズの地図から、世界全図まで、中心点を含む地図が全て検索されているのが判ります。
(c) ATR Creative

この検索結果を見ると、検索UI地図上での中心点を含む地図が全て検索されています。
が、関東全域とか日本地図、世界地図のレベルの表示で探しているのに、たまたま中心点が軽くひっかかっただけで公園の地図が優先検索結果として出てくるのも鬱陶しいものがあるでしょう*3
また、この事例では優先度低くなってますが、世界地図等どこでもひっかかるので、それが優先度高く前の方に検索結果が出てきても困ります。
何らかの形で地図の規模を評価し、優先順位を定める指標のようなものが必要になります。

その指標として、以前の記事でも紹介した、Googleの発明したメルカトル図法を使った4分木地図と同等の考え方を導入すれば、地図の表現する規模間のスケールに対数的指標が定義でき、地図の表現範囲の近さを比較できる(現在の表示範囲に近ければ差の絶対値が小さく、遠ければ規模が大きくても小さくても、差の絶対値が大きくなる)のではないかと考えています。
Google Mapsでは、経度-180度〜180度、緯度-85.05112878度〜85.05112878度の範囲を表す球面メルカトル図法での表示範囲をズーム0として、そこからメルカトル座標換算で経度方向緯度方向とも2分の1、表示面積としては4分の1になる度に、ズームが1つあがっていきます。

同様に地図の表現サイズに関しても、世界地図全域レベルを指標0として、表示範囲の対角線距離(メルカトル図法座標値換算)が半分になる毎に値が1ずつあがっていく指標(インデックス)を定義し、
各地図のインデックスと現在の地図表示範囲のインデックスの差の絶対値を比較し、その差の絶対値の小さい順に優先順位をつけたり、フィルタしたりするという方法です。

具体的な式を挙げると、Google MapsやTMS(Tile Map Service)が採用している球面メルカトル座標系において、座標値換算の対角線距離は

var ZOOM0_DIST = 56674632.1090732; // = Math.sqrt(Math.pow(20037508.34278925*2,2) * 2);

になります。
ここで、求めたい地図のサイズや表示範囲の対角線距離が、既に球面メルカトル座標に換算されているとして

var MAP_DIST = Math.sqrt(Math.pow( (northeast.lat - southwest.lat),2) + Math.pow( (northeast.lng - southwest.lng),2) );

とすると、求める指標値は

var MAP_INDEX = Math.log(ZOOM0_DIST / MAP_DIST) / Math.log(2);

となります(小数値は許容します)。

このインデックスを蓄積している地図毎に求め、地図検索UIでの地図表示範囲のインデックスとの、差の絶対値を比較して適切に優先順位をつけたりフィルタすれば、地図の規模による優先付け検索が実現できます。

*1:アプリではなく、飽くまで「地図」そのもの

*2:そこまで盛り上がってるのは、どこぞのSNSの片隅で「地図タイル工法協会()」等と名乗ってる変なおじさん連中だけかもしれませんが

*3:ちずぶらりでの検索結果については、単純に表示範囲の小さい順に並べているようです。本記事で採り上げたような優先付け手法は、同社内にいた時から考えていたので、ちずぶらりにも実装したつもりでしたが、どうも勘違いだった模様

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