Элегантный способ найти самый короткий и быстрый маршрут в Google Maps API v3?

Я делаю калькулятор тарифов на такси. Одним из бизнес-требований является то, что компания хочет самые короткие и быстрые варианты маршрутов. Я знаю, что Google directionService по умолчанию искал самый быстрый маршрут. Я установил опцию "avoidhighways" в параметре запроса true, чтобы получить самый короткий маршрут, но я не совсем доволен результатом.

У кого-то есть лучшее решение, чем это?

Ответ 1

Чтобы получить кратчайший маршрут от A до BI, предложите сделать разные запросы с параметром "alternatives = true", играя с параметром "избегать" между avoid = toll, avoid = highways, а затем я бы сравнил все результаты выбрать самый короткий маршрут.

 directionsService = new google.maps.DirectionsService;
//avoiding tolls
            directionsService.route({
                origin: {
                    'placeId': originId
                },
                destination: {
                    'placeId': destinationId
                },
                provideRouteAlternatives: true,
                avoidTolls: true,
                travelMode: google.maps.TravelMode.DRIVING
            }, function(response, status) {
                if (status === google.maps.DirectionsStatus.OK) {
                    routesResponses.push(response);
                }
                else {
                    window.alert('Directions request failed due to ' + status);
                }
            });
            //avoiding highways
            directionsService.route({
                origin: {
                    'placeId': originId
                },
                destination: {
                    'placeId': destinationId
                },
                provideRouteAlternatives: true,
                avoidHighways: true,
                travelMode: google.maps.TravelMode.DRIVING
            }, function(response, status) {
                if (status === google.maps.DirectionsStatus.OK) {
                    routesResponses.push(response);
                }
                else {
                    window.alert('Directions request failed due to ' + status);
                }

                //Results analysis and drawing of routes
                var fastest = Number.MAX_VALUE,
                    shortest = Number.MAX_VALUE;

                routesResponses.forEach(function(res) {
                    res.routes.forEach(function(rou, index) {
                        console.log("distance of route " +index+": " , rou.legs[0].distance.value);
                        console.log("duration of route " +index+": " , rou.legs[0].duration.value);
                        if (rou.legs[0].distance.value < shortest) shortest = rou.legs[0].distance.value  ;
                        if (rou.legs[0].duration.value < fastest) fastest = rou.legs[0].duration.value  ;

                    })
                })
                console.log("shortest: ", shortest);
                console.log("fastest: ", fastest);
//painting the routes in green blue and red
                 routesResponses.forEach(function(res) {
                    res.routes.forEach(function(rou, index) {
                        new google.maps.DirectionsRenderer({
                            map:map,
                            directions:res,
                            routeIndex:index,
                            polylineOptions:{
                                strokeColor: rou.legs[0].duration.value == fastest? "red":rou.legs[0].distance.value == shortest?"darkgreen":"blue",
                                strokeOpacity: rou.legs[0].duration.value == fastest? 0.8:rou.legs[0].distance.value == shortest? 0.9: 0.5,
                                strokeWeight: rou.legs[0].duration.value == fastest? 9:rou.legs[0].distance.value == shortest? 8: 3,
                            }
                        })
                    })
                })   
            });
        }

    }

Ответ 2

У вас есть три варианта с опцией alternatives=true. Затем вы можете искать их как для кратчайшего, так и для быстрого возврата маршрутов.

Ответ 3

См. http://codepen.io/jasonmayes/pen/DupCH.

var shortestDistance = function() {  
    var directionsDisplay;
    var directionsService = new google.maps.DirectionsService();
    var map;
    var size = 0;
    var currentPosition;

    // An array of interesting places we want to potentially visit.
    var interestingPlaces = [
    {'title': 'Regents Park', 'latLng': new google.maps.LatLng(51.530686, -0.154753)},
    {'title': 'Hyde Park', 'latLng': new google.maps.LatLng(51.507293, -0.164022)},
    {'title': 'Green Park', 'latLng': new google.maps.LatLng(51.504088, -0.141706)},
    {'title': 'Regents Park', 'latLng': new google.maps.LatLng(51.479185, -0.159903)}
    ];

    // An array to store results from Google routing API.
    var routeResults = [];


    // Call this upon page load to set everything in motion!
    function initialize(currentLat, currentLng) {
    currentPosition = new google.maps.LatLng(currentLat, currentLng);
    directionsDisplay = new google.maps.DirectionsRenderer();
    var mapOptions = {
        zoom: 13,
        center: currentPosition
    };
    map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions);
    directionsDisplay.setMap(map);

    var marker = new google.maps.Marker({
            position: currentPosition,
            map: map,
            title: 'Currrently location.'
    });

    var i = interestingPlaces.length;
        while (i--) {
        interestingPlaces[i].marker = new google.maps.Marker({
        position: interestingPlaces[i].latLng,
        map: map,
        title: interestingPlaces[i].title,
        icon: 'http://maps.google.com/mapfiles/ms/icons/green.png'
        });
    }

    findNearestPlace();
    }


    // Loops through all inteesting places to calculate route between our current position
    // and that place.
    function findNearestPlace() {
    var i = interestingPlaces.length;
    size = interestingPlaces.length;
    routeResults = [];
    while (i--) {
        calcRoute(interestingPlaces[i].latLng, storeResult);
    }
    }


    // A function to calculate the route between our current position and some desired end point.
    function calcRoute(end, callback) {
    var request = {
        origin: currentPosition,
        destination: end,
        travelMode: google.maps.TravelMode.DRIVING
    };
    directionsService.route(request, function(response, status) {
        if (status == google.maps.DirectionsStatus.OK) {
        callback(response);
        } else {
        size--;
        }
    });
    }


    // Stores a routing result from the API in our global array for routes.
    function storeResult(data) {
    routeResults.push(data);
    if (routeResults.length === size) {
        findShortest();
    }
    }


    // Goes through all routes stored and finds which one is the shortest. It then
    // sets the shortest route on the map for the user to see.
    function findShortest() {
    var i = routeResults.length;
    var shortestIndex = 0;
    var shortestLength = routeResults[0].routes[0].legs[0].distance.value;

    while (i--) {
        if (routeResults[i].routes[0].legs[0].distance.value < shortestLength) {
        shortestIndex = i;
        shortestLength = routeResults[i].routes[0].legs[0].distance.value;
        }
    }
    directionsDisplay.setDirections(routeResults[shortestIndex]);
    }

    // Expose the initialize function publicly as "init".
    return {
    init: initialize
    };
}();

// Upon page load, lets start the process!
google.maps.event.addDomListener(window, 'load', shortestDistance.init(51.489554, -0.12969));

ОТКАЗ

ЭТО НЕ МОЙ ПЕН!!! Я ТОЛЬКО ОБРАЩАЮСЬ В ПОЛЕЗНЫЙ РЕСУРС, КОТОРЫЙ МОЖЕТ ПОМОЧЬ

Ответ 4

Прежде всего, извините за то, что мое решение находится в TS, вы можете легко преобразовать его в JS.

Атрибут "avoidhighways" не существует, чтобы получить самый быстрый или короткий маршрут, он там, для чего предлагает название, избегая шоссе.

Я сделал свое собственное решение, всегда получая несколько маршрутов с этим атрибутом:

directionsService.route({
            [...]
            provideRouteAlternatives: true
            [...]
         }, (response, status) => {
            if (status === google.maps.DirectionsStatus.OK) {
                var shortest: google.maps.DirectionsResult = this.shortestRoute(response);
                this.directionsDisplay.setDirections(shortest);
                [...]

И я сделал эту функцию, которая возвращает DirectionsResult только с одним маршрутом. В этом случае это кратчайший, но вы можете tweek его, чтобы он возвращал то, что когда-либо маршрут соответствует вашим потребностям.

    shortestRoute = (routeResults: google.maps.DirectionsResult): google.maps.DirectionsResult => {
        var shortestRoute: google.maps.DirectionsRoute = routeResults.routes[0];
        var shortestLength = shortestRoute.legs[0].distance.value;
        for (var i = 1; i < routeResults.routes.length; i++) {
            if (routeResults.routes[i].legs[0].distance.value < shortestLength) {
                shortestRoute = routeResults.routes[i];
                shortestLength = routeResults.routes[i].legs[0].distance.value;
            }
        }
        routeResults.routes = [shortestRoute];
        return routeResults;
    }

Ответ 5

Я взял код из Soldeplata Saketos и отредактировал его, так как он не работал. Добавлены параметры, поэтому вы можете просто называть это с помощью.

shortestRoute(origin, destination, map); 

Работает для меня всем, хотя я не уверен, насколько это правильно.

Здесь:

function shortestRoute(origin, destination, map) {

  directionsService = new google.maps.DirectionsService();
  var routesResponses = [];
  //avoiding tolls
  directionsService.route({
    origin: origin,
    destination: destination,
    provideRouteAlternatives: true,
    avoidTolls: true,
    travelMode: google.maps.TravelMode.DRIVING
  }, function (response, status) {
    if (status === google.maps.DirectionsStatus.OK) {
      routesResponses.push(response);
    } else {
      window.alert('Directions request failed due to ' + status);
    }
  });
  //avoiding highways
  directionsService.route({
    origin: origin,
    destination: destination,
    provideRouteAlternatives: true,
    avoidHighways: true,
    travelMode: google.maps.TravelMode.DRIVING
  }, function (response, status) {
    if (status === google.maps.DirectionsStatus.OK) {
      routesResponses.push(response);
    } else {
      window.alert('Directions request failed due to ' + status);
    }

    //Results analysis and drawing of routes
    var fastest = Number.MAX_VALUE,
      shortest = Number.MAX_VALUE;

    routesResponses.forEach(function (res) {
      res.routes.forEach(function (rou, index) {
        console.log("distance of route " + index + ": ", rou.legs[0].distance.value);
        console.log("duration of route " + index + ": ", rou.legs[0].duration.value);
        if (rou.legs[0].distance.value < shortest) shortest = rou.legs[0].distance.value;
        if (rou.legs[0].duration.value < fastest) fastest = rou.legs[0].duration.value;

      })
    })
    console.log("shortest: ", shortest);
    console.log("fastest: ", fastest);
    //painting the routes in green blue and red
    routesResponses.forEach(function (res) {
      res.routes.forEach(function (rou, index) {
        new google.maps.DirectionsRenderer({
          map: map,
          directions: res,
          routeIndex: index,
          polylineOptions: {
            strokeColor: rou.legs[0].duration.value == fastest ? "red" : rou.legs[0].distance.value == shortest ? "darkgreen" : "blue",
            strokeOpacity: rou.legs[0].duration.value == fastest ? 0.8 : rou.legs[0].distance.value == shortest ? 0.9 : 0.5,
            strokeWeight: rou.legs[0].duration.value == fastest ? 9 : rou.legs[0].distance.value == shortest ? 8 : 3,
          }
        });
      });
    });
  });
}

Ответ 6

Вышеприведенные решения утомительны и не могут гарантировать работу (избегать дорожных сборов/шоссе и т.д.). Лучшим решением должно быть то, что, запрашивая маршрут несколькими промежуточными парами od. Сумма всех разделов будет маршрутом, если ваши промежуточные пары od правильно установлены. Вы можете попробовать себя. Я уверен, что сумма времени проезда/расстояния между участками очень близка к количеству маршрутов, запрошенных в целом.

Ответ 7

Use optimizeWaypoints: true  in Request perameter. See below code snippet

var request ={
                origin: sStartLatLng,
                destination: sStartLatLng,
                waypoints: waypts,
                optimizeWaypoints: true,
                travelMode: google.maps.DirectionsTravelMode.DRIVING
            };