Shortest Distance on the Mercator map- The Web App

Dear very value reader,

A long time ago, I published an article about the shortest path between two points on Earth. These are actually curved on a Mercator map and are definitely NOT straight lines. See this article to understand why it is so.

To make this concept of distorted paths more didactic, I decided to create a Google Maps application (the projection used by Google Maps is actually Web-Mercator, which is slightly different from the “real” Mercator):

Shortest Distance Google Maps

Feel free to play a bit around to discover the route that follows the shortest route between two points!

 How is the app built?

The app consists of 3 files (click on the link to get them):

index.html

We defined here the essentials “boxes” of our application. There is one box that  contains the whole Google map: (map_canvas), one box for the title, subtitle and the logo of themagiscian.com, and a box that shows the distance of the last shortest route the user has drawn. Here is the code:

 <div id="map_canvas"></div>
 <div id="titleBarBackground">
 <p id="title">Shortest Distance on Earth</p>
 <p id="subTitle">Pick two points on the map to see the path and the distance</p>
 <div class="imgbox">
 <a target="_blank" href="http://themagiscian.com">
 <img src="http://images.themagiscian.com/twitter.png" alt="themagiscian.com"></a>
 </div>
 </div>
 <div id="distanceBox">
 <p>Distance: </p>
 </div>
main.js

This file is the engine of the whole app. It is responsible for calling the google maps map and for drawing the lines from the users’ input.

The first part is about the loading of the map into the map_canvas tag:

 var map = new google.maps.Map(document.getElementById("map_canvas"), {
     center: new google.maps.LatLng(15, 0),
     mapTypeId: google.maps.MapTypeId.TERRAIN,
     panControl: false,
     streetViewControl: false,
     zoomControl: false,
     zoom: 2
 });

The second part of the script takes care of the users’ input. In other words, the first and second point chosen by the user are put into a calculation for getting the distance between the two points. And of course, for drawing the line. We do that via a listener for mouse clicks:

 google.maps.event.addListener(map, "click", function(event) {
     var latitude = event.latLng.lat();
     var longitude = event.latLng.lng();
     var pnt = [latitude, longitude];
     pnts.push(pnt);

The points are first stored in an array. We want furthermore that two consecutive points are used for the calculations. These are used, first, to draw the line using the google.maps.Polyline object (notice that we force the lines to be geodesics and not straight lines):

if (!(pnts.length % 2)) {
    var pnt1 = new google.maps.LatLng(pnts[0][0], pnts[0][1]);
    var pnt2 = new google.maps.LatLng(pnts[1][0], pnts[1][1]); 
    var route = [pnt1, pnt2];
    var path = new google.maps.Polyline({
        strokeColor: getRandomColor(),
        strokeOpacity: 0.75,
        strokeWeight: 2,
        geodesic: true
 });
path.setMap(map);

Each line is assigned a random color via the getRandomColor() function:

function getRandomColor() {
   var letters = '0123456789ABCDEF'.split('');
   var color = '#';
   for (var i = 0; i < 6; i++) {
     color += letters[Math.floor(Math.random() * 16)];
   }
   return color;
}

After the line has been drawn, we need to calculate the real distance between the two points. To do that, we use the object google.maps.geometry.spherical.computeDistanceBetween. We apply the toFixed(0) method to keep no decimals for the display and we display the result to the distanceBox tag of our html:

var distanceKM = (google.maps.geometry.spherical.computeDistanceBetween(pnt1, pnt2)) / 1000;
var distanceKM = distanceKM.toFixed(0);
$("#distanceBox p").text("Distance: " + distanceKM + " km");
styles.css

The style css takes the usual positioning instructions. What we can highlight anyway is the usage of the cursor for the application, which makes it more natural to choose two points by the user:

* {
 cursor: crosshair;
}
#titleBarBackground,
#title,
#subTitle,
.imgbox {
 cursor: default;
}

Leave a Reply

Your email address will not be published.

Proove you're not a robot * Time limit is exhausted. Please reload CAPTCHA.