source: pacpusframework/trunk/src/PacpusTools/src/geodesie.cpp@ 210

Last change on this file since 210 was 210, checked in by Marek Kurdej, 11 years ago

Geodesie: formatting.

  • Property svn:executable set to *
File size: 13.0 KB
Line 
1// %pacpus:license{
2// This file is part of the PACPUS framework distributed under the
3// CECILL-C License, Version 1.0.
4/// @author Marek Kurdej <firstname.surname@utc.fr>
5/// @author Jean Laneurit <firstname.surname@utc.fr>
6/// @date April, 2010
7// %pacpus:license}
8
9#include <Pacpus/PacpusTools/geodesie.h>
10
11#include <fstream>
12
13using ::boost::math::constants::pi;
14using ::boost::math::constants::half_pi;
15using ::std::abs;
16using ::std::atan;
17using ::std::exp;
18using ::std::ifstream;
19using ::std::ostream;
20using ::std::log;
21using ::std::sin;
22using ::std::string;
23
24#ifdef _MSC_VER
25#pragma warning(disable : 4244)
26#endif //_MSC_VER
27
28namespace Geodesy
29{
30
31////////////////////////////////////////////////////////////////////////////////
32Matrice::Matrice(const Matrice& A)
33{
34 c0_l0 = A.c0_l0;
35 c1_l0 = A.c1_l0;
36 c2_l0 = A.c2_l0;
37 c0_l1 = A.c0_l1;
38 c1_l1 = A.c1_l1;
39 c2_l1 = A.c2_l1;
40 c0_l2 = A.c0_l2;
41 c1_l2 = A.c1_l2;
42 c2_l2 = A.c2_l2;
43}
44
45////////////////////////////////////////////////////////////////////////////////
46Matrice::Matrice()
47{
48 c0_l0 = 0.0;
49 c1_l0 = 0.0;
50 c2_l0 = 0.0;
51 c0_l1 = 0.0;
52 c1_l1 = 0.0;
53 c2_l1 = 0.0;
54 c0_l2 = 0.0;
55 c1_l2 = 0.0;
56 c2_l2 = 0.0;
57}
58
59////////////////////////////////////////////////////////////////////////////////
60void Matrice::Apply(double v0, double v1, double v2, double& Mv0, double& Mv1, double& Mv2)
61{
62 Mv0 = c0_l0 * v0 + c1_l0 * v1 + c2_l0 * v2;
63 Mv1 = c0_l1 * v0 + c1_l1 * v1 + c2_l1 * v2;
64 Mv2 = c0_l2 * v0 + c1_l2 * v1 + c2_l2 * v2;
65}
66
67////////////////////////////////////////////////////////////////////////////////
68Matrice ProdMat(Matrice const& A, Matrice const& B)
69{
70 Matrice out;
71
72 out.c0_l0 = A.c0_l0 * B.c0_l0 + A.c1_l0 * B.c0_l1 + A.c2_l0 * B.c0_l2;
73 out.c1_l0 = A.c0_l0 * B.c1_l0 + A.c1_l0 * B.c1_l1 + A.c2_l0 * B.c1_l2;
74 out.c2_l0 = A.c0_l0 * B.c2_l0 + A.c1_l0 * B.c2_l1 + A.c2_l0 * B.c2_l2;
75
76 out.c0_l1 = A.c0_l1 * B.c0_l0 + A.c1_l1 * B.c0_l1 + A.c2_l1 * B.c0_l2;
77 out.c1_l1 = A.c0_l1 * B.c1_l0 + A.c1_l1 * B.c1_l1 + A.c2_l1 * B.c1_l2;
78 out.c2_l1 = A.c0_l1 * B.c2_l0 + A.c1_l1 * B.c2_l1 + A.c2_l1 * B.c2_l2;
79
80 out.c0_l2 = A.c0_l2 * B.c0_l0 + A.c1_l2 * B.c0_l1 + A.c2_l2 * B.c0_l2;
81 out.c1_l2 = A.c0_l2 * B.c1_l0 + A.c1_l2 * B.c1_l1 + A.c2_l2 * B.c1_l2;
82 out.c2_l2 = A.c0_l2 * B.c2_l0 + A.c1_l2 * B.c2_l1 + A.c2_l2 * B.c2_l2;
83 return out;
84}
85
86////////////////////////////////////////////////////////////////////////////////
87Matrice TransMat(Matrice const& A)
88{
89 Matrice out;
90 out.c0_l0 = A.c0_l0;
91 out.c1_l0 = A.c0_l1;
92 out.c2_l0 = A.c0_l2;
93 out.c0_l1 = A.c1_l0;
94 out.c1_l1 = A.c1_l1;
95 out.c2_l1 = A.c1_l2;
96 out.c0_l2 = A.c2_l0;
97 out.c1_l2 = A.c2_l1;
98 out.c2_l2 = A.c2_l2;
99 return out;
100}
101
102////////////////////////////////////////////////////////////////////////////////
103ostream& operator<<(ostream& os, Matrice const& A)
104{
105 os << A.c0_l0 << "\t" << A.c1_l0 << "\t" << A.c2_l0 << "\n";
106 os << A.c0_l1 << "\t" << A.c1_l1 << "\t" << A.c2_l1 << "\n";
107 os << A.c0_l2 << "\t" << A.c1_l2 << "\t" << A.c2_l2 << "\n";
108 return os;
109}
110
111void Write(Matrice const& A, ostream& out)
112{
113 out << A;
114}
115
116////////////////////////////////////////////////////////////////////////////////
117Raf98::Raf98()
118{
119}
120
121////////////////////////////////////////////////////////////////////////////////
122Raf98::~Raf98()
123{
124 m_dvalues.clear();
125}
126
127////////////////////////////////////////////////////////////////////////////////
128bool Raf98::Interpol(double longitude, double latitude, double* Hwgs84) const
129{
130 *Hwgs84 = 0.0;
131 if (m_dvalues.size() == 0) {
132 return false;
133 }
134 const double longitude_min = -5.5;
135 const double longitude_max = 8.5;
136 if (longitude < longitude_min) {
137 return false;
138 }
139 if (longitude > longitude_max) {
140 return false;
141 }
142 const double latitude_min = 42;
143 const double latitude_max = 51.5;
144 if (latitude < latitude_min) {
145 return false;
146 }
147 if (latitude > latitude_max) {
148 return false;
149 }
150 //conversion en position
151 double longPix = (longitude - longitude_min) * 30.;
152 double latPix = (latitude_max - latitude) * 40.;
153
154 double RestCol, RestLig;
155 double ColIni, LigIni;
156 RestCol = modf(longPix, &ColIni);
157 RestLig = modf(latPix, &LigIni);
158
159 double Zbd = (1.0 - RestCol) * (1.0 - RestLig) * LitGrille(ColIni, LigIni);
160 Zbd += RestCol * (1.0 - RestLig) * LitGrille(ColIni + 1, LigIni);
161 Zbd += (1.0 - RestCol) * RestLig * LitGrille(ColIni, LigIni + 1);
162 Zbd += RestCol * RestLig * LitGrille(ColIni + 1, LigIni + 1);
163 *Hwgs84 = Zbd;
164
165 return true;
166}
167
168////////////////////////////////////////////////////////////////////////////////
169double Raf98::LitGrille(unsigned int c, unsigned int l) const
170{
171 const unsigned int w = 421;
172 // const unsigned int h=381;
173 return m_dvalues.at(c + l * w);
174}
175
176////////////////////////////////////////////////////////////////////////////////
177bool Raf98::Load(const string& s)
178{
179 ifstream in(s.c_str());
180 unsigned int w = 421;
181 unsigned int h = 381;
182
183 m_dvalues.reserve(w * h);
184
185 char entete[1024]; //sur 3 lignes
186 in.getline(entete, 1023);
187 in.getline(entete, 1023);
188 in.getline(entete, 1023);
189
190 char bidon[1024];
191 double val;
192 for (unsigned int i = 0; i < h; ++i) {
193 for (unsigned int j = 0; j < 52; ++j) {
194 for (unsigned int k = 0; k < 8; ++k) {
195 in >> val;
196 m_dvalues.push_back(val);
197 }
198 in.getline(bidon, 1023);
199 }
200 for (unsigned int k = 0; k < 5; ++k) {
201 in >> val;
202 m_dvalues.push_back(val);
203 }
204 in.getline(bidon, 1023);
205 if (!in.good()) {
206 m_dvalues.clear();
207 return false;
208 }
209 }
210 return in.good();
211}
212
213} // namespace Geodesy
214
215////////////////////////////////////////////////////////////////////////////////
216////////////////////////////////////////////////////////////////////////////////
217
218////////////////////////////////////////////////////////////////////////////////
219//ALGO0001
220double Geodesy::LatitueIsometrique(double latitude, double e)
221{
222 double li = log(tan(pi<double>() / 4. + latitude / 2.)) + e * log((1 - e * sin(latitude)) / (1 + e * sin(latitude))) / 2;
223 return li;
224}
225
226////////////////////////////////////////////////////////////////////////////////
227//ALGO0002
228double Geodesy::LatitueIsometrique2Lat(double latitude_iso, double e, double epsilon)
229{
230 double latitude_i = 2 * atan(exp(latitude_iso)) - half_pi<double>();
231 double latitude_ip1 = latitude_i + epsilon * 2;
232 while (abs(latitude_i - latitude_ip1) > epsilon) {
233 latitude_i = latitude_ip1;
234 latitude_ip1 = 2 * atan(
235 exp(e * 0.5 * log(
236 (1 + e * sin(latitude_i)) / (1 - e * sin(latitude_i))))
237 * exp(latitude_iso)) - half_pi<double>();
238 }
239 return latitude_ip1;
240}
241
242////////////////////////////////////////////////////////////////////////////////
243void Geodesy::Geo2ProjLambert(
244 double lambda, double phi,
245 double n, double c, double e,
246 double lambdac, double xs, double ys,
247 double& X, double& Y)
248{
249 double lat_iso = LatitueIsometrique(phi, e);
250 X = xs + c * exp(-n * lat_iso) * sin(n * (lambda - lambdac));
251 Y = ys - c * exp(-n * lat_iso) * cos(n * (lambda - lambdac));
252}
253
254////////////////////////////////////////////////////////////////////////////////
255//ALGO0004
256void Geodesy::Proj2GeoLambert(
257 double X, double Y,
258 double n, double c, double e,
259 double lambdac, double xs, double ys,
260 double epsilon,
261 double& lambda, double& phi)
262{
263 double X_xs = X - xs;
264 double ys_Y = ys - Y;
265 double R = sqrt(X_xs * X_xs + ys_Y * ys_Y);
266 double gamma = atan(X_xs / ys_Y);
267 lambda = lambdac + gamma / n;
268 double lat_iso = -1 / n * log(fabs(R / c));
269 phi = LatitueIsometrique2Lat(lat_iso, e, epsilon);
270}
271
272////////////////////////////////////////////////////////////////////////////////
273double Geodesy::ConvMerApp(double longitude)
274{
275 double phi0_Lambert93 = Deg2Rad(46.5);
276 double lambda0_Lambert93 = Deg2Rad(3.0);
277 double conv = -sin(phi0_Lambert93) * (longitude - lambda0_Lambert93);
278 return conv;
279}
280
281////////////////////////////////////////////////////////////////////
282void Geodesy::Geographique_2_Lambert93(const Raf98& raf98, double lambda, double phi, double he, Matrice in, double& E, double& N, double& h, Matrice& out)
283{
284 Matrice passage;
285 double conv = Geodesy::ConvMerApp(lambda);
286 double c_ = cos(conv);
287 double s_ = sin(conv);
288
289 passage.c0_l0 = c_;
290 passage.c0_l1 = s_;
291 passage.c0_l2 = 0.0;
292
293 passage.c1_l0 = -s_;
294 passage.c1_l1 = c_;
295 passage.c1_l2 = 0.0;
296
297 passage.c2_l0 = 0.0;
298 passage.c2_l1 = 0.0;
299 passage.c2_l2 = 1.0;
300
301 out = ProdMat(passage, in);
302 double diff_h;
303 raf98.Interpol(Rad2Deg(lambda), Rad2Deg(phi), &diff_h);
304 h = he - diff_h;
305
306 Geodesy::Geo2ProjLambert(
307 lambda, phi,
308 n_Lambert93, c_Lambert93, e_Lambert93,
309 lambda0_Lambert93, xs_Lambert93, ys_Lambert93,
310 E, N);
311}
312
313////////////////////////////////////////////////////////////////////////
314void Geodesy::Geographique_2_Lambert93(const Raf98& raf98, double lambda, double phi, double he, double& E, double& N, double& h)
315{
316 Geodesy::Geo2ProjLambert(
317 lambda, phi,
318 n_Lambert93, c_Lambert93, e_Lambert93,
319 lambda0_Lambert93, xs_Lambert93, ys_Lambert93,
320 E, N);
321
322 double diff_h;
323 raf98.Interpol(Rad2Deg(lambda), Rad2Deg(phi), &diff_h);
324 h = he - diff_h;
325}
326
327/// Converts Lambert93 coordinates (East, North, Height) into geographical coordinates in radians (Longitude = Rad2Deg(lambda), Latitude = Rad2Deg(phi), Height)
328void Geodesy::Lambert93_2_Geographique(const Raf98& raf98, double E, double N, double h, double& lambda, double& phi, double& he)
329{
330 Geodesy::Proj2GeoLambert(
331 E, N,
332 n_Lambert93, c_Lambert93, e_Lambert93,
333 lambda0_Lambert93, xs_Lambert93, ys_Lambert93,
334 0.0000000000000001,
335 lambda, phi);
336
337 double diff_h;
338 raf98.Interpol(Rad2Deg(lambda), Rad2Deg(phi), &diff_h);
339 he = h + diff_h;
340}
341
342////////////////////////////////////////////////////////////////////////
343void Geodesy::Lambert93_2_Geographique(const Raf98& raf98, double E, double N, double h, Matrice in, double& lambda, double& phi, double& he, Matrice& out)
344{
345 Geodesy::Proj2GeoLambert(
346 E, N,
347 n_Lambert93, c_Lambert93, e_Lambert93,
348 lambda0_Lambert93, xs_Lambert93, ys_Lambert93,
349 0.0000000000000001,
350 lambda, phi);
351
352 Matrice passage;
353 double conv = Geodesy::ConvMerApp(lambda);
354 double c_ = cos(conv);
355 double s_ = sin(conv);
356
357 passage.c0_l0 = c_;
358 passage.c0_l1 = -s_;
359 passage.c0_l2 = 0.0;
360
361 passage.c1_l0 = s_;
362 passage.c1_l1 = c_;
363 passage.c1_l2 = 0.0;
364
365 passage.c2_l0 = 0.0;
366 passage.c2_l1 = 0.0;
367 passage.c2_l2 = 1.0;
368
369 out = ProdMat(passage, in);
370
371 double diff_h;
372 raf98.Interpol(Rad2Deg(lambda), Rad2Deg(phi), &diff_h);
373 he = h + diff_h;
374}
375
376////////////////////////////////////////////////////////////////////////
377void Geodesy::Geographique_2_ECEF(double longitude, double latitude, double he, double& x, double& y, double& z)
378{
379 const double n = GRS_a / sqrt(1.0 - pow(GRS_e, 2) * pow(sin(latitude), 2));
380 x = (n + he) * cos(latitude) * cos(longitude);
381 y = (n + he) * cos(latitude) * sin(longitude);
382 z = (n * (1.0 - pow(GRS_e, 2)) + he) * sin(latitude);
383}
384
385////////////////////////////////////////////////////////////////////////
386void Geodesy::ECEF_2_ENU(double x, double y, double z, double& e, double& n, double& u, double lon0, double lat0, double he0)
387{
388 double slat = sin(lat0);
389 double clat = cos(lat0);
390 double slon = sin(lon0);
391 double clon = cos(lon0);
392
393 Matrice C;
394 C.c0_l0 = -slon;
395 C.c1_l0 = clon;
396
397 C.c0_l1 = -clon * slat;
398 C.c1_l1 = -slon * slat;
399 C.c2_l1 = clat;
400
401 C.c0_l2 = clon * clat;
402 C.c1_l2 = slon * clat;
403 C.c2_l2 = slat;
404
405 double x0, y0, z0;
406 Geographique_2_ECEF(lon0, lat0, he0, x0, y0, z0);
407
408 x -= x0;
409 y -= y0;
410 z -= z0;
411
412 C.Apply(x, y, z, e, n, u);
413}
414
415QMatrix4x4 Geodesy::yprenuToMatrix(QVector3D angle, QVector3D position)
416{
417 float c1 = cos(angle.x());
418 float c2 = cos(angle.y());
419 float c3 = cos(angle.z());
420
421 float s1 = sin(angle.x());
422 float s2 = sin(angle.y());
423 float s3 = sin(angle.z());
424
425 // Source : https://en.wikipedia.org/wiki/Euler_angles
426 return QMatrix4x4(c1 * c2, c1 * s2 * s3 - c3 * s1, s1 * s3 + c1 * c3 * s2, position.x(),
427 c2 * s1, c1 * c3 + s1 * s2 * s3, c3 * s1 * s2 - c1 * s3, position.y(),
428 -s2, c2 * s3, c2 * c3, position.z(),
429 0, 0, 0, 1);
430}
Note: See TracBrowser for help on using the repository browser.