Webで地理情報を扱いたい

モチベーション

地理情報はかなり身近なようで、あまり自分では扱ったことのないジャンルということ、個人的に興味がある分野でも結構使われていて今後必要そうなので、この機会に少し調べてみました。(+自動運転、ドローン、ARのような分野では特に重要なので知っておいて損は無い気がしますね!)タイトルに「Webで」とついていますが、今回はあまり関係ないかもしれません。

(Web)サービスにおける地理情報

Webサービス上では地理情報はインタラクティブなデジタル地図として目にする機会が多いと思います。特に、アクセスマップで会社や施設の位置を表示したり、外食チェーンや銀行などが自社の店舗一覧を表示したりなど、当たり前に使われています。弊社もmealtime.jp内で、ミールタイム紹介ネットワークのページでGoogle Mapを使用して医療機関の場所を表示しています。それ以外の例としては、位置情報を使ったゲームや配車アプリ、またGoogle Analytics上でのアクセス元を地図上に表示したり、人の流れやネットトラフィックを可視化したりする場面でも地理情報が使われています。総じて文字ではわかりにくい情報(関係)を視覚化する際に使われています。(Flightradar24MarineTrafficなどはとてもわかり易い例ですね)

地理情報を扱う上での知識

緯度/経度
地理情報を扱うときの基本。地球上の1点を示すための座標系で、正確には「地理経緯度」というようです。Google Map等を見るときは緯度/経度を意識することはないと思いますが、地図上に何かを重ねたり、表示したりする際には必ずといっていいほど必要になってきます。経緯度はあくまで球面上の座標系であるため、実際にはそれを直接扱うのではなく計算機上で扱いやすい直交座標系に変換して内部的には処理されています(多分)。

地球が丸いということ
当たり前だと思うかもしれませんが、地球は球形(正確には違いますが)なので、地理情報を扱うときはそれを考慮に入れなければいけません。例えばwebページ上に地図を表示したいとき、webページは平面なので、球面である地球、あるいはその一部地域を何らかの変換を行い平面に投影する必要があります。また、2点間の距離を求めたいとき、単純な最短距離では、大きな誤差が生まれる場合があります。以下に示すコードは地球上の2点の最短距離を求める近似解です。

def degreeToRadian(degree)
  degree * Math::PI / 180
end

def distance(coordinate1, coordinate2)
    
    lat1 = degreeToRadian(coordinate1[:lat])
    lng1 = degreeToRadian(coordinate1[:lng])
    lat2 = degreeToRadian(coordinate2[:lat])
    lng2 = degreeToRadian(coordinate2[:lng])

    latDiff = lat1 - lat2
    lngDiff = lng1 - lng2
    latAvg = (lat1 + lat2) / 2.0
    a = 6378137.0
    b = 6356752.314140356
    e2 = 0.00669438002301188
    a1e2 = 6335439.32708317

    sinLat = Math.sin(latAvg)
    w2 = 1.0 - e2 * (sinLat ** 2)
    #子午線曲率半径
    m = a1e2 / (Math.sqrt(w2) ** 3)
    #卯酉子午線半径
    n = a / Math.sqrt(w2)

    t1 = m * latDiff;
    t2 = m * Math.cos(latAvg) * lngDiff
    Math.sqrt((t1 * t1) + (t2 * t2))
end

GIS
Geographic Information Systemのことで、直訳で地理情報システム…のことですが、国土地理院によれば、“地理的位置を手がかりに、位置に関する情報を持ったデータ(空間データ)を総合的に管理・加工し、視覚的に表示し、高度な分析や迅速な判断を可能にする技術”となっています。要するにコンピュータ上で地理情報を扱うためのシステムということです。現在はいくつかの標準規格があり、それに基づいて実装されている例が多いです。GISは位置情報とそれに付属する情報からなっており、例えば以下の例は東京23区とその平均所得をヒートマップで可視化したものになります。(あまりGISの例としては適切でないかもしれません)

・座標系、測地系

plus+codes
Open Location Codeというジオコーディング(情報に地理座標情報を与えること、経緯度もその1種)のこと。くわしくはこちらに記載されていますが、最大で11桁からなり、最小のグリッドは3.5m四方となります。ちなみにGoogle Mapで確認することができ、例えば弊社オフィスの住所は「北区赤羽2-51-3」ですがplus+codesだとQPJF+V4となります。

位置情報
文脈としてはほとんどGPS信号から得られるデータを指していることが多いですが、現在は単純にGPSから得られる情報だけでなく、同じような地球測位システム(GLONASS, 北斗, みちびき等)や携帯電話の基地局、Wi-FiのAP、超広帯域無線等を使い、その精度を向上させています。この測位/精度向上の内部実装については知らないので別の機会に調べますが、我々がWebサービス上で使いたいときは、例えばHTML5のGeolocation APIを使って内部実装を気にせず簡単に利用することができます。また地理的な位置情報だけでなく、オフィス内や施設でのローカルな位置情報も広い意味では地理情報といえるかもしれません。

//Geolocation APIのサンプル
function geolocationExample() {
  //ブラウザの対応可否
  if (!navigator.geolocation){
    return;
  }

  function geoSuccess(position) {
    //経緯度を取得
    var latitude  = position.coords.latitude;
    var longitude = position.coords.longitude;
    alert("緯度:"+latitude+",経度"+longitude);
  }
  function error() {
    alert("エラーコード:"+error.code);
  }

  navigator.geolocation.getCurrentPosition(geoSuccess, error);
}

地理情報を扱う方法

色々と紹介をしてきましたが、すぐに地理情報を扱えるか?というと結構とっつきにくいので、扱う対象によっていくつかの方針を立てると良い気がします。
一般的なwebサービスだと以下の3つの用途がメインになるでしょうか。
・地図上に何かを表示したい
・位置情報を使ったサービスを提供したい
・データ分析で地理/位置情報データを可視化したい

単純に地理情報を扱うといっても様々な用途、手法があるので次回(があれば)は個別の掘り下げを行っていきたいと思います。