3流プログラマのメモ書き

元開発職→社内SE→派遣で営業支援の三流プログラマのIT技術メモ書き。 このメモが忘れっぽい自分とググってきた技術者の役に立ってくれれば幸いです。(jehupc.exblog.jpから移転中)

(PHP)携帯電話から取得したGPS位置情報から半径xxKm内のデータを探したい

(PHP)携帯電話でGPS位置情報取得したいの続きです。

最終的にしたいことは、携帯から取得したGPS座標から任意の距離内にある施設(DBに登録)を探したいということです。

DBに置いておく施設情報には、位置情報が入っていないといけないため、緯度、経度を入れておくフィールドを用意してやります。

今回は MySQL で、"latitude" , "longitude" という DOUBLE 型のフィールドを用意。また、"id","name" 列もあるとします。

で、携帯電話で計測した位置から半径5km以内のデータを探すという処理してます。

(なお、このソースはここの続きなので、"$lat" や "$lon" は携帯から取得した座標が入っているとします。)

//$lat,$lon は時小数点形式の緯度経度が入っているものとする

//DB接続は省略

 

//クエリ生成

$query = "SELECT * FROM store WHERE latitude IS NOT NULL AND longitude IS NOT NULL ";

//クエリ実行

$result = mysql_query($query);

//条件にあうデータを格納する配列

$findAry = array();

while ($row = mysql_fetch_assoc($result)) {

if (isset($lat) && isset($lon)){

//GPSからのクエリの場合距離計算(m)

$dist = distance( $lat , $lon , $row["latitude"] ,$row["longitude"] ,true);

//debug

//echo "dist:" . $dist . " lat:" . $row["latitude"] . " lot:" . $row["longitude"] . "
";

//指定距離内なら配列追加 (今回は5km)

if ($dist < 5000){

array_push($findAry ,array( "id" => $row["id"] ,

"name" => mb_convert_encoding(htmlspecialchars($row["name"]),"sjis-win" , "UTF-8") , //DB,PHPがUFT8のため携帯向けのshift-jisに変換

"lat" => $row["latitude"] ,

"lon" => $row["longitude"] , ));

}

}

}

//$findAryに結果が入ってるので、これをSmartyに渡すなり、そのまま出力したりする。

 

 

/**

* 2地点間の直線距離を求める(Hubenyの簡易式による)携帯電話GPS測地系wgs84なので世界測地系使用

* @param string $a_lati A地点の緯度(時小数点形式 33.000000)

* @param string $a_long A地点の経度(時小数点形式 132.000000)

* @param string $b_lati B地点の緯度(時小数点形式 33.000000)

* @param string $b_long B地点の経度(時小数点形式 132.000000)

* @return double 直線距離(メートル)

*/

function calc_distance($a_lati , $a_long , $b_lati , $b_long ) {

//ラジアンに変換

$a_long = deg2rad($a_long);

$a_lati = deg2rad($a_lati);

$b_long = deg2rad($b_long);

$b_lati = deg2rad($b_lati);

 

$latave = ($a_lati + $b_lati) / 2;

$latidiff = $a_lati - $b_lati;

$longdiff = $a_long - $b_long;

 

//子午線曲率半径

//$meridian = 6334834 / sqrt(pow(1 - 0.006674 * sin($latave) * sin($latave), 3)); //日本測地系

$meridian = 6335439 / sqrt(pow(1 - 0.006694 * sin($latave) * sin($latave), 3)); //世界測地系

 

//卯酉線曲率半径

//$primevertical = 6377397 / sqrt(1 - 0.006674 * sin($latave) * sin($latave)); //日本測地系

$primevertical = 6378137 / sqrt(1 - 0.006694 * sin($latave) * sin($latave)); //世界測地系

 

//Hubenyの簡易式

$x = $meridian * $latidiff;

$y = $primevertical * cos($latave) * $longdiff;

 

return sqrt($x * $x + $y * $y);

}

いろいろ試した結果、Google MAP API で計測した時の距離とどうも誤差があるようです。(Google Maps:地図から距離、方角方位、面積を得るっていうサイトで簡単に半径とか求められれます。)

それが少しではなく、結構あるんですよね。。。

まぁ時間あればこの誤差についても調べて見ようかと思います。

参考:

ぱふぅ家のホームページ:PHPで2地点間の直線距離を求める 位置計算はほぼこちらで作られた関数使わしてもらってます。

katyos開発室:PHPで2点間の距離を計算する(ヒュベニの公式)

緯度経度、距離計測WEBサービス:

Plus-α.net:緯度経度検索 地図上でクリックした位置の緯度経度を表示。

【R1web】地図上の直線距離計測ページv3-1 地図上の2点間の直線距離を計測。

2点間の直線距離がわかる距離計算サイト 2点間の距離計測。