Desired functionality
After gathering pre-defined Start, End and intermediate Waypoints from a database, query the Google Maps API V3 to:
a) Optimize a route based on the Waypoints given.
b) Display such route on a Map. Display the optimal waypoint order.
c) Give the user the possibility to edit the order of waypoints. Please note: It is not desired to drag the waypoint´s marker to change it´s address. The desired behaviour is to have a list of waypoints as ordered by the API and then to be able to manually edit the order and update the map accordingly.
d) Save back to the database the final order after the API´s answer and the user´s possible edits.
What is currently working
Functionality described in points A and B is covered by the following code:
function initialize() {
var mapOptions = {
zoom: 8, <!-- We can also support customizable zoom levels according to the size of delivery area !-->
center: region
};
map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions);
directionsDisplay.setMap(map);
directionsDisplay.setPanel(document.getElementById('directionsPanel'));
google.maps.event.addListener(directionsDisplay, 'directions_changed', function() {
computeTotalDistance(directionsDisplay.getDirections());
});
calcRoute();
}
function calcRoute() {
var request = {
origin: 'Chemnitz, Germany', <!-- This will be the main address, we get it from the database. -->
destination: 'Chemnitz, Germany',
optimizeWaypoints: true,
waypoints:[{location: 'Mittweida, Germany'}, {location: 'Zwickau, Germany'}, {location: 'Dresden, Germany'}, {location: 'Freiberg, Germany'}], <!-- This will be the list of locations the truck has to visit, we get it from the database. -->
travelMode: google.maps.TravelMode.DRIVING <!-- Maps supports many types of transport, but we have to specify this is a particular vehicle. -->
};
directionsService.route(request, function(response, status) {
if (status == google.maps.DirectionsStatus.OK) {
directionsDisplay.setDirections(response);
}
});
}
Question
Is there any method in the API to support manual editing of the waypoint´s order after the API has optimized and displayed them?
Are there any examples of similar solutions that might help me resolve this issue?
Additional information
The reason why I need to support manual editing of the waypoint´s order is that sometimes, there are time constraints for the deliveries these stopovers represent. Therefore, occasionally the user will want to modify the stopovers order to make them more suitably delivered at a convenient time, i.e.: the end of the day, the beginning of the route in the morning, etc.
Thanks in advance for any help.
There is no built-in implementation for this, but it's not difficult to achieve it.
The order of the optimized waypoints may be retrieved via the waypoint_order-property of a route. You may use this order to create a sortable list, when the list will be re-ordered send a new request with the re-ordered waypoints and the optimizeWaypoints-option set to false
Related
I have a list of store addresses, and I'm trying to create a map out of it.
Using the Places API I am able to retrieve most of the informations and manually create and place the markers on the map:
const service = new google.maps.places.PlacesService(map);
service.findPlaceFromQuery({
query: '212 Enterprise Dr, Rockaway, Frank Pizza',
fields: ['all']
}, onPlaceFound);
However I'd like to select the original marker instead of overlapping a new one.
That is because I want the user to be able to open the default info window with store phone number, directions and stuff.
I know that I can re-create it, but it feels kinda lame since all the info is already there.
This SO post ask about the same, yet no solution has been found.
Based on the documentation found here, which shows findPlaceFromQuery(), the second parameter of findPlaceFromQuery should be a function where the first argument of that function is an Array of placeResults.
Therefore, after reviewing a link here and here your onPlaceFound function should be looking something like:
function onPlaceFound(placeResultsArray){
const firstResult = placeResultsArray[0], firstIconURL = firstResult.icon;
const latLng = firstResult.geometry.location, lat = latLng.lat(), lng = latLng.lng();
// do stuff with those variables here
}
Of course, that does not select Google's result as a Marker, but now you have the actual icon, and latitude and longitude.
I have to develop a website on which user enter latitude and longitude of a particular location. based on latitude and longitude I should fetch nearby locations and display it on google maps. As of now, I displayed the nearby locations for one type eg.restaurants, Now I want to fetch more than one type using place-API.
Unfortunately, neither searching with multiple types nor excluding a type from query is possible right now. Google's policy is simply forcing people to send more requests. Sometimes people pay for things they don't want or double/triple for what they could achieve with only one query.
Although there's no searching option for second,third parameter, you can still get what you want, with of course paying for it.
This is how a regular NearbySearch request looks like;
var service = new google.maps.places.PlacesService(map);
let latLng = new google.maps.LatLng(latitude,longitude);
service.nearbySearch(
{location: latLng, radius: 500, type: ['store']},
function(results, status) {
if (status !== 'OK') return;
// results
};
});
If you want to get multiple types, you have to send a request for each type which would look like this;
var service = new google.maps.places.PlacesService(map);
let latLng = new google.maps.LatLng(latitude,longitude);
service.nearbySearch(
{location: latLng, radius: 500, type: ['store']},
function(results, status) {
if (status !== 'OK') return;
// results for store
service.nearbySearch(
{location:latLng, radius: 1500, type : ['fire_station']},
function(fireStationResult, fireStationStatus) {
// firestation results here
// and so on.
}
)
};
});
You have to use nearbySearch request in eachother's blocks since it work async.
Searching for multiple types is not currently supported by the Places API's Nearby Search.
There is an existing feature request for this: https://issuetracker.google.com/issues/112291747. I'd recommend you to comment your use-case in there and star it to receive updates.
I am trying to get data, like phone numbers, from a Place Details Request using The Google Places API Web Service. I am unable to get response data that is similar to the one shown in this guide, even though I'm getting the place id from the same address.
The place id I get is different from the one in the guide. My place id is 'ChIJ8UadyjeuEmsRDt5QbiDg720' and theirs is 'ChIJN1t_tDeuEmsRUsoyG83frY4'. If I use their place id I get all the data I need.
The only data I can get are: address_components, adr_address, formatted_address, geometry, icon, id, name, place_id, reference, scope, types, url, and vicinity. How can I get data like a phone number from a request?
var placesRequest = $http({
method: "post",
url: "https://maps.googleapis.com/maps/api/place/details/json?placeid=" + <my place id>+"&key=<my key>"
});
placesRequest.success(function (data) {
console.log("data", data);
});
Same problem with Google Maps JavaScript API using this code.
function initMap() {
var map = new google.maps.Map(document.getElementById('map'), {
center: {lat: -33.866, lng: 151.196},
zoom: 15
});
google.maps.InfoWindow();
var service = new google.maps.places.PlacesService(map);
service.getDetails({
placeId: $scope.newUserData.address.place_id
}, function(place, status) {
if (status === google.maps.places.PlacesServiceStatus.OK) {
if(place) {
console.log("place", place);
}
}
});
}
initMap();
The phone number is missing in the Google Places API because Google Maps doesn't have a phone number for that particular place. If you request the details for a place with a phone number on Google Maps, it will be returned.
Take a closer look at ChIJ8UadyjeuEmsRDt5QbiDg720. It's an office building called "Workplace 6" — notice that the details say it is of type premise. If you visit the Google Maps URL in the url field (https://maps.google.com/?q=Workplace+6&ftid=0x6b12ae37ca9d46f1:0x6defe0206e50de0e) you'll notice there's no phone number listed there either.
The other Place ID, ChIJN1t_tDeuEmsRUsoyG83frY4, is for one of the businesses located inside that building (Google). If you compare the address_components or formatted_address you'll see they don't have quite the same address (Google's address is floor 5 of that building).
In general, any field of a place might be absent. This happens if Google Maps doesn't know it, or if it simply doesn't apply (e.g. you won't find opening_hours on France). As the documentation for Place Details Results say:
Each result may contain the following fields:
[Emphasis mine.]
I'm trying to create a leaflet routing machine route in my web app using waypoints stored in a database. I'm first creating the control:
var routeControl = L.Routing.control({waypoints: [null]}).addTo(map);
getTestRoute("1");
The function 'getTestRoute' pulls in my waypoints from a db as lat/long pairs and adds them to the control, here's the function:
function getTestRoute(route){
$.ajax({
url: './get_route.php',
type: 'POST',
dataType: 'JSON',
data: {
getRoute: route
},
success: function (res) {
$.each(res,function(key,value){
var newLatLng = new L.LatLng(res[key].latitude, res[key].longitude);
routeControl.spliceWaypoints(0, 0, newLatLng);
})
}
});
}
My issue is that instead of seeing a route on the map I'm seeing my waypoints (five in total) added to the map as markers with no routing between them.
Please please help!!!
Here is a fiddle of my issue: http://jsfiddle.net/c4yfy4ek/46/
As can be seen on the fiddle no routes are created between the points, and the points are added as markers (which I'm assuming is unexpected??).
The problem is the use of spliceWaypoints combined with an undocumented feature in Leaflet Routing Machine.
When the control is created, it will automatically add waypoints such that the route always has a start and an end waypoint, it such waypoints are not already supplied. That means: whatever you do, getWaypoints will always return an array with at least two entries; if not provided, these waypoints will however have their latLng properties set to undefined, indicating the location has not yet been provided.
In the code in question, the control is created and will get two waypoints added implicitly by Leaflet Routing Machine, with undefined locations. Later, you add a couple of new waypoints, but the implicit two waypoints remain, without locations. No route will be calculated, since two waypoints are missing locations.
The solution is to build the array of waypoints first, and then call setWaypoints, instead of spliceWaypoints.
See an updated version of the fiddle: http://jsfiddle.net/c4yfy4ek/53/
so i have random street address, lets say: 5707 dogwood ave. all i want is to get the coordinates of that address so i can view my google map at the street location using angular.
i've search but wasn't able to find anything useful.
the map code(very basic map)
$scope.map = {
center: {
latitude: 33.025859,
longitude: -96.844698
},
zoom: 8
};
html code:
<google-map class="full-image" center="map.center" zoom="map.zoom"></google-map>
You can use an http.get as such to make a GET request at Google's API endpoint and retrieve a json of the address's coordinates:
$http.get('http://maps.google.com/maps/api/geocode/json?address=1600+Amphitheatre+Parkway,+Mountain+View,+CA&sensor=false').success(function(mapData) {
angular.extend($scope, mapData);
});
and you can call out the data at $scope.mapData
Refer to this StackOverflow post for more info:
Google Maps API - Get Coordinates of address
Assuming you have the address you can use the Google Geocoding web service to manually retrieve the location coordinates. (I added a city and state to better refine the data)
https://developers.google.com/maps/documentation/geocoding/
JSON:
http://maps.google.com/maps/api/geocode/json?address=5707%20dogwood%20ave.%20Rosamond,%20CA&sensor=false
XML:
http://maps.google.com/maps/api/geocode/xml?address=5707%20dogwood%20ave.%20Rosamond,%20CA&sensor=false
Alternately there is a javascript wrapper on the API
I would also review this post regarding how to deal with rate limiting if you will be exceeding 2,500 requests per day.
http://www.benbybenjacobs.com/blog/2013/09/11/google-geocoding-service-for-angularjs