道路上のマーカー

「ポケモンGOみたいなゲーム作って〜」と言われたときのために、巨人(Google)の力をかりて、道路上にランダムにマーカーを設置する。

道路上のマーカー

そろそろ、世間では「ポケモンGOみたいの作ってー作ってー」という無茶振りと、それに伴うエンジニアの悲鳴が聞こえてくる季節が近づいてきたかと思います。そこで、いつそんな無茶振りが来ても対応できるように、位置情報を用いたゲームを作る際の高いハードル「人が行ける場所にモンスターを配置する」という難問をグーグル様のお力を利用して、とりあえず形だけでもなんとか取り繕ってみたいと思います。

一応言っておきますと……あんまり、実用的ではないですよ。

ランダムに緯度経度を生成する

まず、手始めに日本が収まる範囲に限定してランダムに1000件の緯度経度を生成します。
turf.jsを使用するとランダムなポイントデータをgeojsonとして簡単に生成できます。

生成したgeojsonをマーカーとして地図上に表示したのが以下となります。

ランダムに生成された1000件のマーカー

ランダムに生成されてはいますが、海の上など不要な場所に大量にマーカーが配置されてしまいました。次のフェーズでは、日本列島以外に配置された不要なマーカーを除去します。

日本列島上の位置情報のみ残してほかを消す

不要な緯度経度データをそぎ落とし、 日本列島上に収まるデータだけを取り出してみます。
turf.jsには、ポイントデータが特定のポリゴン内に含まれているかどうかを判別するためのメソッドがあるので、大まかな日本列島のアウトラインをポリゴンとして生成し、そのポリゴン内に含まれているかどうかを条件としてフィルタリングを行います。

・アウトラインポリゴン
日本列島アウトライン | Github Gist
japan_outline 2016-08-05 20-38-44

上記、geojsonを読み込み先ほど生成したマーカー群とのマッチングを行います。

フィルタリング後の緯度経度を地図上にマーカーとして表示すると以下となります。

日本列島上のみに絞り込んだマーカー

道路上の緯度経度のみを選ぶ

さて、ここからが本番です。
海上に配置されていたマーカーは綺麗さっぱり消すことができましたが、今のままでは、山の上だったり川の中だったりと、人の行けないような場所にもたくさんのマーカーが設置されてしまっています。
この中から、道路上に配置されたマーカーのみを残す、あるいは近くの道路までマーカーを移動するにはどうしたらよいでしょうか?

なかなかの難問ですが、Google様の力を利用することで一部解決できます。

キーとなるのは「ストリートビューAPI」

ストリートビューを表示する以外にも、非常に便利な機能が詰まったこのAPIを使って、ランダムに生成された緯度経度から道路上の緯度経度を取得します。

StreetViewServiceクラスが持つ、getPanoramaByLocationメソッドは、特定の緯度経度から指定した半径(下記では100m)以内にストリートビューに対応したポイントがないかを検索し、対応しているポイントがあればその緯度経度を返します。
このメソッドに、残りの緯度経度データを全て突っ込んで、手当たりしだいに検索リクエストを投げます。
getPanoramaByLocationのレスポンスに含まれる緯度経度は、ストリートビューに対応した「人が訪れることができる場所」として別途保存します。

ちなみに、getPanoramaByLocationメソッドは非同期処理になるので、プロミスで包んで最後にまとめて取得しています。

上記の方法でフィルタリングした緯度経度を地図上に表示したのが以下。だいぶ数が減ってしまいましたが、表示されているマーカーは、すべて人が行ける場所(ほとんどが道路上)に配置されています。

道路上にマッピングしたマーカー

マーカーにはクリックすると、その位置へズームするイベントがバインドされていますので、正しく配置されているか確認してみてください。

道路上のマーカー

サンプルコード

更新されるたびにランダムにマーカーを設置します。
APIの制限数を越えると設置されなくなります。
example

まとめ

最初に生成する緯度経度の数を増やせば、最終的に取得できる数も増えるわけですが、その分Streetviewへのリクエストも増えるので注意してください。今回はAPIの無料制限(1日2500リクエスト)の範囲で収まるように少なめの数で生成しています。