- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

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

Go to the documentation of this file.

    00001 // CLASSIFICATION: UNCLASSIFIED
    00002
    00003 /***************************************************************************/
    00004 /* RSC IDENTIFIER: MILLER
    00005  *
    00006  * ABSTRACT
    00007  *
    00008  *    This component provides conversions between Geodetic coordinates
    00009  *    (latitude and longitude in radians) and Miller Cylindrical projection
    00010  *    coordinates (easting and northing in meters).  The Miller 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  *          MILL_NO_ERROR           : No errors occurred in function
    00023  *          MILL_LAT_ERROR          : Latitude outside of valid range
    00024  *                                      (-90 to 90 degrees)
    00025  *          MILL_LON_ERROR          : Longitude outside of valid range
    00026  *                                      (-180 to 360 degrees)
    00027  *          MILL_EASTING_ERROR      : Easting outside of valid range
    00028  *                                      (False_Easting +/- ~20,000,000 m,
    00029  *                                       depending on ellipsoid parameters)
    00030  *          MILL_NORTHING_ERROR     : Northing outside of valid range
    00031  *                                      (False_Northing +/- ~14,000,000 m,
    00032  *                                       depending on ellipsoid parameters)
    00033  *          MILL_CENT_MER_ERROR     : Central meridian outside of valid range
    00034  *                                      (-180 to 360 degrees)
    00035  *          MILL_A_ERROR            : Semi-major axis less than or equal to zero
    00036  *          MILL_INV_F_ERROR        : Inverse flattening outside of valid range
    00037  *                                                                                          (250 to 350)
    00038  *
    00039  * REUSE NOTES
    00040  *
    00041  *    MILLER is intended for reuse by any application that performs a
    00042  *    Miller Cylindrical projection or its inverse.
    00043  *
    00044  * REFERENCES
    00045  *
    00046  *    Further information on MILLER can be found in the Reuse Manual.
    00047  *
    00048  *    MILLER 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  *    MILLER has no restrictions.
    00060  *
    00061  * ENVIRONMENT
    00062  *
    00063  *    MILLER 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 "MillerCylindrical.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  *    MillerCylindrical.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 TWO_PI = (2.0 * PI);
    00112
    00113
    00114 /************************************************************************/
    00115 /*                              FUNCTIONS
    00116  *
    00117  */
    00118
    00119 MillerCylindrical::MillerCylindrical( double ellipsoidSemiMajorAxis, double ellipsoidFlattening, double centralMeridian, double falseEasting, double falseNorthing ) :
    00120   CoordinateSystem(),
    00121    es2( 0.0066943799901413800 ),
    00122    es4( 4.4814723452405e-005 ),
    00123    es6( 3.0000678794350e-007 ),
    00124    Ra( 6371007.1810824 ),
    00125    Mill_Origin_Long( 0.0 ),
    00126    Mill_False_Easting( 0.0 ),
    00127    Mill_False_Northing( 0.0 ),
    00128    Mill_Delta_Northing( 14675058.0 ),
    00129    Mill_Max_Easting( 20015110.0 ),
    00130    Mill_Min_Easting( -20015110.0 )
    00131 {
    00132 /*
    00133  * The constructor receives the ellipsoid parameters and
    00134  * Miller Cylindrical projcetion parameters as inputs, and sets the corresponding
    00135  * state variables.  If any errors occur, an exception is thrown with a description
    00136  * of the error.
    00137  *
    00138  *    ellipsoidSemiMajorAxis  : Semi-major axis of ellipsoid, in meters   (input)
    00139  *    ellipsoidFlattening     : Flattening of ellipsoid                                                 (input)
    00140  *    centralMeridian         : Longitude in radians at the center of     (input)
    00141  *                              the projection
    00142  *    falseEasting            : A coordinate value in meters assigned to the
    00143  *                              central meridian of the projection.       (input)
    00144  *    falseNorthing           : A coordinate value in meters assigned to the
    00145  *                              origin latitude of the projection         (input)
    00146  */
    00147
    00148   double inv_f = 1 / ellipsoidFlattening;
    00149   char errorStatus[500] = "";
    00150
    00151   if (ellipsoidSemiMajorAxis <= 0.0)
    00152   { /* Semi-major axis must be greater than zero */
    00153     strcat( errorStatus, ErrorMessages::semiMajorAxis );
    00154   }
    00155   if ((inv_f < 250) || (inv_f > 350))
    00156   { /* Inverse flattening must be between 250 and 350 */
    00157     strcat( errorStatus, ErrorMessages::ellipsoidFlattening );
    00158   }
    00159   if ((centralMeridian < -PI) || (centralMeridian > TWO_PI))
    00160   { /* origin longitude out of range */
    00161     strcat( errorStatus, ErrorMessages::centralMeridian );
    00162   }
    00163
    00164   if( strlen( errorStatus ) > 0)
    00165     throw CoordinateConversionException( errorStatus );
    00166
    00167   semiMajorAxis = ellipsoidSemiMajorAxis;
    00168   flattening = ellipsoidFlattening;
    00169
    00170   es2 = 2 * flattening - flattening * flattening;
    00171   es4 = es2 * es2;
    00172   es6 = es4 * es2;
    00173   /* spherical radius */
    00174   Ra = semiMajorAxis * (1.0 - es2 / 6.0 - 17.0 * es4 / 360.0 - 67.0 * es6 /3024.0);
    00175   if (centralMeridian > PI)
    00176     centralMeridian -= TWO_PI;
    00177   Mill_Origin_Long = centralMeridian;
    00178   Mill_False_Easting = falseEasting;
    00179   Mill_False_Northing = falseNorthing;
    00180   if (Mill_Origin_Long > 0)
    00181   {
    00182     Mill_Max_Easting = 19903915.0;
    00183     Mill_Min_Easting = -20015110.0;
    00184   }
    00185   else if (Mill_Origin_Long < 0)
    00186   {
    00187     Mill_Max_Easting = 20015110.0;
    00188     Mill_Min_Easting = -19903915.0;
    00189   }
    00190   else
    00191   {
    00192     Mill_Max_Easting = 20015110.0;
    00193     Mill_Min_Easting = -20015110.0;
    00194   }
    00195 }
    00196
    00197
    00198 MillerCylindrical::MillerCylindrical( const MillerCylindrical &mc )
    00199 {
    00200   semiMajorAxis = mc.semiMajorAxis;
    00201   flattening = mc.flattening;
    00202   es2 = mc.es2;
    00203   es4 = mc.es4;
    00204   es6 = mc.es6;
    00205   Ra = mc.Ra;
    00206   Mill_Origin_Long = mc.Mill_Origin_Long;
    00207   Mill_False_Easting = mc.Mill_False_Easting;
    00208   Mill_False_Northing = mc.Mill_False_Northing;
    00209   Mill_Delta_Northing = mc.Mill_Delta_Northing;
    00210   Mill_Max_Easting = mc.Mill_Max_Easting;
    00211   Mill_Min_Easting = mc.Mill_Min_Easting;
    00212 }
    00213
    00214
    00215 MillerCylindrical::~MillerCylindrical()
    00216 {
    00217 }
    00218
    00219
    00220 MillerCylindrical& MillerCylindrical::operator=( const MillerCylindrical &mc )
    00221 {
    00222   if( this != &mc )
    00223   {
    00224     semiMajorAxis = mc.semiMajorAxis;
    00225     flattening = mc.flattening;
    00226     es2 = mc.es2;
    00227     es4 = mc.es4;
    00228     es6 = mc.es6;
    00229     Ra = mc.Ra;
    00230     Mill_Origin_Long = mc.Mill_Origin_Long;
    00231     Mill_False_Easting = mc.Mill_False_Easting;
    00232     Mill_False_Northing = mc.Mill_False_Northing;
    00233     Mill_Delta_Northing = mc.Mill_Delta_Northing;
    00234     Mill_Max_Easting = mc.Mill_Max_Easting;
    00235     Mill_Min_Easting = mc.Mill_Min_Easting;
    00236   }
    00237
    00238   return *this;
    00239 }
    00240
    00241
    00242 MapProjection3Parameters* MillerCylindrical::getParameters() const
    00243 {
    00244 /*
    00245  * The function getParameters returns the current ellipsoid
    00246  * parameters and Miller Cylindrical projection parameters.
    00247  *
    00248  *    ellipsoidSemiMajorAxis  : Semi-major axis of ellipsoid, in meters   (output)
    00249  *    ellipsoidFlattening     : Flattening of ellipsoid                                                 (output)
    00250  *    centralMeridian         : Longitude in radians at the center of     (output)
    00251  *                              the projection
    00252  *    falseEasting            : A coordinate value in meters assigned to the
    00253  *                              central meridian of the projection.       (output)
    00254  *    falseNorthing           : A coordinate value in meters assigned to the
    00255  *                              origin latitude of the projection         (output)
    00256  */
    00257
    00258   return new MapProjection3Parameters( CoordinateType::millerCylindrical, Mill_Origin_Long, Mill_False_Easting, Mill_False_Northing );
    00259 }
    00260
    00261
    00262 MSP::CCS::MapProjectionCoordinates* MillerCylindrical::convertFromGeodetic( MSP::CCS::GeodeticCoordinates* geodeticCoordinates )
    00263 {
    00264 /*
    00265  * The function convertFromGeodetic converts geodetic (latitude and
    00266  * longitude) coordinates to Miller Cylindrical projection (easting and northing)
    00267  * coordinates, according to the current ellipsoid and Miller Cylindrical projection
    00268  * parameters.  If any errors occur, an exception is thrown with a description
    00269  * of the error.
    00270  *
    00271  *    longitude         : Longitude (lambda) in radians       (input)
    00272  *    latitude          : Latitude (phi) in radians           (input)
    00273  *    easting           : Easting (X) in meters               (output)
    00274  *    northing          : Northing (Y) in meters              (output)
    00275  */
    00276
    00277   double dlam;     /* Longitude - Central Meridan */
    00278   char errorStatus[50] = "";
    00279
    00280   double longitude = geodeticCoordinates->longitude();
    00281   double latitude = geodeticCoordinates->latitude();
    00282   double slat = sin(0.8 * latitude);
    00283
    00284   if ((latitude < -PI_OVER_2) || (latitude > PI_OVER_2))
    00285   {  /* Latitude out of range */
    00286     strcat( errorStatus, ErrorMessages::latitude );
    00287   }
    00288   if ((longitude < -PI) || (longitude > TWO_PI))
    00289   {  /* Longitude out of range */
    00290     strcat( errorStatus, ErrorMessages::longitude );
    00291   }
    00292
    00293   if( strlen( errorStatus ) > 0)
    00294     throw CoordinateConversionException( errorStatus );
    00295
    00296   dlam = longitude - Mill_Origin_Long;
    00297   if (dlam > PI)
    00298   {
    00299     dlam -= TWO_PI;
    00300   }
    00301   if (dlam < -PI)
    00302   {
    00303     dlam += TWO_PI;
    00304   }
    00305   double easting = Ra * dlam + Mill_False_Easting;
    00306   double northing = (Ra / 1.6) * log((1.0 + slat) /
    00307                                (1.0 - slat)) + Mill_False_Northing;
    00308
    00309   return new MapProjectionCoordinates( CoordinateType::millerCylindrical, easting, northing );
    00310 }
    00311
    00312
    00313 MSP::CCS::GeodeticCoordinates* MillerCylindrical::convertToGeodetic( MSP::CCS::MapProjectionCoordinates* mapProjectionCoordinates )
    00314 {
    00315 /*
    00316  * The function convertToGeodetic converts Miller Cylindrical projection
    00317  * (easting and northing) coordinates to geodetic (latitude and longitude)
    00318  * coordinates, according to the current ellipsoid and Miller Cylindrical projection
    00319  * coordinates.  If any errors occur, an exception is thrown with a description
    00320  * of the error.
    00321  *
    00322  *    easting           : Easting (X) in meters                  (input)
    00323  *    northing          : Northing (Y) in meters                 (input)
    00324  *    longitude         : Longitude (lambda) in radians          (output)
    00325  *    latitude          : Latitude (phi) in radians              (output)
    00326  */
    00327
    00328   double dx, dy;
    00329   char errorStatus[50] = "";
    00330
    00331   double easting = mapProjectionCoordinates->easting();
    00332   double northing = mapProjectionCoordinates->northing();
    00333
    00334   if ((easting < (Mill_False_Easting + Mill_Min_Easting))
    00335       || (easting > (Mill_False_Easting + Mill_Max_Easting)))
    00336   { /* Easting out of range  */
    00337     strcat( errorStatus, ErrorMessages::easting );
    00338   }
    00339   if ((northing < (Mill_False_Northing - Mill_Delta_Northing)) ||
    00340       (northing > (Mill_False_Northing + Mill_Delta_Northing) ))
    00341   { /* Northing out of range */
    00342     strcat( errorStatus, ErrorMessages::northing );
    00343   }
    00344
    00345   if( strlen( errorStatus ) > 0)
    00346     throw CoordinateConversionException( errorStatus );
    00347
    00348   dy = northing - Mill_False_Northing;
    00349   dx = easting - Mill_False_Easting;
    00350   double latitude = atan(sinh(0.8 * dy / Ra)) / 0.8;
    00351   double longitude = Mill_Origin_Long + dx / Ra;
    00352
    00353   if (latitude > PI_OVER_2)  /* force distorted values to 90, -90 degrees */
    00354     latitude = PI_OVER_2;
    00355   else if (latitude < -PI_OVER_2)
    00356     latitude = -PI_OVER_2;
    00357
    00358   if (longitude > PI)
    00359     longitude -= TWO_PI;
    00360   if (longitude < -PI)
    00361     longitude += TWO_PI;
    00362
    00363   if (longitude > PI)  /* force distorted values to 180, -180 degrees */
    00364     longitude = PI;
    00365   else if (longitude < -PI)
    00366     longitude = -PI;
    00367
    00368   return new GeodeticCoordinates( CoordinateType::geodetic, longitude, latitude );
    00369 }
    00370
    00371
    00372
    00373 // CLASSIFICATION: UNCLASSIFIED