これは、地理的位置を初めて見たものです。長い質問をお許しください。明確であることを願っています。
緯度と経度のレコードを保持するデータベースがあります。境界ボックスを形成する 4 つの 10 進座標を定義する PHP クラスを作成しようとしています (ボックス内のすべてのレコードを取得するため)。
ユーザーの場所からn km以内にある場所を知る必要があるだけです。ユーザーから場所までの距離は必要ありません。
私はこの答えの最初の部分に基づいています。
上記の回答の核心は次のとおりです。
直線で 10 km は次のとおりです。
on the latitude is equal to ~1'(minute) on the longitude is equal to ~6'(minutes)
これを基礎として簡単な計算を行い、クエリで WHERE 句に追加して、緯度 1'、長さ 6' の仮定でバッファー ゾーンを追加することによって作成される「ボックス」の外側にある場所を削除します。
うーん、「簡単な計算をしてください」とパトリックは言います。数日後、私は正しく計算できませんでした。
私のクラスはそこにぶら下がっていて、10kmでうまくいくようです. ただし、他の距離では機能しません。
最初に秒に移動したので、10km は次のようになります。
on the latitude is equal to 60 seconds
on the longitude is equal to 360 seconds
これはうまくいきました。
しかし、私が試した5kmは次のとおりです。
on the latitude is equal to 30 seconds
on the longitude is equal to 180 seconds
これはうまくいきませんでした。
このアプローチが 5km (および私が試した他の距離) でうまくいかない理由を説明できますか?
以下は私のクラスコードです。明らかにスイッチはゴミです。どんな助けでも感謝します。
class coords
{
/*
Calculate a bounding box from a decimal coordinate and distance.
The public vars are populated with minimum and maximum longitudes and latitudes which define the boundary.
*/
public $dec_lat_min;
public $dec_lat_max;
public $dec_lng_min;
public $dec_lng_max;
function init($dec_lat, $dec_lng, $dist)
{
// This switch is a terrible way to allow multiple distances.
// 10km = 1 min lat = 60 sec lat
// 10km = 6 min lng = 360 sec lng
// 5km = 30 sec lat
// 5km = 180 sec lng
// 1km = 6 sec lat
// 1km = 36 sec lat
// 500m = 3 sec lat
// 500m = 18 sec lat
switch($dist)
{
case 10: // 10km
$sec_diff_lat = 60;
$sec_diff_lng = 360;
break;
case 5: // 5km
$sec_diff_lat = 30;
$sec_diff_lng = 180;
break;
case 1: // 1km
$sec_diff_lat = 6;
$sec_diff_lng = 36;
break;
default: // 500m
$sec_diff_lat = 3;
$sec_diff_lng = 18;
break;
}
// Convert lat to DMS
$dms_lat = $this->dec2dms($dec_lat);
// Allow for western hemisphere (ie negative)
$dms_lat['hem'] == '-' ? $h = -1 : $h = 1;
// Populate min and max latitudes
$this->dec_lat_min = $this->dms2dec($dms_lat['deg'],$dms_lat['min'],$dms_lat['sec']+(-1 * $sec_diff_lat * $h),$dms_lat['hem']);
$this->dec_lat_max = $this->dms2dec($dms_lat['deg'],$dms_lat['min'],$dms_lat['sec']+($sec_diff_lat * $h),$dms_lat['hem']);
$dms_lng = $this->dec2dms($dec_lng);
$dms_lng['hem'] == '-' ? $h = -1 : $h = 1;
$this->dec_lng_min = $this->dms2dec($dms_lng['deg'],$dms_lng['min'],$dms_lng['sec']+(-1 * $sec_diff_lng * $h),$dms_lng['hem']);
$this->dec_lng_max = $this->dms2dec($dms_lng['deg'],$dms_lng['min'],$dms_lng['sec']+($sec_diff_lng * $h),$dms_lng['hem']);
}
function dec2dms($d)
{
$d = (string)$d;
// got dashes?
if ($d[0] == "-") {
$hem = '-';
$dVal = substr($d,1);
} else {
$hem = '';
$dVal = $d;
}
// degrees = degrees
$dVals = explode('.', $dVal);
$dmsDeg = $dVals[0];
// * 60 = mins
$dRemainder = ('0.'.$dVals[1]) * 60;
$dmsMinVals = explode('.', $dRemainder);
$dmsMin = $dmsMinVals[0];
// * 60 again = secs
$dMinRemainder = ('0.'.$dmsMinVals[1]) * 60;
$dmsSec = round($dMinRemainder);
return array("deg"=>$dmsDeg,"min"=>$dmsMin,"sec"=>$dmsSec, "hem"=>$hem);
}
function dms2dec($deg,$min,$sec,$hem)
{
// find decimal latitude
$d = $deg+((($min*60)+($sec))/3600);
$d = $hem.$d;
return $this->round100000($d);
}
function round100000($v)
{
return round($v * 100000) / 100000;
}
}