I recall the Haversine formula coming up when Jason Davies implemented
great arcs and great circles, but I'm not sure if there's a method for
computing the distance exactly…
https://github.com/mbostock/d3/blob/master/src/geo/circle.js
https://github.com/mbostock/d3/blob/master/src/geo/greatArc.js
Mike
The Haversine formula approximates the Earth as a sphere, so is only
accurate up to around 0.5%. You can get better accuracy using an
ellipsoid at the expense (I think) of speed. The most common method for
this is to use Vincenty's formulae, which have millimeter accuracy!
http://en.wikipedia.org/wiki/Vincenty%27s_formulae
http://www.movable-type.co.uk/scripts/latlong-vincenty.html
I've recently discovered simpler formulae for ellipsoids with less
accuracy. No-one travels on an exact ellipsoid anyway so millimeter
accuracy is not that useful, and Haversine is good enough most of the time.
http://en.wikipedia.org/wiki/Geographical_distance#Ellipsoidal-surface_formulae
To compute the great-circle distance in D3 (technically, this always means the
distance on a sphere i.e. Haversine), you can do:
// Multiply angular distance by mean Earth radius of 6,371km.
var d = d3.geo.greatArc().distance({source: a, target: b}) * 6371;
If you're doing multiple calculations, you should just call d3.geo.greatArc()
once for efficiency e.g.
var greatArc = d3.geo.greatArc();
var d = greatArc.distance({source: a: target: b}) * 6371;
I've also added some documentation to the Wiki:
https://github.com/mbostock/d3/wiki/Geo-Paths#wiki-greatArc
https://github.com/mbostock/d3/wiki/Geo-Paths#wiki-circle
--
Jason Davies, http://www.jasondavies.com/
function calcDist (cC) {var dLatRad = Math.abs(mC.lat - cC.lat) * Math.PI/180;var dLonRad = Math.abs(mC.lon - cC.lon) * Math.PI/180;// Calculate origin in Radiansvar lat1Rad = mC.lat * Math.PI/180;var lon1Rad = mC.lon * Math.PI/180;// Calculate new point in Radiansvar lat2Rad = cC.lat * Math.PI/180;var lon2Rad = cC.lon * Math.PI/180;// Earth's Radiusvar eR = 6371;var d1 = Math.sin(dLatRad/2) * Math.sin(dLatRad/2) +Math.sin(dLonRad/2) * Math.sin(dLonRad/2) * Math.cos(lat1Rad) * Math.cos(lat2Rad);var d2 = 2 * Math.atan2(Math.sqrt(d1), Math.sqrt(1-d1));return(eR * d2);}