本文目录导读:

在PHP中计算两点经纬度之间的直线距离,最常用的方法是Haversine公式,以下是几种实现的示例:
Haversine公式(最常用,精度较高)
function haversineDistance($lat1, $lon1, $lat2, $lon2) {
$earthRadius = 6371; // 地球半径,单位:公里
// 如果希望得到英里,使用 3959
// 将角度转换为弧度
$latFrom = deg2rad($lat1);
$lonFrom = deg2rad($lon1);
$latTo = deg2rad($lat2);
$lonTo = deg2rad($lon2);
// 计算纬度和经度的差值
$latDelta = $latTo - $latFrom;
$lonDelta = $lonTo - $lonFrom;
// Haversine公式
$a = sin($latDelta / 2) * sin($latDelta / 2) +
cos($latFrom) * cos($latTo) *
sin($lonDelta / 2) * sin($lonDelta / 2);
$c = 2 * asin(sqrt($a));
// 最终距离
$distance = $earthRadius * $c;
return $distance;
}
// 使用示例
$lat1 = 39.9042; // 北京纬度
$lon1 = 116.4074; // 北京经度
$lat2 = 31.2304; // 上海纬度
$lon2 = 121.4737; // 上海经度
$distance = haversineDistance($lat1, $lon1, $lat2, $lon2);
echo "北京到上海的直线距离约为:" . round($distance, 2) . " 公里";
使用PHP的atan2版本(更精确)
function getDistance($lat1, $lon1, $lat2, $lon2) {
$earthRadius = 6371; // 公里
$latFrom = deg2rad($lat1);
$lonFrom = deg2rad($lon1);
$latTo = deg2rad($lat2);
$lonTo = deg2rad($lon2);
$lonDelta = $lonTo - $lonFrom;
$a = pow(cos($latTo) * sin($lonDelta), 2) +
pow(cos($latFrom) * sin($latTo) - sin($latFrom) * cos($latTo) * cos($lonDelta), 2);
$b = sin($latFrom) * sin($latTo) + cos($latFrom) * cos($latTo) * cos($lonDelta);
$angle = atan2(sqrt($a), $b);
return $angle * $earthRadius;
}
返回多种单位的版本
function calculateDistance($lat1, $lon1, $lat2, $lon2, $unit = 'km') {
$earthRadius = [
'km' => 6371,
'mi' => 3959,
'm' => 6371000,
'nm' => 3440.065 // 海里
];
if (!isset($earthRadius[$unit])) {
$unit = 'km';
}
$latFrom = deg2rad($lat1);
$lonFrom = deg2rad($lon1);
$latTo = deg2rad($lat2);
$lonTo = deg2rad($lon2);
$latDelta = $latTo - $latFrom;
$lonDelta = $lonTo - $lonFrom;
$angle = 2 * asin(sqrt(pow(sin($latDelta / 2), 2) +
cos($latFrom) * cos($latTo) * pow(sin($lonDelta / 2), 2)));
return $earthRadius[$unit] * $angle;
}
// 使用示例
echo calculateDistance(39.9042, 116.4074, 31.2304, 121.4737, 'km'); // 公里
echo calculateDistance(39.9042, 116.4074, 31.2304, 121.4737, 'mi'); // 英里
批量计算距离(适合数据库查询)
function getDistanceSQL($lat, $lng, $tableName = 'locations') {
// 这个SQL可以用于MySQL数据库查询附近的地点
$sql = "SELECT *,
(6371 * acos(
cos(radians($lat)) *
cos(radians(latitude)) *
cos(radians(longitude) - radians($lng)) +
sin(radians($lat)) *
sin(radians(latitude))
)) AS distance
FROM $tableName
HAVING distance < 50
ORDER BY distance";
return $sql;
}
使用geotools库(推荐用于复杂项目)
如果项目需要更复杂的地理计算,可以使用Composer安装geotools:
composer require league/geotools
use League\Geotools\Coordinate\Coordinate;
use League\Geotools\Distance\Vincenty;
function geotoolsDistance($lat1, $lon1, $lat2, $lon2) {
$coordA = new Coordinate([$lat1, $lon1]);
$coordB = new Coordinate([$lat2, $lon2]);
$calculator = new Vincenty();
$distance = $calculator->setFrom($coordA)->setTo($coordB)->calculate();
return $distance->get(); // 返回米
}
精度对比
- Haversine公式:精度约0.5%,适合大多数应用场景
- Vincenty公式:精度更高(<0.5mm),但计算更复杂
- 球面余弦定律:适合短距离计算,对长距离精度会下降
注意事项
- 经纬度格式:确保使用十进制度数,而非度分秒格式
- 地球模型:上述计算假设地球是完美球体,实际为椭球体,但误差通常可接受
- 性能考虑:如果需要大量计算,建议在数据库层直接使用SQL计算
推荐在实际项目中使用第一种Haversine公式,兼顾了精度和性能。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播