سؤال

Me and my partner are working on an exercise web application for our school thesis. We are trying to get a runner's position and track him during his workout with the watchposition() function of the geolocation api. On-screen the runner can check his current distance.

This is the point were we are stuck, we can only calculate the distance between the start and end point but when the course is a circle the total distance covered displays zero.

So we had the solution to store multiple coordinates in an array and calculate the sum of those distances but we aren't the most skilled persons in javascript. I hope this makes a little sense if you want more info just ask.

UPDATE: this is what i got so far

    <script>

        function startTracking() {

            var startPos;   
            var coords = [];

            // Reused code - copyright Moveable Type Scripts - retrieved May 4,2010.
            // http://www.movable-type.co.uk/scripts/latlong.html
            // Under Creative Commons License http://creativecommons.org/licenses/by/3.0/

            function calculateDistance(lat1, lon1, lat2, lon2) {
                var R = 6371000; // m
                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.toFixed(2);    }

            Number.prototype.toRad = function() {
                return this * Math.PI / 180;    }

            if (navigator.geolocation) {
                watchID = navigator.geolocation.watchPosition(function(position) {
                    currentLat = position.coords.latitude;
                    currentLon = position.coords.longitude;

                    coords.push([currentLat, currentLon]);

                    console.log(coords);

                }, function(error) {
                    alert("Error occurred. Error code: " + error.code);
                    // error.code can be:
                    //   0: unknown error
                    //   1: permission denied
                    //   2: position unavailable (error response from locaton provider)
                    //   3: timed out
                });
                // end error    };      // end if  }; // end startTracking

        function stopTracking() {

            if (navigator.geolocation) {
               navigator.geolocation.clearWatch(watchID);   }

            };  
</script>

So now my question is how do i loop over my array to calculate the distance between all the given coordinates to get a (more or less) accurate distance?

هل كانت مفيدة؟

المحلول

This should accomplish what you're looking to do. Feel free to use it in your code, or tear it apart and learn from it. Essentially it appends coordinates to an array and calculates the distance at the same time. You could just save the last coordinate instead of all of them if you just want the distance. This should get you started in the right direction for anything you want to do.

var tracker = (function() {
    var watchID;
    var watchCallback;
    var coords = [];
    var distance = 0;

    function calculateDistance(fromPos, toPos) {
        var radius = 6371;
        var toRad = function(number) {
            return number * Math.PI / 180;
        };

        var latDistance = toRad(toPos.latitude - fromPos.latitude);
        var lonDistance = toRad(toPos.longitude - fromPos.longitude);
        var a = Math.sin(latDistance / 2) * Math.sin(latDistance / 2) + 
                Math.cos(toRad(fromPos.latitude)) * Math.cos(toRad(toPos.latitude)) * 
                Math.sin(lonDistance / 2) * Math.sin(lonDistance / 2);

        return radius * (2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a))); 
    }

    function displayError(error) {
        alert("Error occurred. Error code: " + error.code);
        // error.code can be:
        //   0: unknown error
        //   1: permission denied
        //   2: position unavailable (error response from locaton provider)
        //   3: timed out
    }

    function appendPosition(position) {
        // Calculate distance from last position if available
        var lastPos = coords[coords.length-1];
        if(lastPos) {
            distance += calculateDistance(lastPos, position.coords);
        }

        // Add new coordinates to array
        coords.push(position.coords);

        // Call custom callback
        if(watchCallback) {
            watchCallback(position, distance, watchID);
        }
    }

    function startWatcher(callback, options) {
        if ("geolocation" in navigator) {
            // Watch position updates
            watchCallback = callback;
            // Watch for updates
            watchID = navigator.geolocation.watchPosition(appendPosition, displayError, options);
            var registerWatchPosition = function(position) {
                appendPosition(position);
            };
        } else {
            alert('Geolocation is not supported!');
        }
    }

    function forceUpdate(options) {
        navigator.geolocation.getCurrentPosition(appendPosition, displayError, options);
    }

    function stopWatcher() {
        navigator.geolocation.clearWatch(watchID);
    }

    return {
        start: startWatcher,
        stop: stopWatcher,
        update: forceUpdate
    };
})();


Example usage:

tracker.start(function(position, distance) {
    console.log(position, distance);
});

tracker.stop();


Brief documentation:

tracker.start accepts a callback as first parameter, optional geolocation options as the second.

tracker.update will force check the location, accepts optional geolocation options as first parameter.

tracker.stop will stop geolocation's watchPosition.

JSFiddle Demo:

http://jsfiddle.net/Cavitt/Gcz6H/1/

نصائح أخرى

I am also wondering where to add the enableHighAccuray option. I tried the following:

        function startWatcher(callback, options) {
        if ("geolocation" in navigator) {
            // Watch position updates
            watchCallback = callback;
            // Watch for updates
            watchID = navigator.geolocation.watchPosition(appendPosition, displayError, {
    enableHighAccuracy:true
 });
            var registerWatchPosition = function(position) {
                appendPosition(position);
            };
        } else {
            alert('Geolocation is not supported!');
        }
    }

But didn't work as expected...

Thanks!

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top