I've a question.
I want to calculate the distance between a current position and a calculated route. I'm using the Google Maps API v3 to calculate the route. I've tried to use google.maps.geometry.poly.isLocationOnEdge, but it didn't worked.
Here is my code:
directionsService.route(request, function(result, status) {
if (status == google.maps.DirectionsStatus.OK){
var poly = new google.maps.Polyline({
paths:new Array(result.routes[0].overview_path)
});
var currentPosition = new google.maps.LatLng(51.574470000000005, 4.32713);
if(google.maps.geometry.poly.isLocationOnEdge(currentPosition, poly)){
console.log("On route");
}else{
console.log("Not on route");
}
var directionsDisplay = new google.maps.DirectionsRenderer({
polylineOptions: {
strokeColor: color,
strokeWeight: 3
}
});
directionsDisplay.setMap(map);
directionsDisplay.setDirections(result);
}
});
I'm not sure this is the good way to get the result I want.
Can someone help me?
First of all you might want to set the tolerance in the isLocationOnEdge method. Maybe the point is just a little off. The default tolerance is 10^-9 wich is pretty small. See the documentation for more details.
Do you really need the distance to the route? Or is it enough to know if the marker is on your route?
If so you might want to check out this similar question
It is advised there to use the containsLocation() method.
If you really want to calculate the distance, then i have to say this is not possible according to this post
Related
I am loading markers from a database and then drawing a polyline between markers. I am using the polyline to calculate overall distance instead of having to calculate the distance from marker-a to marker-b to marker-c and so on.
My distance is however inaccurate because if two markers are around a curved road, the polyline just connects them instead of drawing it along the road.
I know this is possible in Google Maps API but the usage restrictions would not suit me which is why I decided to use leaflet.
My markers are not so far apart, because my GPS device sends location every 10 seconds.
I found the leaflet-routing-machine plugin and I was wondering if I can use this to make my polyline snap to the road?
This is how I am adding markers to my map:
function getlocationsfromdb(){
group.clearLayers();
latlngArray.length=0;
var deviceid = $("#selectid").val();
$.ajax({
type: "POST",
url: "functionhandlers/getlocations.php",
data: {deviceid:deviceid,start:start,end:end},
dataType: 'json',
cache: false,
})
.success(function(response) {
$('input').removeClass('error').next('.errormessage').html('');
if(!response.errors && response.result) {
$.each(response.result, function( index, value) {
var latlng = L.latLng(value[7], value[8]);
var marker = L.circleMarker(latlng,{radius:2}).addTo(group);
latlngArray.push(latlng);
});
var polyline = L.polyline(latlngArray, {color: '#605ca8'}).addTo(group);
map.fitBounds(group.getBounds());
var distancetravelled=polyline.measuredDistance();
$("#distancetravelled").html(distancetravelled);
} else {
$.each(response.errors, function( index, value) {
// add error classes
$('input[name*='+index+']').addClass('error').after('<div class="errormessage">'+value+'</div>')
});
}
});
}
Can someone please point me in the right direction?
This can be done rather easily with leaflet-routing-machine. You can just set the waypoints to your latlngArray when you initialize the routing control:
var control = L.Routing.control({
waypoints: latlngArray,
show: false,
waypointMode: 'snap',
createMarker: function() {}
}).addTo(map);
Here, show: false keeps the control from displaying on the map, and the empty createMarker function overrides the default markers that routing machine creates, instead doing nothing (though the markers would be removed when we remove the control, this just keeps them from flashing on the screen when a route is found).
You can extract all the vertices of the routing machine results by listening for the routeselected event, which will return an IRoute object that contains all the directions and geometries for the route. Placing the .route.coordinates in a new L.polyline object will keep the route around, so we can then just get rid of the routing control:
control.on('routeselected', function(e) {
L.polyline(e.route.coordinates).addTo(group);
map.removeControl(control);
});
Placing the above code blocks within your .success callback function right after you populates your latlngArray should give you the route you want. Here's a fiddle showing this at work:
http://fiddle.jshell.net/nathansnider/ygktexbj/
Also, if you're not using the routing control for anything else and want to keep it from showing up entirely (a small white control box may still appear while the route is being calculated), you can simply hide it in CSS:
.leaflet-routing-container {
display:none;
}
I realize that this solution is a bit roundabout, since it creates a control, and then half the code is just preventing that control from showing up on the map
You actually don't have to add it to the map. Furthermore you can attack inner router's route function directly.
var routingControl = L.Routing.control({
waypointMode: 'snap'
});
then
routingControl._router.route(latLngCoordinates, function(err, waypoints) {
var a = waypoints;
});
Be careful, it's raw copy/paste:
- waypoints fits internal format (inspect it)
- latLngCoordinates must be in {lat:, lng:} format
- it might require some cleaning because the url generated encapsulate some very long "hints" data.
Hey guys i'm developing a tracking system in which i have to use the API of google maps to calculate ETA (estimated time of arrival).
I have the driving distance.
But I need the kilometers away to the arrival point in order to be able to predict the time of arrival.
How do I call the driving distance value below?
directionsService.route(request,
function(response, status) {
if ( status == google.maps.DirectionsStatus.OK ) {
(response.routes[0].legs[0].distance.value); // the distance in metres
return((response.routes[0].legs[0].distance.value)/1000); //distance e kilometres
}
else {
// oops, there's no route between these two locations
// every time this happens, a kitten dies
// so please, ensure your address is formatted properly
}
});
function getArrivalTime(distance, vel) {
return distance / vel;
};
console.log(getArrivalTime(distance,vel));
You can actually put your directions request in your function, getArrivalTime. Then you could simply create a var to hold the distance and set it equal to response.routes[0].legs[0].distance.value)/1000 Please see code sample here:
function getArrivalTime(vel) {
var distance;
directionsService.route(request,
function(response, status) {
if ( status == google.maps.DirectionsStatus.OK ) {
(response.routes[0].legs[0].distance.value); // the distance in metres
distance = ((response.routes[0].legs[0].distance.value)/1000); //distance e kilometres
}
else {
// oops, there's no route between these two locations
// every time this happens, a kitten dies
// so please, ensure your address is formatted properly
}
});
return distance / vel;
};
console.log(getArrivalTime(distance,vel));
You may need to put a timeout around return(distance,vel) to ensure the API call has had time to respond to the request before you return the data. One other option would be to create a global variable to hold distance so that you can access it in any function. It's typically best to avoid global variables though, so I'd recommend the first way I mentioned.
I hope this helps!
I want to remove one marker from my Google Map, but I can't seem to get it to work. I find various answers, all telling me to use .setMap(null) on the marker, but I can't seem to get it to work.
$map_canvas = $('#map_canvas');
var youreHere_Marker;
function centerMapToAddress( address ) {
geocoder.geocode( { 'address': address}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
if( typeof youreHere_Marker!=="undefined"){
youreHere_Marker.setMap(null);
}
youreHere_Marker = $map_canvas.gmap('addMarker', {'position': results[0].geometry.location.lat()+','+results[0].geometry.location.lng(), 'bounds': true});
}
});
}
I get TypeError: youreHere_Marker.setMap is not a function. To my knowledge this means that the variable youreHere_Marker doesn't have the method .setMap(), but if I do console.log(youreHere_Marker) and inspect the object, I can see the method.
I have more markers on my map, via the MarkerClusterer. Those should remain untouched
I have the feeling I'm close, could someone point me in the right direction?
Edit: I've also tried .setPosition(), same error. I'm assuming I'm using the variable incorrect, but I don't know how to refer to it properly.
Well, i was working with google maps without jQuery, but i think (i'm not sure, but you may try) that you should get your marker with the following code:
youreHere_Marker = $map_canvas.gmap('get', 'markers')[0];
youreHere_Marker.setMap(null);
I'm really not sure that it will do what you want, but there is a possibility that this will work : )
I hope you'll solve you problems.
Thanks. : )
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 8 years ago.
Improve this question
Hi I want to geocode a location which users entered.
but it seems the geocoder.geocode function does not work
here is that part of the JavaScript
$('#inputButtonGeocode').click(function () {
var sAddress = document.getElementById('inputTextAddress').value;
geocoder.geocode({
'address': sAddress
}, function (results, status) {
if (status == google.maps.GeocoderStatus.OK) {
map.setCenter(results[0].geometry.location);
var marker = new google.maps.Marker({
map: map,
position: results[0].geometry.location
});
} else {
alert("Geocode was not successful for the following reason: " + status);
}
});
it should be a simple problem, but i cannot find the issue
he is the JSFiddle link http://jsfiddle.net/x69chen/u2gP3/7/.
Could anyone help me please, Thank you
Well there are a few things. It doesn't appear as thought your initialize function is ever being run and therefore your geocoder object is never going to be made. As well this API is not compatible with the google maps embed (iframe) API.
You can see in this example that they are creating both a geocoder and then a map using the following to create the map:
map = new google.maps.Map(document.getElementById("map-canvas"), mapOptions);
They are assigning the map to a variable called map. And then they are using that variable to pass into the creation of a marker so that that marker is placed on the right map..
var marker = new google.maps.Marker({
map: map,
position: results[0].geometry.location
});
Also don't forget to load the actual google maps api. The jquery plugin gives you the ability to handle events in the map but it doesn't actually load the api. Here is an example of loading the API asynchronously. You can also load it like any other script, simple and easy, seen here.
You would have to refer the correct window Object. Your JavaScript is on a separate page from your iframe. You could use var theWindow = frames[number].contentWindow || frames[number].contentDocument;. Of course then you need CORS access. I would just not use an iframe. Also, I don't see your initialize() function ever being called. Is new google.maps.Map(); somewhere else? You can use the Google Maps API to load the map directly into the Element of your choice, without using an iframe. The bottom line you have to have a Map Object created with new google.maps.Map(). It will look something like:
var g = google.maps;
var map = new g.Map($('#map'), {zoom:8, center:new g.LatLng(43.472285,-80.544858)});
Of course, you can add and change attributes to the MapOpitons Object. Only after you've made a map do you have access to create a new g.Marker(). Note: I shorten google.maps to g to avoid repetitive typing.
Here is my fiddle . Here i have displayed current location and end location by balloons.
And i am trying to put directions between start and end point in the map. In this case no markers for the directions are displayed may be because both shares common location. But the zoom is too great , results in it is not covering start and end point. User have to make double right click to see both start and location.
I have also tried,
new_boundary = new google.maps.LatLngBounds();
new_boundary.extend(new google.maps.LatLng(start));
new_boundary.extend(new google.maps.LatLng(end));
map.fitBounds(new_boundary);
But it is not working. Whats wrong with my map configuration ?
your script breaks (at least for me) at this line:
dir=((Math.atan2(z.lng()-a.lng(),z.lat()-a.lat())*180)/Math.PI)+360
take a look at this line:
z=(step.lat_lngs.length)?step.lat_lngs[1]:step.end_point,
for the first step lat_lngs.length is 1 , so step.lat_lngs[1] is undefined, the call of z.lng() fails with "Cannot call method 'lng' of undefined"
Possible fix for that error:
z=(step.lat_lngs.length>1)?step.lat_lngs[step.lat_lngs.length-1]:step.end_point,
Related to the zoom:
When you wouldn't have disabled the complete UI you would have seen that the result (zoom ) is correct.
The DirectionsRenderer by default will refresh the viewport of the map so that the complete route is visible.
This will be done(the bounds initally set in your script will be discarded).
To have another result(preserve the current viewport, but extend it that also the route is visible), you must:
set the preserveViewPort-option of the DirectionsRenderer to true(default is false)
extend the bounds of the map with the bounds of the route
directionsService.route(request, function(response, status) {
if (status == google.maps.DirectionsStatus.OK) {
directionsDisplay.set('preserveViewport',true);
map.fitBounds(map.getBounds().union(response.routes[0].bounds));
//continue with your code
This code is correct for example
Your map change resolution when you add
directionsDisplay.setDirections(response);
setDirections(directions:DirectionsResult) None Set the renderer to
use the result from the DirectionsService. Setting a valid set of
directions in this manner will display the directions on the
renderer's designated map and panel.
Hope, that i understand problem right, English i not my native language
Try to add validation as
directionsService.route(request, function(response, status) {
if (status == google.maps.DirectionsStatus.OK) {
if(!response.routes[0].bounds.getNorthEast().equals(response.routes[0].bounds.getSouthWest())){
directionsDisplay.setDirections(response);
}
addDirections(response.routes[0]);
}
});
To check if answer contains different point