person holding brown wooden rolling pin

Googleの逆ジオコーディングをためしてみた

ジオポの地図表示で住所を出したかったので逆ジオコーディング(緯度・経度から住所を取り出すこと)をGoogleのAPI使ってやってみました。

まず基本

Google MapsのAPIと違って、日本語での情報が少ない(マニュアル)けど、

http://maps.google.com/maps/geo?ll=35,135&output=xml&key=GOOGLE_MAPS_API_KEY&hl=ja&oe=UTF8

URLはこのサンプルみたいにして、HTTP GETでXMLが取得できる。

リクエストパラメーター

ll緯度・経度(qでもいいと思う。違いがわからないよ><)
outputxml、kml、cvs、json
keyGoogle maps APIキー
hl言語(日本語だとja、英語ならen)。住所記述方法にも影響
oe文字エンコード

レスポンス(XMLをsimple_xmlでパースした場合)

$parsed_xml
->Response->Status->code
ステータスコード
$parsed_xml
->Response->Placemark
Arrayで結果が複数入る
以下 Placemark[0]が親とする 
AddressDetails[‘Accuracy’]精度。後述
address住所。言語によって記述方法が変化。日本語だと[県][市][町] って具合だけど、英語だと [Street], [City], [Prefecture]
あと、住所には国名が含まれる。
AddressDetails->Country
->CountryNameCode
国のコード。JP
AddressDetails->Country
->CountryName
日本
AddressDetails->Country
->AdministrativeArea
->AdministrativeAreaName
東京都
AddressDetails->Country
->AdministrativeArea
->Locality
->LocalityName
渋谷区
AddressDetails->Country
->AdministrativeArea
->Locality
->DependentLocality
->DependentLocalityName
渋谷
AddressDetails->Country
->AdministrativeArea
->Locality
->DependentLocality
->Thoroughfare
->ThoroughfareName
1丁目26
AddressDetails->Country
->AdministrativeArea
->Locality
->DependentLocality
->PostalCode
->PostalCodeNumber
日本だと取れない。アメリカだけかな?

基本的に詳細な住所ほど、先頭にくるのでPlacemark[0]を見れればokとか考えていたらハマった。

なぜか道路の名前を返す、素敵なリバースジオコーダ-

ときどき、住所がとれなくて変だな?っておもってよくみると「国道1号」みたいに道の名前が配列の先頭にきてた。他にも郵便番号がとれたりする。

そんな道の名前なんか知りたくないので、どうするかというと、Accuracyで判別してやる。

Accuracy

精度値説明
0どこそこ
1国レベル
2州、都道府県レベル
3カウンティレベル
4市町村レベル
5郵便番号レベル
6道レベル
7交差点レベル
8街区レベル
9ビル名、店名

つまり、Accuracyが5とか6のはいらない子なので、ループ回してcontinueとかでスキップすればいい。

これだけに注意しておけば、世界中の逆ジオコーディングがお手軽にできるので、Google APIはとっても魅力的。あと、住所ってそんなに頻繁に変わらないのでキャッシュしておくのは必須かと。

僕は、多言語対応させるために、ジオポコード(バイナリvarcharに注意)と言語をキーにしてキャッシュするようにしました。
住所の記述方法の切り分けは、日本式がそのままくっつける、アメリカ式は反転してから’, ‘をつけて生成みたいな形。

$address = array ();
if ($location['scale'] >= 6) {
	$address[] = $reverse_geocode['administrative_area_name'];
	$address[] = $reverse_geocode['locality_name'];
	$address[] = $reverse_geocode['dependent_locality_name'];
	$address[] = $reverse_geocode['thoroughfare_name'];
}
elseif ($location['scale'] >= 4) {
	$address[] = $reverse_geocode['administrative_area_name'];
	$address[] = $reverse_geocode['locality_name'];
	$address[] = $reverse_geocode['dependent_locality_name'];
}
elseif ($location['scale'] >= 2) {
	$address[] = $reverse_geocode['administrative_area_name'];
	$address[] = $reverse_geocode['locality_name'];
} else {
	$address[] = $reverse_geocode['administrative_area_name'];
}
// 日本式とアメリカ式の住所表記
if ($this->config->item('language_min') == 'ja') {
	$result = implode($address);
} else {
	$address = array_reverse($address);
	$result = implode(', ', $address);
}

ソースにすると↑。ジオポの縮尺が曖昧になっていく度に、住所も曖昧になる。