Commit 8641d689 by xj

附近的站点

parent 224f8bc2
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
namespace App\Http\Controllers\V1\Station; namespace App\Http\Controllers\V1\Station;
use App\Services\GeoHashServices;
use Auth; use Auth;
use App\Http\Controllers\Controller; use App\Http\Controllers\Controller;
use App\Model\BillingTplModel; use App\Model\BillingTplModel;
...@@ -159,7 +160,25 @@ class StationController extends Controller ...@@ -159,7 +160,25 @@ class StationController extends Controller
} }
} }
/**
* 附近的站点
* @param Request $request
* @return mixed
*/
public function nearby(Request $request)
{
$validator = Validator::make($request->all(), [
'longitude' => 'required',
'latitude' => 'required',
]);
if ($validator->fails()) {
abort(400, $validator->errors()->first());
}
$geohash = new GeoHashServices();
$data = $geohash->getNearbyStation($request->get('latitude'), $request->get('longitude'));
return $this->response->array($this->getResponseCode() + ['data' => $data]);
}
} }
......
<?php
namespace App\Services;
use App\Model\StationModel;
/**
* geohash lenght | km error
* 1 | ±2500
* 2 | ±630
* 3 | ±78
* 4 | ±20
* 5 | ±2.4
* 6 | ±0.61
* 7 | ±0.076
* 8 | ±0.019
* Class GeoHashServices
* @package App\Services
*/
class GeoHashServices
{
private $coding = "0123456789bcdefghjkmnpqrstuvwxyz";
private $codingMap = [];
private $level = [
1 => 2500,
2 => 630,
3 => 78,
4 => 20,
5 => 2.4,
6 => 0.61,
7 => 0.076,
8 => 0.019,
];
public function __construct()
{
for ($i = 0; $i < 32; $i++) {
$this->codingMap[bindec(str_pad(decbin($i), 5, "0", STR_PAD_LEFT))] = substr($this->coding, $i,1);
}
}
private function getLat($number, $small, $big, $temp = 20){
$temp--;
$average = ($big + $small) / 2;
if ($temp == 0) {
if ($average <= $number) {
return '1';
} else {
return '0';
}
}
if ($average <= $number) {
return '1' . $this->getLat($number, $average, $big, $temp);
} else {
return '0' . $this->getLat($number, $small, $average, $temp);
}
}
private function joinStr($lat, $lon){
$str = '';
for ($i=0; $i < strlen($lat); $i++) {
$str .= $lon[$i] . $lat[$i];
}
return $str;
}
private function scaleToLevel($scale) {
foreach ($this->level as $key => $value) {
if ($scale > $value) {
return $key;
}
}
return 8;
}
/**
* 获取geohash编码
* @param $latitude
* @param $longitude
* @return string
*/
public function getGeoHash($latitude, $longitude)
{
$latitude = $this->getLat($latitude, -90, 90);
$longitude = $this->getLat($longitude, -180, 180);
$string = $this->joinStr($latitude, $longitude);
$code = '';
for ($i = 0; $i < strlen($string) / 5 ; $i++) {
$code .= $this->codingMap[bindec(substr($string, $i * 5, 5))];
}
return $code;
}
/**
* 角度弧度计算公式
* 360度=2π π=pi()
* x度 = x*π/360 弧度
* @param $degree
* @return float
*/
private function getRadian($degree) {
return $degree * pi() / 180.0;
}
/**
* 根据经纬度计算两点之间的距离
* @param $lat1
* @param $long1
* @param $lat2
* @param $long2
* @return float|int 单位 米
*/
public function getDistance($lat1, $long1, $lat2, $long2)
{
$radLat1 = $this->getRadian($lat1);
$radLat2 = $this->getRadian($lat2);
// 两点纬度差
$a = $radLat1 - $radLat2;
// 两点经度差
$b = $this->getRadian($long1) - $this->getRadian($long2);
$s = 2 * asin(sqrt(pow(sin($a / 2), 2) + cos($radLat1) * cos($radLat2) * pow(sin($b / 2), 2)));
return $s * 6378.137 * 1000;
}
/**
* 获取附近的站点
* @param $latitude
* @param $longitude
* @param int $scale
* @return $this|array|\Illuminate\Database\Query\Builder|\Illuminate\Support\Collection
*/
public function getNearbyStation($latitude, $longitude, $scale = 5000)
{
// 搜索该点附近的站点
$geoHashCode = $this->getGeoHash($latitude, $longitude);
$stations = StationModel::select(['id', 'name', 'longitude', 'latitude', 'geohash'])
->where('geohash', 'like', substr($geoHashCode, 0, 4) . '%')
->get();
if (!$stations)
return [];
$stations = $stations ? $stations->toArray() : [];
foreach ($stations as $key => $station) {
$stations[$key]['distance'] = $this->getDistance($latitude, $longitude, $station['latitude'], $station['longitude']);
}
array_multisort($stations, SORT_ASC, SORT_NUMERIC, array_column($stations, 'distance'), SORT_ASC, SORT_NUMERIC);
return $stations;
}
}
\ No newline at end of file
...@@ -112,7 +112,8 @@ $api->version('v1', ['namespace' => 'App\Http\Controllers\V1', 'prefix' => 'api/ ...@@ -112,7 +112,8 @@ $api->version('v1', ['namespace' => 'App\Http\Controllers\V1', 'prefix' => 'api/
$api->get('user/code/withdraw',['uses' => 'User\WithDrawController@getCode']); $api->get('user/code/withdraw',['uses' => 'User\WithDrawController@getCode']);
// 查找附近的站点
$api->post('station/nearby', 'Station\StationController@nearby');
}); });
$api->post('refresh/token', ['as' => 'wx.refresh.token', 'uses' => 'Wx\AccessController@refreshToken']); $api->post('refresh/token', ['as' => 'wx.refresh.token', 'uses' => 'Wx\AccessController@refreshToken']);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment