坐标系:在一些地点可能需要坐标来满足一些功能,如地图查询、导航、距离远近,一般网站我们可以采用腾讯地图、百度地图、高德地图提供JS API来实现坐标获取,建议至少保留小数点后6及位以上,以此为基础,介绍以下几种可能用到的方法。
1.计算两点间距离
//@desc 根据两点间的经纬度计算距离
//@param float lat1 地点1纬度值
//@param float lng1 地点1经度值
//@param float lat2 地点2纬度值
//@param float lng2 地点2经度值
//@param int precision 距离精度
// 单位:m
function getDistance($lat1, $lng1, $lat2, $lng2, $precision = 0){
$earthRadius = 6367000; //approximate radius of earth in meters
//Convert these degrees to radians
//to work with the formula
$lat1 = ($lat1 * pi()) / 180;
$lng1 = ($lng1 * pi()) / 180;
$lat2 = ($lat2 * pi()) / 180;
$lng2 = ($lng2 * pi()) / 180;
//Using the
//Haversine formula
//http://en.wikipedia.org/wiki/Haversine_formula
//calculate the distance
$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, $precision);
}2.距离格式转换
//@desc 距离转换
//@param float size 距离米
//@param int digits 精度
//@param int en 返回英文单位
//1000比例距离单位数
function size2mb($size, $digits = 2, $en = 0){
//digits,要保留几位小数
$unit = array('米', '公里', '千公里', '百万公里', '太米', '拍米', '艾米', '泽米', '尧米'); //单位数组,是必须1000进制依次的哦。
$en_unit = array('m', 'km', 'Mm', 'Gm', 'Tm', 'Pm', 'Em', 'Zm', 'Ym');
$base = 1000; //对数的基数
$i = floor(log($size, $base)); //字节数对1000取对数,值向下取整。
return ($size > 0 ? round($size / pow($base, $i), $digits) : 0) . ($en ? $en_unit[$i] : $unit[$i]);
}3.返回坐标点一定距离的四角坐标
/**
* 计算某个经纬度的周围某段距离,正方形中心点至四个点的距离为distance
* @param lng float 经度
* @param lat float 纬度
* @param distance float 该点所在圆的半径,该圆与此正方形内切,默认值为1千米
* @param radius 地球半径 平均6371km
* @return array 正方形的四个点的经纬度坐标
*/
function returnSquarePoint($lat, $lng, $distance = 1, $radius = 6371){
$dlng = 2 * asin(sin($distance/(2 *$radius))/cos(deg2rad($lat)));
$dlng = rad2deg($dlng);
$dlat = $distance / $radius;
$dlat = rad2deg($dlat);
return array(
'left-top' => array('lat' => $lat + $dlat,'lng' => $lng - $dlng),
'right-top' => array('lat' => $lat + $dlat,'lng' => $lng + $dlng),
'left-bottom' => array('lat' => $lat - $dlat,'lng' => $lng - $dlng),
'right-bottom' => array('lat' => $lat - $dlat,'lng' => $lng + $dlng)
);
}4.数据库距离运算
这里是在laravel中操作
// 坐标点范围
public function scopeSquarePoint(Builder $query, $lat, $lng, $distance = 1, $radius = 6371){
$point = returnSquarePoint($lat, $lng, $distance, $radius);
$conditions = [
['latitude', '>', $point['right-bottom']['lat']],
['latitude', 'where($conditions);
}
/*
** Get the distance SelectRawSql.
** @returnsql
*/
protected function distanceSelectRawSql($latitude, $longitude){
return 'ACOS(SIN((' . $latitude . ' * 3.1415) / 180 ) *SIN((latitude * 3.1415) / 180 ) +COS((' . $latitude . ' * 3.1415) / 180 ) * COS((latitude * 3.1415) / 180 ) *COS((' . $longitude . '* 3.1415) / 180 - (longitude * 3.1415) / 180 ) ) * 6367 as distance';
}实际调用
$results = Model::where('status',3)
// 指定搜索范围(空间数量多的话最好开启,增加查询速度)
->squarePoint($latitude , $longitude)
->selectRaw('*,'.$this->distanceSelectRawSql($latitude,$longitude))->orderBy('distance', 'asc')->limit(20)->get();
yufan个人站