2010年3月1日月曜日
緯度経度から住所を取得してみる - Google Maps API v3

緯度経度から住所を取得する

サンプルはここにある。
http://code.google.com/intl/ja/apis/maps/documentation/v3/services.html#ReverseGeocoding

まずはGoogle Maps APIにおける、Geocoderのリクエスト方法から。
下記URLを見ると、プロパティの一覧がある。
GeocoderRequest
Google Maps API V3 Reference - Google Maps JavaScript API V3 - Google Code

住所や郵便番号から検索する場合は、addressプロパティに住所か郵便番号を入れてやる。
緯度経度から検索する場合は、latLngに緯度経度を入れてやる。

レスポンスは以下。

GeocoderResponse
Google Maps API V3 Reference - Google Maps JavaScript API V3 - Google Code


formatted_addressというのが、例えば「日本,愛知県名古屋市○○区○○N丁目NNN」のような形式の文字列。

テストは、クリックした箇所を地図の中心にしてマーカーを置くサンプルを下にしました。
http://code.google.com/intl/ja/apis/maps/documentation/v3/examples/event-arguments.html
クリックした箇所の緯度経度はイベントオブジェクトから簡単に取得できるので、そいつをGeocoderに入れてやるようにソースを修正すればいい。

ソースのイメージはこんなふう。

var geocoder = new google.maps.Geocoder();
geocoder.geocode({latLng: location}, function(results, status){
if(status == google.maps.GeocoderStatus.OK){
// 正常に処理ができた場合
} else {
// エラーの場合
}
});


レスポンスである配列resultsの構成はこうなっている。
{types[]: String,
formatted_address: String,
address_components[]: {
short_name: String,
long_name: String,
types[]: String
},
geometry: {
location: LatLng,
location_type: GeocoderLocationType,
viewport: LatLngBounds,
bounds: LatLngBounds?
}
}


まずはresults[].formatted_addressを表示してみる。

名古屋パルコの西館はこういうふうに取得できた
[0]日本, 愛知県名古屋市中区栄3丁目29?1
[1]〒460-8681
[2]〒460-8406
[3]〒460-8430
[4]〒460-8432
[5]〒460-8791
[6]日本, 愛知県名古屋市中区栄3丁目29
[7]日本, 愛知県名古屋市中区栄3丁目
[8]日本, 愛知県名古屋市中区栄
[9]日本, 愛知県名古屋市中区

※ただしクリックする箇所によって番地や郵便番号(の並び)は微妙に異なる。

名古屋パルコといえば、対になるのはナディアパークだよな?ってことでナディアパークはこちら。

[0]日本, 伊勢町通り
[1]〒460-8434
[2]〒460-8435
[3]〒460-8678
[4]〒460-8685
[5]〒460-8433
[6]〒460-8444
[7]〒460-8432
[8]〒460-8674
[9]〒460-8688


住所じゃなくて、通りの名前と郵便番号が取得できた。

名古屋ってことで、市役所はどうかと思って、調べてみると…

[0]〒460-8508
[1]〒460-8501
[2]〒460-8534
[3]〒460-8520
[4]〒460-8522
[5]〒460-8521
[6]〒460-8528
[7]〒460-8513
[8]〒460-8507
[9]〒460-8514

※これもクリックする箇所によって郵便番号の並びが変わったり、「日本,大津通」が出てくる。

こちらも郵便番号。
どういう違いがあるのだろう?

今度はresults[].address_components[]を確認する。
これにはshort_namelong_nametypes[]の三つがあるので、それぞれ表示させる。
面倒なのでresults[0]だけを対象にする。

名古屋パルコ(西館)
---------------
[0]short name : 1
[0]long name : 1
[0]types[0] : sublocality
[0]types[1] : political
---------------
[1]short name : 29
[1]long name : 29
[1]types[0] : sublocality
[1]types[1] : political
---------------
[2]short name : 3丁目
[2]long name : 3丁目
[2]types[0] : sublocality
[2]types[1] : political
---------------
[3]short name : 栄
[3]long name : 栄
[3]types[0] : sublocality
[3]types[1] : political
---------------
[4]short name : 中区
[4]long name : 中区
[4]types[0] : locality
[4]types[1] : political
---------------
[5]short name : 名古屋市
[5]long name : 名古屋市
[5]types[0] : locality
[5]types[1] : political
---------------
[6]short name : 愛知県
[6]long name : 愛知県
[6]types[0] : administrative_area_level_1
[6]types[1] : political
---------------
[7]short name : JP
[7]long name : 日本
[7]types[0] : country
[7]types[1] : political
---------------

※勿論住所が短ければ、配列の数も少なくなる。
「愛知県名古屋市X区XXXN丁目NNN」で終われば、パルコの例よりも配列の要素がひとつ少なくなる。

ナディアパーク
---------------
[0]short name : 伊勢町通り
[0]long name : 伊勢町通り
[0]types[0] : route
---------------
[1]short name : JP
[1]long name : 日本
[1]types[0] : country
[1]types[1] : political
---------------


名古屋市役所
---------------
[0]short name : 460-8508
[0]long name : 460-8508
[0]types[0] : postal_code
---------------
[1]short name : JP
[1]long name : 日本
[1]types[0] : country
[1]types[1] : political
---------------


address_componentsの含まれるshort_namelong_nameについて、「日本」か「JP」の違いしかないようなので、日本ではあまり意味はないか。
typesにはその値の種別が入っていると思っていいのかな?
「日本」が「country」で、「愛知県」が「administrative_area_level_1」か。

…とここまで調べてて、日本語のリファレンスにがっちり載ってたことに気づいた。
http://sites.google.com/site/gmapsapi3/Home/services
折角なので、調べたことは残しておくことにする。

それによると、「administrative_area_level_2」「administrative_area_level_3」まであるようだけど、日本じゃ関係ない。

ただ、これらの結果とリファレンスを見る限り、Google Maps APIのGeocoderを使って緯度経度から住所を取るというのは考え物だと思った。
上の例のように、パルコならまだしも、ナディアパークや市役所のようなパターンになった場合、郵便番号だけだったり、近隣の通りの名前しか取れないパターンがあるんじゃ、判断に困るしなぁ。
例えば一つのresults[]short_nameかlong_nameが三つ以上であれば、それは(それなりの)住所を取得できていると判断するか?



0 コメント | コメントを書く
Template Design: © 2007 Envy Inc.