- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

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

Go to the documentation of this file.

    00001 // CLASSIFICATION: UNCLASSIFIED
    00002
    00003 /***************************************************************************/
    00004 /* RSC IDENTIFIER: ECKERT4
    00005  *
    00006  * ABSTRACT
    00007  *
    00008  *    This component provides conversions between Geodetic coordinates
    00009  *    (latitude and longitude in radians) and Eckert IV projection coordinates
    00010  *    (easting and northing in meters).  This projection employs a spherical
    00011  *    Earth model.  The spherical radius used is the radius of the sphere
    00012  *    having the same area as the ellipsoid.
    00013  *
    00014  * ERROR HANDLING
    00015  *
    00016  *    This component checks parameters for valid values.  If an invalid value
    00017  *    is found, the error code is combined with the current error code using
    00018  *    the bitwise or.  This combining allows multiple error codes to be
    00019  *    returned. The possible error codes are:
    00020  *
    00021  *          ECK4_NO_ERROR           : No errors occurred in function
    00022  *          ECK4_LAT_ERROR          : Latitude outside of valid range
    00023  *                                      (-90 to 90 degrees)
    00024  *          ECK4_LON_ERROR          : Longitude outside of valid range
    00025  *                                      (-180 to 360 degrees)
    00026  *          ECK4_EASTING_ERROR      : Easting outside of valid range
    00027  *                                      (False_Easting +/- ~17,000,000 m,
    00028  *                                                                               depending on ellipsoid parameters)
    00029  *          ECK4_NORTHING_ERROR     : Northing outside of valid range
    00030  *                                      (False_Northing +/- 0 to 8,000,000 m,
    00031  *                                                                               depending on ellipsoid parameters)
    00032  *          ECK4_CENT_MER_ERROR     : Central_Meridian outside of valid range
    00033  *                                      (-180 to 360 degrees)
    00034  *          ECK4_A_ERROR            : Semi-major axis less than or equal to zero
    00035  *          ECK4_INV_F_ERROR        : Inverse flattening outside of valid range
    00036  *                                                                                          (250 to 350)
    00037  *
    00038  * REUSE NOTES
    00039  *
    00040  *    ECKERT4 is intended for reuse by any application that performs a
    00041  *    Eckert IV projection or its inverse.
    00042  *
    00043  * REFERENCES
    00044  *
    00045  *    Further information on ECKERT4 can be found in the Reuse Manual.
    00046  *
    00047  *    ECKERT4 originated from :  U.S. Army Topographic Engineering Center
    00048  *                                Geospatial Information Division
    00049  *                                7701 Telegraph Road
    00050  *                                Alexandria, VA  22310-3864
    00051  *
    00052  * LICENSES
    00053  *
    00054  *    None apply to this component.
    00055  *
    00056  * RESTRICTIONS
    00057  *
    00058  *    ECKERT4 has no restrictions.
    00059  *
    00060  * ENVIRONMENT
    00061  *
    00062  *    ECKERT4 was tested and certified in the following environments:
    00063  *
    00064  *    1. Solaris 2.5 with GCC 2.8.1
    00065  *    2. MS Windows 95 with MS Visual C++ 6
    00066  *
    00067  * MODIFICATIONS
    00068  *
    00069  *    Date              Description
    00070  *    ----              -----------
    00071  *    04-16-99          Original Code
    00072  *    03-06-07          Original C++ Code
    00073  *
    00074  */
    00075
    00076
    00077 /***************************************************************************/
    00078 /*
    00079  *                               INCLUDES
    00080  */
    00081
    00082 #include <math.h>
    00083 #include "Eckert4.h"
    00084 #include "MapProjection3Parameters.h"
    00085 #include "MapProjectionCoordinates.h"
    00086 #include "GeodeticCoordinates.h"
    00087 #include "CoordinateConversionException.h"
    00088 #include "ErrorMessages.h"
    00089
    00090 /*
    00091  *    math.h    - Standard C math library
    00092  *    Eckert4.h - Is for prototype error checking.
    00093  *    MapProjectionCoordinates.h   - defines map projection coordinates
    00094  *    GeodeticCoordinates.h   - defines geodetic coordinates
    00095  *    CoordinateConversionException.h - Exception handler
    00096  *    ErrorMessages.h  - Contains exception messages
    00097  */
    00098
    00099
    00100 using namespace MSP::CCS;
    00101
    00102
    00103 /***************************************************************************/
    00104 /*                               DEFINES
    00105  *
    00106  */
    00107
    00108 const double PI = 3.14159265358979323e0;      /* PI  */
    00109 const double PI_OVER_2 = ( PI / 2.0);
    00110 const double TWO_PI = (2.0 * PI) ;
    00111 const double two_PLUS_PI_OVER_2 = (2.0 + PI / 2.0);
    00112
    00113
    00114 double calculateNum( double theta, double sinTheta, double cosTheta )
    00115 {
    00116   return theta + sinTheta * cosTheta + 2.0 * sinTheta;
    00117 }
    00118
    00119
    00120 /************************************************************************/
    00121 /*                              FUNCTIONS
    00122  *
    00123  */
    00124
    00125 Eckert4::Eckert4( double ellipsoidSemiMajorAxis, double ellipsoidFlattening, double centralMeridian, double falseEasting, double falseNorthing ) :
    00126   CoordinateSystem(),
    00127   es2( 0.0066943799901413800 ),
    00128   es4( 4.4814723452405e-005 ),
    00129   es6( 3.0000678794350e-007 ),
    00130   Ra0( 2690082.6043273 ),
    00131   Ra1( 8451143.5741087 ),
    00132   Eck4_Origin_Long( 0.0 ),
    00133   Eck4_False_Easting( 0.0 ),
    00134   Eck4_False_Northing( 0.0 ),
    00135   Eck4_Delta_Northing( 8451144.0 ),
    00136   Eck4_Max_Easting( 16902288.0 ),
    00137   Eck4_Min_Easting( -16902288.0 )
    00138 {
    00139 /*
    00140  * The constructor receives the ellipsoid parameters and
    00141  * projection parameters as inputs, and sets the corresponding state
    00142  * variables.  If any errors occur, an exception is thrown with a description
    00143  * of the error.
    00144  *
    00145  *    ellipsoidSemiMajorAxis  : Semi-major axis of ellipsoid, in meters   (input)
    00146  *    ellipsoidFlattening     : Flattening of ellipsoid                                                 (input)
    00147  *    centralMeridian         : Longitude in radians at the center of     (input)
    00148  *                              the projection
    00149  *    falseEasting            : A coordinate value in meters assigned to the
    00150  *                              central meridian of the projection.       (input)
    00151  *    falseNorthing           : A coordinate value in meters assigned to the
    00152  *                              origin latitude of the projection         (input)
    00153  */
    00154
    00155   double Ra;              /* Spherical radius */
    00156   double inv_f = 1 / ellipsoidFlattening;
    00157   char errorStatus[500] = "";
    00158
    00159   if (ellipsoidSemiMajorAxis <= 0.0)
    00160   { /* Semi-major axis must be greater than zero */
    00161     strcat( errorStatus, MSP::CCS::ErrorMessages::semiMajorAxis );
    00162   }
    00163   if ((inv_f < 250) || (inv_f > 350))
    00164   { /* Inverse flattening must be between 250 and 350 */
    00165     strcat( errorStatus, MSP::CCS::ErrorMessages::ellipsoidFlattening );
    00166   }
    00167   if ((centralMeridian < -PI) || (centralMeridian > TWO_PI))
    00168   { /* origin longitude out of range */
    00169     strcat( errorStatus, MSP::CCS::ErrorMessages::centralMeridian );
    00170   }
    00171
    00172   if( strlen( errorStatus ) > 0)
    00173     throw CoordinateConversionException( errorStatus );
    00174
    00175   semiMajorAxis = ellipsoidSemiMajorAxis;
    00176   flattening = ellipsoidFlattening;
    00177
    00178   es2 = 2 * flattening - flattening * flattening;
    00179   es4 = es2 * es2;
    00180   es6 = es4 * es2;
    00181   /* spherical radius */
    00182   Ra = semiMajorAxis * (1.0 - es2 / 6.0 - 17.0 * es4 / 360.0 - 67.0 * es6 / 3024.0);
    00183   Ra0 = 0.4222382 * Ra;
    00184   Ra1 = 1.3265004 * Ra;
    00185   if (centralMeridian > PI)
    00186     centralMeridian -= TWO_PI;
    00187   Eck4_Origin_Long = centralMeridian;
    00188   Eck4_False_Easting = falseEasting;
    00189   Eck4_False_Northing = falseNorthing;
    00190   if (Eck4_Origin_Long > 0)
    00191   {
    00192     Eck4_Max_Easting = 16808386.0;
    00193     Eck4_Min_Easting = -16902288.0;
    00194   }
    00195   else if (Eck4_Origin_Long < 0)
    00196   {
    00197     Eck4_Max_Easting = 16902288.0;
    00198     Eck4_Min_Easting = -16808386.0;
    00199   }
    00200   else
    00201   {
    00202     Eck4_Max_Easting = 16902288.0;
    00203     Eck4_Min_Easting = -16902288.0;
    00204   }
    00205 }
    00206
    00207
    00208 Eckert4::Eckert4( const Eckert4 &e )
    00209 {
    00210   semiMajorAxis = e.semiMajorAxis;
    00211   flattening = e.flattening;
    00212   es2 = e.es2;
    00213   es4 = e.es4;
    00214   es6 = e.es6;
    00215   Ra0 = e.Ra0;
    00216   Ra1 = e.Ra1;
    00217   Eck4_Origin_Long = e.Eck4_Origin_Long;
    00218   Eck4_False_Easting = e.Eck4_False_Easting;
    00219   Eck4_False_Northing = e.Eck4_False_Northing;
    00220   Eck4_Delta_Northing = e.Eck4_Delta_Northing;
    00221   Eck4_Max_Easting = e.Eck4_Max_Easting;
    00222   Eck4_Min_Easting = e.Eck4_Min_Easting;
    00223 }
    00224
    00225
    00226 Eckert4::~Eckert4()
    00227 {
    00228 }
    00229
    00230
    00231 Eckert4& Eckert4::operator=( const Eckert4 &e )
    00232 {
    00233   if( this != &e )
    00234   {
    00235     semiMajorAxis = e.semiMajorAxis;
    00236     flattening = e.flattening;
    00237     es2 = e.es2;
    00238     es4 = e.es4;
    00239     es6 = e.es6;
    00240     Ra0 = e.Ra0;
    00241     Ra1 = e.Ra1;
    00242     Eck4_Origin_Long = e.Eck4_Origin_Long;
    00243     Eck4_False_Easting = e.Eck4_False_Easting;
    00244     Eck4_False_Northing = e.Eck4_False_Northing;
    00245     Eck4_Delta_Northing = e.Eck4_Delta_Northing;
    00246     Eck4_Max_Easting = e.Eck4_Max_Easting;
    00247     Eck4_Min_Easting = e.Eck4_Min_Easting;
    00248   }
    00249
    00250   return *this;
    00251 }
    00252
    00253
    00254 MapProjection3Parameters* Eckert4::getParameters() const
    00255 {
    00256 /*
    00257  * The function getParameters returns the current ellipsoid
    00258  * parameters and Eckert IV projection parameters.
    00259  *
    00260  *    ellipsoidSemiMajorAxis  : Semi-major axis of ellipsoid, in meters   (output)
    00261  *    ellipsoidFlattening     : Flattening of ellipsoid                                                 (output)
    00262  *    centralMeridian         : Longitude in radians at the center of     (output)
    00263  *                              the projection
    00264  *    falseEasting            : A coordinate value in meters assigned to the
    00265  *                              central meridian of the projection.       (output)
    00266  *    falseNorthing           : A coordinate value in meters assigned to the
    00267  *                              origin latitude of the projection         (output)
    00268  */
    00269
    00270   return new MapProjection3Parameters( CoordinateType::eckert4, Eck4_Origin_Long, Eck4_False_Easting, Eck4_False_Northing );
    00271 }
    00272
    00273
    00274 MSP::CCS::MapProjectionCoordinates* Eckert4::convertFromGeodetic( MSP::CCS::GeodeticCoordinates* geodeticCoordinates )
    00275 {
    00276 /*
    00277  * The function convertFromGeodetic converts geodetic (latitude and
    00278  * longitude) coordinates to Eckert IV projection (easting and northing)
    00279  * coordinates, according to the current ellipsoid, spherical radius and
    00280  * Eckert IV projection parameters.
    00281  * If any errors occur, an exception is thrown with a description
    00282  * of the error.
    00283  *
    00284  *    longitude         : Longitude (lambda) in radians       (input)
    00285  *    latitude          : Latitude (phi) in radians           (input)
    00286  *    easting           : Easting (X) in meters               (output)
    00287  *    northing          : Northing (Y) in meters              (output)
    00288  */
    00289
    00290   double sin_theta, cos_theta;
    00291   double num;
    00292   double dlam;     /* Longitude - Central Meridan */
    00293   double delta_theta = 1.0;
    00294   double dt_tolerance = 4.85e-10;        /* approximately 1/1000th of
    00295                                             an arc second or 1/10th meter */
    00296   int count = 200;
    00297   char errorStatus[50] = "";
    00298
    00299   double longitude = geodeticCoordinates->longitude();
    00300   double latitude = geodeticCoordinates->latitude();
    00301   double slat = sin(latitude);
    00302   double theta = latitude / 2.0;
    00303
    00304   if ((latitude < -PI_OVER_2) || (latitude > PI_OVER_2))
    00305   {  /* Latitude out of range */
    00306     strcat( errorStatus, MSP::CCS::ErrorMessages::latitude );
    00307   }
    00308   if ((longitude < -PI) || (longitude > TWO_PI))
    00309   {  /* Longitude out of range */
    00310     strcat( errorStatus, MSP::CCS::ErrorMessages::longitude );
    00311   }
    00312
    00313   if( strlen( errorStatus ) > 0)
    00314     throw CoordinateConversionException( errorStatus );
    00315
    00316   dlam = longitude - Eck4_Origin_Long;
    00317   if (dlam > PI)
    00318   {
    00319     dlam -= TWO_PI;
    00320   }
    00321   if (dlam < -PI)
    00322   {
    00323     dlam += TWO_PI;
    00324   }
    00325   while (fabs(delta_theta) > dt_tolerance && count)
    00326   {
    00327     sin_theta = sin(theta);
    00328     cos_theta = cos(theta);
    00329     num = calculateNum(theta, sin_theta, cos_theta);
    00330     delta_theta = -(num - two_PLUS_PI_OVER_2 * slat) /
    00331                   (2.0 * cos_theta * (1.0 + cos_theta));
    00332     theta += delta_theta;
    00333     count --;
    00334   }
    00335
    00336   if(!count)
    00337     throw CoordinateConversionException( ErrorMessages::northing );
    00338
    00339   double easting = Ra0 * dlam * (1.0 + cos(theta)) + Eck4_False_Easting;
    00340   double northing = Ra1 * sin(theta) + Eck4_False_Northing;
    00341
    00342   return new MapProjectionCoordinates( CoordinateType::eckert4, easting, northing );
    00343 }
    00344
    00345
    00346 MSP::CCS::GeodeticCoordinates* Eckert4::convertToGeodetic( MSP::CCS::MapProjectionCoordinates* mapProjectionCoordinates )
    00347 {
    00348 /*
    00349  * The function convertToGeodetic converts Eckert IV projection
    00350  * (easting and northing) coordinates to geodetic (latitude and longitude)
    00351  * coordinates, according to the current ellipsoid, spherical radius and
    00352  * Eckert IV projection coordinates.
    00353  * If any errors occur, an exception is thrown with a description
    00354  * of the error.
    00355  *
    00356  *    easting           : Easting (X) in meters                  (input)
    00357  *    northing          : Northing (Y) in meters                 (input)
    00358  *    longitude         : Longitude (lambda) in radians          (output)
    00359  *    latitude          : Latitude (phi) in radians              (output)
    00360  */
    00361
    00362   double theta;
    00363   double sin_theta, cos_theta;
    00364   double num;
    00365   double dx, dy;
    00366   double i;
    00367   char errorStatus[50] = "";
    00368
    00369   double easting = mapProjectionCoordinates->easting();
    00370   double northing = mapProjectionCoordinates->northing();
    00371
    00372   if ((easting < (Eck4_False_Easting + Eck4_Min_Easting))
    00373       || (easting > (Eck4_False_Easting + Eck4_Max_Easting)))
    00374   { /* Easting out of range  */
    00375     strcat( errorStatus, MSP::CCS::ErrorMessages::easting );
    00376   }
    00377   if ((northing < (Eck4_False_Northing - Eck4_Delta_Northing))
    00378       || (northing > (Eck4_False_Northing + Eck4_Delta_Northing)))
    00379   { /* Northing out of range */
    00380     strcat( errorStatus, MSP::CCS::ErrorMessages::northing );
    00381   }
    00382
    00383   if( strlen( errorStatus ) > 0)
    00384     throw CoordinateConversionException( errorStatus );
    00385
    00386   dy = northing - Eck4_False_Northing;
    00387   dx = easting - Eck4_False_Easting;
    00388   i = dy / Ra1;
    00389   if (i > 1.0)
    00390     i = 1.0;
    00391   else if (i < -1.0)
    00392     i = -1.0;
    00393
    00394   theta = asin(i);
    00395   sin_theta = sin(theta);
    00396   cos_theta = cos(theta);
    00397   num = calculateNum(theta, sin_theta, cos_theta);
    00398
    00399   double latitude = asin(num / two_PLUS_PI_OVER_2);
    00400   double longitude = Eck4_Origin_Long + dx / (Ra0 * (1 + cos_theta));
    00401
    00402   if (latitude > PI_OVER_2)  /* force distorted values to 90, -90 degrees */
    00403     latitude = PI_OVER_2;
    00404   else if (latitude < -PI_OVER_2)
    00405     latitude = -PI_OVER_2;
    00406
    00407   if (longitude > PI)
    00408     longitude -= TWO_PI;
    00409   if (longitude < -PI)
    00410     longitude += TWO_PI;
    00411
    00412   if (longitude > PI)  /* force distorted values to 180, -180 degrees */
    00413     longitude = PI;
    00414   else if (longitude < -PI)
    00415     longitude = -PI;
    00416
    00417   return new GeodeticCoordinates( CoordinateType::geodetic, longitude, latitude );
    00418 }
    00419
    00420
    00421
    00422 // CLASSIFICATION: UNCLASSIFIED