谷歌地图方向服务航路点超过 50 个

Posted

技术标签:

【中文标题】谷歌地图方向服务航路点超过 50 个【英文标题】:Google map direction services waypoints more than 50 【发布时间】:2014-03-29 02:29:47 【问题描述】:

Documentation 表示航点限制为 8 个点。但我必须从 50 多个航点中找到最佳航点订单列表。该怎么做?

我可以使用 Start + Destination + 8 Waypoints 找到航点顺序,但我需要超过 50 个航点的帮助

【问题讨论】:

目前,在 2016 年,文档说 Directions API Web 服务中的最大航点数为 23。 【参考方案1】:

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 或从 google API URL 中删除 &key=YOUR_API_KEY 并将变量“max”设置为 8(使用 API KEY 时 max = 25,不使用时 max = 8使用 API KEY)。

<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>

【讨论】:

这不起作用,因为您“将路线划分为几个部分”,但这些部分是 25 个完全任意点的块。无法保证您随机分成 25 个一组的点甚至彼此接近。事实上,如果您可以确定 point[i]point[i+1] 接近,则根本不需要优化路线。 在我的情况下不需要点优化。在我的情况下,点是已知的,我只需要连接它(点是公共交通车站,它们通常一排排地从一个到另一个)。这取决于目的。在许多情况下,它是合适的解决方案,但我同意这不适用于 100% 的情况。通过在这个答案和这个 ***.com/a/43458012/3826175 中投票,包括积极的 cmets,它帮助了许多用户。在谷歌增加限制之前没有其他更好的方法。 问题要求“找到最佳航点顺序”,这个答案不会。 我认为可能有一个解决方案。在我的情况下,点通常是一排排的(因为公交车站点已经优化)所以我的解决方案运行良好。如果点是随机的,您应该首先按距离对其进行排序 - 例如使用 hasrsine 算法***.com/a/365853/3826175 或者当所有点都在半径几公里内(可以假设地球是平的)时,可以使用更简单+更快的算法。当点按距离(非随机)排序时,当将点传递给我的解决方案时,很有可能获得正确的结果,该解决方案将路线拆分为部分。 按距离排序到什么?到你的参考点?然后你在你周围的一个球体/圆中按半径对它们进行排序,经过仅仅 1 公里的距离排序,这些点将彼此相距 0 到 2 半径(2 公里),具体取决于它们与你所在的方向。如果您按到前一个最近点的距离对每个点进行排序,那么您就有一个 O(n^2) 算法可以进行随机游走,那么最好只进行随机游走。旅行商问题不能这样解决。众所周知,解决问题的复杂性正是航路点如此有限的原因【参考方案2】:

我创建了一个解决方法,但使用起来有点贵(就 API 调用而言)。

我没有使用开始、结束和航路点 LatLngs 创建单个呼叫,而是将航路点分成对进行呼叫。

例子:

问题:路线并获得 100 点的路线

解决办法:

呼叫 1:点 1 和点 2 呼叫 2:第 2 点和第 3 点

调用 3: 第 3 点和第 4 点

...等等。

使用此解决方案,您将永远不必担心 8 个航点的限制,因为您每次只进行 2 点查询。此解决方案的缺点是您将创建大量呼叫,如果使用不当,它会占用您每天 2500 次免费呼叫。

【讨论】:

是的,你是对的。此过程将使用所有可用的免费通话限制。就我而言,每天将有19K-20K 积分。所以这个解决方案对我没有帮助。 优化路线怎么样?有什么用吗? 您好,Google 通常会根据您传递的参数进行自己的路线优化。【参考方案3】:

很遗憾,这是不可能的。

如果您有企业帐户,您最多可以添加大约 25 个航点。企业帐户非常昂贵。

如果您需要使用超过 25 个航点,则需要寻找其他供应商。

【讨论】:

【参考方案4】:

我找到了这个解决方法。

它似乎完全符合您的需要。看看:http://lemonharpy.wordpress.com/2011/12/15/working-around-8-waypoint-limit-in-google-maps-directions-api/

【讨论】:

这对我的情况没有帮助,因为这并不能提供准确的航点顺序,以便为驾驶员方向提供最佳帮助【参考方案5】:

HERE Maps (https://developer.here.com/blog/delivery-made-easy-with-the-here-waypoint-sequence-api) 提供多达 120 个航点的航点优化。看看他们,他们的价格也很合理

【讨论】:

您的链接已损坏。 固定到更新的链接。谢谢你让我注意到罗宾。请支持我的回答,因为我无法删除您的反对票。 :) 投反对票的不是我 ;) 我点击链接了解为什么有人会投反对票。您还可以通过使用 HERE API 提供有关航点的简短代码示例来提高答案的质量。 (然后我会自己投票)

以上是关于谷歌地图方向服务航路点超过 50 个的主要内容,如果未能解决你的问题,请参考以下文章

谷歌地图:自动建议地址问题

使用2个谷歌地图点(纬度和经度)从mongodb查询中查找方形区域数据

如何从谷歌地图 api android 中删除多余的折线

谷歌地图自动完成动态数组

谷歌地图默认图标

绘制折线捕捉到道路Android谷歌地图应用程序