mirror of
https://github.com/tumic0/GPXSee.git
synced 2024-11-30 22:51:16 +01:00
65 lines
1.7 KiB
C++
65 lines
1.7 KiB
C++
#include "greatcircle.h"
|
|
|
|
#define DELTA 1e-5
|
|
|
|
static bool antipodes(const Coordinates &c1, const Coordinates &c2)
|
|
{
|
|
return ((qAbs(c1.lat() + c2.lat()) < DELTA)
|
|
&& (qAbs(180.0 - qAbs(c1.lon() - c2.lon())) < DELTA));
|
|
}
|
|
|
|
GreatCircle::GreatCircle(const Coordinates &c1, const Coordinates &c2)
|
|
{
|
|
double lat1, lon1, lat2, lon2;
|
|
|
|
if (antipodes(c1, c2)) {
|
|
/* In case of antipodes (which would lead to garbage output without
|
|
this hack), move the points DELTA degrees closer to each other in
|
|
a way that the route never crosses the antimeridian. */
|
|
if (c1.lon() < c2.lon()) {
|
|
lon1 = deg2rad(c1.lon() + DELTA);
|
|
lon2 = deg2rad(c2.lon() - DELTA);
|
|
} else {
|
|
lon1 = deg2rad(c1.lon() - DELTA);
|
|
lon2 = deg2rad(c2.lon() + DELTA);
|
|
}
|
|
if (c1.lat() < c2.lat()) {
|
|
lat1 = deg2rad(c1.lat() + DELTA);
|
|
lat2 = deg2rad(c2.lat() - DELTA);
|
|
} else {
|
|
lat1 = deg2rad(c1.lat() - DELTA);
|
|
lat2 = deg2rad(c2.lat() + DELTA);
|
|
}
|
|
} else {
|
|
lat1 = deg2rad(c1.lat());
|
|
lon1 = deg2rad(c1.lon());
|
|
lat2 = deg2rad(c2.lat());
|
|
lon2 = deg2rad(c2.lon());
|
|
}
|
|
|
|
double cosLat1 = cos(lat1);
|
|
double cosLat2 = cos(lat2);
|
|
_sinLat1 = sin(lat1);
|
|
_sinLat2 = sin(lat2);
|
|
|
|
_xA = cosLat1 * cos(lon1);
|
|
_xB = cosLat2 * cos(lon2);
|
|
_yA = cosLat1 * sin(lon1);
|
|
_yB = cosLat2 * sin(lon2);
|
|
|
|
_d = 2 * asin(sqrt(pow((sin((lat1 - lat2) / 2)), 2) + cosLat1 * cosLat2
|
|
* pow(sin((lon1 - lon2) / 2), 2)));
|
|
_sinD = sin(_d);
|
|
}
|
|
|
|
Coordinates GreatCircle::pointAt(double f) const
|
|
{
|
|
double A = sin((1.0 - f) * _d) / _sinD;
|
|
double B = sin(f * _d) / _sinD;
|
|
double x = A * _xA + B * _xB;
|
|
double y = A * _yA + B * _yB;
|
|
double z = A * _sinLat1 + B * _sinLat2;
|
|
|
|
return Coordinates(rad2deg(atan2(y, x)), rad2deg(atan2(z, sqrt(x*x + y*y))));
|
|
}
|