I am trying to write a simple script in order to calculate in a google sheet the travelling time between two locations, by taking in account the traffic.
I am using the class DirectionFinder of the google Maps API.
I have managed to calculate the time necessary for a trip, but whatever departure time I enter, my travelling time stays the same. Any idea on what am I doing wrong ? Is it even possible to take traffic into account using this class ? Do I need to be a business user to have access to this ?
Here is my code :
function DrivingSeconds(origin, destination, Y, M, D, H, S) {
Utilities.sleep(1000);
var time= new Date(Y,M,D,H,S);
var directions = Maps.newDirectionFinder()
.setDepart(time)
.setOrigin(origin)
.setDestination(destination)
.setMode(Maps.DirectionFinder.Mode.DRIVING)
.getDirections();
return directions.routes[0].legs[0].duration.value;
}
Thanks for any advice that you might have ! :)
From Google documentation:
For requests where the travel mode is driving: You can specify the departure_time to receive a route and trip duration (response field: duration_in_traffic) that take traffic conditions into account. This option is only available if the request contains a valid API key, or a valid Google Maps APIs Premium Plan client ID and signature. The departure_time must be set to the current time or some time in the future. It cannot be in the past.
https://developers.google.com/maps/documentation/directions/intro#RequestParameters
So yes, only for Premium users.Then your request should look like this:
var request = {
origin: origin,
destination: destination,
drivingOptions: {
departureTime: new Date(),
},
travelMode: google.maps.TravelMode[DRIVING]
};
var directionsService = new google.maps.DirectionsService();
directionsService.route(request, function(response,status) {
if(status == google.maps.DirectionsStatus.OK) {
console.log(response.routes[0].legs[0].duration_in_traffic);
}
});
directions.routes[0].legs[0].duration_in_traffic may be what you need.
E.g. this code:
function traffic_test() {
var threeAM = new Date();
threeAM.setDate(threeAM.getDate() + 1);
threeAM.setHours(3, 0, 0);
var eightAM = new Date(threeAM);
eightAM.setHours(8, 0, 0);
var directionFinder = Maps.newDirectionFinder()
.setOrigin('Union Square, San Francisco')
.setDestination('Golden Gate Park, San Francisco')
.setMode(Maps.DirectionFinder.Mode.DRIVING);
var directions = directionFinder.setDepart(threeAM).getDirections();
var leg = directions.routes[0].legs[0];
Logger.log('3AM: leg.duration=' + leg.duration.text +
'; leg.duration_in_traffic=' + leg.duration_in_traffic.text);
directions = directionFinder.setDepart(eightAM).getDirections();
leg = directions.routes[0].legs[0];
Logger.log('8AM: leg.duration=' + leg.duration.text +
'; leg.duration_in_traffic=' + leg.duration_in_traffic.text);
}
logs this:
[19-07-21 08:39:54:606 PDT] 3AM: leg.duration=16 mins; leg.duration_in_traffic=12 mins
[19-07-21 08:39:54:795 PDT] 8AM: leg.duration=16 mins; leg.duration_in_traffic=16 mins
Related
I am using the Google Directions API, initially to get the detailed from/to directions, i.e. from let's say Denver to Chicago.
What I need to do is get actual road mileage as they are driving. I am successfully streaming the coordinates from the plugin by geolocator, however, when I get distance between two GPS points it's the distance, not road mileage. This should be somewhat accurate if I take enough of these little readings and add up the distance.
Is this the best way?
I could also keep calling Google API, but that gets very expensive on a long trip with lots of users.
The API provides the distance in the route's Legs. Loop through them to add up the total distance in meters.
DirectionsService.init('API_KEY');
final directionsService = DirectionsService();
final request = DirectionsRequest(
origin: 'New York',
destination: 'San Francisco',
travelMode: TravelMode.driving,
);
directionsService.route(request, (result, status) {
if (status != DirectionsStatus.ok) {
// TODO Handle the error.
return;
}
var totalDistance = 0.0;
result.routes?.first.legs?.forEach((element) {
totalDistance += element.distance?.value?.toDouble() ?? 0.0;
});
print("This trip is $totalDistance meters.");
});
I need to calculate the google maps derived distance between around 72,000 pairs of zip codes. I found a function online for google sheets which will do this, but I of course ran out of calls well before getting through the 72,000. So I set up billing within google maps api and now have an API key along with a ClientID. But I still can't get this to work. See below where "I tried adding this" based on what I've been able to find elsewhere.
function GOOGLEMAPS(start_address,end_address,return_type) {
// I tried adding this: var key = "";
// I tried adding this: var clientID = "YourClientIDHERE.apps.googleusercontent.com"
// I tried adding this: maps.setauthentication(clientID,key);
var mapObj = Maps.newDirectionFinder();
mapObj.setOrigin(start_address);
mapObj.setDestination(end_address);
Utilities.sleep(6000);
var directions = mapObj.getDirections();
var getTheLeg = directions["routes"][0]["legs"][0];
var meters = getTheLeg["distance"]["value"];
switch(return_type){
case "miles":
return meters * 0.000621371;
break;
case "minutes":
// get duration in seconds
var duration = getTheLeg["duration"]["value"];
//convert to minutes and return
return duration / 60;
break;
case "hours":
// get duration in seconds
var duration = getTheLeg["duration"]["value"];
//convert to hours and return
return duration / 60 / 60;
break;
case "kilometers":
return meters / 1000;
break;
default:
return "Error: Wrong Unit Type";
}
}
The function works fine. I tested it between my current home and my childhood home and got 1212 miles. With Google Maps it was 1212 Miles. So pretty close I'd say.
How to get all places like Entertainment, food, gas station etc on google map plotted route from source to destination only on route not nearby.
To build on the link that #geocodezip gave, to work around query limits it might be a better practice to make a bounding box based on steps rather than using the Google Maps utility, and then filter locations by actual distance to a node in the step. This could be accomplished using the following code:
In initialize(), put:
var placeserv = null;
function initialize(){
//setup map
placeserv = new google.maps.PlacesService(map); //use your map variable
}
In the callback function for the Directions Service (using parameters results and status), you can include something like this:
var route = results[0];
var steps = route.legs[0].steps;
for(var i=0; i<steps.length; i++){
var lats = steps[i].path.map(function(a){return a.lat()});
var lngs = steps[i].path.map(function(a){return a.lng()});
var box = new google.maps.LatLngBounds(
new google.maps.LatLng(Math.max.apply(null, lats), Math.max.apply(null, lngs)),
new google.maps.LatLng(Math.min.apply(null, lats), Math.min.apply(null, lngs))
);
placeserv.radarSearch(yourRequest_seeDocumentation_or_geocodezipsCode,
function(r,s){callback(r,s,steps[i].path)}
);
//depending on the number of queries you need to make, you may to add in
//some setTimeouts
}
And then add a callback function for your call that checks if the route is within a specified degree. If so, it will do something with the location. (By the way, this requires the Geometry Library for Google Maps. Please look it up.)
var minimumDist = 300 //within 300 meters of a point on the route
function callback(results, status, stepPts){
if(results == 'OK'){
for(var j=0; j<results.length; j++){
for(var k=0; k<stepPts.length; k++){
var dist = google.maps.geometry.spherical.computeDistanceBetween(stepPts[k], results[j].geometry.location);
if(dist < minimumDist){
//do something with the location
}
}
}
}
}
Again, geocodezip has a very complete and excellent post in the link he gave you. This is just the implementation I would use to cut down on Places Service calls.
geocomplete = "<?php echo $source ?>";
autocomplete = "<?php echo $destination ?>";
var request = {
origin: geocomplete,
destination: autocomplete,
travelMode: google.maps.DirectionsTravelMode.DRIVING,
provideRouteAlternatives: true,
};
directionsService.route(request, function (result, status) {
if (status == google.maps.DirectionsStatus.OK) {
if (true) {
size = result.routes.length;
for (i = 0; i < result.routes.length; i++) {
// alert("Route "+ (i+1)+" is "+result.routes[i].summary);
summary[i] = result.routes[i].summary;
distance[i] = result.routes[i].legs[0].distance.text;
duration[i] = result.routes[i].legs[0].duration.text;
};
}
}
}
This is my code I can get the distance ,time and summary for given route using Google maps API , i need to check whether is there any traffic in given route? how to traffic details? i do not want whole traffic details . i just wanted to know . Traffic is there or not like Boolean option. Thanks in advance
Directions Service
durationInTraffic (optional) specifies whether the DirectionsLeg result should include a duration that takes into account current traffic conditions. This feature is only available for Google Maps API for Work customers. The time in current traffic will only be returned if traffic information is available in the requested area.
You also have the Traffic Layer but there is no documented method to retrieve detailed information.
When I was using TRANSIT as my travel mode in Google Map api V3, I defined the origin, destination and some waypoints in DirectionsRequest. However when DirectionsResult came back, DirectionsLeg only started with my origin and ended with my destination, it skipped all my waypoints.
My codes are shown as below
Does anyone get the same problem here?
function calcRoute(waypts, mode) {
var sites = [];
var mode;
//Add waypoints to array, the first and last one are not added in waypoints
for (var i = 1; i < waypts.length-2; i++) {
sites.push({
location:waypts[i],
stopover:true}); //Set true to show that stop is required
}
var request = {
origin: waypts[0], //Set the first one as origin
destination:waypts[waypts.length-1],//Set the last one as destination
waypoints:sites,//Set waypoints
optimizeWaypoints:false,
travelMode: google.maps.TravelMode[mode]
};
//Send to Google
directionsService.route(request, function(response, status) {
if (status == google.maps.DirectionsStatus.OK) {
directionsDisplay.setDirections(response);
var route = response.routes[0];
var HTMLContent = "";
//Get response and show on my HTML
for(var i =0; i < route.legs.length; i++){
HTMLContent = "From " + route.legs[i].start_address + "To " + route.legs[i].end_address + "<br>";
HTMLContent = HTMLContent + "Distance:" + route.legs[i].distance.text + "<br>";
}
$("#route_Scroll").append(HTMLContent);
}else{
alert(status);
}
});
}
Yup,
https://developers.google.com/maps/documentation/javascript/directions#TransitOptions
"The available options for a directions request vary between travel modes. When requesting transit directions, the avoidHighways, avoidTolls, waypoints[] and optimizeWaypoints options will be ignored. You can specify transit specific routing options through the TransitOptions object literal."
If you want to use it you would have to split the request.
You can't specify waypoints when TravelMode is TRANSIT.
the documentation (now) states:
Waypoints are not supported for transit directions.
The directions service always returns INVALID_REQUEST in that case.
Example