php中getdistance函数_在PHP中测量两个坐标之间的距离

Hi I have the need to calculate the distance between two points having the lat and long.

I would like to avoid any call to external API.

I tried to implement the Haversine Formula in PHP:

Here is the code:

class CoordDistance

{

public $lat_a = 0;

public $lon_a = 0;

public $lat_b = 0;

public $lon_b = 0;

public $measure_unit = 'kilometers';

public $measure_state = false;

public $measure = 0;

public $error = '';

public function DistAB()

{

$delta_lat = $this->lat_b - $this->lat_a ;

$delta_lon = $this->lon_b - $this->lon_a ;

$earth_radius = 6372.795477598;

$alpha = $delta_lat/2;

$beta = $delta_lon/2;

$a = sin(deg2rad($alpha)) * sin(deg2rad($alpha)) + cos(deg2rad($this->lat_a)) * cos(deg2rad($this->lat_b)) * sin(deg2rad($beta)) * sin(deg2rad($beta)) ;

$c = asin(min(1, sqrt($a)));

$distance = 2*$earth_radius * $c;

$distance = round($distance, 4);

$this->measure = $distance;

}

}

Testing it with some given points which have public distances I don't get a reliable result.

I don't understand if there is an error in the original formula or in my implementation

解决方案

Not long ago I wrote an example of the haversine formula, and published it on my website:

/**

* Calculates the great-circle distance between two points, with

* the Haversine formula.

* @param float $latitudeFrom Latitude of start point in [deg decimal]

* @param float $longitudeFrom Longitude of start point in [deg decimal]

* @param float $latitudeTo Latitude of target point in [deg decimal]

* @param float $longitudeTo Longitude of target point in [deg decimal]

* @param float $earthRadius Mean earth radius in [m]

* @return float Distance between points in [m] (same as earthRadius)

*/

function haversineGreatCircleDistance(

$latitudeFrom, $longitudeFrom, $latitudeTo, $longitudeTo, $earthRadius = 6371000)

{

// convert from degrees to radians

$latFrom = deg2rad($latitudeFrom);

$lonFrom = deg2rad($longitudeFrom);

$latTo = deg2rad($latitudeTo);

$lonTo = deg2rad($longitudeTo);

$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 $angle * $earthRadius;

}

➽ Note that you get the distance back in the same unit as you pass in with the parameter $earthRadius. The default value is 6371000 meters so the result will be in [m] too. To get the result in miles, you could e.g. pass 3959 miles as $earthRadius and the result would be in [mi]. In my opinion it is a good habit to stick with the SI units, if there is no particular reason to do otherwise.

Edit:

As TreyA correctly pointed out, the Haversine formula has weaknesses with antipodal points because of rounding errors (though it is stable for small distances). To get around them, you could use the Vincenty formula instead.

/**

* Calculates the great-circle distance between two points, with

* the Vincenty formula.

* @param float $latitudeFrom Latitude of start point in [deg decimal]

* @param float $longitudeFrom Longitude of start point in [deg decimal]

* @param float $latitudeTo Latitude of target point in [deg decimal]

* @param float $longitudeTo Longitude of target point in [deg decimal]

* @param float $earthRadius Mean earth radius in [m]

* @return float Distance between points in [m] (same as earthRadius)

*/

public static function vincentyGreatCircleDistance(

$latitudeFrom, $longitudeFrom, $latitudeTo, $longitudeTo, $earthRadius = 6371000)

{

// convert from degrees to radians

$latFrom = deg2rad($latitudeFrom);

$lonFrom = deg2rad($longitudeFrom);

$latTo = deg2rad($latitudeTo);

$lonTo = deg2rad($longitudeTo);

$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;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值