Превышение лимита в 23 путевых точки на запрос в Google Directions API (уровень Business/Work)

Я хотел бы использовать API направлений Google для разработки программного обеспечения для планирования маршрутов для компании, которая занимается снегоочистителями зимой и ландшафтным дизайном летом. Одним из требований клиента является то, что он должен уметь рассчитывать маршруты как минимум с 30 (желательно больше) путевыми точками. Согласно документации (приведенной ниже), даже клиенты Google Maps API for Work ограничены всего 23 путевыми точками на запрос.

Использование Google Directions API ограничено 2500 запросами маршрутов в день. Запросы отдельных маршрутов могут содержать до 8 промежуточных путевых точек. Клиенты Google Maps API for Work могут запрашивать до 100 000 запросов маршрутов в день, при этом в каждом запросе допускается до 23 путевых точек.

Кто-нибудь знает об обходном пути - каким-либо образом - чтобы обойти это?

Кроме того, можно ли использовать обходной путь для бесплатного API? Я слышал, что премьер-аккаунты довольно дорогие.

Спасибо!! Марк


person Marc H    schedule 08.01.2012    source источник
comment
Вот мое решение проблемы. Примечания: - Установите MAX_WAYPOINTS_PER_REQUEST на 8, 23 или любое другое значение. - Каждый объект запроса, отправляемый в Google, также регистрируется в консоли браузера, чтобы вы могли его проверить.   -  person CrazyTim    schedule 05.07.2012
comment
эй, @CrazyTim, в какой-то момент я получаю статус=ZERO_RESULTS. если я удалю точку, она работает. как пропустить точку   -  person Nullify    schedule 30.09.2013
comment
@Kousik, я не знаю другого способа изолировать latlong, который вызывает ошибку ZERO_RESULTS, кроме ручной проверки каждой ссылки в цепочке. Возможно, лучше всего опубликовать это как отдельный вопрос.   -  person CrazyTim    schedule 01.10.2013
comment
эй, я положил один вопрос в стопку, я думаю, вы будете лучшим человеком для ответа. спасибо stackoverflow.com/questions/19116578/   -  person Nullify    schedule 01.10.2013
comment
@CrazyTim я исправил проблему, см. это jsfiddle.net/67tbw/29   -  person Nullify    schedule 03.10.2013
comment
Это техническое ограничение, наложенное для обеспечения соблюдения. Вы не можете загружать всю базу данных Google. Воспользуйтесь бесплатной картой, такой как Wikimapia или OSM, и выполните маршрутизацию на своей копии.   -  person Erkin Alp Güney    schedule 10.01.2017


Ответы (4)


Вы правы, первоначальная цена довольно высока, начиная с 10 000 долларов, в последний раз, когда я разговаривал с представителем Google по телефону.

Я нашел обходной путь, который я применил, чтобы обойти ограничение в 8 путевых точек. Я смог заставить его работать.

Я сделал это, получив свои путевые точки и разбив их на разные маршруты, но объединив их в один и тот же маршрут.

Например, если бы нужно было 30 путевых точек, я бы нарисовал 4 линии, но одного цвета и т. д. Таким образом, в основном вы разрезаете путевые точки на разные маршруты, каждый раз вызывая средство визуализации направлений, как если бы это был другой маршрут. Суть в том, что после первого маршрута следующий маршрут должен начинаться с последней путевой точки предыдущего маршрута (это гарантирует, что линии маршрута связаны друг с другом)

Это работает, но вам нужно написать гораздо больше кода, чем если бы у вас была основная учетная запись, и в этом случае вы требуете гораздо больше указаний.

Я искал и думал о других способах сделать это, не имея главной учетной записи, и потерпел неудачу.

Хотя, когда я разговаривал с Google, они сказали, что намеревались создать многоуровневую структуру оплаты для клиентов с разными желаниями / потребностями. Например, если клиенту просто нужно больше путевых точек, а не куча дополнительных запросов направлений.

Надеюсь, это поможет, так как это сработало для меня в практическом приложении.

person Bill Blankenship    schedule 09.01.2012
comment
Google действительно думает, что все такие же богатые, как они - person Pacerier; 10.01.2012
comment
Это работает для меня, и я знаю нескольких других, которые используют это таким образом. Это работает только в том случае, если вы не бьете его по тысяче раз в день. - person Bill Blankenship; 02.07.2012
comment
Что работает для вас? Где хак? В направлении API направление имеет 23 путевых точки, но в чем хак? Это как в моем ответе про загрузку библиотеки а не сколько путевых точек направления вы стреляете по гуглу???? - person Gigamegs; 02.07.2012
comment
Пожалуйста, прочтите эту ссылку. Мы не говорим о проблеме TSP. Мы говорим об ограничениях путевых точек с помощью средства визуализации направлений и о том, как проложить маршрут, который имеет больше, чем максимально допустимое с помощью этого ограничения использования, которое предоставляет Google. developers.google.com/maps/documentation/business/ - person Bill Blankenship; 02.07.2012
comment
Если вы этого не понимаете, обратитесь в Google, там указан номер телефона. - person Bill Blankenship; 02.07.2012
comment
Ну, я не уверен, почему ты тогда минусуешь меня? Другой парень, CrazyTim, тоже жалуется на мой ответ. Я все равно не делового уровня. Так что извините меня, если я вас неправильно понял. - person Gigamegs; 02.07.2012
comment
@BillBlankenship, у вас есть какой-нибудь код, чтобы поделиться? У меня есть аналогичная потребность в приложении для борьбы с комарами. - person MikeSchem; 28.09.2018
comment
Очень простой человек, просто создайте 8-точечный маршрут, а затем создайте второй маршрут с началом, начинающимся в конце 8-точечного маршрута. По сути, возьмите все свои путевые точки GPS, разделите их на 8, и это количество маршрутов, которые вам нужно создать независимо, а затем просто свяжите их вместе. - person Bill Blankenship; 01.10.2018

function initMap() {
    var service = new google.maps.DirectionsService;
    var map = new google.maps.Map(document.getElementById('map'));

    // list of points
    var stations = [
        {lat: 48.9812840, lng: 21.2171920, name: 'Station 1'},
        {lat: 48.9832841, lng: 21.2176398, name: 'Station 2'},
        {lat: 48.9856443, lng: 21.2209088, name: 'Station 3'},
        {lat: 48.9861461, lng: 21.2261563, name: 'Station 4'},
        {lat: 48.9874682, lng: 21.2294855, name: 'Station 5'},
        {lat: 48.9909244, lng: 21.2295512, name: 'Station 6'},
        {lat: 48.9928871, lng: 21.2292352, name: 'Station 7'},
        {lat: 48.9921334, lng: 21.2246742, name: 'Station 8'},
        {lat: 48.9943196, lng: 21.2234792, name: 'Station 9'},
        {lat: 48.9966345, lng: 21.2221262, name: 'Station 10'},
        {lat: 48.9981191, lng: 21.2271386, name: 'Station 11'},
        {lat: 49.0009168, lng: 21.2359527, name: 'Station 12'},
        {lat: 49.0017950, lng: 21.2392890, name: 'Station 13'},
        {lat: 48.9991912, lng: 21.2398272, name: 'Station 14'},
        {lat: 48.9959850, lng: 21.2418410, name: 'Station 15'},
        {lat: 48.9931772, lng: 21.2453901, name: 'Station 16'},
        {lat: 48.9963512, lng: 21.2525850, name: 'Station 17'},
        {lat: 48.9985134, lng: 21.2508423, name: 'Station 18'},
        {lat: 49.0085000, lng: 21.2508000, name: 'Station 19'},
        {lat: 49.0093000, lng: 21.2528000, name: 'Station 20'},
        {lat: 49.0103000, lng: 21.2560000, name: 'Station 21'},
        {lat: 49.0112000, lng: 21.2590000, name: 'Station 22'},
        {lat: 49.0124000, lng: 21.2620000, name: 'Station 23'},
        {lat: 49.0135000, lng: 21.2650000, name: 'Station 24'},
        {lat: 49.0149000, lng: 21.2680000, name: 'Station 25'},
        {lat: 49.0171000, lng: 21.2710000, name: 'Station 26'},
        {lat: 49.0198000, lng: 21.2740000, name: 'Station 27'},
        {lat: 49.0305000, lng: 21.3000000, name: 'Station 28'},
    ];
    
    // Zoom and center map automatically by stations (each station will be in visible map area)
    var lngs = stations.map(function(station) { return station.lng; });
    var lats = stations.map(function(station) { return station.lat; });
    map.fitBounds({
        west: Math.min.apply(null, lngs),
        east: Math.max.apply(null, lngs),
        north: Math.min.apply(null, lats),
        south: Math.max.apply(null, lats),
    });
    
    // Show stations on the map as markers
    for (var i = 0; i < stations.length; i++) {
        if (!stations[i].name)
            continue;
        new google.maps.Marker({
            position: stations[i],
            map: map,
            title: stations[i].name
        });
    }

    // Divide route to several parts because max stations limit is 25 (23 waypoints + 1 origin + 1 destination)
    for (var i = 0, parts = [], max = 8 - 1; i < stations.length; i = i + max)
        parts.push(stations.slice(i, i + max + 1));

    // Callback function to process service results
    var service_callback = function(response, status) {
        if (status != 'OK') {
            console.log('Directions request failed due to ' + status);
            return;
        }
        var renderer = new google.maps.DirectionsRenderer;
        renderer.setMap(map);
        renderer.setOptions({ suppressMarkers: true, preserveViewport: true });
        renderer.setDirections(response);
    };
        
    // Send requests to service to get route (for stations count <= 25 only one request will be sent)
    for (var i = 0; i < parts.length; i++) {
        // Waypoints does not include first station (origin) and last station (destination)
        var waypoints = [];
        for (var j = 1; j < parts[i].length - 1; j++)
            waypoints.push({location: parts[i][j], stopover: false});
        // Service options
        var service_options = {
            origin: parts[i][0],
            destination: parts[i][parts[i].length - 1],
            waypoints: waypoints,
            travelMode: 'WALKING'
        };
        // Send request
        service.route(service_options, service_callback);
    }
  }
html, body {
    height: 100%;
    margin: 0;
    padding: 0;
}
#map {
    height: 100%;     
    width: 100%;
    height: 100%;
}
<div id="map"></div>

<!-- without API KEY set variable "max" to 8 -->
<script async defer src="https://maps.googleapis.com/maps/api/js?callback=initMap"></script>

<!-- with API KEY set variable "max" to 25 -->
<!-- <script async defer src="https://maps.googleapis.com/maps/api/js?callback=initMap&key=YOUR_API_KEY"></script>-->

С помощью следующего кода вы можете использовать столько путевых точек, сколько вам нужно, и вы никогда не получите ошибку MAX_WAYPOINTS_EXCEEDED. Не забудьте заменить «YOUR_API_KEY» на ваш API KEY или удалить &key=YOUR_API_KEY из URL-адреса API Google и установить для переменной «max» значение 8 (max = 25 при использовании API KEY, max = 8, если нет используя ключ API).

<style>
html, body { height: 100%; margin: 0; padding: 0; }
#map { height: 100%; width: 100%; height: 100%; }
</style>
<div id="map"></div>
<script>
  function initMap() {
    var service = new google.maps.DirectionsService;
    var map = new google.maps.Map(document.getElementById('map'));

    // list of points
    var stations = [
        {lat: 48.9812840, lng: 21.2171920, name: 'Station 1'},
        {lat: 48.9832841, lng: 21.2176398, name: 'Station 2'},
        {lat: 48.9856443, lng: 21.2209088, name: 'Station 3'},
        {lat: 48.9861461, lng: 21.2261563, name: 'Station 4'},
        {lat: 48.9874682, lng: 21.2294855, name: 'Station 5'},
        {lat: 48.9909244, lng: 21.2295512, name: 'Station 6'},
        {lat: 48.9928871, lng: 21.2292352, name: 'Station 7'},
        {lat: 48.9921334, lng: 21.2246742, name: 'Station 8'},
        {lat: 48.9943196, lng: 21.2234792, name: 'Station 9'},
        {lat: 48.9966345, lng: 21.2221262, name: 'Station 10'},
        {lat: 48.9981191, lng: 21.2271386, name: 'Station 11'},
        {lat: 49.0009168, lng: 21.2359527, name: 'Station 12'},
        {lat: 49.0017950, lng: 21.2392890, name: 'Station 13'},
        {lat: 48.9991912, lng: 21.2398272, name: 'Station 14'},
        {lat: 48.9959850, lng: 21.2418410, name: 'Station 15'},
        {lat: 48.9931772, lng: 21.2453901, name: 'Station 16'},
        {lat: 48.9963512, lng: 21.2525850, name: 'Station 17'},
        {lat: 48.9985134, lng: 21.2508423, name: 'Station 18'},
        {lat: 49.0085000, lng: 21.2508000, name: 'Station 19'},
        {lat: 49.0093000, lng: 21.2528000, name: 'Station 20'},
        {lat: 49.0103000, lng: 21.2560000, name: 'Station 21'},
        {lat: 49.0112000, lng: 21.2590000, name: 'Station 22'},
        {lat: 49.0124000, lng: 21.2620000, name: 'Station 23'},
        {lat: 49.0135000, lng: 21.2650000, name: 'Station 24'},
        {lat: 49.0149000, lng: 21.2680000, name: 'Station 25'},
        {lat: 49.0171000, lng: 21.2710000, name: 'Station 26'},
        {lat: 49.0198000, lng: 21.2740000, name: 'Station 27'},
        {lat: 49.0305000, lng: 21.3000000, name: 'Station 28'},
        // ... as many other stations as you need
    ];

    // Zoom and center map automatically by stations (each station will be in visible map area)
    var lngs = stations.map(function(station) { return station.lng; });
    var lats = stations.map(function(station) { return station.lat; });
    map.fitBounds({
        west: Math.min.apply(null, lngs),
        east: Math.max.apply(null, lngs),
        north: Math.min.apply(null, lats),
        south: Math.max.apply(null, lats),
    });

    // Show stations on the map as markers
    for (var i = 0; i < stations.length; i++) {
        new google.maps.Marker({
            position: stations[i],
            map: map,
            title: stations[i].name
        });
    }

    // Divide route to several parts because max stations limit is 25 (23 waypoints + 1 origin + 1 destination)
    for (var i = 0, parts = [], max = 25 - 1; i < stations.length; i = i + max)
        parts.push(stations.slice(i, i + max + 1));

    // Service callback to process service results
    var service_callback = function(response, status) {
        if (status != 'OK') {
            console.log('Directions request failed due to ' + status);
            return;
        }
        var renderer = new google.maps.DirectionsRenderer;
        renderer.setMap(map);
        renderer.setOptions({ suppressMarkers: true, preserveViewport: true });
        renderer.setDirections(response);
    };

    // Send requests to service to get route (for stations count <= 25 only one request will be sent)
    for (var i = 0; i < parts.length; i++) {
        // Waypoints does not include first station (origin) and last station (destination)
        var waypoints = [];
        for (var j = 1; j < parts[i].length - 1; j++)
            waypoints.push({location: parts[i][j], stopover: false});
        // Service options
        var service_options = {
            origin: parts[i][0],
            destination: parts[i][parts[i].length - 1],
            waypoints: waypoints,
            travelMode: 'WALKING'
        };
        // Send request
        service.route(service_options, service_callback);
    }
  }
</script>
<script async defer src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&callback=initMap"></script>

Здесь вы видите экран.

поиграйте с кнопками отображения/скрытия линий

person mikep    schedule 17.04.2017
comment
@Tenz хранит ссылки на var map и var renderer где-то, чтобы они были доступны позже. Например: window.gMap = map; и if (!window.gRenderers) { window.renderers = []; } window.gRenderers.push(renderer); и позже, чтобы скрыть/отобразить строку, используйте for (var r of gRenderers) r.setMap(null);, чтобы скрыть и for (var r of gRenderers) r.setMap(gMap);, чтобы показать. Кстати, чтобы сразу скрыть строку по умолчанию, добавьте suppressPolylines = true к renderer.setOptions({}). К сожалению, установка suppressPolylines позже не работает (только при инициализации), поэтому мы используем must use setMap() хак. - person mikep; 19.03.2018
comment
Как я могу сделать это в Android, не могли бы вы помочь?! - person Amal Kronz; 21.03.2019
comment
Привет @mikep, вы знаете, можно ли открыть ту же карту направлений в родном приложении Google Maps на iOS с таким же количеством путевых точек? - person doorman; 23.08.2019
comment
Как мы можем вычислить общее время и расстояние в этом случае? - person Anurag.Desai; 30.01.2020
comment
@ Anurag.Desai Извините, я этого не знаю, в моем случае мне просто нужно было нарисовать маршрут между многими точками (не заботясь о времени и расстояниях). Попробуйте найти это в документации API карт Google. - person mikep; 30.01.2020
comment
Я получил его с помощью response.routes[0].legs[0].duration, а затем использовал алгоритм из stackoverflow.com/questions/30326091/ - person Anurag.Desai; 30.01.2020

Существует легко вокруг этого решения.

Сохраняйте путевые точки в массиве на основе порогового значения расстояния и продолжайте добавлять их. Как только вы достигнете предела в 8 значений в массиве, назначьте 1-ю позицию (начало) массива путевых точек новому массиву путевых точек.... Назначьте последнюю путевую точку новой путевой точке в качестве 2-го элемента... теперь замените старый массив путевых точек с этим новым и продолжить.

Независимо от того, что вы делаете, путевые точки никогда не будут пересекать более 8 значений, и он будет отслеживать выбранный маршрут, чтобы нанести его на карту (если путешествие не слишком длинное).

var addWaypoint = function(point) {
    if($scope.waypoints.length > 8){
        var temp = [];
        temp.push($scope.waypoints[0]); //Start Point
        temp.push($scope.waypoints[7]); //Last point
        temp.push(point); //New point
        $scope.waypoints = temp; //Replace the old object with this new one
    }
    else 
        $scope.waypoints.push(point);
}
person anupsahu    schedule 04.10.2016

Приведенный ниже код на C# вычисляет, сколько вызовов вы сделаете через Google Directions API и сколько путевых точек на каждой итерации. Вы можете изменить Modmin, чтобы изменить минимальное количество путевых точек, которое вы хотите на последней итерации.

Например, если у вас totalWaypoints.Count = 97:

97 Mod 23 = 5, в этом случае я хочу, чтобы Modmin был больше 5, поэтому я снова буду вычислять с меньшим значением waypointsByIteration;

97 Mod 22 = 9, (9 > Modmin), ОК;

итерации = ((97 - (97 % 22)) / (22)) + 1 = 5;

На последней итерации waypointsByIteration будет остатком.

        var iterations = 1;//Number of iterations
        var waypointsByIteration = 23;//Number of waypoints by iteration
        var modMin = 5;//Minimum of Waypoints in the last iteration
        var residue = 0;//Residue of the division (totalWaypoints % waypointsByIteration)

        if (totalWaypoints.Count <= waypointsByIteration)
        {
            waypointsByIteration = totalWaypoints.Count;
        }
        else
        {
            while (totalWaypoints.Count % waypointsByIteration < modMin)
            {
                waypointsByIteration--;
            }

            //Calculate number of waypoints by iteracoes
            iterations = ((totalWaypoints.Count - (totalWaypoints.Count % waypointsByIteration)) / (waypointsByIteration)) + 1;
        }

        residue = totalWaypoints % waypointsByIteration;

        for(i=0;i<iterations;i++)
        {
            //If it is the last index, the waypointsByIteration will be the residue
            if(i == iteration - 1)
            {
                waypointsByIteration = residue;
            }
        }
person Jonathan Molina    schedule 04.05.2017