Reputation: 27231
I am trying to find the distance between two longitude and latitude points. I am trying ot use the great circle distance. This is the formula:
I am not sure why but my program is not working. This is the result I am getting:
Change Angle: 0.00016244370761414
Earth Radius: 6371
RESULTS:
Correct Distance: 24.883 km
Computed Distance: 1.0349288612097
Source:
$latStart = 44.638;
$longStart = -63.587;
$latFinish = 44.644;
$longFinish = -63.597;
# Convert Input to Radians
$latStart = deg2Rad($latStart);
$longStart = deg2Rad($longStart);
$latFinish = deg2Rad($latFinish);
$longFinish = deg2Rad($longFinish);
# Because the Earth is not perfectly spherical, no single value serves as its
# natural radius. Distances from points on the surface to the center range from
# 6,353 km to 6,384 km (≈3,947–3,968 mi). Several different ways of modeling the
# Earth as a sphere each yield a convenient mean radius of 6371 km (≈3,959 mi).
# http://en.wikipedia.org/wiki/Earth_radius
$earthRadius = 6371;
# difference in Long/Lat
$latChange = $latFinish - $latStart;
$longChange = $longFinish - $longStart;
# haversine formula
# numerically stable for small distances
# http://en.wikipedia.org/wiki/Great-circle_distance
$changeAngle = 2 * asin(
sqrt(
pow(sin($latChange/2),2) +
cos($latStart) * cos($latFinish) * pow(sin($longChange/2),2)
)
);
echo "Change Angle: $changeAngle\n";
echo "Earth Radius: $earthRadius\n";
Upvotes: 3
Views: 4338
Reputation: 35689
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;
}
}
Upvotes: 1
Reputation: 38129
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);
Upvotes: 1
Reputation: 65854
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.
Upvotes: 2