3

I am using geolocation to get the users current location and monitor it using the watchPosition method. However, is there a way of calculating the distance between the users starting position and current position? Below is my code:

var x = document.getElementById("info");

function getLocation() {
    if(navigator.geolocation) {
        navigator.geolocation.watchPosition(showPosition, showError, {
            enableHighAccuracy: true,
            maximumAge: 60000,
            timeout: 27000
        })
    } else {
        x.innerHTML = "Geolocation is not supported by this browser.";
    }
}
var flightPathCoordinates = [];

function showPosition(position) {
    x.innerHTML = "Latitude: " + position.coords.latitude + "<br>Longitude: " + position.coords.longitude + "<br>Accuracy: " + position.coords.accuracy + "<br>Altitude: " + position.coords.altitude + "<br>Altitude Accuracy: " + position.coords.altitudeAccuracy + "<br>Heading: " + position.coords.heading + "<br>Speed: " + position.coords.speed + "<br>Speed (mph): " + position.coords.speed * 2.2369 + "<br>Speed (km): " + position.coords.speed * 3.6 + "<br>Timestamp: " + new Date(position.timestamp).toLocaleString() + "<br>Distance Travelled (km): " + calculateDistance(position.coords.latitude, position.coords.longitude, position.coords.latitude, position.coords.longitude);
    // Distance Calculator

    function calculateDistance(lat1, lon1, lat2, lon2) {
        if(typeof (Number.prototype.toRad) === "undefined") {
            Number.prototype.toRad = function () {
                return this * Math.PI / 180;
            }
        }
        var R = 6371; // km
        var dLat = (lat2 - lat1).toRad();
        var dLon = (lon2 - lon1).toRad();
        var a = Math.sin(dLat / 2) * Math.sin(dLat / 2) + Math.cos(lat1.toRad()) * Math.cos(lat2.toRad()) * Math.sin(dLon / 2) * Math.sin(dLon / 2);
        var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
        var d = R * c;
        return d;
    }
    Number.prototype.toRad = function () {
        return this * Math.PI / 180;
    }
    lat = position.coords.latitude;
    lon = position.coords.longitude;
    latlon = new google.maps.LatLng(lat, lon)
    mapholder = document.getElementById('mapholder')
    var myOptions = {
        center: latlon,
        zoom: 16,
        mapTypeId: google.maps.MapTypeId.ROADMAP,
        mapTypeControl: true,
        navigationControlOptions: {
            style: google.maps.NavigationControlStyle.SMALL
        }
    }
    var map = new google.maps.Map(document.getElementById("mapholder"), myOptions);

Any help would be very much appreciated as I am quite new to this.

Thanks!

Derek 朕會功夫
  • 92,235
  • 44
  • 185
  • 247
Liam O'Byrne
  • 61
  • 1
  • 8

2 Answers2

3

you can use Haversine formula

rad = function(x) {return x*Math.PI/180;}

distHaversine = function(p1, p2) { // Points are Geolocation.coords objects
  var R = 6371; // earth's mean radius in km
  var dLat  = rad(p2.latitude - p1.latitude);
  var dLong = rad(p2.longitude - p1.longitude);

  var a = Math.sin(dLat/2) * Math.sin(dLat/2) +
          Math.cos(rad(p1.lat())) * Math.cos(rad(p2.lat())) * Math.sin(dLong/2) * Math.sin(dLong/2);
  var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
  var d = R * c;

  return d.toFixed(3);
}

Two tips

  1. typeof is not a function. Use it like this: typeof something
  2. Do not put polyfills in listeners. you are repeating the polyfill action in every time listener fires.
Mohsen
  • 64,437
  • 34
  • 159
  • 186
  • Thanks for your quick response Mohsen! I am not using the getCurrentPosition() method - instead, I am using the watchPosition(). Do you think I would need to use both methods? – Liam O'Byrne Mar 20 '13 at 18:18
  • @LiamO'Byrne Yes you can use both methods. – Foreever Dec 16 '13 at 12:41
3

This has been adapted from the Google Maps API, and reworked to be independent of the library.

Example - calculate the distance from the center of New York City to the center of Philadelphia.

JS

function distanceFrom(points) {
    var lat1 = points.lat1;
    var radianLat1 = lat1 * (Math.PI / 180);
    var lng1 = points.lng1;
    var radianLng1 = lng1 * (Math.PI / 180);
    var lat2 = points.lat2;
    var radianLat2 = lat2 * (Math.PI / 180);
    var lng2 = points.lng2;
    var radianLng2 = lng2 * (Math.PI / 180);
    var earth_radius = 3959; // or 6371 for kilometers
    var diffLat = (radianLat1 - radianLat2);
    var diffLng = (radianLng1 - radianLng2);
    var sinLat = Math.sin(diffLat / 2);
    var sinLng = Math.sin(diffLng / 2);
    var a = Math.pow(sinLat, 2.0) + Math.cos(radianLat1) * Math.cos(radianLat2) * Math.pow(sinLng, 2.0);
    var distance = earth_radius * 2 * Math.asin(Math.min(1, Math.sqrt(a)));
    return distance.toFixed(3);
}

var distance = distanceFrom({
    // NYC
    'lat1': 40.713955826286046,
    'lng1': -74.00665283203125,
    // Philly
    'lat2': 39.952335,
    'lng2': -75.163789
});

The result is 80.524 miles or 129.583 kilometers.

Community
  • 1
  • 1
couzzi
  • 6,316
  • 3
  • 24
  • 40
  • 1
    Thanks for your quick response Couzzi! I had a look at the links you provided. They work as intended but they don't use geolocation. I'm confused as to how I could manipulate it to suit my code above. – Liam O'Byrne Mar 20 '13 at 18:21
  • Glad I could help. To use my example, you just need to pass the `distanceFrom()` function an `object` that contains the coordinates of point A, and the coordinates of point B. In your case, store the *first* set of coordinates (your start position), then, any following coordinates will be your second set. Each time a new *second* set of changes and is compared to your **first** set of coordinates (via the `distanceFrom()` function), the distance returned will reflect that. – couzzi Mar 20 '13 at 18:46
  • 1
    So what you're saying is I would need to obtain the users location using the getCurrentPosition() first. Then, use watchPosition() to monitor the users movement? – Liam O'Byrne Mar 20 '13 at 20:00
  • Exactly. You *could*, on the first run of `watchPosition()`, store the result as the "initial" position, and then carry on with updating the new position. But using both methods would work perfectly. – couzzi Mar 20 '13 at 20:03
  • Thank you so much for your time. I will your mark feedback comment as the answer, so don't worry! I just have one more question. How could I store the initial position results of watchPosition()? – Liam O'Byrne Mar 20 '13 at 20:22
  • No worries, heres [a pastebin link](http://pastebin.com/WwDBKhz9) to an overview. – couzzi Mar 20 '13 at 20:38