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

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

Geodesie: minor fixes.

  • Property svn:executable set to *
File size: 13.0 KB
RevLine 
[89]1// %pacpus:license{
2// This file is part of the PACPUS framework distributed under the
3// CECILL-C License, Version 1.0.
[208]4/// @author Marek Kurdej <firstname.surname@utc.fr>
[162]5/// @author Jean Laneurit <firstname.surname@utc.fr>
6/// @date April, 2010
[89]7// %pacpus:license}
8
9#include <Pacpus/PacpusTools/geodesie.h>
10
11#include <fstream>
12
[210]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;
[198]23
[89]24#ifdef _MSC_VER
[210]25#pragma warning(disable : 4244)
[89]26#endif //_MSC_VER
27
[209]28namespace Geodesy
[208]29{
30
[210]31////////////////////////////////////////////////////////////////////////////////
32Matrice::Matrice(const Matrice& A)
[208]33{
[210]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;
[89]43}
[208]44
[210]45////////////////////////////////////////////////////////////////////////////////
[208]46Matrice::Matrice()
47{
[210]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;
[89]57}
[208]58
[210]59////////////////////////////////////////////////////////////////////////////////
60void Matrice::Apply(double v0, double v1, double v2, double& Mv0, double& Mv1, double& Mv2)
[208]61{
[210]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;
[89]65}
[208]66
[210]67////////////////////////////////////////////////////////////////////////////////
68Matrice ProdMat(Matrice const& A, Matrice const& B)
[208]69{
[89]70 Matrice out;
71
[210]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;
[89]75
[210]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;
[89]79
[210]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;
[89]83 return out;
84}
85
[210]86////////////////////////////////////////////////////////////////////////////////
87Matrice TransMat(Matrice const& A)
[208]88{
[89]89 Matrice out;
[210]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;
[89]99 return out;
100}
101
[210]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;
[89]109}
110
[210]111void Write(Matrice const& A, ostream& out)
112{
113 out << A;
114}
115
116////////////////////////////////////////////////////////////////////////////////
117Raf98::Raf98()
118{
119}
120
121////////////////////////////////////////////////////////////////////////////////
122Raf98::~Raf98()
123{
[89]124 m_dvalues.clear();
125}
126
[210]127////////////////////////////////////////////////////////////////////////////////
128bool Raf98::Interpol(double longitude, double latitude, double* Hwgs84) const
129{
[89]130 *Hwgs84 = 0.0;
[210]131 if (m_dvalues.size() == 0) {
[89]132 return false;
[210]133 }
134 const double longitude_min = -5.5;
135 const double longitude_max = 8.5;
136 if (longitude < longitude_min) {
[89]137 return false;
[210]138 }
139 if (longitude > longitude_max) {
[89]140 return false;
[210]141 }
142 const double latitude_min = 42;
143 const double latitude_max = 51.5;
144 if (latitude < latitude_min) {
[89]145 return false;
[210]146 }
147 if (latitude > latitude_max) {
[89]148 return false;
[210]149 }
[89]150 //conversion en position
151 double longPix = (longitude - longitude_min) * 30.;
[210]152 double latPix = (latitude_max - latitude) * 40.;
[89]153
[210]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);
[89]163 *Hwgs84 = Zbd;
164
165 return true;
166}
[208]167
[210]168////////////////////////////////////////////////////////////////////////////////
169double Raf98::LitGrille(unsigned int c, unsigned int l) const
[208]170{
[210]171 const unsigned int w = 421;
[89]172 // const unsigned int h=381;
[210]173 return m_dvalues.at(c + l * w);
[89]174}
[208]175
[210]176////////////////////////////////////////////////////////////////////////////////
177bool Raf98::Load(const string& s)
[208]178{
[210]179 ifstream in(s.c_str());
[89]180 unsigned int w = 421;
181 unsigned int h = 381;
182
[210]183 m_dvalues.reserve(w * h);
[89]184
[210]185 char entete[1024]; //sur 3 lignes
186 in.getline(entete, 1023);
187 in.getline(entete, 1023);
188 in.getline(entete, 1023);
189
[89]190 char bidon[1024];
191 double val;
[210]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) {
[89]195 in >> val;
[210]196 m_dvalues.push_back(val);
[89]197 }
[210]198 in.getline(bidon, 1023);
[89]199 }
[210]200 for (unsigned int k = 0; k < 5; ++k) {
[89]201 in >> val;
[210]202 m_dvalues.push_back(val);
[89]203 }
[210]204 in.getline(bidon, 1023);
205 if (!in.good()) {
[89]206 m_dvalues.clear();
207 return false;
208 }
209 }
210 return in.good();
211}
212
[209]213} // namespace Geodesy
[89]214
[210]215////////////////////////////////////////////////////////////////////////////////
216////////////////////////////////////////////////////////////////////////////////
[89]217
[210]218////////////////////////////////////////////////////////////////////////////////
[89]219//ALGO0001
[209]220double Geodesy::LatitueIsometrique(double latitude, double e)
[208]221{
[210]222 double li = log(tan(pi<double>() / 4. + latitude / 2.)) + e * log((1 - e * sin(latitude)) / (1 + e * sin(latitude))) / 2;
[89]223 return li;
224}
225
[210]226////////////////////////////////////////////////////////////////////////////////
[89]227//ALGO0002
[210]228double Geodesy::LatitueIsometrique2Lat(double latitude_iso, double e, double epsilon)
[208]229{
230 double latitude_i = 2 * atan(exp(latitude_iso)) - half_pi<double>();
231 double latitude_ip1 = latitude_i + epsilon * 2;
[210]232 while (abs(latitude_i - latitude_ip1) > epsilon) {
[208]233 latitude_i = latitude_ip1;
234 latitude_ip1 = 2 * atan(
[210]235 exp(e * 0.5 * log(
236 (1 + e * sin(latitude_i)) / (1 - e * sin(latitude_i))))
237 * exp(latitude_iso)) - half_pi<double>();
[89]238 }
239 return latitude_ip1;
240}
[210]241
242////////////////////////////////////////////////////////////////////////////////
[209]243void Geodesy::Geo2ProjLambert(
[210]244 double lambda, double phi,
245 double n, double c, double e,
246 double lambdac, double xs, double ys,
247 double& X, double& Y)
[89]248{
[210]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));
[89]252}
[210]253
254////////////////////////////////////////////////////////////////////////////////
[89]255//ALGO0004
[209]256void Geodesy::Proj2GeoLambert(
[210]257 double X, double Y,
258 double n, double c, double e,
259 double lambdac, double xs, double ys,
[89]260 double epsilon,
[210]261 double& lambda, double& phi)
[89]262{
[210]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);
[89]270}
[210]271
272////////////////////////////////////////////////////////////////////////////////
273double Geodesy::ConvMerApp(double longitude)
274{
[89]275 double phi0_Lambert93 = Deg2Rad(46.5);
276 double lambda0_Lambert93 = Deg2Rad(3.0);
[210]277 double conv = -sin(phi0_Lambert93) * (longitude - lambda0_Lambert93);
278 return conv;
[89]279}
280
281////////////////////////////////////////////////////////////////////
[210]282void Geodesy::Geographique_2_Lambert93(const Raf98& raf98, double lambda, double phi, double he, Matrice in, double& E, double& N, double& h, Matrice& out)
[208]283{
[89]284 Matrice passage;
[210]285 double conv = Geodesy::ConvMerApp(lambda);
286 double c_ = cos(conv);
287 double s_ = sin(conv);
[89]288
289 passage.c0_l0 = c_;
290 passage.c0_l1 = s_;
[210]291 passage.c0_l2 = 0.0;
[89]292
293 passage.c1_l0 = -s_;
294 passage.c1_l1 = c_;
[210]295 passage.c1_l2 = 0.0;
[89]296
[210]297 passage.c2_l0 = 0.0;
298 passage.c2_l1 = 0.0;
299 passage.c2_l2 = 1.0;
300
301 out = ProdMat(passage, in);
[89]302 double diff_h;
[210]303 raf98.Interpol(Rad2Deg(lambda), Rad2Deg(phi), &diff_h);
304 h = he - diff_h;
305
[209]306 Geodesy::Geo2ProjLambert(
[210]307 lambda, phi,
308 n_Lambert93, c_Lambert93, e_Lambert93,
309 lambda0_Lambert93, xs_Lambert93, ys_Lambert93,
310 E, N);
[89]311}
[210]312
[89]313////////////////////////////////////////////////////////////////////////
[210]314void Geodesy::Geographique_2_Lambert93(const Raf98& raf98, double lambda, double phi, double he, double& E, double& N, double& h)
315{
[209]316 Geodesy::Geo2ProjLambert(
[210]317 lambda, phi,
318 n_Lambert93, c_Lambert93, e_Lambert93,
319 lambda0_Lambert93, xs_Lambert93, ys_Lambert93,
320 E, N);
[89]321
322 double diff_h;
[210]323 raf98.Interpol(Rad2Deg(lambda), Rad2Deg(phi), &diff_h);
324 h = he - diff_h;
[89]325}
[208]326
327/// Converts Lambert93 coordinates (East, North, Height) into geographical coordinates in radians (Longitude = Rad2Deg(lambda), Latitude = Rad2Deg(phi), Height)
[210]328void Geodesy::Lambert93_2_Geographique(const Raf98& raf98, double E, double N, double h, double& lambda, double& phi, double& he)
329{
[209]330 Geodesy::Proj2GeoLambert(
[210]331 E, N,
332 n_Lambert93, c_Lambert93, e_Lambert93,
333 lambda0_Lambert93, xs_Lambert93, ys_Lambert93,
334 0.0000000000000001,
335 lambda, phi);
[89]336
337 double diff_h;
[210]338 raf98.Interpol(Rad2Deg(lambda), Rad2Deg(phi), &diff_h);
339 he = h + diff_h;
[89]340}
[208]341
[89]342////////////////////////////////////////////////////////////////////////
[210]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{
[209]345 Geodesy::Proj2GeoLambert(
[210]346 E, N,
347 n_Lambert93, c_Lambert93, e_Lambert93,
348 lambda0_Lambert93, xs_Lambert93, ys_Lambert93,
349 0.0000000000000001,
350 lambda, phi);
[89]351
352 Matrice passage;
[210]353 double conv = Geodesy::ConvMerApp(lambda);
354 double c_ = cos(conv);
355 double s_ = sin(conv);
[89]356
357 passage.c0_l0 = c_;
358 passage.c0_l1 = -s_;
[210]359 passage.c0_l2 = 0.0;
[89]360
361 passage.c1_l0 = s_;
362 passage.c1_l1 = c_;
[210]363 passage.c1_l2 = 0.0;
[89]364
[210]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
[89]371 double diff_h;
[210]372 raf98.Interpol(Rad2Deg(lambda), Rad2Deg(phi), &diff_h);
373 he = h + diff_h;
[89]374}
375
376////////////////////////////////////////////////////////////////////////
[210]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));
[89]380 x = (n + he) * cos(latitude) * cos(longitude);
381 y = (n + he) * cos(latitude) * sin(longitude);
[210]382 z = (n * (1.0 - pow(GRS_e, 2)) + he) * sin(latitude);
[89]383}
384
385////////////////////////////////////////////////////////////////////////
[210]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);
[89]392
[210]393 Matrice C;
[89]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;
[210]406 Geographique_2_ECEF(lon0, lat0, he0, x0, y0, z0);
[89]407
408 x -= x0;
409 y -= y0;
410 z -= z0;
411
[210]412 C.Apply(x, y, z, e, n, u);
[89]413}
[99]414
[211]415//QMatrix4x4 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.