Use the haversine formula for small greatcircle distances, rather
than clamping to zero.
This commit is contained in:
parent
a910454c02
commit
08c14484cd
16
track.c
16
track.c
|
@ -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)
|
||||||
|
|
Loading…
Reference in a new issue