-
Notifications
You must be signed in to change notification settings - Fork 4
/
vinc.cpp
58 lines (46 loc) · 2.42 KB
/
vinc.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
#include <tuple>
#include <pybind11/pybind11.h>
namespace py = pybind11;
std::tuple<double, double> vinc(double latp, double latc, double longp, double longc) {
constexpr double req = 6378137.0; //Radius at equator
constexpr double flat = 1 / 298.257223563; //flattening of earth
constexpr double rpol = (1 - flat) * req;
double sin_sigma, cos_sigma, sigma, sin_alpha, cos_sq_alpha, cos2sigma;
double C, lam_pre;
// convert to radians
latp = M_PI * latp / 180.0;
latc = M_PI * latc / 180.0;
longp = M_PI * longp / 180.0;
longc = M_PI * longc / 180.0;
const double u1 = atan((1 - flat) * tan(latc));
const double u2 = atan((1 - flat) * tan(latp));
double lon = longp - longc;
double lam = lon;
constexpr double tol = pow(10., -12.); // iteration tolerance
double diff = 1.;
while (abs(diff) > tol) {
sin_sigma = sqrt(pow((cos(u2) * sin(lam)), 2.) + pow(cos(u1)*sin(u2) - sin(u1)*cos(u2)*cos(lam), 2.));
cos_sigma = sin(u1) * sin(u2) + cos(u1) * cos(u2) * cos(lam);
sigma = atan(sin_sigma / cos_sigma);
sin_alpha = (cos(u1) * cos(u2) * sin(lam)) / sin_sigma;
cos_sq_alpha = 1 - pow(sin_alpha, 2.);
cos2sigma = cos_sigma - ((2 * sin(u1) * sin(u2)) / cos_sq_alpha);
C = (flat / 16) * cos_sq_alpha * (4 + flat * (4 - 3 * cos_sq_alpha));
lam_pre = lam;
lam = lon + (1 - C) * flat * sin_alpha * (sigma + C * sin_sigma * (cos2sigma + C * cos_sigma * (2 * pow(cos2sigma, 2.) - 1)));
diff = abs(lam_pre - lam);
}
const double usq = cos_sq_alpha * ((pow(req, 2.) - pow(rpol, 2.)) / pow(rpol ,2.));
const double A = 1 + (usq / 16384) * (4096 + usq * (-768 + usq * (320 - 175 * usq)));
const double B = (usq / 1024) * (256 + usq * (-128 + usq * (74 - 47 * usq)));
const double delta_sig = B * sin_sigma * (cos2sigma + 0.25 * B * (cos_sigma * (-1 + 2 * pow(cos2sigma, 2.)) -
(1 / 6) * B * cos2sigma * (-3 + 4 * pow(sin_sigma, 2.)) *
(-3 + 4 * pow(cos2sigma, 2.))));
const double dis = rpol * A * (sigma - delta_sig);
const double azi1 = atan2((cos(u2) * sin(lam)), (cos(u1) * sin(u2) - sin(u1) * cos(u2) * cos(lam)));
return std::make_tuple(dis, azi1);
}
PYBIND11_MODULE(vinc_cpp, m){
m.doc() = "Vincentys formula in C++";
m.def("vinc", &vinc, "Vincentys formula");
}