1#include "geo_transform.h"
8 static const double POSITION_TOLERANCE = 0.001;
10 typedef fvec<float, 3>
vec3;
11 typedef fvec<double, 2>
dvec2;
12 typedef fvec<double, 3>
dvec3;
14 dvec3 ECFE_from_geodetic(
const dvec3& geodetic,
double a,
double e)
16 const double& phi = geodetic.x();
17 const double& lambda = geodetic.y();
18 const double& h = geodetic.z();
20 double phi_rad = cgv::math::deg2rad(phi);
21 double lambda_rad = cgv::math::deg2rad(lambda);
25 double sin_phi = sin(phi_rad);
26 double cos_phi = cos(phi_rad);
27 double sin_lambda = sin(lambda_rad);
28 double cos_lambda = cos(lambda_rad);
29 double N = a / sqrt(1 - e_2 * sin_phi * sin_phi);
33 (h + N) * cos_phi * cos_lambda,
34 (h + N) * cos_phi * sin_lambda,
35 (h + (1 - e_2) * N) * sin_phi);
39 template <
class reference_ellipso
id>
40 void cartesian_to_geodetic_iterative(
const double X,
const double Y,
const double Z,
41 double& phi,
double& lambda,
double& h)
45 dvec3 geodetic_from_ECFE(
const dvec3& ECFE,
double a,
double e)
53 const double& X = ECFE[0];
54 const double& Y = ECFE[1];
55 const double& Z = ECFE[2];
58 double& phi = geodetic[0];
59 double& lambda = geodetic[1];
60 double& h = geodetic[2];
63 double p, slat, N, htold, latold;
64 p = sqrt(X * X + Y * Y);
65 if (p < POSITION_TOLERANCE / 5)
67 phi = (Z > 0 ? 90.0 : -90.0);
69 h = ::fabs(Z) - a * sqrt(1.0 - eccSq);
72 phi = ::atan2(Z, p * (1.0 - eccSq));
74 for (
int i = 0; i < 5; i++) {
76 N = a / sqrt(1.0 - eccSq * slat * slat);
78 h = p / ::cos(phi) - N;
80 phi = ::atan2(Z, p * (1.0 - eccSq * (N / (N + h))));
81 if (::fabs(phi - latold) < 1.0e-9 && fabs(h - htold) < 1.0e-9 * a)
break;
83 lambda = ::atan2(Y, X);
84 if (lambda < 0.0) lambda += 2.0 * cgv::math::constants::phi;
85 phi = cgv::math::rad2deg(phi);
86 lambda = cgv::math::rad2deg(lambda);
90 dvec3 geodetic_from_ECFE_approx(
const dvec3& ECFE,
double a,
double e)
95 const double& X = ECFE[0];
96 const double& Y = ECFE[1];
97 const double& Z = ECFE[2];
100 double& phi = geodetic[0];
101 double& lambda = geodetic[1];
102 double& h = geodetic[2];
110 double e_4 = e_2 * e_2;
115 if (sqrt(X_2 + Y_2 + Z_2) > (a * e_2 / (sqrt(1.0 - e_2)))) {
116 if (!((std::abs(X) < POSITION_TOLERANCE) && (std::abs(Y) < POSITION_TOLERANCE)))
119 double p = (X_2 + Y_2) / a_2;
120 double q = ((1.0 - e_2) / a_2) * Z_2;
121 double r = (p + q - e_4) / 6.0;
122 double s = e_4 * ((p * q) / (4.0 * r * r * r));
123 double t = std::pow(1.0 + s + sqrt(s * (2.0 + s)), 1.0 / 3.0);
124 double u = r * (1.0 + t + 1.0 / t);
125 double v = sqrt(u * u + e_4 * q);
126 double w = e_2 * (u + v - q) / (2 * v);
127 double k = sqrt(u + v + w * w) - w;
128 double D = (k * sqrt(X_2 + Y_2)) / (k + e_2);
135 h = ((k + e_2 - 1) / k) * sqrt(D_2 + Z_2);
138 phi = 2 * atan(Z / (D + sqrt(D_2 + Z_2)));
139 phi = cgv::math::rad2deg(phi);
144 lambda = 0.5 * cgv::math::constants::pi - 2.0 * atan(X / (sqrt(X_2 + Y_2) + Y));
148 lambda = -0.5 * cgv::math::constants::pi + 2.0 * atan(X / (sqrt(X_2 + Y_2) + Y));
150 lambda = cgv::math::rad2deg(lambda);
153 std::cout <<
"\nError! Input coordinates not valid";
158 dvec3 ENU_from_geodetic(
const dvec3& position_geodetic,
const dvec3& origin_geodetic,
double a,
double e)
160 const double& phi_geo = position_geodetic[0];
161 const double& lambda_geo = position_geodetic[1];
162 const double& h_geo = position_geodetic[2];
163 const double& phi_origin = origin_geodetic[0];
164 const double& lambda_origin = origin_geodetic[1];
165 const double& h_origin = origin_geodetic[2];
167 double phi_rad = cgv::math::deg2rad(phi_origin);
168 double lambda_rad = cgv::math::deg2rad(lambda_origin);
169 double sin_phi = sin(phi_rad);
170 double cos_phi = cos(phi_rad);
171 double sin_lambda = sin(lambda_rad);
172 double cos_lambda = cos(lambda_rad);
175 dvec3 position_ECFE = ECFE_from_geodetic(position_geodetic, a, e);
176 dvec3 origin_ECFE = ECFE_from_geodetic(origin_geodetic, a, e);
177 const double& X_geo = position_ECFE[0];
178 const double& Y_geo = position_ECFE[1];
179 const double& Z_geo = position_ECFE[2];
180 const double& X_origin = origin_ECFE[0];
181 const double& Y_origin = origin_ECFE[1];
182 const double& Z_origin = origin_ECFE[2];
188 double x = X_geo - X_origin;
189 double y = Y_geo - Y_origin;
190 double z = Z_geo - Z_origin;
193 -sin_lambda * x + cos_lambda * y,
194 -sin_phi * cos_lambda * x - sin_phi * sin_lambda * y + cos_phi * z,
195 cos_phi * cos_lambda * x + cos_phi * sin_lambda * y + sin_phi * z);
cgv::math::fvec< double, 3 > dvec3
declare type of 3d double precision floating point vectors
cgv::math::fvec< float, 3 > vec3
declare type of 3d single precision floating point vectors
cgv::math::fvec< double, 2 > dvec2
declare type of 2d double precision floating point vectors