根据中心点经纬度求经纬度距离排序,整理版本超级简单

精简实用4年前 (2020-12-14)8750


已知中心点经纬度求一定范围内的距离排序,thinkphp经纬度距离排序,如3公里范围内的附近店铺,距离从近到远排序,整理后的代码如下

//先定义西安光电园的经纬度坐标
$start_lng = '108.882223'; //起点经度
$start_lat = '34.233231'; //起点维度
//获取6000米半径范围最大、最小经纬度数组 方法一
$nearby_data = getAround($start_lat,$start_lng,6000);
//(`latitude` >= minLat) AND (`latitude` <=maxLat) 
$condition['lat']  = array(array('EGT',$nearby_data['minLat']),array('ELT',$nearby_data['maxLat']),'and');
//(`longitude` >= minLng) AND (`longitude` <= maxLng)
$condition['lng'] = array(array('EGT',$nearby_data['minLng']),array('ELT',$nearby_data['maxLng']),'and');

//获取6000米半径范围最大、最小经纬度数组 方法二
$where = "ROUND(6378.138 * 2 * ASIN(SQRT( POW(SIN(($lat * PI() / 180 - lat * PI() / 180
                                    ) / 2),2) + COS( $lat * PI() / 180) * COS(lat * PI() / 180) * POW(
                                SIN(($lon * PI() / 180 - lng * PI() / 180) / 2),2))) * 1000) < 6000";

$condition['status'] = 1;
//$condition['uid'] = 102;
//自定义距离字段
$distance_feild = "*,ROUND(6378.138 * 2 * ASIN(SQRT( POW(SIN(($start_lat * PI() / 180 - lat * PI() / 180
                                      ) / 2),2) + COS( $start_lat * PI() / 180) * COS(lat * PI() / 180) * POW(
                                  SIN(($start_lng * PI() / 180 - lng * PI() / 180) / 2),2))) * 1000) AS distance";
//求出6000米范围内的店铺数据
$data = D('StoreShop')->field($distance_feild)->where($condition)->order('distance asc')->page($page,30)->select();
//var_dump($data);
//exit;


/**
 * @desc   根据半径求范围最大、最小经纬度数组
 * @param  $latitude 纬度    
 * @param  $longitude 经度
 * @param  $raidus 半径范围(单位:米)
 * @return multitype:number
 */
function getAround($latitude,$longitude,$raidus){
    $PI = 3.14159265;
    $degree = (24901*1609)/360.0;
    $dpmLat = 1/$degree;
    $radiusLat = $dpmLat*$raidus;
    $minLat = $latitude - $radiusLat;
    $maxLat = $latitude + $radiusLat;
    $mpdLng = $degree*cos($latitude * ($PI/180));
    $dpmLng = 1 / $mpdLng;
    $radiusLng = $dpmLng*$raidus;
    $minLng = $longitude - $radiusLng;
    $maxLng = $longitude + $radiusLng;
    return array (minLat=>$minLat, maxLat=>$maxLat, minLng=>$minLng, maxLng=>$maxLng);
}

//另外附加提供三种计算距离的方法

/**
 * 计算两个坐标之间的距离(米)
 * @param float $fP1Lat 起点(纬度)
 * @param float $fP1Lon 起点(经度)
 * @param float $fP2Lat 终点(纬度)
 * @param float $fP2Lon 终点(经度)
 * @return int
 */
function distanceBetween($fP1Lat, $fP1Lon, $fP2Lat, $fP2Lon){
    $fEARTH_RADIUS = 6378137;
    //角度换算成弧度
    $fRadLon1 = deg2rad($fP1Lon);
    $fRadLon2 = deg2rad($fP2Lon);
    $fRadLat1 = deg2rad($fP1Lat);
    $fRadLat2 = deg2rad($fP2Lat);
    //计算经纬度的差值
    $fD1 = abs($fRadLat1 - $fRadLat2);
    $fD2 = abs($fRadLon1 - $fRadLon2);
    //距离计算
    $fP = pow(sin($fD1/2), 2) +
          cos($fRadLat1) * cos($fRadLat2) * pow(sin($fD2/2), 2);
    return intval($fEARTH_RADIUS * 2 * asin(sqrt($fP)) + 0.5);
}


/** 
* @desc 根据两点间的经纬度计算距离 
* @param float $lat 纬度值 
* @param float $lng 经度值 
*/ 
function getDistanceLocal($lat1, $lng1, $lat2, $lng2){ 
    $earthRadius = 6367000; //approximate radius of earth in meters 
    $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))); 
    $calculatedDistance = $earthRadius * $stepTwo; 
    return round($calculatedDistance); 
}


/**
 * @param int $lat1 纬度1
 * @param int $lng1 经度1
 * @param int $lat2 纬度2
 * @param int $lng2 经度2
 * @return array
 */
function getDistance($lat1=0,$lng1=0,$lat2=0,$lng2=0)
{
    $ak = '';//您的百度地图ak,可以去百度开发者中心去免费申请  
    $distance = array();
    $distance['distance'] = 0.00;//距离 公里
    $distance['duration'] = 0.00;//时间 分钟
    $url = 'https://api.map.baidu.com/routematrix/v2/driving?output=json&origins='.$lat1.','.$lng1.'&destinations='.$lat2.','.$lng2.'&ak='.$ak;
    $data = file_get_contents($url);
    $data = json_decode($data,true);
    if (!empty($data) && $data['status'] == 0) {
        $distance['distance'] =preg_replace('/[^\.0123456789]/s', '', $data['result'][0]['distance']['text']); //计算距离
    }
    return $distance;
}


发表评论

访客

看不清,换一张

◎欢迎参与讨论,请在这里发表您的看法和观点。