compute distance between two geo points

1,577 views
Skip to first unread message

Joe Golike

unread,
Jan 18, 2012, 8:05:46 PM1/18/12
to d3-js
I'm looking to compute the distance between two lat/lon pairs, and I
came across this:
http://groups.google.com/group/Google-Maps-API/browse_thread/thread/c59cebcfd4ee0953

I'm planning to add this code to my project's library, but I was
wondering if it already exists in d3.geo?

Mike Bostock

unread,
Jan 18, 2012, 8:15:49 PM1/18/12
to d3...@googlegroups.com
> I'm planning to add this code to my project's library, but I was
> wondering if it already exists in d3.geo?

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

Jason Davies

unread,
Jan 19, 2012, 4:33:06 AM1/19/12
to d3...@googlegroups.com
On Wed, Jan 18, 2012 at 05:15:49PM -0800, Mike Bostock wrote:
> > I'm planning to add this code to my project's library, but I was
> > wondering if it already exists in d3.geo?
>
> 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…

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/

Joe Golike

unread,
Jan 19, 2012, 11:42:00 AM1/19/12
to d3-js
Awesome, thanks guys for the info. I'll try these out.

Joe

Jamie Popkin

unread,
Jan 19, 2012, 12:00:51 PM1/19/12
to d3...@googlegroups.com
Hey Joe.

I used the Haversine formula for calculating distance in this example:

The code looks like this:

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 Radians
      var lat1Rad = mC.lat * Math.PI/180;
      var lon1Rad = mC.lon * Math.PI/180;
      // Calculate new point in Radians
      var lat2Rad = cC.lat * Math.PI/180;
      var lon2Rad = cC.lon * Math.PI/180;

      // Earth's Radius
      var 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);
   }

mC is the position of the big red dot.
cC is the position of the new dot when you click the map.

Good luck.
Jamie

--
Jamie Popkin
Little Earth
Reply all
Reply to author
Forward
0 new messages