我的数据库有坐标条目。我想获取包含指定半径圆的坐标的条目。因此,我使用spherical law of cosines。
但是在所有数据库条目上检查这样的条件成本太高。
因此,我首先获取位于边界框中的坐标(此框包含上面指定的圆),然后对它们应用spherical law of cosines
。
但问题是即使我有满足条件的条目,MySQL也会返回NULL。
我分别检查了上述2个条件并且知道spherical law of cosines
有效,但是在使用其他条件(边界框)时会出现问题。
此link包含我用于这两种情况的代码。
以下是我的代码:
$R = 3959; // earth's mean radius in mile
// first-cut bounding box (in degrees)
$from_Lat = $userTrip->fromLat; // latitude of centre of bounding circle in degrees
$from_Lon = $userTrip->fromLon; // longitude of centre of bounding circle in degrees
$from_Rad = $userTripLength * 0.25; // radius of bounding circle in kilometers
$from_MaxLat = $from_Lat + rad2deg($from_Rad/$R);
$from_MinLat = $from_Lat - rad2deg($from_Rad/$R);
// compensate for degrees longitude getting smaller with increasing latitude
$from_MaxLon = $from_Lon + rad2deg($from_Rad/$R/cos(deg2rad($from_Lat)));
$from_MinLon = $from_Lon - rad2deg($from_Rad/$R/cos(deg2rad($from_Lat)));
$to_Lat = $userTrip->toLat; // latitude of centre of bounding circle in degrees
$to_Lon = $userTrip->toLon; // longitude of centre of bounding circle in degrees
$to_Rad = $userTripLength * 0.50; // radius of bounding circle in kilometers
$to_MaxLat = $to_Lat + rad2deg($to_Rad/$R);
$to_MinLat = $to_Lat - rad2deg($to_Rad/$R);
// compensate for degrees longitude getting smaller with increasing latitude
$to_MaxLon = $to_Lon + rad2deg($to_Rad/$R/cos(deg2rad($to_Lat)));
$to_MinLon = $to_Lon - rad2deg($to_Rad/$R/cos(deg2rad($to_Lat)));
$sql = "Select userTrip.id, userTrip.fromLat, userTrip.fromLon, userTrip.toLat, userTrip.toLon,
acos(sin(:from_lat)*sin(radians(userTrip.fromLat)) + cos(:from_lat)*cos(radians(userTrip.fromLat))*cos(radians(userTrip.fromLon) - :from_lon)) * :R AS SourceDistance,
acos(sin(:to_lat)*sin(radians(userTrip.toLat)) + cos(:to_lat)*cos(radians(userTrip.toLat))*cos(radians(userTrip.toLon) - :to_lon)) * :R AS DestinationDistance
From (
Select userTrip.id, userTrip.fromLat, userTrip.fromLon, userTrip.toLat, userTrip.toLon,
From userTrip
Where userTrip.userId != $this->userId
AND userTrip.departureTime > '".date('Y-m-d H:i:s')."'
AND userTrip.fromLat Between :from_minLat And :from_maxLat
AND userTrip.fromLon Between :from_minLon And :from_maxLon
AND userTrip.toLat Between :to_minLat And :to_maxLat
AND userTrip.toLon Between :to_minLon And :to_maxLon
)
Where acos(sin(:from_lat)*sin(radians(userTrip.fromLat)) + cos(:from_lat)*cos(radians(userTrip.fromLat))*cos(radians(userTrip.fromLon) - :from_lon)) * :R < :from_rad
AND acos(sin(:to_lat)*sin(radians(userTrip.toLat)) + cos(:to_lat)*cos(radians(userTrip.toLat))*cos(radians(userTrip.toLon) - :to_lon)) * :R < :to_rad";
$params = array(
'from_lat' => $from_Lat,
'from_lon' => $from_Lon,
'from_minLat' => $from_MinLat,
'from_minLon' => $from_MinLon,
'from_maxLat' => $from_MaxLat,
'from_maxLon' => $from_MaxLon,
'from_rad' => $from_Rad,
'to_lat' => $to_Lat,
'to_lon' => $to_Lon,
'to_minLat' => $to_MinLat,
'to_minLon' => $to_MinLon,
'to_maxLat' => $to_MaxLat,
'to_maxLon' => $to_MaxLon,
'to_rad' => $to_Rad,
'R' => $R
);
$stmt = $this->dbLink->prepare($sql);
try
{
$stmt->execute($params);
$matchCandidates = $stmt->fetchAll();
}
catch (PDOException $err)
{
echo $err->getMessage();
}
if ($matchCandidates == null)
throw new ErrorException("No match candidates found!");
这始终显示错误“找不到匹配的候选人!”。 在$ params数组中,我最初将纬度和经度转换为弧度(即使不起作用),但经过大量调试后我相信它们应该是度数。
提前谢谢。
答案 0 :(得分:0)
$myUserId = $this->userId
Select ...
Where userTrip.userId != $myUserId
您可以直接在查询中$this->userId
而无需转义它。
答案 1 :(得分:0)
我发现了错误,下面是正确的查询。
$sql = "Select id,fromLat,fromLon,toLat,toLon,
acos(sin(:from_lat)*sin(radians(fromLat)) + cos(:from_lat)*cos(radians(fromLat))*cos(radians(fromLon) - :from_lon)) * :R AS SourceDistance,
acos(sin(:to_lat)*sin(radians(toLat)) + cos(:to_lat)*cos(radians(toLat))*cos(radians(toLon) - :to_lon)) * :R AS DestinationDistance
From (
Select userTrip.id, userTrip.fromLat, userTrip.fromLon, userTrip.toLat, userTrip.toLon,
From userTrip
Where userTrip.userId != $this->userId
AND userTrip.departureTime > '".date('Y-m-d H:i:s')."'
AND userTrip.fromLat Between :from_minLat And :from_maxLat
AND userTrip.fromLon Between :from_minLon And :from_maxLon
AND userTrip.toLat Between :to_minLat And :to_maxLat
AND userTrip.toLon Between :to_minLon And :to_maxLon
) AS InitialResult
Where acos(sin(:from_lat)*sin(radians(fromLat)) + cos(:from_lat)*cos(radians(fromLat))*cos(radians(fromLon) - :from_lon)) * :R < :from_rad
AND acos(sin(:to_lat)*sin(radians(toLat)) + cos(:to_lat)*cos(radians(toLat))*cos(radians(toLon) - :to_lon)) * :R < :to_rad";
1)我必须为内部SELECT查询的结果提供别名。在这种情况下Initialresult
2)我不能在外部SELECT中使用userTrip.
因为它在InitialResult
而不是userTrip
上执行。