PHP 根据经纬度计算两点距离

//计算距离
function getDistance($s_lat, $s_lnt, $n_lat, $n_lnt)
{
    // 地球半径
    $r = 6378137;
    $radLat1 = deg2rad($s_lat);

    $radLat2 = deg2rad($n_lat);

    $radLnt1 = deg2rad($s_lnt);

    $radLnt2 = deg2rad($n_lnt);

    // 结果
    $s = acos(cos($radLat1) * cos($radLat2) * cos($radLnt1 - $radLnt2) + sin($radLat1) * sin($radLat2)) * $r;
    // 精度
    $s = round($s * 10000) / 10000;
    return round($s);
}

/**
 * 计算距离
 * @param  Decimal $lat1 起点纬度
 * @param  Decimal $lng1  起点经度
 * @param  Decimal $lat2 终点纬度
 * @param  Decimal $lng2  终点经度
 */
function getDistance($lat1, $lng1, $lat2, $lng2){
    $earthRadius = 6367000; //近似地球半径(米)
    $lat1 = ($lat1 * pi() ) / 180;
    $lng1 = ($lng1 * pi() ) / 180;
    $lat2 = ($lat2 * pi() ) / 180;
    $lng2 = ($lng2 * pi() ) / 180;
    $calcLongitude = $lng2 - $lng1;     //长度
    $calcLatitude = $lat2 - $lat1;      //纬度
    $stepOne = pow(sin($calcLatitude / 2), 2) + cos($lat1) * cos($lat2) * pow(sin($calcLongitude / 2), 2);
    $stepTwo = 2 * asin(min(1, sqrt($stepOne)));
    $Distance = $earthRadius * $stepTwo;

    if ($Distance >= 1000) {
        $Distance = round($Distance/1000,2);
        return $Distance . 'km';
    }

    return round($Distance) . 'm';
}


 
















getdistanceAction(){

    $lng1=117.27;  //经度1

    $lat1=31.86;   //纬度1

    $lng2=120.19;  //经度2

    $lat2=30.26;   //纬度2

    $EARTH_RADIUS = 6378137;   //地球半径

    $RAD = pi() / 180.0;

    $radLat1 = $lat1 * $RAD;

    $radLat2 = $lat2 * $RAD;

    $a = $radLat1 - $radLat2;    // 两点纬度差

    $b = ($lng1 - $lng2) * $RAD;  // 两点经度差

    $s = 2 * asin(sqrt(pow(sin($a / 2), 2) + cos($radLat1) * cos($radLat2) * pow(sin($b / 2), 2)));

    $s = $s * $EARTH_RADIUS;

    $s = round($s * 10000) / 10000;

    print_r($s);   //正确答案:330518.674

}







///----
<?php

declare (strict_types=1);

namespace qbfast\vehicle;

use app\BaseController;

class Distance extends BaseController
{
    public function __construct()
    {

    }

    const  EARTH_RADIUS_AVG = (6378137 + 6356752.3142) / 2;//地球半径 平均值,单位米

    /**
     * 参数:纬度1,经度1、纬度2.经度2、
     * 使用Haversine公式,计算2个经纬度之间的距离。
     *
     * @param mixed $lat1 纬度1
     * @param mixed $lon1 经度1
     * @param mixed $lat2 纬度2
     * @param mixed $lon2 经度2
     * @return float|int 返回距离,单位:米
     */
    public static function GetDistance($lat1, $lon1, $lat2, $lon2)
    {
        //经纬度转换成弧度
        $lat1 = self::GetRadians($lat1);
        $lon1 = self::GetRadians($lon1);
        $lat2 = self::GetRadians($lat2);
        $lon2 = self::GetRadians($lon2);
        //差值
        $vLon = Abs($lon1 - $lon2);
        $vLat = Abs($lat1 - $lat2);
        $h = self::HaverSin($vLat) + Cos($lat1) * Cos($lat2) * self::HaverSin($vLon);
        return 2 * self::EARTH_RADIUS_AVG * Asin(Sqrt($h));
    }

    /**
     * 将角度换算为弧度
     *
     * @param $deg 角度
     * @return float 弧度
     */
    public static function GetRadians($deg)
    {
        return PI() * $deg / 180.0;
    }


    /**
     * 半正矢公式(Haversine公式)
     *
     * @param $theta
     * @return float|int
     */
    public static function HaverSin($theta)
    {
        $v = Sin($theta / 2);
        return $v * $v;
    }


    /**
     * 判断是否电子围栏内
     * @param array $point 当前经纬度[]
     * @param array $polygon 围栏所有经纬度[]
     * @return bool
     */
    public static function isInsidePolygon($point, $polygon)
    {
        $n = count($polygon);
        $inside = false;
        for ($i = 0, $j = $n - 1; $i < $n; $j = $i++) {
            if (((($polygon[$i]['lat'] <= $point['lat']) && ($point['lat'] < $polygon[$j]['lat'])) ||
                    (($polygon[$j]['lat'] <= $point['lat']) && ($point['lat'] < $polygon[$i]['lat']))) &&
                ($point['lng'] < ($polygon[$j]['lng'] - $polygon[$i]['lng']) * ($point['lat'] - $polygon[$i]['lat']) / ($polygon[$j]['lat'] - $polygon[$i]['lat']) + $polygon[$i]['lng'])) {
                $inside = !$inside;
            }
        }
        return $inside;
    }
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值