路径导航:这里分享的主行程并入途经点的腾讯地图类,了解原理后你也可以采用其他地图制作类调用。
<?phpnamespace App\Services;use App\Services\Traits\HandleActions;// 腾讯地图class TencentMap{use HandleActions;public $mapLimit = 300; //坐标点相差多少米视为同意坐标public $sendMsgOK = true; // 发送模板消息开关public $sendSubMsgOK = true; // 发送订阅消息开关function serviceName(){return 'TencentMap';}function getKey(){return config('app.tencent_map_key');}// 先用matrixPointsData计算各点距离,选出起点\终点和途径点,再以此用routePlanningData获取总行程距离/*** 路线规划* @description: 驾车(driving):支持结合实时路况、少收费、不走高速等多种偏好,精准预估到达时间(ETA)* @param {Array} $startPoint 起始地 ['latitude'=>0,'longitude'=>0]* @param {Array} $endPoint 终点 ['latitude'=>0,'longitude'=>0]* @param {Array} $roadPoints 途经点 [['latitude'=>0,'longitude'=>0],['latitude'=>0,'longitude'=>0]] 最大支持16个,已按先后顺序排列好* @param {*} $plateNumber 车牌号* @return {*}*/function routePlanningData($startPoint, $endPoint, $roadPoints = [], $plateNumber = ''){$_this = $this;$result = null;$cacheKey = 'routePlanningData';// 缓存redis锁$this->lockCache($cacheKey, 5, function () use ($_this, $startPoint, $endPoint, $roadPoints, $plateNumber, &$result) {$result = $_this->routePlanningDataRun($startPoint, $endPoint, $roadPoints, $plateNumber);usleep(250000); //延迟0.25秒,防止并发});return $result;}public function routePlanningDataRun($startPoint, $endPoint, $roadPoints = [], $plateNumber = ''){$tencent_map_key = $this->getKey();$fromPoint = $startPoint['latitude'] . ',' . $startPoint['longitude'];$toPoint = $endPoint['latitude'] . ',' . $endPoint['longitude'];$wayPoints = '';$speed = 10; //速度,单位:米/秒foreach ($roadPoints as $key => $point) {if ($key > 15) break;$wayPoints .= ($wayPoints ? ';' : '') . $point['latitude'] . ',' . $point['longitude'];}$url = 'https://apis.map.qq.com/ws/direction/v1/driving/?from=' . $fromPoint . '&to=' . $toPoint . '&output=json&speed=' . $speed . '&key=' . $tencent_map_key;if ($wayPoints) $url .= '&waypoints=' . $wayPoints;if ($plateNumber) $url .= '&plate_number=' . $plateNumber;//不返回路线引导信息$url .= '&no_step=1';$data = dCurl($url);// curl请求方法,Get$result = json_decode($data, true);$resultLog = $result;if ($resultLog['status'] == 0) {unset($resultLog['result']['routes'][0]['polyline']);}// 这里只做了日志记录,有能力的可以做下路径规划数据缓存,有请求过得就不用再去api接口调用占用名额logInfo('路径规划', ['time' => now()->format('Y-m-d H:i:s') . ':' . microtime(true),'startPoint' => $startPoint,'endPoint' => $endPoint,'roadPoints' => $roadPoints,'plateNumber' => $plateNumber,'result' => $resultLog,]);$_result = $result;if ($result['status'] == 0) {$_result = $resultLog;// 判断下面三个相同就不再请求或其他规则$_result['startPoint'] = $startPoint;$_result['endPoint'] = $endPoint;$_result['roadPoints'] = $roadPoints;$_result['distance'] = $result['result']['routes'][0]['distance']; // 总距离(单位:米)$_result['duration'] = $result['result']['routes'][0]['duration']; // 估算时间(含路况,单位:分钟)$_result['polyline'] = $result['result']['routes'][0]['polyline']; // 方案路线坐标点串}// 只需要总距离return $_result;}/*** 距离矩阵* @description: 用于批量计算一组起终点的路面距离(或称导航距离)* @param {Array} $startPoints 起始地 [['latitude'=>0,'longitude'=>0],['latitude'=>0,'longitude'=>0]]* @param {Array} $endPoints 终点 [['latitude'=>0,'longitude'=>0],['latitude'=>0,'longitude'=>0]]* 个数限制: 多对一计算<=200个,多对多计算from和to坐标数乘积<=625且单侧<=50个* @return {*}*/function matrixPointsData($startPoints, $endPoints){$_this = $this;$result = null;$cacheKey = 'matrixPointsData';$this->lockCache($cacheKey, 5, function () use ($_this, $startPoints, $endPoints, &$result) {$result = $_this->matrixPointsDataDistanceRun($startPoints, $endPoints);//个人开发,并发量不够,官方是按两个坐标点一次并发// $result = $_this->matrixPointsDataApiRun($startPoints, $endPoints);// sleep(1);//延迟1秒// usleep(250000);//延迟0.25秒});return $result;}// 坐标距离public function matrixPointsDataDistanceRun($startPoints, $endPoints){$rows = [];foreach ($startPoints as $start_no => $start) {$elements = [];foreach ($endPoints as $end_no => $end) {// 上文的坐标系-距离$distance = getDistance($start['latitude'], $start['longitude'], $end['latitude'], $end['longitude']);$elements[$end_no] = ['type' => $end['type'],'distance' => $distance,'duration' => ceil($distance / 13.88), //秒,50km/h];}$rows[$start_no] = ['elements' => $elements,];}$result = ['status' => 0,'message' => 'query ok','result' => ['rows' => $rows,]];return $result;}// 路线距离public function matrixPointsDataApiRun($startPoints, $endPoints){$tencent_map_key = $this->getKey();$fromPoints = '';$toPoints = '';foreach ($startPoints as $key1 => $point) {if ($key1 > 50) break;$fromPoints .= ($fromPoints ? ';' : '') . $point['latitude'] . ',' . $point['longitude'];}foreach ($endPoints as $key2 => $point) {if ($key2 > 50) break;$toPoints .= ($toPoints ? ';' : '') . $point['latitude'] . ',' . $point['longitude'];}$url = 'https://apis.map.qq.com/ws/distance/v1/matrix/?mode=driving&from=' . $fromPoints . '&to=' . $toPoints . '&output=json&key=' . $tencent_map_key;$data = dCurl($url);$result = json_decode($data, true);logInfo('矢量规划', [// 'key' => $tencent_map_key,'time' => now()->format('Y-m-d H:i:s') . ':' . microtime(true),'startPoints' => $startPoints,'endPoints' => $endPoints,'result' => $result]);return $result;if ($result['status'] == 0) {return $result;// $distance = $result['result']['rows'][0]['elements'][0]['distance'];//起点到终点的距离,单位:米// $duration = $result['result']['rows'][0]['elements'][0]['duration'];//表示从起点到终点的结合路况的时间,秒为单位}return null;}function testDispatchCarsRoute(){// $startPoints = [// ['latitude'=>24.866162, 'longitude'=>118.607634],// ['latitude'=>24.877208, 'longitude'=>118.617732],// ];// // [0,all],[1,1]// $endPoints = [// ['latitude'=>24.877208, 'longitude'=>118.617732],// ['latitude'=>24.872074, 'longitude'=>118.638374],// ['latitude'=>24.870474, 'longitude'=>118.684264]// ];dd(getDistance(24.866162, 118.607634, 24.866298, 118.608382));// $result = (new TencentMap)->matrixPointsData($startPoints,$endPoints);$startPoint = ['latitude' => 24.866162, 'longitude' => 118.607634];$endPoint = ['latitude' => 24.870474, 'longitude' => 118.684264];$roadPoints = [['latitude' => 24.877208, 'longitude' => 118.617732],['latitude' => 24.872074, 'longitude' => 118.638374],];$result = $this->routePlanningData($startPoint, $endPoint, $roadPoints);}}
yufan个人站