初めて地図周りの技術に触れた時に作ったまとめ資料

関連して以下も参考にしてください

> * [GoogleMapのオープンソース版地図アプリ（OSRM）のインストール - Qiita](http://qiita.com/laqiiz/items/e188b0d5d21fe7aa0de7)
* [住所（市区町村番地）から緯度経度を取得する - Qiita](http://qiita.com/laqiiz/items/842fe2a32e80bac92364)

# <i class="fa fa-cubes" style="font-size:1em;"></i>まとめたこと
やりたい事ベースでざっくり分類

0. 住所（地名） ⇔ 緯度/経度変換
0. 地図上への位置情報のプロット
0. 距離計算・ルーティング（緯度経度計算、2点間の距離を計測）

# <i class="fa fa-cube" style="font-size:1em;"></i>詳しく

## <i class="fa fa-arrows" style="font-size:1em;"></i> 住所（地名） ⇔ 緯度/経度変換

住所（地名）→緯度/経度の変換は**ジオコーディング(Geocoding)**と呼ばれる。
（昔はアドレスマッチングとも呼ばれていたらしい）
緯度/経度→住所（地名）の変換は**逆ジオコーディング(Reverse Geocoding)**や**アドレスマッチング**と呼ばれる。
 
 緯度は```latitude(lat)```、経度は```longitude(lng)```で各Web/APIドキュメントをみるとよく出てくる。
住所は```address```とか```location```と表現されることが多い。

ジオコーディングをプログラミングから使うときは```Ruby```実装が有名。
> Ruby geocoderがすごい
> http://blog.mogya.com/2013/10/ruby-geocoder.html


## <i class="fa fa-exclamation-triangle" style="font-size:1em;"></i>オンプレミスでジオコーディングする上での障壁

上記のRuby実装は内部的に```Google Geocoding API```をキックしている。
利用制限などを回避するため、オンプレミスでジオコーディング対応したくなるが難しい問題が立ちはだかる。

**住所名の揺れ対応が難しい**
「兵庫県XXX市1-2-3」 と 「ヒョウゴ県xxx市１丁目２番地３号」 を同じ緯度経度としたいが、名寄せ（データクレンジング）して同一視させるのは大変。

そのためので```Google Map API```に頼りたくなる
（名寄せについて、有料のプロダクトはあるがOSSは目ぼしいのが無いことも影響）

**名寄せ手法**
以下の「Geocodingで自前のGISデータを作ってみよう 」は名寄せについて参考になる
https://codeiq.jp/magazine/2014/05/8400/

**名寄せしなくて良い場合**
住所の完全一致前提でシステム要件的に許容できれば国交省のデータを使うのがてっとり早い
http://qiita.com/laqiiz/items/842fe2a32e80bac92364

**その他**
一方、逆ジオコーディングでは、緯度経度の表記は基本的にブレないので名寄せをほぼ意識しなくて済む。

また、ある地点から半径XXXメートル以内のXXXの関連施設を検索したいといった場合には、2点間の緯度経度から距離を計算して関連施設の属性とともにフィルタリングして取得するクエリを発行することで実現する。


## <i class="fa fa-map-marker" style="font-size:1em;"></i> 地図上への位置情報のプロット

言うにおよばず```Google Map API```が有名。
マーカーピンをたてたり、吹き出しを作ったり、エリアに色を塗ったり…
こちらについては各サービスごとのAPIを覚えてJSで作業させる。


## <i class="fa fa-cogs" style="font-size:1em;"></i> 距離計算

地球は丸いので、2点間の緯度経度から三角関数で単純に距離を出してはダメらしい。
理由は直線だと地中を通ってしまうことになるから（・・・！！）

以下の記事は上記のことをわかりやすく説明していた
> [ジオグラフィ型というものがある - Qiita](http://qiita.com/yellow_73/items/e9006d69262739c59984)

緯度経度から距離の計算はヒュベニの公式というのを用いて簡単に計算できるらしい。
難しそうな数式が並ぶ‥。
> http://yamadarake.jp/trdi/report000001.html

通常のアプリであれば、Postgre拡張のPostGISにある```distance```関数などで計算させることが多そう。
以下は「PostGISを使って検索してみる」ということで様々なクエリが記載されてた
> https://sites.google.com/site/pcchatnetoiles/home/postgis/postgis-2

## <i class="fa fa-car" style="font-size:1em;"></i> ルーティング

実際の道路や高低差を意識した経路選択の話。
アルゴリズム的には最短経路問題になる。

# <i class="fa fa-search" style="font-size:1em;"></i> もっと詳しく
## ジオコーディング

地名や建物名（例：東京タワー）から緯度・経度を検索すること。
Googleの[Geocoding](http://www.geocoding.jp/)やYahoo!の[ジオコーダAPI](http://developer.yahoo.co.jp/webapi/map/openlocalplatform/v1/geocoder.html)が有名。
オープンなものとしては```Open Street Map```というものががある。

GoogleやYahoo!が提供してくれるAPIは、情報が豊富でリッチな機能があり簡単に使えると非常に人気だが、利用回数などの制限がネック。

## 各サービス特徴メモ

ザックリ読むだけで流れと注意点がわかる。

> 各種ジオコーディングapiの罠と対処法
> http://treeapps.hatenablog.com/entry/2012/11/17/%E5%90%84%E7%A8%AE%E3%82%B8%E3%82%AA%E3%82%B3%E3%83%BC%E3%83%87%E3%82%A3%E3%83%B3%E3%82%B0api%E3%81%AE%E7%BD%A0%E3%81%A8%E5%AF%BE%E5%87%A6%E6%B3%95

### 【<i class="fa fa-google"></i>】Google Geocoding API

**無料API**
2500回/24時間まで
5回/1秒まで
Googleマップを使わずGeocodingだけ用いるのは規約的にNG。

有償版コースもあり。

>https://developers.google.com/maps/documentation/geocoding/?hl=ja#Limits

### 【<i class="fa fa-yahoo"></i>】Yahoo!ジオコーダAPI
**無料API**
50,000回/1日まで

* アプリケーションの登録は10個まで可能。
* 午前0:00に利用回数がリセットされる。

> http://developer.yahoo.co.jp/appendix/rate.html


### <i class="fa fa-sitemap"></i> OSM（OpenStreetMap）

ユーザ編集型の地図データのこと。
Wikipediaのようにユーザ自身がGPSログをアップロードしたりベクトルデータを編集可能。
ForesquareというWebサービスのバックエンドで使われているみたいです。

#### OSMの環境構築

* [OpenStreetMapサーバを自作する(Install OpenStreetMap on AWS EC2/Ubuntu14.04)
](http://dev.classmethod.jp/cloud/aws/install-openstreetmap-on-ec2-ubuntu14_04/)
 * OSSなので自サーバが構築できる

#### 利用できるAPI

以下にまとめられていた。
自前サーバを構築もできるが、公開用のサーバがありアクセスが出来る。
OSMのデータにはOverpassというAPIを用いてアクセスするらしい。

> [OpenStreetMap] Overpass APIで地点検索 - Qiita
> http://qiita.com/taku/items/f3c6ed375a2461551d7c

#### 利用制限
1日に合計おおよそ1,000,000リクエスト。
余り他のユーザに迷惑をかけないように、ということらしい。

#### 機能

地図をズームしたり、マーカーを立てるなど基本操作は出来る。

* [OpenStreetMap API 実験室](http://openstreetmap.piyolab.net/)
   * 地図上にマーカやテキストを配置するAPIを説明してくれている

* http://wiki.openstreetmap.org/wiki/JA:Overpass_API
    * 公式っぽいWiki

#### その他参考情報

[地図サービスの王Googleマップをじわじわと追いかけるOpenStreetMap - Gigazine](http://gigazine.net/news/20140303-openstreetmap/)
└ GoogleMapの有料化に伴いOSMにユーザが大量引っ越ししたとのこと

[世界がOpenStreetMapを必要とする理由 - Qiita](http://qiita.com/nyampire/items/073c850f083cf9fb8d35)
└ 地図情報を特定の企業に独占させることの危険性

[OpenStreetMap Japan](https://openstreetmap.jp/)
└ 日本語での情報提供や相互互助の支援を行っているサイト
　　└ 定期的にマッピングパーティを行っている


## <i class="fa fa-car" style="font-size:1em;"></i> ルーティング

緯度経度からの距離計算では、実際の建物や道路を無視しているので現実的には精度が低い。
そのため、道路や建物の地図情報を元に経路を計算することが必要。

### OSRM（Open Source Routing Service）

有名ドコロにOSRMがある。
C++で実装されており、OSM(Open Street Map)のデータを利用している。
http://project-osrm.org/

#### 環境構築
以前、インストール作業を以下にまとめた。
[オープンソース地図アプリ（OSRM）のインストール - Qiita](http://qiita.com/laqiiz/items/e188b0d5d21fe7aa0de7)

#### 利用API
OSRMのWeb/APIは以下のWikiに。
https://github.com/Project-OSRM/osrm-backend/wiki/Server-api

中を見ると大体やりたいことは網羅している。

| service  | Description                                               |eg|
|----------|-----------------------------------------------------------|----|
| viaroute | 最短経路の検索                   | http://{server}/viaroute?loc={lat,lon}&loc={lat,lon}<&loc={lat,lon} ...> |
| nearest  | 最も近い道路のセグメントを取得 | http://{server}/nearest?loc={lat,lon} |
| locate   | 最も近いノードを取得                |http://{server}/locate?loc={lat,lon} |
| table    | 距離の組み合わせ計算     | http://{server}/table?loc={lat,lon}&loc={lat,lon}<&loc={lat,lon} ...>|
| match    | GPS情報から最適のルートを実施  | http://{server}/match?loc={lat,lon}&t={timestamp}&loc={lat,lon}&t={timestamp}<&loc={lat,lon}&t={timestamp} ...> |

#### <i class="fa fa-table"></i> OSRMのデータ構造

インストール時に作成するデータの説明は以下のWiki参照。
https://github.com/Project-OSRM/osrm-backend/wiki/Running-OSRM

グラフ情報については以下以下のWiki参照。
https://github.com/Project-OSRM/osrm-backend/wiki/Graph-representation


### <i class="fa fa-road" style="font-size:1em;"></i> 道路交通情報

OSRMは道路工事や道路渋滞の情報が考慮されていないので、現実には精度が低下する（はず）。
また、車での情報しか存在しなかったため、徒歩を含めたその他の交通期間での移動時間は考慮出来ていない。
（取り込みファイルには```.car```みたいなサフィックスが付いていたので、徒歩情報も作成すれば対応出来そうではある）

ちなみに日本で渋滞情報を取得しようとするとVICS(ビックスと読む)（Vehicle Information and Communication System）が有名。
http://vics.or.jp/about/index.html

# <i class="fa fa-cloud-download" style="font-size:1em;"></i> データ取得元

国土数値情報　行政区域データ（shape形式）
http://nlftp.mlit.go.jp/ksj/gml/datalist/KsjTmplt-N03.html
 
国土交通省　国土情報課　位置情報参照サービス（CSV形式）
http://nlftp.mlit.go.jp/isj/

データの地番、街区、住所表示などの基礎知識は以下を参考に。
http://www.pasco.co.jp/recommend/word/word082/
https://ja.wikipedia.org/wiki/%E4%BD%8F%E6%89%80#.E6.97.A5.E6.9C.AC.E3.81.AB.E3.81.8A.E3.81.91.E3.82.8B.E4.BD.8F.E6.89.80.E3.81.AE.E8.A1.A8.E8.A8.98
 
# 技術要素

## <i class="fa fa-cogs" style="font-size:1em;"></i> GIS 

GISとは地理情報システム（GIS：Geographic Information System）のことで、地理的情報を視覚的に表示させる技術の総称とのこと。
http://www.gsi.go.jp/GIS/whatisgis.html

このページが簡単でわかりやすい。
http://www.gis.jacic.or.jp/gis/gakushu/whatisgis/whatisgis1.html

## データ型

### <i class="fa fa-file-text" style="font-size:1em;"></i>  GeoJSON(Geometry JSON)

GeoJSON は様々な地理的データ構造を持つフォーマットで、最近GithubやGoogleでも利用できるようになっているデファクトスタンダードな存在。
仕様は (http://s.kitazaki.name/docs/geojson-spec-ja.html) で定義されている。

以下は簡単にGeoJSONについて説明してくれている。
http://blog.qaramell.com/?p=8191

GeoJSONを用いれば、緯度経度だけではなく店舗の営業時間や地理情報も設定できるらしいので、地図に独自の情報を付けて付加価値を高めるサービスを作るときは必要になってくるとのこと。

### <i class="fa fa-file" style="font-size:1em;"></i>  Shape（シェープ）ファイル

「図形情報と属性情報をもった地図データファイル」が集まったデータファイル。
下記が詳しい。
http://www.pasco.co.jp/recommend/word/word028/

GIS業界の標準フォーマットらしいので、国などでDLすると大体このフォーマットになっている。
ShapeファイルからGeoJSONへの変換は調べるとよく出てくる。

## <i class="fa fa-database"  style="font-size:1em;"></i>PostGIS
他にもPostgreSQLにはPostGISという拡張モジュールがあり、これで距離系のデータが上手く扱える。
ざっくりというと緯度経度を保持するデータ型があり、そこから上手く距離を計算したクエリがかける。

PostGISのクエリでできることは下記でざっくりつかめる。
http://lets.postgresql.jp/documents/tutorial/PostGIS/1/

Oracleも11gリリース2からジオメトリ型データというのを使えるとのこと。
https://www.infoscoop.org/blogjp/2015/01/21/tutorial_for_geodb/

## <i class="fa fa-picture-o" style="font-size:1em;"></i>ビジュアライズ

地図情報をD3.jsを用いて描画する先人も。凄い。
> [D3.jsとOpen Data〜その１地図を描画する](http://qiita.com/sawamur@github/items/ec32237bcbaaba94108d)


# <i class="fa fa-graduation-cap" style="font-size:1em;"></i> まとめ

基本的にGoogleのGeocodingを使えば問題なし。
利用制限に引っかかったらYahooo!のジオコーダAPIを使いましょう。
それすら超過しそうなら自前で準備しましょう