我想使用google Directions API为一家公司开发路线规划软件,该公司在冬季处理除雪机,在夏季进行景观美化。客户要求之一是他能够计算至少30个(最好是更多)航点的航线。根据文档(引用如下),即使Google Maps API for Work客户每个请求仅限于23个航点。
使用Google Directions API时,查询限制为每天2,500个路线请求。单个路线请求可在请求中包含最多8个中间路点。 Google Maps API for Work客户每天最多可查询100,000个路线请求,每个请求最多允许23个路标。
是否有人知道一种解决方法 - 任何方式 - 解决这个问题?
此外 - 是否可以使用免费API的变通方法?我听说首要账户非常昂贵。
谢谢! 马克
答案 0 :(得分:18)
你是正确的,首次定价相当昂贵起价为10,000美元,上次我在电话上与谷歌代表交谈。
我找到了一种解决方法,我以某种方式绕过了8个航点限制。我能够使它发挥作用。
我这样做是通过接收我的航点并将它们分成不同的路线,但将它们作为相同的路线绘制在一起。
例如,如果需要30个航点,我会绘制4条线,但颜色相同等等。因此,基本上你将航点切入不同的路线,每次调用方向渲染器就好像它是一条不同的路线。关键是在第一条路线之后,下一条路线必须从前一条路线的最后一个航路点开始(这样可以确保路线相互连接)
它有效,但是你需要编写比你拥有高级帐户更多的代码,并且在这种情况下你需要更多的方向。
我已经搜索并考虑过其他方法,在没有高级帐户的情况下做到这一点并且失败了。
虽然我在与谷歌交谈时确实表示他们打算为有不同需求/需求的客户创建分层付款结构。例如,如果客户只需要更多的路标而不是更多的方向请求。
希望这会有所帮助,因为它在练习应用程序中对我有用。
答案 1 :(得分:11)
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网址中删除&amp; key = YOUR_API_KEY ,并将变量“max”设置为8(使用API KEY时max = 25,max = 8不使用API KEY时。)
<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>
答案 2 :(得分:0)
这是一个使用超过8个航点的黑客攻击。请检查我的解决方案。
Drawing roadmap with more than 8 waypoints using Google directions API
答案 3 :(得分:0)
这个解决方案很简单。
根据距离阈值保持阵列中的航点并继续添加它们。一旦达到数组中8个值的限制,将航点阵列的第一个位置(原点)分配给新的航点阵列....将最后一个航点指定为新航点作为第二个元素...现在替换使用这个新的路点阵列并继续。
你做的Watever航点永远不会超过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);
}
答案 4 :(得分:-2)
C#中的以下代码计算您将使用Google Directions API调用的次数以及每次迭代的路点数。您可以修改Modmin以更改上次迭代时所需的最小航路点。
例如,如果你有totalWaypoints.Count = 97:
97 Mod 23 = 5,在这种情况下我想要一个大于5的Modmin,所以我将用较低的waypointsByIteration再次计算;
97 Mod 22 = 9,(9&gt; Modmin),OK;
iterations =((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;
}
}