- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

# Y:/msp/devkits/temp_geotrans/master/geotrans3.1/CCS/src/dtcc/CoordinateSystems/trcyleqa/TransverseCylindricalEqualArea.cpp

Go to the documentation of this file.

    00001 // CLASSIFICATION: UNCLASSIFIED
    00002
    00003 /***************************************************************************/
    00004 /* RSC IDENTIFIER: TRANSVERSE CYLINDRICAL EQUAL AREA
    00005  *
    00006  * ABSTRACT
    00007  *
    00008  *    This component provides conversions between Geodetic coordinates
    00009  *    (latitude and longitude in radians) and Transverse Cylindrical Equal Area
    00010  *    projection coordinates (easting and northing in meters).
    00011  *
    00012  * ERROR HANDLING
    00013  *
    00014  *    This component checks parameters for valid values.  If an invalid value
    00015  *    is found, the error code is combined with the current error code using
    00016  *    the bitwise or.  This combining allows multiple error codes to be
    00017  *    returned. The possible error codes are:
    00018  *
    00019  *          TCEA_NO_ERROR           : No errors occurred in function
    00020  *          TCEA_LAT_ERROR          : Latitude outside of valid range
    00021  *                                      (-90 to 90 degrees)
    00022  *          TCEA_LON_ERROR          : Longitude outside of valid range
    00023  *                                      (-180 to 360 degrees)
    00024  *          TCEA_EASTING_ERROR      : Easting outside of valid range
    00025  *                                      (False_Easting +/- ~6,500,000 m,
    00026  *                                       depending on ellipsoid parameters
    00027  *                                       and Origin_Latitude)
    00028  *          TCEA_NORTHING_ERROR     : Northing outside of valid range
    00029  *                                      (False_Northing +/- ~20,000,000 m,
    00030  *                                       depending on ellipsoid parameters
    00031  *                                       and Origin_Latitude)
    00032  *          TCEA_ORIGIN_LAT_ERROR   : Origin latitude outside of valid range
    00033  *                                      (-90 to 90 degrees)
    00034  *          TCEA_CENT_MER_ERROR     : Central meridian outside of valid range
    00035  *                                      (-180 to 360 degrees)
    00036  *          TCEA_A_ERROR            : Semi-major axis less than or equal to zero
    00037  *          TCEA_INV_F_ERROR        : Inverse flattening outside of valid range
    00038  *                                      (250 to 350)
    00039  *          TCEA_SCALE_FACTOR_ERROR : Scale factor outside of valid
    00040  *                                      range (0.3 to 3.0)
    00041  *          TCEA_LON_WARNING        : Distortion will result if longitude is more
    00042  *                                     than 90 degrees from the Central Meridian
    00043  *
    00044  * REUSE NOTES
    00045  *
    00046  *    TRANSVERSE CYLINDRICAL EQUAL AREA is intended for reuse by any application that
    00047  *    performs a Transverse Cylindrical Equal Area projection or its inverse.
    00048  *
    00049  * REFERENCES
    00050  *
    00051  *    Further information on TRANSVERSE CYLINDRICAL EQUAL AREA can be found in the Reuse Manual.
    00052  *
    00053  *    TRANSVERSE CYLINDRICAL EQUAL AREA originated from :
    00054  *                                U.S. Army Topographic Engineering Center
    00055  *                                Geospatial Information Division
    00056  *                                7701 Telegraph Road
    00057  *                                Alexandria, VA  22310-3864
    00058  *
    00059  * LICENSES
    00060  *
    00061  *    None apply to this component.
    00062  *
    00063  * RESTRICTIONS
    00064  *
    00065  *    TRANSVERSE CYLINDRICAL EQUAL AREA has no restrictions.
    00066  *
    00067  * ENVIRONMENT
    00068  *
    00069  *    TRANSVERSE CYLINDRICAL EQUAL AREA was tested and certified in the following environments:
    00070  *
    00071  *    1. Solaris 2.5 with GCC, version 2.8.1
    00072  *    2. Windows 95 with MS Visual C++, version 6
    00073  *
    00074  * MODIFICATIONS
    00075  *
    00076  *    Date              Description
    00077  *    ----              -----------
    00078  *    3-1-07            Original C++ Code
    00079  *
    00080  */
    00081
    00082
    00083 /***************************************************************************/
    00084 /*
    00085  *                               INCLUDES
    00086  */
    00087
    00088 #include <math.h>
    00089 #include "TransverseCylindricalEqualArea.h"
    00090 #include "MapProjection5Parameters.h"
    00091 #include "MapProjectionCoordinates.h"
    00092 #include "GeodeticCoordinates.h"
    00093 #include "CoordinateConversionException.h"
    00094 #include "ErrorMessages.h"
    00095 #include "WarningMessages.h"
    00096
    00097 /*
    00098  *    math.h     - Standard C math library
    00099  *    TransverseCylindricalEqualArea.h - Is for prototype error checking
    00100  *    MapProjectionCoordinates.h   - defines map projection coordinates
    00101  *    GeodeticCoordinates.h   - defines geodetic coordinates
    00102  *    CoordinateConversionException.h - Exception handler
    00103  *    ErrorMessages.h  - Contains exception messages
    00104  *    WarningMessages.h  - Contains warning messages
    00105  */
    00106
    00107
    00108 using namespace MSP::CCS;
    00109
    00110
    00111 /***************************************************************************/
    00112 /*                               DEFINES
    00113  *
    00114  */
    00115
    00116 const double PI = 3.14159265358979323e0;  /* PI                            */
    00117 const double PI_OVER_2 = ( PI / 2.0);
    00118 const double TWO_PI = (2.0 * PI);
    00119 const double MIN_SCALE_FACTOR = 0.3;
    00120 const double MAX_SCALE_FACTOR = 3.0;
    00121
    00122
    00123 /************************************************************************/
    00124 /*                              FUNCTIONS
    00125  *
    00126  */
    00127
    00128 TransverseCylindricalEqualArea::TransverseCylindricalEqualArea( double ellipsoidSemiMajorAxis, double ellipsoidFlattening, double centralMeridian, double latitudeOfTrueScale, double falseEasting, double falseNorthing, double scaleFactor ) :
    00129   CoordinateSystem(),
    00130   es2( 0.0066943799901413800 ),
    00131   es4( 4.4814723452405e-005 ),
    00132   es6( 3.0000678794350e-007 ),
    00133   es( .081819190842622 ),
    00134   M0( 0.0 ),
    00135   qp( 1.9955310875028 ),
    00136   One_MINUS_es2( .99330562000986 ),
    00137   One_OVER_2es( 6.1110357466348 ),
    00138   a0( .0022392088624809 ),
    00139   a1( 2.8830839728915e-006 ),
    00140   a2( 5.0331826636906e-009 ),
    00141   b0( .0025188265843907 ),
    00142   b1( 3.7009490356205e-006 ),
    00143   b2( 7.4478137675038e-009 ),
    00144   b3( 1.7035993238596e-011 ),
    00145   c0( .99832429845280 ),
    00146   c1( .0025146070605187 ),
    00147   c2( 2.6390465943377e-006 ),
    00148   c3( 3.4180460865959e-009 ),
    00149   Tcea_Origin_Long( 0.0 ),
    00150   Tcea_Origin_Lat( 0.0 ),
    00151   Tcea_False_Easting( 0.0 ),
    00152   Tcea_False_Northing( 0.0 ),
    00153   Tcea_Scale_Factor( 1.0 ),
    00154   Tcea_Min_Easting( -6398628.0 ),
    00155   Tcea_Max_Easting( 6398628.0 ),
    00156   Tcea_Min_Northing( -20003931.0 ),
    00157   Tcea_Max_Northing( 20003931.0 )
    00158 {
    00159 /*
    00160  * The constructor receives the ellipsoid parameters and
    00161  * Transverse Cylindrical Equal Area projection parameters as inputs, and sets the
    00162  * corresponding state variables.  If any errors occur, an exception is thrown with a description
    00163  * of the error.
    00164  *
    00165  *    ellipsoidSemiMajorAxis     : Semi-major axis of ellipsoid, in meters   (input)
    00166  *    ellipsoidFlattening        : Flattening of ellipsoid                   (input)
    00167  *    centralMeridian            : Longitude in radians at the center of     (input)
    00168  *                                 the projection
    00169  *    latitudeOfTrueScale        : Latitude in radians at which the          (input)
    00170  *                                 point scale factor is 1.0
    00171  *    falseEasting               : A coordinate value in meters assigned to the
    00172  *                                 central meridian of the projection.       (input)
    00173  *    falseNorthing              : A coordinate value in meters assigned to the
    00174  *                                 origin latitude of the projection         (input)
    00175  *    scaleFactor                : Multiplier which reduces distances in the
    00176  *                                 projection to the actual distance on the
    00177  *                                 ellipsoid                                 (input)
    00178  */
    00179
    00180   double sin_lat_90 = sin(PI_OVER_2);
    00181   double x, j, three_es4;
    00182   double Sqrt_One_MINUS_es2;
    00183   double e1, e2, e3, e4;
    00184   double lat, sin2lat, sin4lat, sin6lat;
    00185   double temp, temp_northing;
    00186   double inv_f = 1 / ellipsoidFlattening;
    00187   char errorStatus[500] = "";
    00188
    00189   if (ellipsoidSemiMajorAxis <= 0.0)
    00190   { /* Semi-major axis must be greater than zero */
    00191     strcat( errorStatus, ErrorMessages::semiMajorAxis );
    00192   }
    00193   if ((inv_f < 250) || (inv_f > 350))
    00194   { /* Inverse flattening must be between 250 and 350 */
    00195     strcat( errorStatus, ErrorMessages::ellipsoidFlattening );
    00196   }
    00197   if ((latitudeOfTrueScale < -PI_OVER_2) || (latitudeOfTrueScale > PI_OVER_2))
    00198   { /* origin latitude out of range */
    00199     strcat( errorStatus, ErrorMessages::originLatitude );
    00200   }
    00201   if ((centralMeridian < -PI) || (centralMeridian > TWO_PI))
    00202   { /* origin longitude out of range */
    00203     strcat( errorStatus, ErrorMessages::centralMeridian );
    00204   }
    00205   if ((scaleFactor < MIN_SCALE_FACTOR) || (scaleFactor > MAX_SCALE_FACTOR))
    00206   {
    00207     strcat( errorStatus, ErrorMessages::scaleFactor );
    00208   }
    00209
    00210   if( strlen( errorStatus ) > 0)
    00211     throw CoordinateConversionException( errorStatus );
    00212
    00213   semiMajorAxis = ellipsoidSemiMajorAxis;
    00214   flattening = ellipsoidFlattening;
    00215
    00216   Tcea_Origin_Lat = latitudeOfTrueScale;
    00217   if (centralMeridian > PI)
    00218     centralMeridian -= TWO_PI;
    00219   Tcea_Origin_Long = centralMeridian;
    00220   Tcea_False_Northing = falseNorthing;
    00221   Tcea_False_Easting = falseEasting;
    00222   Tcea_Scale_Factor = scaleFactor;
    00223
    00224   es2 = 2 * flattening - flattening * flattening;
    00225   es = sqrt(es2);
    00226   One_MINUS_es2 = 1.0 - es2;
    00227   Sqrt_One_MINUS_es2 = sqrt(One_MINUS_es2);
    00228   One_OVER_2es = 1.0 / (2.0 * es);
    00229   es4 = es2 * es2;
    00230   es6 = es4 * es2;
    00231   x = es * sin_lat_90;
    00232   qp = TCEA_Q(sin_lat_90,x);
    00233
    00234   a0 = es2 / 3.0 + 31.0 * es4 / 180.0 + 517.0 * es6 / 5040.0;
    00235   a1 = 23.0 * es4 / 360.0 + 251.0 * es6 / 3780.0;
    00236   a2 = 761.0 * es6 / 45360.0;
    00237
    00238   e1 = (1.0 - Sqrt_One_MINUS_es2) / (1.0 + Sqrt_One_MINUS_es2);
    00239   e2 = e1 * e1;
    00240   e3 = e2 * e1;
    00241   e4 = e3 * e1;
    00242   b0 = 3.0 * e1 / 2.0 - 27.0 * e3 / 32.0;
    00243   b1 = 21.0 * e2 / 16.0 - 55.0 * e4 / 32.0;
    00244   b2 = 151.0 * e3 / 96.0;
    00245   b3 = 1097.0 * e4 / 512.0;
    00246
    00247   j = 45.0 * es6 / 1024.0;
    00248   three_es4 = 3.0 * es4;
    00249   c0 = 1.0 - es2 / 4.0 - three_es4 / 64.0 - 5.0 * es6 / 256.0;
    00250   c1 = 3.0 * es2 / 8.0 + three_es4 / 32.0 + j;
    00251   c2 = 15.0 * es4 / 256.0 + j;
    00252   c3 = 35.0 * es6 / 3072.0;
    00253   lat = c0 * Tcea_Origin_Lat;
    00254   sin2lat = TCEA_COEFF_TIMES_SIN(c1, 2.0, Tcea_Origin_Lat);
    00255   sin4lat = TCEA_COEFF_TIMES_SIN(c2, 4.0, Tcea_Origin_Lat);
    00256   sin6lat = TCEA_COEFF_TIMES_SIN(c3, 6.0, Tcea_Origin_Lat);
    00257   M0 = TCEA_M(lat, sin2lat, sin4lat, sin6lat);
    00258
    00259   GeodeticCoordinates gcTemp( CoordinateType::geodetic, PI, PI_OVER_2 );
    00260   MapProjectionCoordinates* tempCoordinates = convertFromGeodetic( &gcTemp );
    00261   temp = tempCoordinates->easting();
    00262   temp_northing = tempCoordinates->northing();
    00263   delete tempCoordinates;
    00264
    00265   if (temp_northing > 0)
    00266   {
    00267     Tcea_Min_Northing = temp_northing - 20003931.458986;
    00268     Tcea_Max_Northing = temp_northing;
    00269
    00270     if(Tcea_False_Northing)
    00271     {
    00272       Tcea_Min_Northing -= Tcea_False_Northing;
    00273       Tcea_Max_Northing -= Tcea_False_Northing;
    00274     }
    00275   }
    00276   else if (temp_northing < 0)
    00277   {
    00278     Tcea_Max_Northing = temp_northing + 20003931.458986;
    00279     Tcea_Min_Northing = temp_northing;
    00280
    00281     if(Tcea_False_Northing)
    00282     {
    00283       Tcea_Min_Northing -= Tcea_False_Northing;
    00284       Tcea_Max_Northing -= Tcea_False_Northing;
    00285     }
    00286   }
    00287 }
    00288
    00289
    00290 TransverseCylindricalEqualArea::TransverseCylindricalEqualArea( const TransverseCylindricalEqualArea &tcea )
    00291 {
    00292   semiMajorAxis = tcea.semiMajorAxis;
    00293   flattening = tcea.flattening;
    00294   es2 = tcea.es2;
    00295   es4 = tcea.es4;
    00296   es6 = tcea.es6;
    00297   es = tcea.es;
    00298   M0 = tcea.M0;
    00299   qp = tcea.qp;
    00300   One_MINUS_es2 = tcea.One_MINUS_es2;
    00301   One_OVER_2es = tcea.One_OVER_2es;
    00302   a0 = tcea.a0;
    00303   a1 = tcea.a1;
    00304   a2 = tcea.a2;
    00305   b0 = tcea.b0;
    00306   b1 = tcea.b1;
    00307   b2 = tcea.b2;
    00308   b3 = tcea.b3;
    00309   c0 = tcea.c0;
    00310   c1 = tcea.c1;
    00311   c2 = tcea.c2;
    00312   c3 = tcea.c3;
    00313   Tcea_Origin_Long = tcea.Tcea_Origin_Long;
    00314   Tcea_Origin_Lat = tcea.Tcea_Origin_Lat;
    00315   Tcea_False_Easting = tcea.Tcea_False_Easting;
    00316   Tcea_False_Northing = tcea.Tcea_False_Northing;
    00317   Tcea_Scale_Factor = tcea.Tcea_Scale_Factor;
    00318   Tcea_Min_Easting = tcea.Tcea_Min_Easting;
    00319   Tcea_Max_Easting = tcea.Tcea_Max_Easting;
    00320   Tcea_Min_Northing = tcea.Tcea_Min_Northing;
    00321   Tcea_Max_Northing = tcea.Tcea_Max_Northing;
    00322 }
    00323
    00324
    00325 TransverseCylindricalEqualArea::~TransverseCylindricalEqualArea()
    00326 {
    00327 }
    00328
    00329
    00330 TransverseCylindricalEqualArea& TransverseCylindricalEqualArea::operator=( const TransverseCylindricalEqualArea &tcea )
    00331 {
    00332   if( this != &tcea )
    00333   {
    00334     semiMajorAxis = tcea.semiMajorAxis;
    00335     flattening = tcea.flattening;
    00336     es2 = tcea.es2;
    00337     es4 = tcea.es4;
    00338     es6 = tcea.es6;
    00339     es = tcea.es;
    00340     M0 = tcea.M0;
    00341     qp = tcea.qp;
    00342     One_MINUS_es2 = tcea.One_MINUS_es2;
    00343     One_OVER_2es = tcea.One_OVER_2es;
    00344     a0 = tcea.a0;
    00345     a1 = tcea.a1;
    00346     a2 = tcea.a2;
    00347     b0 = tcea.b0;
    00348     b1 = tcea.b1;
    00349     b2 = tcea.b2;
    00350     b3 = tcea.b3;
    00351     c0 = tcea.c0;
    00352     c1 = tcea.c1;
    00353     c2 = tcea.c2;
    00354     c3 = tcea.c3;
    00355     Tcea_Origin_Long = tcea.Tcea_Origin_Long;
    00356     Tcea_Origin_Lat = tcea.Tcea_Origin_Lat;
    00357     Tcea_False_Easting = tcea.Tcea_False_Easting;
    00358     Tcea_False_Northing = tcea.Tcea_False_Northing;
    00359     Tcea_Scale_Factor = tcea.Tcea_Scale_Factor;
    00360     Tcea_Min_Easting = tcea.Tcea_Min_Easting;
    00361     Tcea_Max_Easting = tcea.Tcea_Max_Easting;
    00362     Tcea_Min_Northing = tcea.Tcea_Min_Northing;
    00363     Tcea_Max_Northing = tcea.Tcea_Max_Northing;
    00364   }
    00365
    00366   return *this;
    00367 }
    00368
    00369
    00370 MapProjection5Parameters* TransverseCylindricalEqualArea::getParameters() const
    00371 {
    00372 /*
    00373  * The function getParameters returns the current ellipsoid
    00374  * parameters, Transverse Cylindrical Equal Area projection parameters, and scale factor.
    00375  *
    00376  *    ellipsoidSemiMajorAxis  : Semi-major axis of ellipsoid, in meters   (output)
    00377  *    ellipsoidFlattening     : Flattening of ellipsoid                   (output)
    00378  *    centralMeridian         : Longitude in radians at the center of     (output)
    00379  *                            the projection
    00380  *    latitudeOfTrueScale     : Latitude in radians at which the          (output)
    00381  *                            point scale factor is 1.0
    00382  *    falseEasting            : A coordinate value in meters assigned to the
    00383  *                            central meridian of the projection.         (output)
    00384  *    falseNorthing           : A coordinate value in meters assigned to the
    00385  *                            origin latitude of the projection           (output)
    00386  *    scaleFactor             : Multiplier which reduces distances in the
    00387  *                            projection to the actual distance on the
    00388  *                            ellipsoid                                   (output)
    00389  */
    00390
    00391   return new MapProjection5Parameters( CoordinateType::transverseCylindricalEqualArea, Tcea_Origin_Long, Tcea_Origin_Lat, Tcea_Scale_Factor, Tcea_False_Easting, Tcea_False_Northing );
    00392 }
    00393
    00394
    00395 MSP::CCS::MapProjectionCoordinates* TransverseCylindricalEqualArea::convertFromGeodetic( MSP::CCS::GeodeticCoordinates* geodeticCoordinates )
    00396 {
    00397 /*
    00398  * The function convertFromGeodetic converts geodetic (latitude and
    00399  * longitude) coordinates to Transverse Cylindrical Equal Area projection (easting and
    00400  * northing) coordinates, according to the current ellipsoid and Transverse Cylindrical
    00401  * Equal Area projection parameters.  If any errors occur, an exception is thrown with a description
    00402  * of the error.
    00403  *
    00404  *    longitude         : Longitude (lambda) in radians       (input)
    00405  *    latitude          : Latitude (phi) in radians           (input)
    00406  *    easting           : Easting (X) in meters               (output)
    00407  *    northing          : Northing (Y) in meters              (output)
    00408  */
    00409
    00410   double x;
    00411   double dlam;                      /* Longitude - Central Meridan */
    00412   double qq, qq_OVER_qp;
    00413   double beta, betac;
    00414   double sin2betac, sin4betac, sin6betac;
    00415   double PHIc;
    00416   double phi, sin2phi, sin4phi, sin6phi;
    00417   double sinPHIc;
    00418   double Mc;
    00419   char errorStatus[256] = "";
    00420
    00421   double longitude = geodeticCoordinates->longitude();
    00422   double latitude = geodeticCoordinates->latitude();
    00423   double sin_lat = sin(latitude);
    00424
    00425   if ((latitude < -PI_OVER_2) || (latitude > PI_OVER_2))
    00426   { /* Latitude out of range */
    00427     strcat( errorStatus, ErrorMessages::latitude );
    00428   }
    00429   if ((longitude < -PI) || (longitude > TWO_PI))
    00430   { /* Longitude out of range */
    00431     strcat( errorStatus, ErrorMessages::longitude );
    00432   }
    00433
    00434   if( strlen( errorStatus ) > 0)
    00435     throw CoordinateConversionException( errorStatus );
    00436
    00437   dlam = longitude - Tcea_Origin_Long;
    00438   if (fabs(dlam) >= (PI / 2))
    00439   { /* Distortion will result if Longitude is more than 90 degrees from the Central Meridian */
    00440     strcat( errorStatus, MSP::CCS::WarningMessages::longitude );
    00441   }
    00442
    00443   if (dlam > PI)
    00444   {
    00445     dlam -= TWO_PI;
    00446   }
    00447   if (dlam < -PI)
    00448   {
    00449     dlam += TWO_PI;
    00450   }
    00451   if (latitude == PI_OVER_2)
    00452   {
    00453     qq = qp;
    00454     qq_OVER_qp = 1.0;
    00455   }
    00456   else
    00457   {
    00458     x = es * sin_lat;
    00459     qq = TCEA_Q(sin_lat, x);
    00460     qq_OVER_qp = qq / qp;
    00461   }
    00462
    00463
    00464   if (qq_OVER_qp > 1.0)
    00465     qq_OVER_qp = 1.0;
    00466   else if (qq_OVER_qp < -1.0)
    00467     qq_OVER_qp = -1.0;
    00468
    00469   beta = asin(qq_OVER_qp);
    00470   betac = atan(tan(beta) / cos(dlam));
    00471
    00472   if ((fabs(betac) - PI_OVER_2) > 1.0e-8)
    00473     PHIc = betac;
    00474   else
    00475   {
    00476     sin2betac = TCEA_COEFF_TIMES_SIN(a0, 2.0, betac);
    00477     sin4betac = TCEA_COEFF_TIMES_SIN(a1, 4.0, betac);
    00478     sin6betac = TCEA_COEFF_TIMES_SIN(a2, 6.0, betac);
    00479     PHIc = TCEA_L(betac, sin2betac, sin4betac, sin6betac);
    00480   }
    00481
    00482   sinPHIc = sin(PHIc);
    00483   double easting = semiMajorAxis * cos(beta) * cos(PHIc) * sin(dlam) /
    00484              (Tcea_Scale_Factor * cos(betac) * sqrt(1.0 - es2 *
    00485                                                     sinPHIc * sinPHIc)) + Tcea_False_Easting;
    00486
    00487   phi = c0 * PHIc;
    00488   sin2phi = TCEA_COEFF_TIMES_SIN(c1, 2.0, PHIc);
    00489   sin4phi = TCEA_COEFF_TIMES_SIN(c2, 4.0, PHIc);
    00490   sin6phi = TCEA_COEFF_TIMES_SIN(c3, 6.0, PHIc);
    00491   Mc = TCEA_M(phi, sin2phi, sin4phi, sin6phi);
    00492
    00493   double northing = Tcea_Scale_Factor * (Mc - M0) + Tcea_False_Northing;
    00494
    00495   return new MapProjectionCoordinates( CoordinateType::transverseCylindricalEqualArea, errorStatus, easting, northing );
    00496 }
    00497
    00498
    00499 MSP::CCS::GeodeticCoordinates* TransverseCylindricalEqualArea::convertToGeodetic( MSP::CCS::MapProjectionCoordinates* mapProjectionCoordinates )
    00500 {
    00501 /*
    00502  * The function convertToGeodetic converts Transverse
    00503  * Cylindrical Equal Area projection (easting and northing) coordinates
    00504  * to geodetic (latitude and longitude) coordinates, according to the
    00505  * current ellipsoid and Transverse Cylindrical Equal Area projection
    00506  * coordinates.  If any errors occur, an exception is thrown with a description
    00507  * of the error.
    00508  *
    00509  *    easting           : Easting (X) in meters                  (input)
    00510  *    northing          : Northing (Y) in meters                 (input)
    00511  *    longitude         : Longitude (lambda) in radians          (output)
    00512  *    latitude          : Latitude (phi) in radians              (output)
    00513  */
    00514
    00515   double x;
    00516   double dx;     /* Delta easting - Difference in easting (easting-FE)      */
    00517   double dy;     /* Delta northing - Difference in northing (northing-FN)   */
    00518   double Mc;
    00519   double MUc;
    00520   double sin2mu, sin4mu, sin6mu, sin8mu;
    00521   double PHIc;
    00522   double Qc;
    00523   double sin_lat;
    00524   double beta, betac, beta_prime;
    00525   double sin2beta, sin4beta, sin6beta;
    00526   double cosbetac;
    00527   double Qc_OVER_qp;
    00528   double temp;
    00529   char errorStatus[50] = "";
    00530
    00531   double easting = mapProjectionCoordinates->easting();
    00532   double northing = mapProjectionCoordinates->northing();
    00533
    00534   if ((easting < (Tcea_False_Easting + Tcea_Min_Easting))
    00535       || (easting > (Tcea_False_Easting + Tcea_Max_Easting)))
    00536   { /* Easting out of range */
    00537     strcat( errorStatus, ErrorMessages::easting );
    00538   }
    00539   if ((northing < (Tcea_False_Northing + Tcea_Min_Northing))
    00540       || (northing > (Tcea_False_Northing + Tcea_Max_Northing)))
    00541   { /* Northing out of range */
    00542     strcat( errorStatus, ErrorMessages::northing );
    00543   }
    00544
    00545   if( strlen( errorStatus ) > 0)
    00546     throw CoordinateConversionException( errorStatus );
    00547
    00548   dy = northing - Tcea_False_Northing;
    00549   dx = easting - Tcea_False_Easting;
    00550   Mc = M0 + dy / Tcea_Scale_Factor;
    00551   MUc = Mc / (semiMajorAxis * c0);
    00552
    00553   sin2mu = TCEA_COEFF_TIMES_SIN(b0, 2.0, MUc);
    00554   sin4mu = TCEA_COEFF_TIMES_SIN(b1, 4.0, MUc);
    00555   sin6mu = TCEA_COEFF_TIMES_SIN(b2, 6.0, MUc);
    00556   sin8mu = TCEA_COEFF_TIMES_SIN(b3, 8.0, MUc);
    00557   PHIc = MUc + sin2mu + sin4mu + sin6mu + sin8mu;
    00558
    00559   sin_lat = sin(PHIc);
    00560   x = es * sin_lat;
    00561   Qc = TCEA_Q(sin_lat, x);
    00562   Qc_OVER_qp = Qc / qp;
    00563
    00564   if (Qc_OVER_qp < -1.0)
    00565     Qc_OVER_qp = -1.0;
    00566   else if (Qc_OVER_qp > 1.0)
    00567     Qc_OVER_qp = 1.0;
    00568
    00569   betac = asin(Qc_OVER_qp);
    00570   cosbetac = cos(betac);
    00571   temp = Tcea_Scale_Factor * dx * cosbetac * sqrt(1.0 -
    00572                                                   es2 * sin_lat * sin_lat) / (semiMajorAxis * cos(PHIc));
    00573   if (temp > 1.0)
    00574     temp = 1.0;
    00575   else if (temp < -1.0)
    00576     temp = -1.0;
    00577   beta_prime = -asin(temp);
    00578   beta = asin(cos(beta_prime) * sin(betac));
    00579
    00580   sin2beta = TCEA_COEFF_TIMES_SIN(a0, 2.0, beta);
    00581   sin4beta = TCEA_COEFF_TIMES_SIN(a1, 4.0, beta);
    00582   sin6beta = TCEA_COEFF_TIMES_SIN(a2, 6.0, beta);
    00583   double latitude = TCEA_L(beta, sin2beta, sin4beta, sin6beta);
    00584
    00585   double longitude = Tcea_Origin_Long - atan(tan(beta_prime) / cosbetac);
    00586
    00587   if (latitude > PI_OVER_2)  /* force distorted values to 90, -90 degrees */
    00588     latitude = PI_OVER_2;
    00589   else if (latitude < -PI_OVER_2)
    00590     latitude = -PI_OVER_2;
    00591
    00592   if (longitude > PI)
    00593     longitude -= TWO_PI;
    00594   if (longitude < -PI)
    00595     longitude += TWO_PI;
    00596
    00597   if (longitude > PI) /* force distorted values to 180, -180 degrees */
    00598     longitude = PI;
    00599   else if (longitude < -PI)
    00600     longitude = -PI;
    00601
    00602   return new GeodeticCoordinates( CoordinateType::geodetic, longitude, latitude );
    00603 }
    00604
    00605
    00606 double TransverseCylindricalEqualArea::TCEA_Q( double sinlat, double x )
    00607 {
    00608   return One_MINUS_es2*(sinlat/(1.0-es2*sinlat*sinlat)-One_OVER_2es*log((1-x)/(1+x)));
    00609 }
    00610
    00611
    00612 double TransverseCylindricalEqualArea::TCEA_COEFF_TIMES_SIN( double coeff, double x, double latit )
    00613 {
    00614   return coeff * sin(x*latit);
    00615 }
    00616
    00617
    00618 double TransverseCylindricalEqualArea::TCEA_M( double c0lat, double c1lat, double c2lat, double c3lat )
    00619 {
    00620   return semiMajorAxis * (c0lat - c1lat + c2lat - c3lat);
    00621 }
    00622
    00623
    00624 double TransverseCylindricalEqualArea::TCEA_L( double Beta, double c0lat, double c1lat, double c2lat )
    00625 {
    00626   return Beta + c0lat + c1lat + c2lat;
    00627 }
    00628
    00629 // CLASSIFICATION: UNCLASSIFIED