00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051 #include "cxutils/math/coordinates.h"
00052 #include "cxutils/math/cxmath.h"
00053 #include <iostream>
00054 #include <iomanip>
00055 #include <math.h>
00056 #include <cstdio>
00057 #include "cxutils/math/cxmath.h"
00058
00059 const double WGS_84_EQUATORIAL_RADIUS = 6378137;
00060 const double WGS_84_ECCENTRICITY = 0.081819190842622;
00061 const double WGS_84_ECCENTRICITY_SQ = 0.00669437999014;
00062 const double WGS_84_ECCENTRICITY_PRIME_SQ = 0.00673949674227510014704353279764;
00063 const double WGS_84_SEMI_MAJOR_AXIS = 6378137.0;
00064 const double WGS_84_SEMI_MINOR_AXIS = 6356752.314245;
00065 const double WGS_84_FLATTENING = 1.0/298.257223563;
00066 const double WGS_84_MAJOR_SQUARE = WGS_84_SEMI_MAJOR_AXIS * WGS_84_SEMI_MAJOR_AXIS;
00067 const double WGS_84_MINOR_SQUARE = WGS_84_SEMI_MINOR_AXIS * WGS_84_SEMI_MINOR_AXIS;
00068 const double WGS_84_ECCPRIME_SQUARE = (WGS_84_MAJOR_SQUARE - WGS_84_MINOR_SQUARE)/(WGS_84_MINOR_SQUARE);
00069 const double EARTH_AVG_RADIUS = 6371010;
00070
00071 void CxUtils::GccXyzToWgsHpr(const CxUtils::Gcc& gcc,
00072 const CxUtils::Point3D& xyz,
00073 CxUtils::Wgs& wgs,
00074 CxUtils::Point3D& hpr)
00075 {
00076 Vector3D n0, e0, d0;
00077 Vector3D n1, e1, d1;
00078 Vector3D n, e, d;
00079 Vector3D x0, y0, z0;
00080 Vector3D x1, y1, z1;
00081 Vector3D x2, y2, z2;
00082 Vector3D x3, y3, z3;
00083 double w, a;
00084 Quaternion q;
00085
00086
00087
00088 wgs << gcc;
00089
00090
00091
00093
00094
00095 n0(0, 0, 1);
00096 e0(0, 1, 0);
00097 d0(-1, 0, 0);
00098
00099
00100
00101
00102 w = CX_DEG2RAD(wgs.mLongitude);
00103 a = CX_DEG2RAD(wgs.mLatitude);
00104
00105
00106
00107 q.CreateRotation( n0, w );
00108 n1 = n0;
00109 e1 = q.Rotate(e0);
00110 d1 = q.Rotate(d0);
00111
00112
00113
00114 q.CreateRotation( e1*-1, a );
00115 n = q.Rotate( n1 );
00116 e = e1;
00117 d = q.Rotate( d1 );
00118
00119
00120
00121 x0( 1, 0, 0 );
00122 y0( 0, 1, 0 );
00123 z0( 0, 0, 1 );
00124
00125
00126
00127
00128 q.CreateRotation( z0, xyz.mX );
00129 x1 = q.Rotate( x0 );
00130 y1 = q.Rotate( y0 );
00131 z1 = q.Rotate( z0 );
00132
00133
00134
00135 q.CreateRotation(y1, xyz.mY );
00136 x2 = q.Rotate( x1 );
00137 y2 = q.Rotate( y1 );
00138 z2 = q.Rotate( z1 );
00139
00140
00141 q.CreateRotation(x2, xyz.mZ );
00142 x3 = q.Rotate( x2 );
00143 y3 = q.Rotate( y2 );
00144 z3 = q.Rotate( z2 );
00145
00146
00147
00148
00149
00150 x0 = n;
00151 y0 = e;
00152 z0 = d;
00153
00154 hpr.mX = atan2( x3.Dot(y0), x3.Dot( x0 ) );
00155 hpr.mY = atan2( -1*(x3.Dot(z0)),
00156 sqrt( ( (x3.Dot(x0)) * (x3.Dot(x0)) ) +
00157 ( (x3.Dot(y0)) * (x3.Dot(y0)) )
00158 )
00159 );
00160 q.CreateRotation(z0, hpr.mX);
00161 y2 = y1 = q.Rotate(y0);
00162 q.CreateRotation(y1, hpr.mY);
00163 z2 = q.Rotate(z0);
00164 hpr.mZ = atan2( y3.Dot(z2), y3.Dot(y2) );
00165 }
00166
00167
00168 void CxUtils::WgsHprToGccXyz(const CxUtils::Wgs& wgs,
00169 const CxUtils::Point3D& hpr,
00170 CxUtils::Gcc& gcc,
00171 CxUtils::Point3D& xyz)
00172 {
00173 Vector3D n0, e0, d0;
00174 Vector3D n1, e1, d1;
00175 Vector3D n, e, d;
00176 Vector3D x0, y0, z0;
00177 Vector3D x1, y1, z1;
00178 Vector3D x2, y2, z2;
00179 Vector3D x3, y3, z3;
00180 Quaternion q;
00181 double w, a;
00182
00183
00184
00185 wgs >> gcc;
00186
00187
00188
00189 n0(0, 0, 1);
00190 e0(0, 1, 0);
00191 d0(-1, 0, 0);
00192
00193 w = CX_DEG2RAD(wgs.mLongitude);
00194 a = CX_DEG2RAD(wgs.mLatitude);
00195
00196
00197
00198 q.CreateRotation( n0, w );
00199 n1 = n0;
00200 e1 = q.Rotate(e0);
00201 d1 = q.Rotate(d0);
00202
00203
00204
00205 q.CreateRotation( e1*-1, a );
00206 n = q.Rotate( n1 );
00207 e = e1;
00208 d = q.Rotate( d1 );
00209
00210
00211
00212
00213 x0 = n;
00214 y0 = e;
00215 z0 = d;
00216
00217
00218
00219
00220 q.CreateRotation( z0, hpr.mX );
00221 x1 = q.Rotate( x0 );
00222 y1 = q.Rotate( y0 );
00223 z1 = q.Rotate( z0 );
00224
00225
00226
00227 q.CreateRotation(y1, hpr.mY );
00228 x2 = q.Rotate( x1 );
00229 y2 = q.Rotate( y1 );
00230 z2 = q.Rotate( z1 );
00231
00232
00233 q.CreateRotation(x2, hpr.mZ );
00234 x3 = q.Rotate( x2 );
00235 y3 = q.Rotate( y2 );
00236 z3 = q.Rotate( z2 );
00237
00238
00239
00240
00241 x0( 1, 0, 0 );
00242 y0( 0, 1, 0 );
00243 z0( 0, 0, 1 );
00244
00245 xyz.mX = atan2( x3.Dot(y0), x3.Dot( x0 ) );
00246 xyz.mY = atan2( -1*(x3.Dot(z0)),
00247 sqrt( ( (x3.Dot(x0)) * (x3.Dot(x0)) ) +
00248 ( (x3.Dot(y0)) * (x3.Dot(y0)) )
00249 )
00250 );
00251 q.CreateRotation(z0, xyz.mX);
00252 y2 = y1 = q.Rotate(y0);
00253 q.CreateRotation(y1, xyz.mY);
00254 z2 = q.Rotate(z0);
00255 xyz.mZ = atan2( y3.Dot(z2), y3.Dot(y2) );
00256 }
00257
00258
00259 void CxUtils::WgsHprToGccXyz(const CxUtils::Wgs& wgs,
00260 const CxUtils::Point3D& hpr,
00261 CxUtils::Point3D& xyz)
00262 {
00263 Vector3D n0, e0, d0;
00264 Vector3D n1, e1, d1;
00265 Vector3D n, e, d;
00266 Vector3D x0, y0, z0;
00267 Vector3D x1, y1, z1;
00268 Vector3D x2, y2, z2;
00269 Vector3D x3, y3, z3;
00270 Quaternion q;
00271 double w, a;
00272
00273
00274
00275
00276
00277
00278
00279 n0(0, 0, 1);
00280 e0(0, 1, 0);
00281 d0(-1, 0, 0);
00282
00283 w = CX_DEG2RAD(wgs.mLongitude);
00284 a = CX_DEG2RAD(wgs.mLatitude);
00285
00286
00287
00288 q.CreateRotation( n0, w );
00289 n1 = n0;
00290 e1 = q.Rotate(e0);
00291 d1 = q.Rotate(d0);
00292
00293
00294
00295 q.CreateRotation( e1*-1, a );
00296 n = q.Rotate( n1 );
00297 e = e1;
00298 d = q.Rotate( d1 );
00299
00300
00301
00302
00303 x0 = n;
00304 y0 = e;
00305 z0 = d;
00306
00307
00308
00309
00310 q.CreateRotation( z0, hpr.mX );
00311 x1 = q.Rotate( x0 );
00312 y1 = q.Rotate( y0 );
00313 z1 = q.Rotate( z0 );
00314
00315
00316
00317 q.CreateRotation(y1, hpr.mY );
00318 x2 = q.Rotate( x1 );
00319 y2 = q.Rotate( y1 );
00320 z2 = q.Rotate( z1 );
00321
00322
00323 q.CreateRotation(x2, hpr.mZ );
00324 x3 = q.Rotate( x2 );
00325 y3 = q.Rotate( y2 );
00326 z3 = q.Rotate( z2 );
00327
00328
00329
00330
00331 x0( 1, 0, 0 );
00332 y0( 0, 1, 0 );
00333 z0( 0, 0, 1 );
00334
00335 xyz.mX = atan2( x3.Dot(y0), x3.Dot( x0 ) );
00336 xyz.mY = atan2( -1*(x3.Dot(z0)),
00337 sqrt( ( (x3.Dot(x0)) * (x3.Dot(x0)) ) +
00338 ( (x3.Dot(y0)) * (x3.Dot(y0)) )
00339 )
00340 );
00341 q.CreateRotation(z0, xyz.mX);
00342 y2 = y1 = q.Rotate(y0);
00343 q.CreateRotation(y1, xyz.mY);
00344 z2 = q.Rotate(z0);
00345 xyz.mZ = atan2( y3.Dot(z2), y3.Dot(y2) );
00346 }
00347
00348
00349 using namespace CxUtils;
00350
00351
00357 Wgs::Wgs()
00358 {
00359 mLatitude = mLongitude = mElevation = 0;
00360 }
00361
00362
00368 Wgs::Wgs(const Wgs& wgs)
00369 {
00370 Set(wgs.mLatitude, wgs.mLongitude, wgs.mElevation);
00371 }
00372
00373
00379 Wgs::Wgs(const Utm& utm)
00380 {
00381 mLatitude = mLongitude = mElevation = 0;
00382 *this << utm;
00383 }
00384
00385
00394 Wgs::Wgs(const double latitude, const double longitude)
00395 {
00396 Set(latitude, longitude, 0.0);
00397 }
00398
00408 Wgs::Wgs(const double latitude, const double longitude, const double elevation)
00409 {
00410 Set(latitude, longitude, elevation);
00411 }
00412
00413
00414
00425 int Wgs::Set(const double latitude, const double longitude)
00426 {
00427 if( latitude >= -90.0 && latitude <= 90.0 &&
00428 longitude >= -180.0 && longitude <= 180.0 )
00429 {
00430 mLatitude = latitude;
00431 mLongitude = longitude;
00432 return 1;
00433 }
00434
00435 return 0;
00436 }
00437
00438
00450 int Wgs::Set(const double latitude, const double longitude, const double elevation)
00451 {
00452 if( latitude >= -90.0 && latitude <= 90.0 &&
00453 longitude >= -180.0 && longitude <= 180.0 &&
00454 elevation >= -10000 && elevation <= 35000)
00455 {
00456 mLatitude = latitude;
00457 mLongitude = longitude;
00458 mElevation = elevation;
00459 return 1;
00460 }
00461
00462 return 0;
00463 }
00464
00465
00481 int Wgs::Set(const double latDeg, const double latMin, const double latSec,
00482 const double lonDeg, const double lonMin, const double lonSec)
00483 {
00484 double lat;
00485 double lon;
00486 if(latDeg < 0)
00487 {
00488 lat = latDeg - latMin/60.0 - latSec/3600.0;
00489 }
00490 else
00491 {
00492 lat = latDeg + latMin/60.0 + latSec/3600.0;
00493 }
00494 if(lonDeg < 0)
00495 {
00496 lon = lonDeg - lonMin/60.0 - lonSec/3600.0;
00497 }
00498 else
00499 {
00500 lon = lonDeg + lonMin/60.0 + lonSec/3600.0;
00501 }
00502
00503 return Set(lat, lon);
00504 }
00505
00506
00523 int Wgs::Set(const double latDeg, const double latMin, const double latSec,
00524 const double lonDeg, const double lonMin, const double lonSec,
00525 const double elevation)
00526 {
00527 double lat;
00528 double lon;
00529 if(latDeg < 0)
00530 {
00531 lat = latDeg - latMin/60.0 - latSec/3600.0;
00532 }
00533 else
00534 {
00535 lat = latDeg + latMin/60.0 + latSec/3600.0;
00536 }
00537 if(lonDeg < 0)
00538 {
00539 lon = lonDeg - lonMin/60.0 - lonSec/3600.0;
00540 }
00541 else
00542 {
00543 lon = lonDeg + lonMin/60.0 + lonSec/3600.0;
00544 }
00545
00546 return Set(lat, lon, elevation);
00547 }
00548
00549
00560 int Wgs::Get(double& latitude, double& longitude) const
00561 {
00562 latitude = mLatitude;
00563 longitude = mLongitude;
00564 return 1;
00565 }
00566
00567
00579 int Wgs::Get(double& latitude, double& longitude, double &elevation) const
00580 {
00581 latitude = mLatitude;
00582 longitude = mLongitude;
00583 elevation = mElevation;
00584 return 1;
00585 }
00586
00587
00603 int Wgs::Get(double& latDeg, double& latMin, double& latSec,
00604 double& lonDeg, double& lonMin, double& lonSec,
00605 double &elevation) const
00606 {
00607 latDeg = (double)((int)(mLatitude));
00608 latMin = 60.0*(mLatitude - latDeg);
00609 if(latMin < 0)
00610 latMin *= -1.0;
00611 latSec = 60.0*(latMin - ( (int)(latMin) ));
00612 latMin = (double)((int)(latMin));
00613
00614 lonDeg = (double)((int)(mLongitude));
00615 lonMin = 60.0*(mLongitude - lonDeg);
00616 if(lonMin < 0)
00617 lonMin *= -1.0;
00618 lonSec = 60.0*(lonMin - ( (int)(lonMin) ));
00619 lonMin = (double)((int)(lonMin));
00620
00621 elevation = mElevation;
00622 return 1;
00623 }
00624
00625
00631 void Wgs::Print() const
00632 {
00633 std::cout << "WGS - Latitude: " << std::setprecision(8) << mLatitude << " Longitude: " << std::setprecision(8) << mLongitude << " Elevation: " << std::setprecision(8) << mElevation << std::endl;
00634 }
00635
00636
00647 std::string Wgs::ToString(const bool degreesMinutesFlag) const
00648 {
00649 char buffer[256];
00650 if(degreesMinutesFlag)
00651 {
00652 double latDeg, latMin, latSec;
00653 double lonDeg, lonMin, lonSec;
00654 double elevation;
00655 Get(latDeg, latMin, latSec, lonDeg, lonMin, lonSec, elevation);
00656 sprintf(buffer, "Latitude: %d.%d.%d, Longitude: %d.%d.%d, Elevation: %lf", (int)latDeg, (int)latMin, (int)latSec, (int)lonDeg, (int)lonMin, (int)lonSec, elevation);
00657 }
00658 else
00659 {
00660 sprintf(buffer, "Latitude: %lf, Longitude: %lf, Elevation: %lf", mLatitude, mLongitude, mElevation);
00661 }
00662 return std::string(buffer);
00663 }
00664
00665
00666
00677 double Wgs::GreatCircleDistance(const Wgs& p1, const Wgs& p2)
00678 {
00679 Wgs rad1(CX_DEG2RAD(p1.mLatitude), CX_DEG2RAD(p1.mLongitude), p1.mElevation);
00680 Wgs rad2(CX_DEG2RAD(p2.mLatitude), CX_DEG2RAD(p2.mLongitude), p2.mElevation);
00681 double deltaSigma = 0.0;
00682
00683 double lonDelta = rad1.mLongitude - rad2.mLongitude;
00684 deltaSigma = atan2( sqrt( pow( cos(rad2.mLatitude) * sin(lonDelta), 2.0) +
00685 pow( cos(rad1.mLatitude) * sin(rad2.mLatitude) - sin(rad1.mLatitude) * cos(rad2.mLatitude) * cos(lonDelta), 2.0) ),
00686 sin( rad1.mLatitude) * sin(rad2.mLatitude) + cos(rad1.mLatitude) * cos(rad2.mLatitude) * cos(lonDelta));
00687 return EARTH_AVG_RADIUS*deltaSigma;
00688 }
00689
00690
00700 Wgs& Wgs::operator()(const double lat, const double lon, const double elev)
00701 {
00702 Set(lat, lon, elev);
00703 return *this;
00704 }
00705
00711 Wgs& Wgs::operator=(const Wgs& wgs)
00712 {
00713 mLatitude = wgs.mLatitude;
00714 mLongitude = wgs.mLongitude;
00715 mElevation = wgs.mElevation;
00716
00717 return *this;
00718 }
00719
00720
00727 Wgs& Wgs::operator<<(const Utm& utm)
00728 {
00729 double k0 = 0.9996;
00730 double a = WGS_84_EQUATORIAL_RADIUS;
00731 double e1 = (1 - sqrt(1.0 - WGS_84_ECCENTRICITY_SQ))/(1 + sqrt(1 - WGS_84_ECCENTRICITY_SQ));
00732 double N1, T1, C1, R1, D, M;
00733 double longOrigin;
00734 double mu, phi1, phi1Rad;
00735 double x, y;
00736 int northernHemisphere;
00737
00738 x = utm.mEasting - 500000.0;
00739 y = utm.mNorthing;
00740
00741 if(utm.mZoneLetter - 'N' >= 0)
00742 northernHemisphere = 1;
00743 else {
00744 northernHemisphere = 0;
00745 y -= 10000000.0;
00746 }
00747
00748 longOrigin = (utm.mZoneNumber - 1)*6 - 180.0 + 3;
00749
00750 M = y / k0;
00751 mu = M/(a*(1-WGS_84_ECCENTRICITY_SQ/4-3*WGS_84_ECCENTRICITY_SQ*WGS_84_ECCENTRICITY_SQ/64-5*WGS_84_ECCENTRICITY_SQ*WGS_84_ECCENTRICITY_SQ*WGS_84_ECCENTRICITY_SQ/256));
00752
00753 phi1Rad = mu + (3*e1/2-27*e1*e1*e1/32)*sin(2*mu)
00754 + (21*e1*e1/16-55*e1*e1*e1*e1/32)*sin(4*mu)
00755 +(151*e1*e1*e1/96)*sin(6*mu);
00756 phi1 = CX_RAD2DEG(phi1Rad);
00757
00758 N1 = a/sqrt(1-WGS_84_ECCENTRICITY_SQ*sin(phi1Rad)*sin(phi1Rad));
00759 T1 = tan(phi1Rad)*tan(phi1Rad);
00760 C1 = WGS_84_ECCENTRICITY_PRIME_SQ*cos(phi1Rad)*cos(phi1Rad);
00761 R1 = a*(1-WGS_84_ECCENTRICITY_SQ)/pow(1-WGS_84_ECCENTRICITY_SQ*sin(phi1Rad)*sin(phi1Rad), 1.5);
00762 D = x/(N1*k0);
00763
00764 this->mLatitude = phi1Rad - (N1*tan(phi1Rad)/R1)*(D*D/2-(5+3*T1+10*C1-4*C1*C1-9*WGS_84_ECCENTRICITY_PRIME_SQ)*D*D*D*D/24
00765 +(61+90*T1+298*C1+45*T1*T1-252*WGS_84_ECCENTRICITY_PRIME_SQ-3*C1*C1)*D*D*D*D*D*D/720);
00766 this->mLatitude = CX_RAD2DEG(this->mLatitude);
00767
00768 this->mLongitude = (D-(1+2*T1+C1)*D*D*D/6+(5-2*C1+28*T1-3*C1*C1+8*WGS_84_ECCENTRICITY_PRIME_SQ+24*T1*T1)
00769 *D*D*D*D*D/120)/cos(phi1Rad);
00770 this->mLongitude = longOrigin + CX_RAD2DEG(this->mLongitude);
00771 this->mElevation = utm.mElevation;
00772
00773 return *this;
00774 }
00775
00776
00783 Wgs& Wgs::operator<<(const Gcc& gcc)
00784 {
00785 double p = sqrt(gcc.mX * gcc.mX + gcc.mY * gcc.mY);
00786 double n1 = gcc.mZ*WGS_84_SEMI_MAJOR_AXIS;
00787 double d1 = p*WGS_84_SEMI_MINOR_AXIS;
00788
00789 double m = sqrt(n1*n1 + d1*d1);
00790 n1 /= m;
00791 d1 /= m;
00792
00793 double n2 = gcc.mZ + + WGS_84_ECCPRIME_SQUARE*WGS_84_SEMI_MINOR_AXIS * n1 * n1 * n1;
00794 double d2 = p - WGS_84_ECCENTRICITY_SQ*WGS_84_SEMI_MAJOR_AXIS * d1 * d1 * d1;
00795
00796 m = sqrt(n2 * n2 + d2 * d2);
00797 n2 /= m;
00798 d2 /= m;
00799
00800 mLatitude = atan2(n2, d2);
00801 mLongitude = atan2(gcc.mY, gcc.mX);
00802 mElevation = p / d2 - WGS_84_SEMI_MAJOR_AXIS / sqrt(1.0 - WGS_84_ECCENTRICITY_SQ * n2 * n2);
00803
00804 mLatitude = CX_RAD2DEG(mLatitude);
00805 mLongitude = CX_RAD2DEG(mLongitude);
00806
00807 if(CX_ISNAN(mElevation))
00808 mElevation = 0;
00809
00810 return *this;
00811 }
00812
00813
00819 void Wgs::operator>>(Utm& utm) const
00820 {
00821 double a = WGS_84_EQUATORIAL_RADIUS;
00822 double k0 = 0.9996;
00823 double longOrigin;
00824 double N, T, C, A, M;
00825 double latRad = CX_DEG2RAD(this->mLatitude);
00826 double longRad = CX_DEG2RAD(this->mLongitude);
00827 double longOriginRad = 0.0;
00828
00829 utm.mZoneNumber = (int)( (this->mLongitude + 180.0)/6.0 + 1 );
00830 if( this->mLatitude >= 56.0 && this->mLatitude < 64.0 && this->mLongitude >= 3.0 && this->mLongitude < 12.0 )
00831 utm.mZoneNumber = 32;
00832
00833 longOrigin = (utm.mZoneNumber - 1)*6 - 180.0 + 3;
00834 longOriginRad = CX_DEG2RAD(longOrigin);
00835
00836 if((84 >= this->mLatitude) && (this->mLatitude >= 72)) utm.mZoneLetter = 'X';
00837 else if((72 > this->mLatitude) && (this->mLatitude >= 64)) utm.mZoneLetter = 'W';
00838 else if((64 > this->mLatitude) && (this->mLatitude >= 56)) utm.mZoneLetter = 'V';
00839 else if((56 > this->mLatitude) && (this->mLatitude >= 48)) utm.mZoneLetter = 'U';
00840 else if((48 > this->mLatitude) && (this->mLatitude >= 40)) utm.mZoneLetter = 'T';
00841 else if((40 > this->mLatitude) && (this->mLatitude >= 32)) utm.mZoneLetter = 'S';
00842 else if((32 > this->mLatitude) && (this->mLatitude >= 24)) utm.mZoneLetter = 'R';
00843 else if((24 > this->mLatitude) && (this->mLatitude >= 16)) utm.mZoneLetter = 'Q';
00844 else if((16 > this->mLatitude) && (this->mLatitude >= 8)) utm.mZoneLetter = 'P';
00845 else if(( 8 > this->mLatitude) && (this->mLatitude >= 0)) utm.mZoneLetter = 'N';
00846 else if(( 0 > this->mLatitude) && (this->mLatitude >= -8)) utm.mZoneLetter = 'M';
00847 else if((-8> this->mLatitude) && (this->mLatitude >= -16)) utm.mZoneLetter = 'L';
00848 else if((-16 > this->mLatitude) && (this->mLatitude >= -24)) utm.mZoneLetter = 'K';
00849 else if((-24 > this->mLatitude) && (this->mLatitude >= -32)) utm.mZoneLetter = 'J';
00850 else if((-32 > this->mLatitude) && (this->mLatitude >= -40)) utm.mZoneLetter = 'H';
00851 else if((-40 > this->mLatitude) && (this->mLatitude >= -48)) utm.mZoneLetter = 'G';
00852 else if((-48 > this->mLatitude) && (this->mLatitude >= -56)) utm.mZoneLetter = 'F';
00853 else if((-56 > this->mLatitude) && (this->mLatitude >= -64)) utm.mZoneLetter = 'E';
00854 else if((-64 > this->mLatitude) && (this->mLatitude >= -72)) utm.mZoneLetter = 'D';
00855 else if((-72 > this->mLatitude) && (this->mLatitude >= -80)) utm.mZoneLetter = 'C';
00856 else utm.mZoneLetter = 'Z';
00857
00858 N = a/sqrt(1-WGS_84_ECCENTRICITY_SQ*sin(latRad)*sin(latRad));
00859 T = tan(latRad)*tan(latRad);
00860 C = WGS_84_ECCENTRICITY_PRIME_SQ*cos(latRad)*cos(latRad);
00861 A = cos(latRad)*(longRad-longOriginRad);
00862
00863 M = a*((1 - WGS_84_ECCENTRICITY_SQ/4 - 3*WGS_84_ECCENTRICITY_SQ*WGS_84_ECCENTRICITY_SQ/64 - 5*WGS_84_ECCENTRICITY_SQ*WGS_84_ECCENTRICITY_SQ*WGS_84_ECCENTRICITY_SQ/256)*latRad
00864 - (3*WGS_84_ECCENTRICITY_SQ/8 + 3*WGS_84_ECCENTRICITY_SQ*WGS_84_ECCENTRICITY_SQ/32 + 45*WGS_84_ECCENTRICITY_SQ*WGS_84_ECCENTRICITY_SQ*WGS_84_ECCENTRICITY_SQ/1024)*sin(2*latRad)
00865 + (15*WGS_84_ECCENTRICITY_SQ*WGS_84_ECCENTRICITY_SQ/256 + 45*WGS_84_ECCENTRICITY_SQ*WGS_84_ECCENTRICITY_SQ*WGS_84_ECCENTRICITY_SQ/1024)*sin(4*latRad)
00866 - (35*WGS_84_ECCENTRICITY_SQ*WGS_84_ECCENTRICITY_SQ*WGS_84_ECCENTRICITY_SQ/3072)*sin(6*latRad));
00867
00868 utm.mEasting = (double)(k0*N*(A+(1-T+C)*A*A*A/6
00869 + (5-18*T+T*T+72*C-58*WGS_84_ECCENTRICITY_PRIME_SQ)*A*A*A*A*A/120)
00870 + 500000.0);
00871
00872 utm.mNorthing = (double)(k0*(M+N*tan(latRad)*(A*A/2+(5-T+9*C+4*C*C)*A*A*A*A/24
00873 + (61-58*T+T*T+600*C-330*WGS_84_ECCENTRICITY_PRIME_SQ)*A*A*A*A*A*A/720)));
00874 if(this->mLatitude < 0)
00875 utm.mNorthing += 10000000.0;
00876
00877 utm.mElevation = this->mElevation;
00878 }
00879
00880
00886 void Wgs::operator>>(Gcc& gcc) const
00887 {
00888 double latRad, lonRad;
00889 double sinTheta, cosTheta;
00890 latRad = CX_DEG2RAD(this->mLatitude);
00891 lonRad = CX_DEG2RAD(this->mLongitude);
00892 sinTheta = sin(latRad);
00893 cosTheta = cos(latRad);
00894 double n = WGS_84_SEMI_MAJOR_AXIS/sqrt(1.0 - WGS_84_ECCENTRICITY_SQ*sinTheta*sinTheta);
00895
00896 gcc.mX = gcc.mY = (n + mElevation)*cosTheta;
00897 gcc.mX *= cos(lonRad);
00898 gcc.mY *= sin(lonRad);
00899 gcc.mZ = (n * (1.0 - WGS_84_ECCENTRICITY_SQ) + mElevation) * sinTheta;
00900 }
00901
00907 bool Wgs::operator==(const Wgs& wgs) const
00908 {
00909 if( fabs( mLatitude - wgs.mLatitude ) < .000001 &&
00910 fabs( mLongitude - wgs.mLongitude) < .000001 &&
00911 fabs( mElevation - wgs.mElevation) < .000001 )
00912 {
00913 return true;
00914 }
00915 return false;
00916 }
00917
00918
00924 Utm::Utm()
00925 {
00926 mZoneNumber = mZoneLetter = 0;
00927 mNorthing = mEasting = mElevation = 0.0;
00928 }
00929
00930
00936 Utm::Utm(const Utm& utm)
00937 {
00938 mNorthing = utm.mNorthing;
00939 mEasting = utm.mEasting;
00940 mZoneNumber = utm.mZoneNumber;
00941 mZoneLetter = utm.mZoneLetter;
00942 mElevation = utm.mElevation;
00943 }
00944
00945
00951 Utm::Utm(const Wgs& wgs)
00952 {
00953 mZoneNumber = mZoneLetter = 0;
00954 mNorthing = mEasting = mElevation = 0.0;
00955 *this << wgs;
00956 }
00957
00958
00969 Utm::Utm(const double northing, const double easting,
00970 const int zoneNumber, const int zoneLetter)
00971 {
00972 mNorthing = northing;
00973 mEasting = easting;
00974 mZoneNumber = zoneNumber;
00975 mZoneLetter = zoneLetter;
00976 }
00977
00978
00991 int Utm::Set(const double northing, const double easting,
00992 const int zoneNumber, const int zoneLetter)
00993 {
00994 mNorthing = northing;
00995 mEasting = easting;
00996 mZoneNumber = zoneNumber;
00997 mZoneLetter = zoneLetter;
00998 return 1;
00999 }
01000
01001
01015 int Utm::Set(const double northing, const double easting,
01016 const int zoneNumber, const int zoneLetter,
01017 const double elevation)
01018 {
01019 mNorthing = northing;
01020 mEasting = easting;
01021 mZoneNumber = zoneNumber;
01022 mZoneLetter = zoneLetter;
01023 mElevation = elevation;
01024
01025 return 1;
01026 }
01027
01028
01041 int Utm::Get(double& northing, double& easting,
01042 int& zoneNumber, int& zoneLetter) const
01043 {
01044 northing = mNorthing;
01045 easting = mEasting;
01046 zoneNumber = mZoneNumber;
01047 zoneLetter = mZoneLetter;
01048 return 1;
01049 }
01050
01051
01065 int Utm::Get(double& northing, double& easting,
01066 int& zoneNumber, int& zoneLetter,
01067 double &elevation) const
01068 {
01069 northing = mNorthing;
01070 easting = mEasting;
01071 zoneNumber = mZoneNumber;
01072 zoneLetter = mZoneLetter;
01073 elevation = mElevation;
01074 return 1;
01075 }
01076
01082 void Utm::Print() const
01083 {
01084 std::cout << "UTM - Northing: " << mNorthing << " Easting: " << mEasting << " " << mZoneNumber << (char)mZoneLetter << " Elevation: " << mElevation << std::endl;
01085 }
01086
01087
01088
01094 double Utm::Distance(const Utm& utm1, const Utm& utm2)
01095 {
01096 if(utm1.mZoneNumber != utm2.mZoneNumber ||
01097 utm1.mZoneLetter != utm2.mZoneLetter)
01098 {
01099
01100
01101
01102
01103 Wgs wgs1;
01104 Wgs wgs2;
01105 wgs1 << utm1;
01106 wgs2 << utm2;
01107 return Wgs::GreatCircleDistance(wgs1, wgs2);
01108 }
01109 else
01110 {
01111 return sqrt( pow(utm1.mEasting - utm2.mEasting, 2.0) +
01112 pow(utm1.mNorthing - utm2.mNorthing, 2.0) +
01113 pow(utm1.mElevation - utm2.mElevation, 2.0) );
01114 }
01115 }
01116
01122 Utm& Utm::operator=(const Utm& utm)
01123 {
01124 mNorthing = utm.mNorthing;
01125 mEasting = utm.mEasting;
01126 mZoneNumber = utm.mZoneNumber;
01127 mZoneLetter = utm.mZoneLetter;
01128 mElevation = utm.mElevation;
01129 return *this;
01130 }
01131
01132
01139 Utm& Utm::operator<<(const Wgs& wgs)
01140 {
01141 wgs >> *this;
01142 return *this;
01143 }
01144
01145
01152 Utm& Utm::operator<<(const Gcc& gcc)
01153 {
01154 Wgs wgs;
01155 wgs << gcc;
01156 wgs >> *this;
01157 return *this;
01158 }
01159
01160
01166 void Utm::operator>>(Wgs& wgs) const
01167 {
01168 wgs << *this;
01169 }
01170
01171
01177 void Utm::operator>>(Gcc& gcc) const
01178 {
01179 Wgs wgs;
01180 wgs << *this;
01181 wgs >> gcc;
01182 }
01183
01184
01190 bool Utm::operator==(const Utm& utm) const
01191 {
01192 if( mZoneLetter == utm.mZoneLetter &&
01193 mZoneNumber == utm.mZoneNumber &&
01194 fabs( mNorthing - utm.mNorthing ) < .000001 &&
01195 fabs( mEasting - utm.mEasting) < .000001 &&
01196 fabs( mElevation - utm.mElevation) < .000001 )
01197 {
01198 return true;
01199 }
01200 return false;
01201 }
01202
01208 Gcc::Gcc()
01209 {
01210 mX = mY = mZ = 0.0;
01211 }
01212
01213
01219 Gcc::Gcc(const Gcc& gcc) : Point3D(gcc.mX, gcc.mY, gcc.mZ)
01220 {
01221 }
01222
01223
01233 Gcc::Gcc(const double x, const double y, const double z)
01234 {
01235 mX = x; mY = y; mZ = z;
01236 }
01237
01238
01244 void Gcc::Print() const
01245 {
01246 std::cout << "GCC - X: " << mX << " Y: " << mY << " Z: " << mZ << std::endl;
01247 }
01248
01249
01257 double Gcc::GetMagnitude() const
01258 {
01259 return sqrt(mX*mX + mY*mY + mZ*mZ);
01260 }
01261
01262
01268 Gcc& Gcc::operator=(const Point3D& p3d)
01269 {
01270 mX = p3d.mX;
01271 mY = p3d.mY;
01272 mZ = p3d.mZ;
01273 return *this;
01274 }
01275
01276
01282 Gcc& Gcc::operator=(const Gcc& gcc)
01283 {
01284 mX = gcc.mX;
01285 mY = gcc.mY;
01286 mZ = gcc.mZ;
01287 return *this;
01288 }
01289
01290
01297 Gcc& Gcc::operator<<(const Wgs& wgs)
01298 {
01299 wgs >> *this;
01300 return *this;
01301 }
01302
01303
01310 Gcc& Gcc::operator<<(const Utm& utm)
01311 {
01312 Wgs wgs;
01313 wgs << utm;
01314 wgs >> *this;
01315 return *this;
01316 }
01317
01318
01324 void Gcc::operator>>(Wgs& wgs) const
01325 {
01326 wgs << *this;
01327 }
01328
01329
01335 void Gcc::operator>>(Utm& utm) const
01336 {
01337 Wgs wgs;
01338 wgs << *this;
01339 wgs >> utm;
01340 }
01341
01342
01348 bool Gcc::operator==(const Gcc& gcc) const
01349 {
01350 if( fabs( mX - gcc.mX ) < .000001 &&
01351 fabs( mY - gcc.mY ) < .000001 &&
01352 fabs( mZ - gcc.mZ ) < .000001 )
01353 {
01354 return true;
01355 }
01356 return false;
01357 }
01358
01359
01372 double Orientation::AngleDiff(const double angleSrc,
01373 const double angleDest,
01374 const bool radiansFlag)
01375 {
01376 double diff = angleDest - angleSrc;
01377
01378 if(radiansFlag)
01379 {
01380 while(diff > CX_PI)
01381 {
01382 diff -= CX_TWO_PI;
01383 }
01384 while(diff <= -CX_PI)
01385 {
01386 diff += CX_TWO_PI;
01387 }
01388 }
01389 else
01390 {
01391 while(diff > 180.0)
01392 {
01393 diff -= 360.0;
01394 }
01395 while(diff <= -180.0)
01396 {
01397 diff += 360.0;
01398 }
01399 }
01400
01401 return diff;
01402 }
01403
01404
01417 Point3D Orientation::AngleDiff(const Point3D& angleSrc,
01418 const Point3D& angleDest,
01419 const bool radiansFlag)
01420 {
01421 return Point3D(AngleDiff(angleSrc.mX, angleDest.mX, radiansFlag),
01422 AngleDiff(angleSrc.mY, angleDest.mY, radiansFlag),
01423 AngleDiff(angleSrc.mZ, angleDest.mZ, radiansFlag));
01424 }
01425
01437 double Orientation::AddToAngle(const double angleSrc,
01438 const double angleDiff,
01439 const bool radiansFlag)
01440 {
01441 double result = angleSrc + angleDiff;
01442 if(fabs(result) <= .00001) return 0;
01443 if(radiansFlag)
01444 {
01445 result = fmod(result,CxUtils::CX_TWO_PI);
01446 if(result > CxUtils::CX_PI)
01447 {
01448 result -= CxUtils::CX_TWO_PI;
01449 }
01450 else if (result <= -CxUtils::CX_PI)
01451 {
01452 result += CxUtils::CX_TWO_PI;
01453 }
01454 }
01455 else
01456 {
01457 result = fmod(result,360.);
01458 if(result > 180)
01459 {
01460 result -= 360;
01461 }
01462 else if (result <= -180)
01463 {
01464 result += 360;
01465 }
01466 }
01467 return result;
01468
01469 }
01470
01471
01483 Point3D Orientation::AddAngles(const Point3D& src,
01484 const Point3D& delta,
01485 const bool radiansFlag)
01486 {
01487 Point3D result(AddToAngle(src.mX, delta.mX, radiansFlag),
01488 AddToAngle(src.mY, delta.mY, radiansFlag),
01489 AddToAngle(src.mZ, delta.mZ, radiansFlag));
01490 return result;
01491 }
01492
01493
01505 double Orientation::GetGlobalAngle(const Wgs& srcPos,
01506 const Wgs& destPos,
01507 const bool radiansFlag)
01508 {
01509 Utm a(srcPos);
01510 Utm b(destPos);
01511 return GetGlobalAngle(a, b, radiansFlag);
01512 }
01513
01514
01526 double Orientation::GetGlobalAngle(const Utm& srcPos,
01527 const Utm& destPos,
01528 const bool radiansFlag)
01529 {
01530 double result = atan2(destPos.mEasting - srcPos.mEasting, destPos.mNorthing - srcPos.mNorthing);
01531 if(radiansFlag)
01532 {
01533 return result;
01534 }
01535 else
01536 {
01537 return CX_RAD2DEG(result);
01538 }
01539 }
01540
01541
01550
01551
01552
01553
01554
01555
01556
01557
01558
01559
01560
01561
01562
01563
01564
01565
01566
01567