2012年02月19日

PHPで Google Static Maps API のポリラインエンコード

 Google MapのAPIに、Google Static Maps APIというものがある。データを埋め込みにして、静的な地図を生成するものである(static mapだから当然だが)。このAPIでも、地図上に直線(パス)を引けるのだが、線を引くためのデータはURL中に埋め込む(GETメソッドで引き渡す)ので、含められるパスのポイント数には上限がある。
 で、渡せるポイント数を多くするため?に、Googleがポリラインエンコード(http://code.google.com/intl/ja/apis/maps/documentation/utilities/polylinealgorithm.html)という方法を提供している。ざっくり言うと差分値をエンコードして並べ、クエリ文字数を短縮しようというようなことである。
 
 どんなものかは上記URLの先にあるドキュメントに書いてある。しかも結構丁寧に書いてあるのでわかりやすい。ここまで丁寧にしてくれるなら、いっそサンプルコードかライブラリを提供してくれればいいのにな、とも思わなくもない。

 ということで、ポリラインエンコードをするコードを作っていたので、サンプルを貼っておくと誰かがコピペで使えるのではないか、と。(サンプルソースのファイルはこちら。中身はいっしょ。)
// 配列に入った緯度経度をポリラインエンコードする
// 1つのポイントは array(緯度10進数,経度10進数) の形式
// ポイントを array( ポイント, ポイント, ... ) で列挙
function latlon2GooglePolyline($data)
{
$plat = false; // 1つ前の緯度
$plon = false; // 1つ前の経度

foreach($data as $point){
// 初回以外は差分を取る
$lat = $plat !== false ? $point[0] - $plat : $point[0];
$lon = $plon !== false ? $point[1] - $plon : $point[1];

// 緯度と経度をポリラインエンコードしてクエリに追加
$query .= GooglePolyline_Encode($lat).GooglePolyline_Encode($lon);

$plat = $point[0];
$plon = $point[1];
}

return $query;
}

// 単体の緯度または経度をポリラインエンコードする
// 入力値 $value は10進数の緯度または経度
function GooglePolyline_Encode($value)
{
$value = ($value * pow(10,5)) << 1; // ステップ2,3,4: 10^5を掛け左1ビットシフト
if( $value < 0 ) $value = ~$value; // ステップ5: 元の数値が負の時はビット反転

//ステップ6,7: 下位から5ビットずつ切り出す(逆順になる)
for($i=0;$i<6;$i++){
$arr[$i] = $value & 0x0000001F;
$value = $value >> 5;
}

// 不要なバイトを取り除く(上位で0が続く間そのバイトは除去、但し0の時は1バイト残す)
while( $arr[ count($arr)-1 ] === 0 && count($arr) > 1 ){
array_pop($arr);
}

//ステップ8: 最下位バイト以外に後続ビットを立てる(0x20論理和を加算)
for($i=0;$i<count($arr)-1;$i++){
$arr[$i] |= 0x20;
}

//ステップ9,10,11: 各バイトに63を加算してASCII文字に変換
$ret = '';
for($i=0;$i<count($arr);$i++){
$ret .= chr($arr[$i]+63);
}
return $ret;
}

// テスト用データ・山手線各駅の緯度経度
$data = array(
array(35.619772,139.728439),
array(35.625974,139.723822),
array(35.633923,139.715775),
array(35.646685,139.710070),
array(35.658871,139.701238),
array(35.670646,139.702592),
array(35.683061,139.702042),
array(35.689729,139.700464),
array(35.700875,139.700261),
array(35.712677,139.703715),
array(35.720476,139.706228),
array(35.730256,139.711086),
array(35.731586,139.728885),
array(35.733445,139.739303),
array(35.736825,139.748053),
array(35.737781,139.761229),
array(35.731954,139.766857),
array(35.727908,139.771287),
array(35.721484,139.778015),
array(35.713790,139.777043),
array(35.707282,139.774727),
array(35.698547,139.773091),
array(35.691173,139.770641),
array(35.681391,139.766103),
array(35.675441,139.763806),
array(35.666151,139.758654),
array(35.655391,139.757135),
array(35.645736,139.747575),
array(35.628760,139.738999),
array(35.619772,139.728439)
);

// テスト用データをポリラインエンコードしてURLを出力(実際は改行は入っていない)
echo "http://maps.google.com/maps/api/staticmap?sensor=false&
size=640x640&maptype=roadmap&path=color:0x0000ffFF%7Cweight:
5%7Cenc:".latlon2GooglePolyline($data)."\n";
 実行すると、こんな感じで出力される(実際は改行は入っていない)。
$ php polylineencode.php
http://maps.google.com/maps/api/staticmap?sensor=false&size=640x640&maptype=roadmap&
path=color:0x0000ffFF%7Cweight:5%7Cenc:q~kxEuuysYwe@x[sp@fq@wnArb@ckAdv@qhAmGqlAlBsh
@xHsdAf@whAqTuo@uNa|@i]iGenBqJa`AaTsu@}DiqAjc@cb@fXuZbg@_i@`o@`Erg@lMpu@dI`m@fNb|@h[
bd@hM`y@d_@dbAlHh{@tz@`iBpt@bw@|`A
 このままIMGタグに張り込むと、こうなる(クリックで原寸)。


 というわけで、Usoinfo GPSログトレースマップ緯度経度トレースマップを、Google Mapsに対応。地形図とか航空写真をプロットしてみると、これはこれでなかなか面白い。
posted by usoinfo at 13:44 | Comment(0) | 開発 | このブログの読者になる | 更新情報をチェックする
この記事へのコメント
コメントを書く
お名前: [必須入力]

メールアドレス:

ホームページアドレス:

コメント: [必須入力]