坐标系-路线规划
2022-01-11 08:47 / 浏览量:1506

路径导航:这里分享的主行程并入途经点的腾讯地图类,了解原理后你也可以采用其他地图制作类调用。

<?php
namespace 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);  }}