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 void epsg4326_to_epsg3857(
double lon,
double lat,
double& x,
double& y)
16 x = (epsg3857_scale / 180) * lon;
17 y = (epsg3857_scale / M_PI) * log(tan((M_PI / 360) * (lat + 90)));
19 void epsg3857_to_epsg4326(
double x,
double y,
double& lon,
double& lat)
21 lon = (180 / epsg3857_scale) * x;
22 lat = (360 / M_PI) * atan(exp((M_PI / epsg3857_scale) * y)) - 90;
24 dvec3 ECFE_from_geodetic(
const dvec3& geodetic,
double a,
double e)
26 const double& phi = geodetic.x();
27 const double& lambda = geodetic.y();
28 const double& h = geodetic.z();
30 double phi_rad = cgv::math::deg2rad(phi);
31 double lambda_rad = cgv::math::deg2rad(lambda);
35 double sin_phi = sin(phi_rad);
36 double cos_phi = cos(phi_rad);
37 double sin_lambda = sin(lambda_rad);
38 double cos_lambda = cos(lambda_rad);
39 double N = a / sqrt(1 - e_2 * sin_phi * sin_phi);
43 (h + N) * cos_phi * cos_lambda,
44 (h + N) * cos_phi * sin_lambda,
45 (h + (1 - e_2) * N) * sin_phi);
49 template <
class reference_ellipso
id>
50 void cartesian_to_geodetic_iterative(
const double X,
const double Y,
const double Z,
51 double& phi,
double& lambda,
double& h)
55 dvec3 geodetic_from_ECFE(
const dvec3& ECFE,
double a,
double e)
63 const double& X = ECFE[0];
64 const double& Y = ECFE[1];
65 const double& Z = ECFE[2];
68 double& phi = geodetic[0];
69 double& lambda = geodetic[1];
70 double& h = geodetic[2];
73 double p, slat, N, htold, latold;
74 p = sqrt(X * X + Y * Y);
75 if (p < POSITION_TOLERANCE / 5)
77 phi = (Z > 0 ? 90.0 : -90.0);
79 h = ::fabs(Z) - a * sqrt(1.0 - eccSq);
82 phi = ::atan2(Z, p * (1.0 - eccSq));
84 for (
int i = 0; i < 5; i++) {
86 N = a / sqrt(1.0 - eccSq * slat * slat);
88 h = p / ::cos(phi) - N;
90 phi = ::atan2(Z, p * (1.0 - eccSq * (N / (N + h))));
91 if (::fabs(phi - latold) < 1.0e-9 && fabs(h - htold) < 1.0e-9 * a)
break;
93 lambda = ::atan2(Y, X);
94 if (lambda < 0.0) lambda += 2.0 * cgv::math::constants::phi;
95 phi = cgv::math::rad2deg(phi);
96 lambda = cgv::math::rad2deg(lambda);
100 dvec3 geodetic_from_ECFE_approx(
const dvec3& ECFE,
double a,
double e)
105 const double& X = ECFE[0];
106 const double& Y = ECFE[1];
107 const double& Z = ECFE[2];
110 double& phi = geodetic[0];
111 double& lambda = geodetic[1];
112 double& h = geodetic[2];
120 double e_4 = e_2 * e_2;
125 if (sqrt(X_2 + Y_2 + Z_2) > (a * e_2 / (sqrt(1.0 - e_2)))) {
126 if (!((std::abs(X) < POSITION_TOLERANCE) && (std::abs(Y) < POSITION_TOLERANCE)))
129 double p = (X_2 + Y_2) / a_2;
130 double q = ((1.0 - e_2) / a_2) * Z_2;
131 double r = (p + q - e_4) / 6.0;
132 double s = e_4 * ((p * q) / (4.0 * r * r * r));
133 double t = std::pow(1.0 + s + sqrt(s * (2.0 + s)), 1.0 / 3.0);
134 double u = r * (1.0 + t + 1.0 / t);
135 double v = sqrt(u * u + e_4 * q);
136 double w = e_2 * (u + v - q) / (2 * v);
137 double k = sqrt(u + v + w * w) - w;
138 double D = (k * sqrt(X_2 + Y_2)) / (k + e_2);
145 h = ((k + e_2 - 1) / k) * sqrt(D_2 + Z_2);
148 phi = 2 * atan(Z / (D + sqrt(D_2 + Z_2)));
149 phi = cgv::math::rad2deg(phi);
154 lambda = 0.5 * cgv::math::constants::pi - 2.0 * atan(X / (sqrt(X_2 + Y_2) + Y));
158 lambda = -0.5 * cgv::math::constants::pi + 2.0 * atan(X / (sqrt(X_2 + Y_2) + Y));
160 lambda = cgv::math::rad2deg(lambda);
163 std::cout <<
"\nError! Input coordinates not valid";
168 dvec3 ENU_from_geodetic(
const dvec3& position_geodetic,
const dvec3& origin_geodetic,
double a,
double e)
170 const double& phi_geo = position_geodetic[0];
171 const double& lambda_geo = position_geodetic[1];
172 const double& h_geo = position_geodetic[2];
173 const double& phi_origin = origin_geodetic[0];
174 const double& lambda_origin = origin_geodetic[1];
175 const double& h_origin = origin_geodetic[2];
177 double phi_rad = cgv::math::deg2rad(phi_origin);
178 double lambda_rad = cgv::math::deg2rad(lambda_origin);
179 double sin_phi = sin(phi_rad);
180 double cos_phi = cos(phi_rad);
181 double sin_lambda = sin(lambda_rad);
182 double cos_lambda = cos(lambda_rad);
185 dvec3 position_ECFE = ECFE_from_geodetic(position_geodetic, a, e);
186 dvec3 origin_ECFE = ECFE_from_geodetic(origin_geodetic, a, e);
187 const double& X_geo = position_ECFE[0];
188 const double& Y_geo = position_ECFE[1];
189 const double& Z_geo = position_ECFE[2];
190 const double& X_origin = origin_ECFE[0];
191 const double& Y_origin = origin_ECFE[1];
192 const double& Z_origin = origin_ECFE[2];
198 double x = X_geo - X_origin;
199 double y = Y_geo - Y_origin;
200 double z = Z_geo - Z_origin;
203 -sin_lambda * x + cos_lambda * y,
204 -sin_phi * cos_lambda * x - sin_phi * sin_lambda * y + cos_phi * z,
205 cos_phi * cos_lambda * x + cos_phi * sin_lambda * y + sin_phi * z);
this header is dependency free
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