Question

So I've got the Haversine formula going on to find locations along a route retrieved from Google Maps, as seen below, using miles.

var R = 3959 //in miles;
var lat1 = result.routes[0].overview_path[index].k.toFixed(5);
var lat2 = locations[index2].lat;
var lon1 = result.routes[0].overview_path[index].A.toFixed(5);
var lon2 = locations[index2].lng;
var deltaLat = (lat2-lat1).toRad();
var deltaLon = (lon2-lon1).toRad();
var a = Math.sin(deltaLat/2)*Math.sin(deltaLat/2) + Math.cos(lat1) * Math.cos(lat2) *
                Math.sin(deltaLon/2)*Math.sin(deltaLon/2);
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
var d = R*c;

But when it uses the points (for instance) 36.64756, -97.34593 (somewhere on the path between Wichita, KS and Dallas TX) and 39.933321, -91.409415 (a location in Quincy, IL), my distance is less than 20 miles. Obviously this isn't correct. I haven't been able to replicate the error with other values - I happened upon this by accident.

Here's the toRad prototype, btw -

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

My original guess was a floating-point overflow somewhere but I haven't been able to isolate it or alleviate it with toFixed. Anyone have any ideas?

Was it helpful?

Solution

I believe your equation is wrong. Here is a javascript version you can compare against: http://www.movable-type.co.uk/scripts/latlong.html

The difference is your terms Math.cos(lat1) * Math.cos(lat2). You need to convert lat1 and lat2 to radians first.

OTHER TIPS

toFixed returns String with the value, remember that.

http://www.w3schools.com/jsref/jsref_tofixed.asp

You can use my package here to calculate for you: https://www.npmjs.com/package/haversine-calculator

const haversineCalculator = require('haversine-calculator')

const start = {
  latitude: -23.754842,
  longitude: -46.676781
}

const end = {
  latitude: -23.549588,
  longitude: -46.693210
}

console.log(haversineCalculator(start, end))
console.log(haversineCalculator(start, end, {unit: 'meter'}))
console.log(haversineCalculator(start, end, {unit: 'mile'}))
console.log(haversineCalculator(start, end, {threshold: 1}))
console.log(haversineCalculator(start, end, {threshold: 1, unit: 'meter'}))
console.log(haversineCalculator(start, end, {threshold: 1, unit: 'mile'}))

Have a look , I think that this code will be more easily maintainable and flexible than doing it by manually.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top