Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
328 views
in Technique[技术] by (71.8m points)

java - Quicker way to calculate geographic distance between two points

I borrowed the following method from somewhere on the internet (Can't remember where). But its doing a straight forward process, finding the distance between two gps points. It works just fine, except that it may be a little slow, as I'm running it across millions of points. I was wondering if anyone knows an approach that would be computationally less expensive.

The accuracy needs to be in the general area of 'correct' but doesn't need to be 100% accurate.

private double distFrom(double lat1, double lng1, double lat2, double lng2) {
    double earthRadius = 3958.75;
    double dLat = Math.toRadians(lat2-lat1);
    double dLng = Math.toRadians(lng2-lng1);
    double a = Math.sin(dLat/2) * Math.sin(dLat/2) +
           Math.cos(Math.toRadians(lat1)) * Math.cos(Math.toRadians(lat2)) *
           Math.sin(dLng/2) * Math.sin(dLng/2);
    double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
    return   earthRadius * c;
  }
}

P.s I did indeed find a number of other relevant questions, but they don't really focus on my speed concern.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

If you don't mind ignoring the slight oblateness of the Earth (and your posted Haversine code does just that anyway) consider pre-converting all of your spherical (lat/long) coordinates into 3D unit-length cartesian coordinates first, per:

http://en.wikipedia.org/wiki/Spherical_coordinate_system

Then your spherical distance between cartesian coordinates p1 and p2 is simply:

r * acos(p1 . p2)

Since p1 and p2 will have unit length this reduces to four multiplications, two additions and one inverse trig operation per pair.

Also note that the calculation of dot products is an ideal candidate for optimisation, e.g. via GPU, MMX extensions, vector libraries, etc.

Furthermore, if your intent is to order the pairs by distance, potentially ignoring more distant pairs, you can defer the expensive r*acos() part of the equation by sorting the list just on the dot product value since for all valid inputs (i.e. the range [-1, 1]) it's guaranteed that:

acos(x) < acos(y) if x > y

You then just take the acos() of the values you're actually interested in.

Re: the potential inaccuracies with using acos(), those are really only significant if you're using single-precision float variables. Using a double with 16 significant digits should get you distances accurate to within one metre or less.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...