- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

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

Go to the documentation of this file.

    00001 // CLASSIFICATION: UNCLASSIFIED
    00002
    00003 /********************************************************************/
    00004 /* RSC IDENTIFIER: UPS
    00005  *
    00006  *
    00007  * ABSTRACT
    00008  *
    00009  *    This component provides conversions between geodetic (latitude
    00010  *    and longitude) coordinates and Universal Polar Stereographic (UPS)
    00011  *    projection (hemisphere, easting, and northing) coordinates.
    00012  *
    00013  *
    00014  * ERROR HANDLING
    00015  *
    00016  *    This component checks parameters for valid values.  If an
    00017  *    invalid value is found the error code is combined with the
    00018  *    current error code using the bitwise or.  This combining allows
    00019  *    multiple error codes to be returned. The possible error codes
    00020  *    are:
    00021  *
    00022  *         UPS_NO_ERROR           : No errors occurred in function
    00023  *         UPS_LAT_ERROR          : Latitude outside of valid range
    00024  *                                   (North Pole: 83.5 to 90,
    00025  *                                    South Pole: -79.5 to -90)
    00026  *         UPS_LON_ERROR          : Longitude outside of valid range
    00027  *                                   (-180 to 360 degrees)
    00028  *         UPS_HEMISPHERE_ERROR   : Invalid hemisphere ('N' or 'S')
    00029  *         UPS_EASTING_ERROR      : Easting outside of valid range,
    00030  *                                   (0 to 4,000,000m)
    00031  *         UPS_NORTHING_ERROR     : Northing outside of valid range,
    00032  *                                   (0 to 4,000,000m)
    00033  *         UPS_A_ERROR            : Semi-major axis less than or equal to zero
    00034  *         UPS_INV_F_ERROR        : Inverse flattening outside of valid range
    00035  *                                                                                     (250 to 350)
    00036  *
    00037  *
    00038  * REUSE NOTES
    00039  *
    00040  *    UPS is intended for reuse by any application that performs a Universal
    00041  *    Polar Stereographic (UPS) projection.
    00042  *
    00043  *
    00044  * REFERENCES
    00045  *
    00046  *    Further information on UPS can be found in the Reuse Manual.
    00047  *
    00048  *    UPS originated from :  U.S. Army Topographic Engineering Center
    00049  *                           Geospatial Information Division
    00050  *                           7701 Telegraph Road
    00051  *                           Alexandria, VA  22310-3864
    00052  *
    00053  *
    00054  * LICENSES
    00055  *
    00056  *    None apply to this component.
    00057  *
    00058  *
    00059  * RESTRICTIONS
    00060  *
    00061  *    UPS has no restrictions.
    00062  *
    00063  *
    00064  * ENVIRONMENT
    00065  *
    00066  *    UPS was tested and certified in the following environments:
    00067  *
    00068  *    1. Solaris 2.5 with GCC version 2.8.1
    00069  *    2. Windows 95 with MS Visual C++ version 6
    00070  *
    00071  *
    00072  * MODIFICATIONS
    00073  *
    00074  *    Date              Description
    00075  *    ----              -----------
    00076  *    2-27-07          Original Code
    00077  *
    00078  *
    00079  */
    00080
    00081
    00082 /************************************************************************/
    00083 /*
    00084  *                               INCLUDES
    00085  */
    00086
    00087 #include <math.h>
    00088 #include "UPS.h"
    00089 #include "PolarStereographic.h"
    00090 #include "PolarStereographicScaleFactorParameters.h"
    00091 #include "MapProjectionCoordinates.h"
    00092 #include "UPSCoordinates.h"
    00093 #include "GeodeticCoordinates.h"
    00094 #include "CoordinateConversionException.h"
    00095 #include "ErrorMessages.h"
    00096
    00097 /*
    00098  *    UPS.h      - Defines the function prototypes for the ups module.
    00099  *    PolarStereographic.h    - Is used to convert polar stereographic coordinates
    00100  *    MapProjectionCoordinates.h   - defines map projection coordinates
    00101  *    UPSCoordinates.h   - defines UPS coordinates
    00102  *    GeodeticCoordinates.h   - defines geodetic coordinates
    00103  *    CoordinateConversionException.h - Exception handler
    00104  *    ErrorMessages.h  - Contains exception messages
    00105  */
    00106
    00107
    00108 using namespace MSP::CCS;
    00109
    00110
    00111 /***************************************************************************/
    00112 /*
    00113  *                              DEFINES
    00114  */
    00115
    00116 #define EPSILON 1.75e-7   /* approx 1.0e-5 degrees (~1 meter) in radians */
    00117
    00118 const double PI = 3.14159265358979323e0;     /* PI     */
    00119 const double PI_OVER = (PI/2.0e0);           /* PI over 2 */
    00120 const double MAX_LAT = 90.0 * (PI / 180.0);    /* 90 degrees in radians */
    00121 const double MAX_ORIGIN_LAT = 81.114528 * (PI / 180.0);
    00122 const double MIN_NORTH_LAT = 83.5 * (PI / 180.0);
    00123 const double MAX_SOUTH_LAT = -79.5 * (PI / 180.0);
    00124 const double MIN_EAST_NORTH = 0.0;
    00125 const double MAX_EAST_NORTH = 4000000.0;
    00126
    00127 const double UPS_False_Easting = 2000000;
    00128 const double UPS_False_Northing = 2000000;
    00129 const double UPS_Origin_Longitude = 0.0;
    00130
    00131
    00132 /************************************************************************/
    00133 /*                              FUNCTIONS
    00134  *
    00135  */
    00136
    00137 UPS::UPS( double ellipsoidSemiMajorAxis, double ellipsoidFlattening ) :
    00138   CoordinateSystem(),
    00139   UPS_Origin_Latitude( MAX_ORIGIN_LAT )
    00140 {
    00141 /*
    00142  * The constructor receives the ellipsoid parameters and sets
    00143  * the corresponding state variables. If any errors occur, an exception is
    00144  * thrown with a description of the error.
    00145  *
    00146  *   ellipsoidSemiMajorAxis     : Semi-major axis of ellipsoid in meters (input)
    00147  *   ellipsoidFlattening        : Flattening of ellipsoid                                              (input)
    00148  */
    00149
    00150   double inv_f = 1 / ellipsoidFlattening;
    00151   char errorStatus[500] = "";
    00152
    00153   if (ellipsoidSemiMajorAxis <= 0.0)
    00154   { /* Semi-major axis must be greater than zero */
    00155     strcat( errorStatus, ErrorMessages::semiMajorAxis );
    00156   }
    00157   if ((inv_f < 250) || (inv_f > 350))
    00158   { /* Inverse flattening must be between 250 and 350 */
    00159     strcat( errorStatus, ErrorMessages::ellipsoidFlattening );
    00160   }
    00161
    00162   if( strlen( errorStatus ) > 0)
    00163     throw CoordinateConversionException( errorStatus );
    00164
    00165   semiMajorAxis = ellipsoidSemiMajorAxis;
    00166   flattening = ellipsoidFlattening;
    00167
    00168   polarStereographicMap['N'] = new PolarStereographic(semiMajorAxis, flattening, UPS_Origin_Longitude, .994, 'N', UPS_False_Easting, UPS_False_Northing);
    00169   polarStereographicMap['S'] = new PolarStereographic(semiMajorAxis, flattening, UPS_Origin_Longitude, .994, 'S', UPS_False_Easting, UPS_False_Northing);
    00172 }
    00173
    00174
    00175 UPS::UPS( const UPS &u )
    00176 {
    00177   std::map< char, PolarStereographic* > tempPolarStereographicMap = u.polarStereographicMap;
    00178   polarStereographicMap['N'] = new PolarStereographic( *tempPolarStereographicMap['N'] );
    00179   polarStereographicMap['S'] = new PolarStereographic( *tempPolarStereographicMap['S'] );
    00180   semiMajorAxis = u.semiMajorAxis;
    00181   flattening = u.flattening;
    00182   UPS_Origin_Latitude = u.UPS_Origin_Latitude;
    00183 }
    00184
    00185
    00186 UPS::~UPS()
    00187 {
    00188         while( polarStereographicMap.begin() != polarStereographicMap.end() )
    00189         {
    00190                 delete ( ( *polarStereographicMap.begin() ).second );
    00191                 polarStereographicMap.erase( polarStereographicMap.begin() );
    00192         }
    00193 }
    00194
    00195
    00196 UPS& UPS::operator=( const UPS &u )
    00197 {
    00198   if( this != &u )
    00199   {
    00200     std::map< char, PolarStereographic* > tempPolarStereographicMap = u.polarStereographicMap;
    00201     polarStereographicMap['N']->operator=( *tempPolarStereographicMap['N'] );
    00202     polarStereographicMap['S']->operator=( *tempPolarStereographicMap['S'] );
    00203     semiMajorAxis = u.semiMajorAxis;
    00204     flattening = u.flattening;
    00205     UPS_Origin_Latitude = u.UPS_Origin_Latitude;
    00206   }
    00207
    00208   return *this;
    00209 }
    00210
    00211
    00212 MSP::CCS::UPSCoordinates* UPS::convertFromGeodetic( MSP::CCS::GeodeticCoordinates* geodeticCoordinates )
    00213 {
    00214 /*
    00215  * The function convertFromGeodetic converts geodetic (latitude and
    00216  * longitude) coordinates to UPS (hemisphere, easting, and northing)
    00217  * coordinates, according to the current ellipsoid parameters.
    00218  * If any errors occur, an exception is thrown with a description
    00219  * of the error.
    00220  *
    00221  *    latitude      : Latitude in radians                       (input)
    00222  *    longitude     : Longitude in radians                      (input)
    00223  *    hemisphere    : Hemisphere either 'N' or 'S'              (output)
    00224  *    easting       : Easting/X in meters                       (output)
    00225  *    northing      : Northing/Y in meters                      (output)
    00226  */
    00227
    00228   char hemisphere;
    00229   char errorStatus[50] = "";
    00230
    00231   double longitude = geodeticCoordinates->longitude();
    00232   double latitude = geodeticCoordinates->latitude();
    00233
    00234   if ((latitude < -MAX_LAT) || (latitude > MAX_LAT))
    00235   {   /* latitude out of range */
    00236     strcat( errorStatus, ErrorMessages::latitude );
    00237   }
    00238   else if ((latitude < 0) && (latitude >= (MAX_SOUTH_LAT + EPSILON)))
    00239     strcat( errorStatus, ErrorMessages::latitude );
    00240   else if ((latitude >= 0) && (latitude < (MIN_NORTH_LAT - EPSILON)))
    00241     strcat( errorStatus, ErrorMessages::latitude );
    00242   if ((longitude < -PI) || (longitude > (2 * PI)))
    00243   {  /* longitude out of range */
    00244     strcat( errorStatus, ErrorMessages::longitude );
    00245   }
    00246
    00247   if( strlen( errorStatus ) > 0)
    00248     throw CoordinateConversionException( errorStatus );
    00249
    00250   if (latitude < 0)
    00251   {
    00252     UPS_Origin_Latitude = -MAX_ORIGIN_LAT;
    00253     hemisphere = 'S';
    00254   }
    00255   else
    00256   {
    00257     UPS_Origin_Latitude = MAX_ORIGIN_LAT;
    00258     hemisphere = 'N';
    00259   }
    00260
    00261   PolarStereographic polarStereographic = *polarStereographicMap[hemisphere];
    00262   MapProjectionCoordinates* polarStereographicCoordinates = polarStereographic.convertFromGeodetic( geodeticCoordinates );
    00263
    00264   double easting = polarStereographicCoordinates->easting();
    00265   double northing = polarStereographicCoordinates->northing();
    00266   delete polarStereographicCoordinates;
    00267
    00268   return new UPSCoordinates( CoordinateType::universalPolarStereographic, hemisphere, easting, northing );
    00269 }
    00270
    00271
    00272 MSP::CCS::GeodeticCoordinates* UPS::convertToGeodetic( MSP::CCS::UPSCoordinates* upsCoordinates )
    00273 {
    00274 /*
    00275  * The function convertToGeodetic converts UPS (hemisphere, easting,
    00276  * and northing) coordinates to geodetic (latitude and longitude) coordinates
    00277  * according to the current ellipsoid parameters.  If any errors occur, an
    00278  * exception is thrown with a description of the error.
    00279  *
    00280  *    hemisphere    : Hemisphere either 'N' or 'S'              (input)
    00281  *    easting       : Easting/X in meters                       (input)
    00282  *    northing      : Northing/Y in meters                      (input)
    00283  *    latitude      : Latitude in radians                       (output)
    00284  *    longitude     : Longitude in radians                      (output)
    00285  */
    00286
    00287   char errorStatus[50] = "";
    00288
    00289   char hemisphere = upsCoordinates->hemisphere();
    00290   double easting = upsCoordinates->easting();
    00291   double northing = upsCoordinates->northing();
    00292
    00293   if ((hemisphere != 'N') && (hemisphere != 'S'))
    00294     strcat( errorStatus, ErrorMessages::hemisphere );
    00295   if ((easting < MIN_EAST_NORTH) || (easting > MAX_EAST_NORTH))
    00296     strcat( errorStatus, ErrorMessages::easting );
    00297   if ((northing < MIN_EAST_NORTH) || (northing > MAX_EAST_NORTH))
    00298     strcat( errorStatus, ErrorMessages::northing );
    00299
    00300   if (hemisphere =='N')
    00301   {
    00302     UPS_Origin_Latitude = MAX_ORIGIN_LAT;
    00303   }
    00304   else if (hemisphere =='S')
    00305   {
    00306     UPS_Origin_Latitude = -MAX_ORIGIN_LAT;
    00307   }
    00308
    00309   if( strlen( errorStatus ) > 0)
    00310     throw CoordinateConversionException( errorStatus );
    00311
    00312   MapProjectionCoordinates polarStereographicCoordinates( CoordinateType::polarStereographicStandardParallel, easting, northing );
    00313   PolarStereographic polarStereographic = *polarStereographicMap[hemisphere];
    00314   GeodeticCoordinates* geodeticCoordinates = polarStereographic.convertToGeodetic( &polarStereographicCoordinates );
    00315
    00316   double latitude = geodeticCoordinates->latitude();
    00317
    00318   if ((latitude < 0) && (latitude >= (MAX_SOUTH_LAT + EPSILON)))
    00319   {
    00320     delete geodeticCoordinates;
    00321     throw CoordinateConversionException( ErrorMessages::latitude );
    00322   }
    00323   if ((latitude >= 0) && (latitude < (MIN_NORTH_LAT - EPSILON)))
    00324   {
    00325     delete geodeticCoordinates;
    00326     throw CoordinateConversionException( ErrorMessages::latitude );
    00327   }
    00328
    00329   return geodeticCoordinates;
    00330 }
    00331
    00332 // CLASSIFICATION: UNCLASSIFIED