Как рассчитать пройденное расстояние (НЕ ПЕРЕМЕЩЕНИЕ) по формуле гаверсина?

Я пытаюсь написать код JS, который вычисляет расстояние, которое проходит пользователь, по формуле Хаверсина.

Теперь формула Хаверсина принимает начальную и текущую координаты и выдает расстояние между этими двумя координатами. Однако это всего лишь ПЕРЕМЕЩЕНИЕ, а НЕ расстояние, которое пользователь мог бы пройти, чтобы достичь конечной точки.

Мне нужен кто-то, кто поможет мне с кодом, который я сделал ниже (который дает смещение), и предложит, что я должен сделать еще, чтобы он вычислял расстояние.

//Geolocation
var startPos;
var watchId;
//Start Tracking Position
function startTracking() {
    if(navigator.geolocation) {
        if (document.getElementById('startBtn').innerHTML === " Stop Tracking?")
        {
            stopTracking();
            stopClock();
            return;
        }
        document.getElementById('startBtn').innerHTML = " Stop Tracking?";
        //Get Position
        navigator.geolocation.getCurrentPosition(showPosition, showError);
        //Watch Position
        watchId = navigator.geolocation.watchPosition(showPositionUpdate, showError);
    }
    else {
        alert('Geolocation is not supported by your browser');
    }
}
//Show Start Position
function showPosition(position) {
    startPos = position;
    document.getElementById('startLat').innerHTML = startPos.coords.latitude;
    document.getElementById('startLon').innerHTML = startPos.coords.longitude;
}
//Updated Position
function showPositionUpdate(position) {
    document.getElementById('currentLat').innerHTML = position.coords.latitude;
    document.getElementById('currentLon').innerHTML = position.coords.longitude;
    var distance = calculateDistance(startPos.coords.latitude, startPos.coords.longitude, position.coords.latitude, position.coords.longitude);
    if (distance < 1) {
        document.getElementById('distance').innerHTML = (Math.round(distance * 1000)) + "m";
    } else {
        document.getElementById('distance').innerHTML = (Math.round(distance * 100) / 100) + "Km";
    }
}
//Error Handler
function showError(error) {
    switch(error.code) {
        case error.PERMISSION_DENIED:
            alert('User denied the request for Geolocation');
            break;
        case error.POSITION_UNAVAILABLE:
            alert('Location Not Available');
            break;
        case error.TIMEOUT:
            alert('The request has timed-out');
            break;
        case error.UNKNOWN_ERROR:
            alert('There was an unknown error');
            break;
    }
}
//Calculate the distance between start and updated, Haversine Formula
function calculateDistance(lat1, lon1, lat2, lon2) {
    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;
}
//Stop Tracking
function stopTracking() {
    navigator.geolocation.clearWatch(watchId);
    alert('Tracking has stopped');
    document.getElementById('startBtn').innerHTML = "Start Tracking?";
}

person Shubham Mehta    schedule 01.07.2015    source источник
comment
Какие? Haversine вычисляет длину линии на поверхности сферы (например, земли), которая дает вам расстояние от точки A до точки B. Если вы говорите о маршрутизации, использовании дорог и тому подобном, это совершенно другая проблема, и вам, вероятно, лучше всего использовать API маршрутизации карт (google, yahoo, OSM и т. д.).   -  person Mark Kahn    schedule 01.07.2015
comment
Я думал об этом, но я считаю, что это добавило бы очень больших накладных расходов. Я из развивающейся страны с не очень сильными или надежными сотовыми сетями во всех частях. Поэтому я хотел сделать это как можно легче.   -  person Shubham Mehta    schedule 01.07.2015
comment
Я не вижу, что не так с вашим кодом, хотя. Вы подписываетесь на информацию о местоположении, которая даст вам поток координат, верно? Сохраните последнюю позицию и рассчитайте позицию между последней и новой. Таким образом, общее расстояние = a->b + b->c + c->d, а не a->d.   -  person Mark Kahn    schedule 01.07.2015


Ответы (1)


Просто записывайте смещение каждые x секунд или около того и суммируйте смещения. У вас будет довольно хорошее приближение. Или просто сначала запишите точки в разное время, а затем сделайте расчет в конце.

var checkpoints = [],
    interval = null;

function record() {
  checkpoints.push( /* current position */ )
}

function distance(a, b) {
  return /* your distance calculation */
}

function start() {
  checkpoints = [];
  interval = setInterval(record, 1000); // record current pos every second
}

function end() {
  clearInterval(interval);

  var distanceTravelled = checkpoints.reduce(function(x, current, i, checkpoints){
    return x + distance(current, checkpoints[i-1]);
  }, 0);

  // do something nice with the distance
}

ОБНОВЛЕНИЕ

Я только сейчас понял, что вы используете watch с обратным вызовом. Затем вы можете использовать следующий подход,

var lastPoint = null,
    travelled = 0;

function update(point) {
  if (lastPoint != null)
    travelled += calculateDistance(lastPoint.long, lastPoint.lat, point.long, point.lat);      

  lastPoint = point;
}

ОБНОВЛЕНИЕ 2 Рабочее решение: http://jsfiddle.net/ymz3a5pb/

person lordvlad    schedule 01.07.2015
comment
Я сделал это, вдохновленный в первую очередь вашим ответом. Увы, в нем есть ошибки в ссылках. Не могли бы вы взглянуть на это? jsfiddle.net/sa4m0u1z - person Shubham Mehta; 01.07.2015
comment
какие ошибки ссылок? может быть, вы можете опубликовать сообщения об ошибках? Кроме того, какой метод вы выбрали? - person lordvlad; 01.07.2015
comment
drive.google.com/file/d/0BwUagjky4-pbdjBuQjZDZU9WXzA/ подобные ошибки. Мой объект HTML вызывает функцию startTracking. Так что я не выбирал метод. Я просто нажал «Начать отслеживание» на странице, и это вызывает функцию startTracking. Извините, я новичок в JS. - person Shubham Mehta; 01.07.2015
comment
Да, спасибо! Это прекрасно работает. вы инициализируете startPos до currentPos. Да, я понимаю. Я сделал что-то подобное в прошлый день и допустил какую-то синтаксическую ошибку (приходит к новичку в языке). Большое спасибо! :) - person Shubham Mehta; 01.07.2015
comment
вы могли бы опубликовать здесь скрипку, чтобы, возможно, я мог пометить ее как принятое решение и закрыть этот вопрос для дальнейшего использования. Я имею в виду, что это только мой второй вопрос, этот, на форумах, но я думаю, что это было бы хорошей практикой. - person Shubham Mehta; 01.07.2015