Skip to content

Instantly share code, notes, and snippets.

@esutton
Last active September 14, 2016 13:08
Show Gist options
  • Save esutton/0034c06f2bb182f091a7e5900824b3b4 to your computer and use it in GitHub Desktop.
Save esutton/0034c06f2bb182f091a7e5900824b3b4 to your computer and use it in GitHub Desktop.
Haversine to calculate distance between two pairs pf latitutde and longitude, plus a bearing function
// haversine
// By Nick Justice (niix)
// https://github.com/niix/haversine
//
// Corroborated using: http://andrew.hedges.name/experiments/haversine/
import {Waypoint} from "./Waypoint" // Implement https://developer.mozilla.org/en-US/docs/Web/API/Position/coords
module.exports = {
// convert to radians
toRad(num) {
return num * Math.PI / 180;
},
/// Radians to degrees
toDeg(radians) {
return radians * (180 / Math.PI);
},
/// Returns bearing in degrees range 0 - 360
/// waypoint objects implement https://developer.mozilla.org/en-US/docs/Web/API/Position/coords
waypointBearingDegrees(waypointStart, waypointEnd) {
if(waypointStart == null) {
return -1.0;
}
if(waypointEnd == null) {
return -1.0;
}
if(false == waypointEnd.gpsFixed) {
return -1.0;
}
var dLon = this.toRad(waypointEnd.position.coords.longitude - waypointStart.position.coords.longitude)
var lat1 = this.toRad(waypointStart.position.coords.latitude)
var lat2 = this.toRad(waypointEnd.position.coords.latitude)
var y = Math.sin(dLon) * Math.cos(lat2);
var x = Math.cos(lat1)*Math.sin(lat2) -
Math.sin(lat1)*Math.cos(lat2)*Math.cos(dLon);
var bearing = this.toDeg(Math.atan2(y, x))
bearing = 360 - ((bearing + 360) % 360);
return bearing;
},
// Returns meters by default
haversine(start, end, options) {
if(start == null) {
console.log('start: null');
return;
}
if(end == null) {
console.log('end: null');
return;
}
var m = 6371*1000;
var km = 6371
var mile = 3960
options = options || {}
var R = m;
if(options.unit === 'mile') {
R = mile;
} else if(options.unit === 'km') {
R = km;
}
var dLat = this.toRad(end.latitude - start.latitude)
var dLon = this.toRad(end.longitude - start.longitude)
var lat1 = this.toRad(start.latitude)
var lat2 = this.toRad(end.latitude)
var a = Math.sin(dLat/2) * Math.sin(dLat/2) +
Math.sin(dLon/2) * Math.sin(dLon/2) * Math.cos(lat1) * Math.cos(lat2)
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a))
if (options.threshold) {
return options.threshold > (R * c)
} else {
return R * c
}
},
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment