Distance between lat/long points using the haversine formula

只谈情不闲聊 提交于 2019-12-05 20:48:50

Let's do a back-of-the-envelope check using a planar approximation. The difference in latitude is 0.006°, and the difference in longitude is 0.01°, but multiply by cosine of latitude to get 0.0075°. Apply Pythagoras:

>>> sqrt(0.006 ** 2 + 0.0075 ** 2)
0.0096046863561492727

which is about 0.000167 radians, pretty close to your computation. (Even more back-of-the-envelope check: a degree is about 69 miles, which is a bit over 100 km, so 0.01° should be a bit over 1 km.)

So I think it's your alleged "Correct distance" that's wrong, not your computation.

Your approach is loosely based on Pythagoras' Theorem -- I've always done it the hard way, i.e. something like (In reality, I pre-calculate the values for the axis and store them in the database alongside the data):

$startXAxis   = cos(deg2Rad($latStart)) * cos(deg2Rad($longStart));
$startYAxis   = cos(deg2Rad($latStart)) * sin(deg2Rad($longStart));
$startZAxis   = sin(deg2Rad($latStart));
$finishXAxis   = cos(deg2Rad($latFinish)) * cos(deg2Rad($longFinish));
$finishYAxis   = cos(deg2Rad($latFinish)) * sin(deg2Rad($longFinish));
$finishZAxis   = sin(deg2Rad($latFinish));

$changeAngle = acos($startXAxis * $finishXAxis + $startYAxis * $finishYAxis + $startZAxis * $finishZAxis);

Your formula looks different to my implementation. However mine's in .NET but I've unit tested it and it works well.

It's a slightly rewritten version of this: http://megocode3.wordpress.com/2008/02/05/haversine-formula-in-c/

/// <summary>
/// Implementation of the Haversine formula
/// For calculating the distance between 2 points on a sphere
/// http://en.wikipedia.org/wiki/Haversine_formula
/// </summary>
public class Haversine
{
    /// <summary>
    /// Calculate the distance between 2 points in miles or kilometers
    /// http://megocode3.wordpress.com/2008/02/05/haversine-formula-in-c/
    /// 
    /// This assumes sea level
    /// </summary>
    public double Distance(LatLon pos1, LatLon pos2, DistanceType type)
    {
        const double RADIUS_OF_EARTH_IN_MILES = 3963.1676;
        const double RADIUS_OF_EARTH_IN_KILOMETERS = 6378.1;

        //radius of the earth
        double R = (type == DistanceType.Miles) ? RADIUS_OF_EARTH_IN_MILES : RADIUS_OF_EARTH_IN_KILOMETERS;

        //Deltas
        double dLat = ToRadian(pos2.Lat - pos1.Lat);
        double dLon = ToRadian(pos2.Lon - pos1.Lon);

        double a = Math.Sin(dLat/2)*Math.Sin(dLat/2) + Math.Cos(ToRadian(pos1.Lat))*Math.Cos(ToRadian(pos2.Lat)) * Math.Sin(dLon / 2) * Math.Sin(dLon / 2);
        double c = 2 * Math.Asin(Math.Min(1, Math.Sqrt(a)));

        double d = R*c;
        return d;
    }

    /// <summary>
    /// Convert to Radians.
    /// </summary>
    private double ToRadian(double val)
    {
        return (Math.PI / 180) * val;
    }
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!