Finding the distance between two points using the Google Maps API v3

Following code gives an insight on how to find the distance between two locations using google map api v3. Usage is pretty simple. Just initialize geocoder in the initialize method which in turn is called by body onload. Then we pass the two locations to the function distance and it simply returns the distance between those two locations. When working on this, I was long time stuck with my JS code getting executed, API getting called but not getting result at the point where I want it. By the time the call back from Google comes back, my code had reached its final lines with nothing in my hand. For the solution I had to work out this. If you look closely, there are two pillars of this code. One is usage of global variables and another is recursive call for geocoding. Reason for using both of them is same. Since, the JS is asynchronous by nature, by the time callback from google server returns virtually your whole rest of the code would have been executed, leaving the data returned useless for any usage. Hence, we have to depend on a miniature model of recursive call, called when the server returns the results and then call the next point. Once all the points have been geocoded just run the distance function based on their lat and lang coordinates and store result in global variable. Else, how would you get the result :) .  Easy isnt it. Same logic can be extended for calculating multiple points distance etc.
 <script type="text/javascript" src="<a href="http://maps.google.com/maps/api/js?sensor=false" target="_blank">http://maps.google.com/maps/api/js?sensor=false</a>"></script>
<div id=":1b"><script type="text/javascript">
 var geocoder;
 var map;
 var addresses;
 var results;
 var dist;

 function initialize() {
 geocoder = new google.maps.Geocoder();
 (distance("Silver Spring, US", "Bethesda, US"));
 }

 function distance(add1, add2) {
 if (!geocoder)
 return 'Error, no geocoder';

 addresses = new Array(2);
 addresses[0] = add1;
 addresses[1] = add2;
 results = new Array(2);
 results[0] = new Array(2);
 results[1] = new Array(2);

 results[0][0] = 0; results[0][1] = 0; results[1][0] = 0; results[1][1] = 0.87;
 geocoded(1);

 }

 function geocoded(i) {
 geocoder.geocode( { 'address': addresses[i] }, function(res, status) {
 if (status == google.maps.GeocoderStatus.OK) {
 results[i][0] = parseFloat(res[0].geometry.location.lat());
 results[i][1] = parseFloat(res[0].geometry.location.lng());
 i--;

 if (i >= 0)
 geocoded(i);
 else
 dist = distances(results[0][0], results[0][1], results[1][0], results[1][1]);

 }// if ok
 }); // geo coder add find
 }

 function distances(lat1, lon1, lat2, lon2) {
 // ACOS(SIN(lat1)*SIN(lat2)+COS(lat1)*COS(lat2)*COS(lon2-lon1))*6371
 // Convert lattitude/longitude (degrees) to radians for calculations
 var R = 3963.189; // meters

 // Find the deltas
 delta_lon = deg2rad(lon2) - deg2rad(lon1);

 // Find the Great Circle distance
 distance = Math.acos(Math.sin(deg2rad(lat1)) * Math.sin(deg2rad(lat2)) + Math.cos(deg2rad(lat1)) * Math.cos(deg2rad(lat2)) *
 Math.cos(delta_lon)) * 3963.189;

 alert(distance + ' miles');
 return distance;
 }

 function deg2rad(val) {
 var pi = Math.PI;
 var de_ra = ((eval(val))*(pi/180));
 return de_ra;
 }
 </script>

</head>
<body onload="initialize()" >
</body></div>
<div>
  • http://twitter.com/scriblogs Scriblogs

    The recursive call after response from call back helped me. Otherwise I just kept calling API in for loop and didn’t get any results since execution passed the point by the time call back is executed.

  • http://twitter.com/scriblogs Scriblogs

    The recursive call after response from call back helped me. Otherwise I just kept calling API in for loop and didn’t get any results since execution passed the point by the time call back is executed.

  • ExcelMacros

    I prefer to work in Excel 2010, using cell formulas. So for an interim solution I plan to convert the JavaScript distances function into a user-defined function fDist in VBA. Later, I may survive in a no-macros environment (such as Microsoft’s Live) by coding the fDist macro as a cell-resident {ArrayFormula} which contains an implied do loop. Thanks for the code.

    • arpan

      if you have fix list of addresses or a volume of calculation needs to be done, it will be definitely faster to cache them in sheet and then use lat long for distance calculation.

      But if your addresses are dynamic, then you have to geocode on the fly

      • ExcelMacros

        In Dispatch.xls, I’m writing macro Closest which will loop through the cached lon lat values to see which Service Technician is closest to the Customer who needs service. Thanks for the idea. Art

        • arpan

          thats a good idea :)