- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

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

Go to the documentation of this file.

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