这是我第一次接触地理位置。请原谅我的长篇问题,希望它很清楚。
我有一个数据库,其中包含具有纬度和经度的记录。我正在尝试编写一个PHP类,定义四个小数坐标,形成一个边界框(然后检索框内的所有记录)。
我只需要知道哪些位置在用户位置附近的n公里范围内。我不需要知道用户到位置的距离。
我正在构建这个答案的第一部分。
上述答案的核心是:
这个没问题。
但是,我接着尝试了“5km is:”。
我有一个数据库,其中包含具有纬度和经度的记录。我正在尝试编写一个PHP类,定义四个小数坐标,形成一个边界框(然后检索框内的所有记录)。
我只需要知道哪些位置在用户位置附近的n公里范围内。我不需要知道用户到位置的距离。
我正在构建这个答案的第一部分。
上述答案的核心是:
10 km in a straight line is:
on the latitude is equal to ~1'(minute) on the longitude is equal to ~6'(minutes)
Using this as a basis, do some quick math and in your query add to the WHERE clause removing any locations that are outside the 'box' that is created by adding the buffer zone with the assumption of 1' lat & 6' long.
帕特里克说:“做些快速的数学计算。”我在几天后仍然没能正确地完成这个数学问题。
我的班级正在坚持下去,似乎可以运行10公里。然而,我无法使它适用于其他距离。
首先,我将距离转换为秒,那么10公里就是:
on the latitude is equal to 60 seconds
on the longitude is equal to 360 seconds
这个没问题。
但是,我接着尝试了“5km is:”。
on the latitude is equal to 30 seconds
on the longitude is equal to 180 seconds
这种方法不起作用。
您能解释一下为什么这种方法对5km(以及其他我尝试过的距离)无效吗?
以下是我的类代码。 显然,switch语句很糟糕。 感谢任何帮助。
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;
}
}