GoogleMapsを利用して路線を表示する

2015年に実験的に試した内容。メモしておいた内容を今更ながら自分用メモとして投稿。
間違い等あったらごめんなさい。
markdown をイマイチよくわかってない。。。

# 条件
* 国土交通省_国土数値情報_鉄道データを利用することとする。
* 鉄道データをkmlフォーマットに変換しfusion tableに登録しgoogle maps上にオーバーレイ表示する
* 変換はrubyスクリプトにて実施する
* 表示確認は chorme のみ

# 問題
* GoogleMap 標準に乗換案内レイヤ(TransitLayer)があるが、日本だと地下鉄だけの表示となってしまう。
以下のURL（引数でdata=!5m1!1e2を指定する）でTransitLayerが表示されるが日本だと地下鉄だけ表示される  
https://www.google.co.jp/maps/@34.6614067,135.4193668,10z/data=!5m1!1e2  
その他、レイヤ表示される内容

|表示対象|data引数の値|日本での対応状況|
|:--|:--:|:--:|
|道路状況|<notextile>!5m1!1e1</notextile> |地下鉄のみ表示|
|自転車|<notextile>!5m1!1e3</notextile>|使えない|
|地形|<notextile>!5m1!1e4</notextile>|○|

* GoogleMapAPIV3で乗換検索した結果を利用して路線表示しようとしたが、交通手段を公共交通機関（google.maps.TravelMode.TRANSIT）にすると日本だと検索できない。  
https://developers.google.com/maps/documentation/javascript/examples/directions-travel-modes?hl=ja  
上記サンプルを日本に変更して試したが動作しない。
公共交通機関以外の道路網（google.maps.TravelMode.DRIVING）、歩行（google.maps.TravelMode.WALKING）は検索可能（自転車（google.maps.TravelMode.BICYCLING）はダメ）

# 対応手順
## 鉄道データをkmlに変換
* 鉄道データを以下のサイトよりダウンロードする
http://nlftp.mlit.go.jp/ksj/gml/datalist/KsjTmplt-N02.html

* ダウンロードした鉄道データ(N02-13.xml)は以下の構造となっている。

|内容|キー|備考|
|:--|:--:|:--:|
|ヘッダ情報|gml:boundedBy,gml:description,ksj:Datase|ファイル自体の基本情報。今回は使用しない|
|カーブ情報|gml:Curv|路線または駅の位置情報が含まれる|
|路線情報|ksj:RailroadSection|事業者名、路線名、駅情報へのリンク等が含まれる。駅情報が含まれる場合はホームと同じ長さが保持されている（と思う）|
|駅情報|ksj:Station|事業者名、路線名、駅名、路線情報へのリンク等が含まれる|

* 鉄道データの注意するポイント
 * 路線情報は、１つの路線で複数存在する。また、１区間（駅と駅の間）で１つの路線情報とも限らない（と思う）。
 * 駅情報は、１つの駅で複数存在する場合がある（事業者名＋駅名ではユニークとならない）。対象となる駅に路線が複数ある場合、路線数の駅情報が存在する。
 * 駅情報に対応するカーブ情報の位置情報は１点だけではない。おそらく駅ホームの長さ分の位置情報が含まれている。
 * １つの路線を形成するカーブ情報が、あまりに細かく分断されていると、google map に表示したとき、ズームレベルを小さくすると点線となってしまう場合がある。
よって、可能な範囲で路線を形成するカーブ情報は、変換時になるべく繋ぎ合わせる必要がある。
 * 鉄道データの位置情報は、経度(lng), 緯度(lat) の順で記述されているが、出力する kml ファイル上は 緯度(lat), 経度(lng) の順に出力する必要がある。

* 鉄道データをrubyスクリプトで変換する
 * 鉄道データ(N02-13.xml)は、30MB程あるため、xml パーサー等で変換すると時間が異常にかかる（または例外が発生する）。よって自力で解析する
 * 解析方法は、 鉄道データを読み込みメモリ上に展開し、カーブ情報、路線情報、駅情報それぞれを正規表現で繰り返し取得する。各要素は要素単位に正規表現にて取得する。
 * １つの路線を形成するカーブ情報を繋ぎ合わせる方法は、単純に１つの路線データの終端位置が、他の路線データの先頭位置と同値を確認し、同値ならば１つに纏める。（もっといい方法があるかもしれない。。。）
 * 出力するジオメトリ情報は、data_type に rail(路線名),station(駅名)があり、railは ポリライン、stationはマーカーとする。
 * 変換スクリプトは以下のサイトに登録ずみ。  
https://github.com/oya3/gis_analyze.git  
実行方法  
>$ ruby gis_analyze -m mix N02-13.xml N02-13.kml  
※windows上でのみ動作。  
※-m オプションには、rail(路線のみ), station(駅のみ),mix(両方)が指定可能  

 * 変換後のkmlファイルの1レコードの情報は以下の通り

|key|value|
|:--|:--:|
|description|事業者名（kmlファイル必須項目らしい）|
|name|路線名または駅名（kmlファイル必須項目らしい）|
|data_type|railまたはstation|
|company_name|事業者名|
|line_name|路線名|
|station_name|駅名|
|railway_type|鉄道区分コード http://nlftp.mlit.go.jp/ksj/gml/datalist/img/N02-1.gif 参照|
|service_provider_type|事業者種別コード http://nlftp.mlit.go.jp/ksj/gml/datalist/img/N02-1.gif 参照|

## 変換した鉄道データ(kml)を fusion table に登録する

google にログイン状態で以下のサイトにアクセスし鉄道データ(kml)を fusion table に登録する
https://www.google.com/fusiontables/data?dsrcid=implicit

* 登録済み参考kml   
https://www.google.com/fusiontables/DataSource?docid=1oVouXsjBueThIMExCZh9LhYNVINnqIjzrnuc1fIT

## fusion table をgoogle map上に表示する

fusion table に登録した際の URL 引数にある docid を FusionTablesLayer の query from に設定する
参考サイトの
https://www.google.com/fusiontables/DataSource?docid=1oVouXsjBueThIMExCZh9LhYNVINnqIjzrnuc1fIT
の場合
docid は "1oVouXsjBueThIMExCZh9LhYNVINnqIjzrnuc1fIT" となる

<pre><code class="javascript">
var map, layer;

function initialize() {
  var center = new google.maps.LatLng(34.686871327463116, 135.52652215576177); // 大阪
  map = new google.maps.Map(document.getElementById('map-canvas'), {
    center: center,
    zoom: 11
  });
  layer = new google.maps.FusionTablesLayer({
    query: {
      from: '1oVouXsjBueThIMExCZh9LhYNVINnqIjzrnuc1fIT' // <---- ここに docid を設定する
    }
  });
  layer.setMap(map);
}
google.maps.event.addDomListener(window, 'load', initialize);
</code></pre>

# 成果物

* 以下にすべて登録ずみ。
https://github.com/oya3/gis_analyze.git
 * gis_analyze.rb ... 変換スクリプト
 * map.html ... 表示サンプル
* 動作サンプル
http://oya3.net/map/map.html  

# リンク

* [GoogleMapsのFusionTablesLayerで条件を指定してスタイルを変更する](http://qiita.com/oya3/items/a947044ca926935f7699)  
* [GoogleMapsのFusionTablesLayerで表示物のクリックイベントで表示されるInfoWindowの内容を変更する](http://qiita.com/oya3/items/a48d45f6f1749d1d2d81)