I just managed to visualize markers from a Google Fusion Table on my Map. Now I would like to know the distance from a user specified point to those markes stored in the table. I thought of using the Distance Matrix for this. The code example from https://developers.google.com/maps/documentation/javascript/distancematrix works just fine for me, however, I have no clue how to define the markers from the table as destinations in my Distance Matrix function.
As mentioned above, I now need my variable which calls the markers from the Fusion Table as destination instead of destA and destB.
Here is my variable:
var schools = new google.maps.FusionTablesLayer({
query: {
select: 'geometry',
from: '1mae334i-txYZFixePEiC7lgYYyi4w6qDN87XAyw'
},
});
Here is the basic code from the google documentation.
var origin1 = new google.maps.LatLng(55.930385, -3.118425);
var origin2 = "Greenwich, England";
var destinationA = "Stockholm, Sweden";
var destinationB = new google.maps.LatLng(50.087692, 14.421150);
var service = new google.maps.DistanceMatrixService();
service.getDistanceMatrix(
{
origins: [origin1, origin2],
destinations: [destinationA, destinationB],
travelMode: google.maps.TravelMode.DRIVING,
avoidHighways: false,
avoidTolls: false
}, callback);
function callback(response, status) {
}
I would be very happy if anyone could help me with this. I suppose there should be some pretty straight-forward solution to this, but I just don't get it :/
Anyway, thanks a lot for any kind of help!
You need to query the FusionTable for the locations in there and use those in the query to the DistanceMatrix. As you have less than 500 rows in the table I would probably use the google visualization library, but the new JSONP API should work as well.
The DistanceMatrix is limited to 25 destinations. Proof of concept for your table with 94 rows, much more than that would be problematic (run into query limits and the quota)
http://www.geocodezip.com/v3_SO_FusionTables_DistanceMatrix.html
code to get the first 25 results:
// query the table for the destinations
var queryString ="SELECT 'geometry' FROM "+FT_TableID;
var queryText = encodeURIComponent(queryString);
var query = new google.visualization.Query('http://www.google.com/fusiontables/gvizdata?tq=' + queryText);
//set the callback function
query.send(createDestinations);
}
function createDestinations(response) {
if (!response) {
alert('no response');
return;
}
if (response.isError()) {
alert('Error in query: ' + response.getMessage() + ' ' + response.getDetailedMessage());
return;
}
FTresponse = response;
//for more information on the response object, see the documentation
//http://code.google.com/apis/visualization/documentation/reference.html#QueryResponse
numRows = response.getDataTable().getNumberOfRows();
numCols = response.getDataTable().getNumberOfColumns();
var geoXml = new geoXML3.parser();
var bounds = new google.maps.LatLngBounds();
var request=0;
destinations[0] = [];
for (var i=0; ((i<numRows) && (i<25)); i++) {
var kml = FTresponse.getDataTable().getValue(i,0);
geoXml.parseKmlString("<Placemark>"+kml+"</Placemark>");
destinations[request].push(geoXml.docs[i].markers[0].getPosition());
bounds.extend(geoXml.docs[i].markers[0].getPosition());
}
map.fitBounds(bounds);
calculateDistances(0);
}
function calculateDistances(request) {
service.getDistanceMatrix({
origins: [origin],
destinations: destinations[request],
travelMode: google.maps.TravelMode.DRIVING,
unitSystem: google.maps.UnitSystem.IMPERIAL,
avoidHighways: false,
avoidTolls: false
}, function (response, status) {
if (status != google.maps.DistanceMatrixStatus.OK) {
alert('Error was: ' + status);
} else {
var origins = response.originAddresses;
var destinationAdds = response.destinationAddresses;
htmlString = '<table border="1">';
deleteOverlays();
for (var i = 0; i < origins.length; i++) {
var results = response.rows[i].elements;
for (var j = 0; j < results.length; j++) {
htmlString += '<tr><td>'+destinationAdds[j]+'</td><td>' + results[j].distance.text +'</td></tr>';
}
}
}
var outputDiv = document.getElementById('outputDiv');
htmlString += '</table>';
outputDiv.innerHTML = htmlString;
});
}
working example that gets the first 25 results
Related
Vuejs variable using in function google maps matrix api problem.
I am using Google distance matrix api to get the distance between two locations. I declared a variable globally. Changed this variable in function. But as per normal circumstances I should be able to access this changed value of variable after calling my function. But now I am not being able to access the changed value of variable
using : Matrix google maps api + autocomplete input place api
export default {
data () {
return {
data:{
adrdep:{adrs:'',lat:0,lng:0},
adrarr:{adrs:'',lat:0,lng:0},
distance:0,
date:null,
time:null,
check:false,
camion:'',
etage:9,
assenseur:'assenseur'
}
}
},
methods: {
getAddressDatadep: function (addressData, placeResultData, id) {
this.data.adrdep.lat =addressData.latitude;
this.data.adrdep.lng = addressData.longitude;
},
getAddressDataArr: function (addressData, placeResultData, id) {
this.data.adrarr.lat = addressData.latitude;
this.data.adrarr.lng = addressData.longitude;
},
async getDistance(){
var a1={lat:this.data.adrdep.lat,lng:this.data.adrdep.lng};
var a2={lat:this.data.adrarr.lat,lng:this.data.adrarr.lng};
var p1 = new google.maps.LatLng(a1.lat, a1.lng);
var p2 = new google.maps.LatLng(a2.lat, a2.lng);
var origins = [a1.lat + "," + a1.lng];
var destinations = [a2.lat + "," + a2.lng];
var distanceMatrix = new google.maps.DistanceMatrixService();
var distanceRequest = {
origins: origins,
destinations: destinations,
travelMode: google.maps.TravelMode.DRIVING,
unitSystem: google.maps.UnitSystem.METRIC,
avoidHighways: false,
avoidTolls: false
};
distanceMatrix.getDistanceMatrix(distanceRequest, function(response, status) {
var totalDistance
if (status != google.maps.DistanceMatrixStatus.OK) {
console.log("error")
} else {
var origins = response.originAddresses;
var destinations = response.destinationAddresses;
//debugger;
if (response.rows[0].elements[0].distance != null) {
totalDistance = response.rows[0].elements[0].distance.value;
var totalTime = response.rows[0].elements[0].duration.value;
var ratioPerOneMeter = totalDistance / totalTime;
var PRDifference = 0;
this.data.distance=totalDistance*0.001;
console.log("return distance")
} else {
console.log('The Distance And Time Cannot Be Calculated')
}
}
return totalDistance*0.001;
});
}
};
plz help me :)
calculateDistances() {
var a1={lat:this.data.adrdep.lat,lng:this.data.adrdep.lng};
var a2={lat:this.data.adrarr.lat,lng:this.data.adrarr.lng};
var p1 = new google.maps.LatLng(a1.lat, a1.lng);
var p2 = new google.maps.LatLng(a2.lat, a2.lng);
var service = new google.maps.DistanceMatrixService();
service.getDistanceMatrix(
{
origins: [p1],
destinations: [p2],
travelMode: google.maps.TravelMode.DRIVING,
unitSystem: google.maps.UnitSystem.METRIC,
avoidHighways: false,
avoidTolls: false
}, this.callback);
},
callback(response, status) {
if (status != google.maps.DistanceMatrixStatus.OK) {
alert('Error was: ' + status);
} else {
var origins = response.originAddresses;
var totalDistance = response.rows[0].elements[0].distance.value;
var totalTime = response.rows[0].elements[0].duration.value;
this.data.distance=parseFloat(totalDistance*0.001).toFixed(2);
this.e1=2;
}
}
I made a distance calculator between zipcodes in the US that utilizes the google distance matrix api and I figured out how to get it work for just about all locations but places like Key West FL zip code 33040 do not seem to work.
At first many places weren't working, but then I added "US" to the parameters and it fixed the problem for the most part, besides the one mentioned.
var button= document.getElementById('submit');
button.onclick = function initMap() {
var origin = '07675';
var temp = document.getElementById('address').value;
var destination = temp + ' US';
var geocoder = new google.maps.Geocoder;
var service = new google.maps.DistanceMatrixService;
service.getDistanceMatrix({
origins: [origin],
destinations: [destination],
travelMode: 'DRIVING',
unitSystem: google.maps.UnitSystem.IMPERIAL,
avoidHighways: false,
avoidTolls: false
}, function(response, status) {
if (status !== 'OK') {
alert('Error was: ' + status);
} else {
var originList = response.originAddresses;
var destinationList = response.destinationAddresses;
var outputDiv = document.getElementById('output');
outputDiv.innerHTML = '';
var results = response.rows[0].elements;
var numbah = ((results[0].distance.value * .15 / 1609) + 400);
var nums = numbah.toFixed(2);
geocoder.geocode({'address': originList[0]});
geocoder.geocode({'address': destinationList[0]});
outputDiv.innerHTML += originList[0] + ' to ' + destinationList[0] +
':<br>' + results[0].distance.text + '<br>The cost of shipping is estimated to be: $' + nums;
}
The expected output should be the distance from the origin and the calculated shipping cost, and it works for just about any zipcode besides obscure ones like the one I mentioned earlier.
The DistanceMatrix is returning a status of ZERO_RESULTS for that route:
[{"status":"ZERO_RESULTS"}]
between Westwood, NJ 07675, USA and East Rockland Key, FL 33040, USA.
If I look at the coordinates returned for that address, I see it is in the water:
Neither the DistanceMatrix nor the DirectionsService work for locations that can't be reached by road (like this place in the middle of the water near the Florida Keys)
EDIT: It seems that I'm hitting the query limit, but I'm not being returned a full 200 results. So upon further research it looks like the Google API will let me query 10 boxes, return those results, and then smacks me with an OVER_QUERY_LIMIT status for the rest. So I figure I now have two options: slow my queries, or broaden my distance to create fewer boxes along the route.
I'm currently fooling around building a little web app that provides a details about places along a route (like gas stations and coffee on a road trip). I'm using the Google Maps API with the Places Library and RouteBoxer. I'm generating all the appropriate boxes with RouteBoxer, but when the boxes are passed to the Places Library I'm only getting back some of the places. Usually I'll get the first half of the route (on shorter routes) or a few random chunks (for longer routes). San Francisco to Seattle returns me gas stations around Seattle and around Medford, OR only.
Initially I thought maybe I was hitting the results cap of 200, but it's making a separate request for each box, and my total results often aren't hitting 200. Results returned are generally pretty consistent from what I can see. When looking at the details of my network requests and responses, it seems that the script is moving through the boxes making requests with the Places library, and suddenly it stops part way through.
The live app where you can see results and boxes is on Heroku.
My JavaScript isn't the strongest by any means. That's part of why I wanted to work with this API, so please pardon my ignorance if I'm making a trivial mistake. The full script is below. Any direction is tremendously appreciated!
var infowindow = new google.maps.InfoWindow();
var map;
var routeBoxer;
var service;
function initialize() {
directionsDisplay = new google.maps.DirectionsRenderer();
var mapOptions = {
zoom: 4,
center: new google.maps.LatLng(39, -98),
mapTypeId: google.maps.MapTypeId.ROADMAP,
};
map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions);
service = new google.maps.places.PlacesService(map);
routeBoxer = new RouteBoxer();
directionService = new google.maps.DirectionsService();
directionsRenderer = new google.maps.DirectionsRenderer({ map: map })
directionsDisplay.setMap(map);
directionsDisplay.setPanel(document.getElementById('directions-panel'));
}
function calcRoute() {
var start = document.getElementById('start').value;
var end = document.getElementById('end').value;
var waypt1 = document.getElementById('waypoint1').value;
var waypt2 = document.getElementById('waypoint2').value;
var waypts = []
if (waypt1) {
waypts.push({
location:waypt1,
stopover:true});
}
if (waypt2) {
waypts.push({
location:waypt2,
stopover:true});
}
var request = {
origin: start,
destination: end,
waypoints: waypts,
optimizeWaypoints: true,
travelMode: google.maps.TravelMode.DRIVING
};
directionService.route(request, function(response, status) {
if (status == google.maps.DirectionsStatus.OK) {
directionsDisplay.setDirections(response);
// Build boxes around route
var path = response.routes[0].overview_path;
var boxes = routeBoxer.box(path, 2); // distance in km from route
drawBoxes(boxes);
for (var i=0; i < boxes.length; i++) {
var bounds = boxes[i];
findPlaces(bounds);
findPlacesByText(bounds);
}
} else {
alert("Directions query failed: " + status);
}
});
}
function findPlaces(bounds) {
var selectedTypes = [];
var inputElements = document.getElementsByClassName('placeOption');
for (var i=0; inputElements[i]; i++) {
if (inputElements[i].checked) {
selectedTypes.push(inputElements[i].value)
}
}
var request = {
bounds: bounds,
types: selectedTypes
};
if (selectedTypes.length > 0) {
service.radarSearch(request, callback);
}
}
function findPlacesByText(bounds) {
var selectedTypes = '';
var inputElements = document.getElementsByClassName('textOption');
for (var i=0; inputElements[i]; i++) {
if (inputElements[i].checked) {
selectedTypes += inputElements[i].value + ', '
}
}
var request = {
bounds: bounds,
query: selectedTypes
};
if (selectedTypes.length > 0) {
service.textSearch(request, callback);
}
}
function callback(results, status) {
if (status == google.maps.places.PlacesServiceStatus.OK) {
for (var i = 0; i < results.length; i++) {
createMarker(results[i]);
}
}
}
function createMarker(place) {
var marker = new google.maps.Marker({
map: map,
position: place.geometry.location
});
var request = {
reference: place.reference
};
google.maps.event.addListener(marker,'click',function(){
service.getDetails(request, function(place, status) {
if (status == google.maps.places.PlacesServiceStatus.OK) {
var contentStr = '<h5>' + place.name + '</h5><p>' + place.formatted_address;
if (!!place.formatted_phone_number) contentStr += '<br />' + place.formatted_phone_number;
if (!!place.website) contentStr += '<br /><a target="_blank" href="' + place.website + '">' + place.website + '</a>';
contentStr += '<br />' + place.types + '</p>';
infowindow.setContent(contentStr);
infowindow.open(map,marker);
} else {
var contentStr = "<h5>No Result, status=" + status + "</h5>";
infowindow.setContent(contentStr);
infowindow.open(map,marker);
}
});
});
}
google.maps.event.addDomListener(window, 'load', initialize);
After much experimentation and further research, I decided to try to slow my queries. The way I handled that was to write a new function that calls my query function, and then recursively calls itself with a delay for the next route box. If an OVER_QUERY_LIMIT status is returned, it recalls that box with an increased delay. So far it seems to be working great, but it quickly increases the delay to nearly a half second (or more) between calls, which can take a while if you have a long route with many boxes. My new function that seems to have solves the problem is below. It'll take some more fine-tuning to really get it right, but it's close!
var delay = 100;
...
function queryPlaces(boxes, searchIndex) {
// delay calls to Places API to prevent going over query limit (10/sec)
var bounds = boxes[searchIndex];
findPlaces(bounds);
findPlacesByText(bounds);
if (searchIndex > 0) {
searchIndex--;
setTimeout(queryPlaces, delay, boxes, searchIndex);
}
}
I am creating a windows store application in javascript.
I have a list of locations in a JSON object array(destinations) and another array of JSON objects(origins).
I would like to click on an origin marker and use the distance matrix to find the closest destination or list of sorted destinations.
I don't want to use PHP or anything like that.
Please help me!
Thank you
The documentation is pretty neat;
var origin1 = new google.maps.LatLng(55.930385, -3.118425);
var origin2 = "Greenwich, England";
var destinationA = "Stockholm, Sweden";
var destinationB = new google.maps.LatLng(50.087692, 14.421150);
var service = new google.maps.DistanceMatrixService();
service.getDistanceMatrix(
{
origins: [origin1, origin2],
destinations: [destinationA, destinationB],
travelMode: google.maps.TravelMode.DRIVING,
unitSystem: UnitSystem,
durationInTraffic: Boolean,
avoidHighways: false,
avoidTolls: false
}, callback);
function callback(response, status) {
if (status == google.maps.DistanceMatrixStatus.OK) {
var origins = response.originAddresses;
var destinations = response.destinationAddresses;
for (var i = 0; i < origins.length; i++) {
var results = response.rows[i].elements;
for (var j = 0; j < results.length; j++) {
var element = results[j];
var distance = element.distance.text;
var duration = element.duration.text;
var from = origins[i];
var to = destinations[j];
}
}
}
}
i have a very simple question,
I try to let google calculate the distance between an adress and a gsp-variable containing
[53.57532, 10.01534]
i´m not able to get variable ${center} to an google.maps.LatLng-Object
heres the function
jQuery(document).ready(function() {
var result = '${center}';
console.log(result);// [53.57532, 10.01534]
var origin = new google.maps.LatLng(55.930385, -3.118425);
var destination = new google.maps.LatLng(result);
var service = new google.maps.DistanceMatrixService();
service.getDistanceMatrix(
{
origins: [origin],
destinations: [destination],
travelMode: google.maps.TravelMode.DRIVING,
avoidHighways: false,
avoidTolls: false
}, callback);
function callback(response, status) {
if (status == google.maps.DistanceMatrixStatus.OK) {
console.log('status OK!');//status OK!
var origins = response.originAddresses;
var destinations = response.destinationAddresses;
for (var i = 0; i < origins.length; i++) {
var results = response.rows[i].elements;
for (var j = 0; j < results.length; j++) {
var element = results[j];
var distance = element.distance.text;
var duration = element.duration.text;
var from = origins[i];
var to = destinations[j];
console.log(distance);//Uncaught TypeError: Cannot read property 'text' of undefined
}
}
}
}
});
in the "source code" above google throws error
Uncaught TypeError: Cannot read property 'text' of undefined
i tryed alot of senseless shit, but i just don get it,
maybe someone can give a hint what i am doing wrong?
thanks in advance
according to the comments here´s my gmap3 also failing, but i woulkd rather this one to put to work but i guess it´s the same problem here, that converting to lat lon does´nt work
function getDistance(adress){
var to;
var result = '${center}';
$("#getdistance").gmap3({
getdistance:{
options:{
origins:adress,
destinations:result ,
travelMode: google.maps.TravelMode.DRIVING
},
callback: function(results, status){
var html = "";
if (results){
for (var i = 0; i < results.rows.length; i++){
var elements = results.rows[i].elements;
for(var j=0; j<elements.length; j++){
switch(elements[j].status){
case "OK":
html += elements[j].distance.text + " (" + elements[j].duration.text + ")<br />";
break;
case "NOT_FOUND":
html += "The origin and/or destination of this pairing could not be geocoded<br />";
break;
case "ZERO_RESULTS":
html += "No route could be found between the origin and destination.<br />";
break;
}
}
}
} else {
html = "error";
}
console.log('start '+adress);
console.log('start '+latte);
console.log('start '+html);
}
}
});
}
here i´m parsing an adress as a string to the function as adress
How about
var result = ${center};
var destination = new google.maps.LatLng(result[0], result[1]);
google.maps.LatLng doesn't accept an array. Arguments it accepts are: number, number, bool.
https://developers.google.com/maps/documentation/javascript/reference#LatLng