Subscribed unsubscribe Subscribe Subscribe

GPSなどの緯度経度の2点間の直線距離を求めるPHP関数

開発 PHP

実は去年ぐらいに書いたプログラムですが、それなりに調べて書いたのでエントリーに書いておきたいと思います。
個人的にはこれとGPS取得PHPクラスと各種APIを使って、モバろけモバなびというケータイで使えるWebAppを作ったりしました。
モバろけを作った背景にはiPhoneがあるわけですが、iPhoneのMapAppみたいなことをケータイのWebAppでできないかと思って作ったのがモバろけです。
まぁ、そんな前置きはいいとして本題に…

緯度経度の2点間の直線距離を求めるには?

最初はこんなの簡単じゃーんって思っていたのです。単純にXY座標に置き換えて考えて直線距離を出せば良いんでしょと思っていたのですがよくよく調べてみたらそうもいかないのです。
なぜなら地球は球体!球体なので直線距離といってもその分湾曲した線の距離を考えないといけない。
それでいてしかも地球は完全な球体ではない!なんてこった!どうすりゃいいんだ!と思っていたのですが、いろいろ調べて解決したのでした。

http://vldb.gsi.go.jp/sokuchi/surveycalc/algorithm/
http://www.tom.sfc.keio.ac.jp/~next/tdiary/?date=20040825
http://ameblo.jp/katyos/entry-10241752990.html

というわけで書いたPHP関数

ということで、以下のような関数を書きました。
緯度経度1、緯度経度2を引数として与えると、前述したような計算をざざざっとしてくれて、最後におまけで単位計算もして返してくれます。
単位計算されたのは1000m以下ならメートルで記述、1000m以上はの数をkmで記述されます。


使い方はこんな感じ…

$hoge=location_distance($lat1, $lon1, $lat2, $lon2);
$hoge["distance"]//が小数点付きの直線距離を返します(メートル単位)。
$hoge["distance_unit"]//が整形された直線距離を返す(1000m以下ならメートルで記述 例:836m | 1000m以上は小数点第一位以上の数をkmで記述 例:2.8km)


実際の関数がこちら…

<?php
//GPSなどの緯度経度の2点間の直線距離を求める(世界測地系)

//$lat1, $lon1 --- A地点の緯度経度
//$lat2, $lon2 --- B地点の緯度経度
function location_distance($lat1, $lon1, $lat2, $lon2){
	$lat_average = deg2rad( $lat1 + (($lat2 - $lat1) / 2) );//2点の緯度の平均
	$lat_difference = deg2rad( $lat1 - $lat2 );//2点の緯度差
	$lon_difference = deg2rad( $lon1 - $lon2 );//2点の経度差
	$curvature_radius_tmp = 1 - 0.00669438 * pow(sin($lat_average), 2);
	$meridian_curvature_radius = 6335439.327 / sqrt(pow($curvature_radius_tmp, 3));//子午線曲率半径
	$prime_vertical_circle_curvature_radius = 6378137 / sqrt($curvature_radius_tmp);//卯酉線曲率半径
	
	//2点間の距離
	$distance = pow($meridian_curvature_radius * $lat_difference, 2) + pow($prime_vertical_circle_curvature_radius * cos($lat_average) * $lon_difference, 2);
	$distance = sqrt($distance);
	
	$distance_unit = round($distance);
	if($distance_unit < 1000){//1000m以下ならメートル表記
		$distance_unit = $distance_unit."m";
	}else{//1000m以上ならkm表記
		$distance_unit = round($distance_unit / 100);
		$distance_unit = ($distance_unit / 10)."km";
	}
	
	//$hoge['distance']で小数点付きの直線距離を返す(メートル)
	//$hoge['distance_unit']で整形された直線距離を返す(1000m以下ならメートルで記述 例:836m | 1000m以下は小数点第一位以上の数をkmで記述 例:2.8km)
	return array("distance" => $distance, "distance_unit" => $distance_unit);
}
?>


間違ってるよーとかあったらコメントください。