如何使用 Haversine 公式计算行进的距离(不是位移)?
How to calculate distance (NOT DISPLACEMENT) travelled using Haversine Formula?
我正在尝试编写一些 JS,使用 Haversine 公式计算用户移动的距离。
现在 Haversine 公式接受起始坐标和当前坐标,并给出这两个坐标之间的间隔。然而,这只是 DISPLACEMENT 而不是用户可能已经到达终点的距离。
我需要有人帮助我编写下面的代码(提供位移)并建议我应该做些什么才能计算距离。
//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?";
}
每隔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/
我正在尝试编写一些 JS,使用 Haversine 公式计算用户移动的距离。
现在 Haversine 公式接受起始坐标和当前坐标,并给出这两个坐标之间的间隔。然而,这只是 DISPLACEMENT 而不是用户可能已经到达终点的距离。
我需要有人帮助我编写下面的代码(提供位移)并建议我应该做些什么才能计算距离。
//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?";
}
每隔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/