Use the haversine formula for small greatcircle distances, rather

than clamping to zero.
This commit is contained in:
Oliver Jowett 2016-08-26 11:36:29 +01:00
parent a910454c02
commit 08c14484cd

16
track.c
View file

@ -112,16 +112,24 @@ struct aircraft *trackFindAircraft(uint32_t addr) {
// (but we don't use it in situations where that matters) // (but we don't use it in situations where that matters)
static double greatcircle(double lat0, double lon0, double lat1, double lon1) static double greatcircle(double lat0, double lon0, double lat1, double lon1)
{ {
double dlat, dlon;
lat0 = lat0 * M_PI / 180.0; lat0 = lat0 * M_PI / 180.0;
lon0 = lon0 * M_PI / 180.0; lon0 = lon0 * M_PI / 180.0;
lat1 = lat1 * M_PI / 180.0; lat1 = lat1 * M_PI / 180.0;
lon1 = lon1 * M_PI / 180.0; lon1 = lon1 * M_PI / 180.0;
// avoid NaN dlat = fabs(lat1 - lat0);
if (fabs(lat0 - lat1) < 0.0001 && fabs(lon0 - lon1) < 0.0001) dlon = fabs(lon1 - lon0);
return 0.0;
return 6371e3 * acos(sin(lat0) * sin(lat1) + cos(lat0) * cos(lat1) * cos(fabs(lon0 - lon1))); // use haversine for small distances for better numerical stability
if (dlat < 0.001 && dlon < 0.001) {
double a = sin(dlat/2) * sin(dlat/2) + cos(lat0) * cos(lat1) * sin(dlon/2) * sin(dlon/2);
return 6371e3 * 2 * atan2(sqrt(a), sqrt(1.0 - a));
}
// spherical law of cosines
return 6371e3 * acos(sin(lat0) * sin(lat1) + cos(lat0) * cos(lat1) * cos(dlon));
} }
static void update_range_histogram(double lat, double lon) static void update_range_histogram(double lat, double lon)