- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

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

Go to the documentation of this file.

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