- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

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

Go to the documentation of this file.

    00001 // CLASSIFICATION: UNCLASSIFIED
    00002
    00003 /***************************************************************************/
    00004 /* RSC IDENTIFIER: POLAR STEREOGRAPHIC
    00005  *
    00006  *
    00007  * ABSTRACT
    00008  *
    00009  *    This component provides conversions between geodetic (latitude and
    00010  *    longitude) coordinates and Polar Stereographic (easting and northing)
    00011  *    coordinates.
    00012  *
    00013  * ERROR HANDLING
    00014  *
    00015  *    This component checks parameters for valid values.  If an invalid
    00016  *    value is found the error code is combined with the current error code
    00017  *    using the bitwise or.  This combining allows multiple error codes to
    00018  *    be returned. The possible error codes are:
    00019  *
    00020  *          POLAR_NO_ERROR           : No errors occurred in function
    00021  *          POLAR_LAT_ERROR          : Latitude outside of valid range
    00022  *                                      (-90 to 90 degrees)
    00023  *          POLAR_LON_ERROR          : Longitude outside of valid range
    00024  *                                      (-180 to 360 degrees)
    00025  *          POLAR_ORIGIN_LAT_ERROR   : Latitude of true scale outside of valid
    00026  *                                      range (-90 to 90 degrees)
    00027  *          POLAR_ORIGIN_LON_ERROR   : Longitude down from pole outside of valid
    00028  *                                      range (-180 to 360 degrees)
    00029  *          POLAR_EASTING_ERROR      : Easting outside of valid range,
    00030  *                                      depending on ellipsoid and
    00031  *                                      projection parameters
    00032  *          POLAR_NORTHING_ERROR     : Northing outside of valid range,
    00033  *                                      depending on ellipsoid and
    00034  *                                      projection parameters
    00035  *          POLAR_RADIUS_ERROR       : Coordinates too far from pole,
    00036  *                                      depending on ellipsoid and
    00037  *                                      projection parameters
    00038  *          POLAR_A_ERROR            : Semi-major axis less than or equal to zero
    00039  *          POLAR_INV_F_ERROR        : Inverse flattening outside of valid range
    00040  *                                                                                        (250 to 350)
    00041  *
    00042  *
    00043  * REUSE NOTES
    00044  *
    00045  *    POLAR STEREOGRAPHIC is intended for reuse by any application that
    00046  *    performs a Polar Stereographic projection.
    00047  *
    00048  *
    00049  * REFERENCES
    00050  *
    00051  *    Further information on POLAR STEREOGRAPHIC can be found in the
    00052  *    Reuse Manual.
    00053  *
    00054  *
    00055  *    POLAR STEREOGRAPHIC originated from :
    00056  *                                U.S. Army Topographic Engineering Center
    00057  *                                Geospatial Information Division
    00058  *                                7701 Telegraph Road
    00059  *                                Alexandria, VA  22310-3864
    00060  *
    00061  *
    00062  * LICENSES
    00063  *
    00064  *    None apply to this component.
    00065  *
    00066  *
    00067  * RESTRICTIONS
    00068  *
    00069  *    POLAR STEREOGRAPHIC has no restrictions.
    00070  *
    00071  *
    00072  * ENVIRONMENT
    00073  *
    00074  *    POLAR STEREOGRAPHIC was tested and certified in the following
    00075  *    environments:
    00076  *
    00077  *    1. Solaris 2.5 with GCC, version 2.8.1
    00078  *    2. Window 95 with MS Visual C++, version 6
    00079  *
    00080  *
    00081  * MODIFICATIONS
    00082  *
    00083  *    Date              Description
    00084  *    ----              -----------
    00085  *    2-27-07          Original Code
    00086  *
    00087  *
    00088  */
    00089
    00090
    00091 /************************************************************************/
    00092 /*
    00093  *                               INCLUDES
    00094  */
    00095
    00096 #include <stdio.h>
    00097 #include <math.h>
    00098 #include "PolarStereographic.h"
    00099 #include "PolarStereographicStandardParallelParameters.h"
    00100 #include "PolarStereographicScaleFactorParameters.h"
    00101 #include "MapProjectionCoordinates.h"
    00102 #include "GeodeticCoordinates.h"
    00103 #include "CoordinateConversionException.h"
    00104 #include "ErrorMessages.h"
    00105
    00106 /*
    00107  *    math.h     - Standard C math library
    00108  *    PolarStereographic.h  - Is for prototype error checking
    00109  *    MapProjectionCoordinates.h   - defines map projection coordinates
    00110  *    GeodeticCoordinates.h   - defines geodetic coordinates
    00111  *    CoordinateConversionException.h - Exception handler
    00112  *    ErrorMessages.h  - Contains exception messages
    00113  */
    00114
    00115
    00116 using namespace MSP::CCS;
    00117
    00118
    00119 /************************************************************************/
    00120 /*                               DEFINES
    00121  *
    00122  */
    00123
    00124 const double PI = 3.14159265358979323e0;       /* PI     */
    00125 const double PI_OVER_2 = (PI / 2.0);
    00126 const double PI_OVER_4 = (PI / 4.0);
    00127 const double TWO_PI = (2.0 * PI);
    00128
    00129 #define MIN_SCALE_FACTOR  0.1
    00130 #define MAX_SCALE_FACTOR  3.0
    00131
    00132
    00133 /************************************************************************/
    00134 /*                              FUNCTIONS
    00135  *
    00136  */
    00137
    00138 PolarStereographic::PolarStereographic( double ellipsoidSemiMajorAxis, double ellipsoidFlattening, double centralMeridian, double standardParallel, double falseEasting, double falseNorthing ) :
    00139   CoordinateSystem(),
    00140   coordinateType( CoordinateType::polarStereographicStandardParallel ),
    00141   es( 0.08181919084262188000 ),
    00142   es_OVER_2( .040909595421311 ),
    00143   Southern_Hemisphere( 0 ),
    00144   Polar_tc( 1.0 ),
    00145   Polar_k90( 1.0033565552493 ),
    00146   Polar_a_mc( 6378137.0 ),
    00147   two_Polar_a( 12756274.0 ),
    00148   Polar_Central_Meridian( 0.0 ),
    00149   Polar_Standard_Parallel( ((PI * 90) / 180) ),
    00150   Polar_False_Easting( 0.0 ),
    00151   Polar_False_Northing( 0.0 ),
    00152   Polar_Scale_Factor( 1.0 ),
    00153   Polar_Delta_Easting( 12713601.0 ),
    00154   Polar_Delta_Northing( 12713601.0 )
    00155 {
    00156 /*
    00157  * The constructor receives the ellipsoid
    00158  * parameters and Polar Stereograpic (Standard Parallel) projection parameters as inputs, and
    00159  * sets the corresponding state variables.  If any errors occur, an
    00160  * exception is thrown with a description of the error.
    00161  *
    00162  *  ellipsoidSemiMajorAxis                : Semi-major axis of ellipsoid, in meters         (input)
    00163  *  ellipsoidFlattening                   : Flattening of ellipsoid                                                     (input)
    00164  *  centralMeridian                       : Longitude down from pole, in radians            (input)
    00165  *  standardParallel                      : Latitude of true scale, in radians              (input)
    00166  *  falseEasting                          : Easting (X) at center of projection, in meters  (input)
    00167  *  falseNorthing                         : Northing (Y) at center of projection, in meters (input)
    00168  */
    00169
    00170   double es2;
    00171   double slat, sinolat, cosolat;
    00172   double essin;
    00173   double one_PLUS_es, one_MINUS_es;
    00174   double one_PLUS_es_sinolat, one_MINUS_es_sinolat;
    00175   double pow_es;
    00176   double inv_f = 1 / ellipsoidFlattening;
    00177   char errorStatus[500] = "";
    00178
    00179   if (ellipsoidSemiMajorAxis <= 0.0)
    00180   { /* Semi-major axis must be greater than zero */
    00181     strcat( errorStatus, ErrorMessages::semiMajorAxis );
    00182   }
    00183   if ((inv_f < 250) || (inv_f > 350))
    00184   { /* Inverse flattening must be between 250 and 350 */
    00185     strcat( errorStatus, ErrorMessages::ellipsoidFlattening );
    00186   }
    00187   if ((standardParallel < -PI_OVER_2) || (standardParallel > PI_OVER_2))
    00188   { /* Origin Latitude out of range */
    00189     strcat( errorStatus, ErrorMessages::originLatitude );
    00190   }
    00191   if ((centralMeridian < -PI) || (centralMeridian > TWO_PI))
    00192   { /* Origin Longitude out of range */
    00193     strcat( errorStatus, ErrorMessages::centralMeridian );
    00194   }
    00195
    00196   if( strlen( errorStatus ) > 0)
    00197     throw CoordinateConversionException( errorStatus );
    00198
    00199   semiMajorAxis = ellipsoidSemiMajorAxis;
    00200   flattening = ellipsoidFlattening;
    00201
    00202   two_Polar_a = 2.0 * semiMajorAxis;
    00203
    00204   if (centralMeridian > PI)
    00205     centralMeridian -= TWO_PI;
    00206   if (standardParallel < 0)
    00207   {
    00208     Southern_Hemisphere = 1;
    00209     Polar_Standard_Parallel = -standardParallel;
    00210     Polar_Central_Meridian = -centralMeridian;
    00211   }
    00212   else
    00213   {
    00214     Southern_Hemisphere = 0;
    00215     Polar_Standard_Parallel = standardParallel;
    00216     Polar_Central_Meridian = centralMeridian;
    00217   }
    00218   Polar_False_Easting = falseEasting;
    00219   Polar_False_Northing = falseNorthing;
    00220
    00221   es2 = 2 * flattening - flattening * flattening;
    00222   es = sqrt(es2);
    00223   es_OVER_2 = es / 2.0;
    00224
    00225   if (fabs(fabs(Polar_Standard_Parallel) - PI_OVER_2) > 1.0e-10)
    00226   {
    00227     sinolat = sin(Polar_Standard_Parallel);
    00228     essin = es * sinolat;
    00229     pow_es = polarPow(essin);
    00230     cosolat = cos(Polar_Standard_Parallel);
    00231     double mc = cosolat / sqrt(1.0 - essin * essin);
    00232     Polar_a_mc = semiMajorAxis * mc;
    00233     Polar_tc = tan(PI_OVER_4 - Polar_Standard_Parallel / 2.0) / pow_es;
    00234   }
    00235
    00236   one_PLUS_es = 1.0 + es;
    00237         one_MINUS_es = 1.0 - es;
    00238         Polar_k90 = sqrt(pow(one_PLUS_es, one_PLUS_es) * pow(one_MINUS_es, one_MINUS_es));
    00239
    00240   slat = sin(fabs(standardParallel));
    00241   one_PLUS_es_sinolat = 1.0 + es * slat;
    00242   one_MINUS_es_sinolat = 1.0 - es * slat;
    00243   Polar_Scale_Factor = ((1 + slat) / 2) * (Polar_k90 / sqrt(pow(one_PLUS_es_sinolat, one_PLUS_es) * pow(one_MINUS_es_sinolat, one_MINUS_es)));
    00244
    00245   /* Calculate Radius */
    00246   GeodeticCoordinates tempGeodeticCoordinates = GeodeticCoordinates( CoordinateType::geodetic, centralMeridian, 0 );
    00247   //MapProjectionCoordinates* tempCoordinates = convertFromGeodetic( (GeodeticCoordinates&) GeodeticCoordinates( CoordinateType::geodetic, centralMeridian, 0 ) );
    00248   MapProjectionCoordinates* tempCoordinates = convertFromGeodetic( &tempGeodeticCoordinates );
    00249   Polar_Delta_Northing = tempCoordinates->northing();
    00250   delete tempCoordinates;
    00251
    00252   if(Polar_False_Northing)
    00253     Polar_Delta_Northing -= Polar_False_Northing;
    00254   if (Polar_Delta_Northing < 0)
    00255     Polar_Delta_Northing = -Polar_Delta_Northing;
    00256   Polar_Delta_Northing *= 1.01;
    00257
    00258   Polar_Delta_Easting = Polar_Delta_Northing;
    00259 }
    00260
    00261
    00262 PolarStereographic::PolarStereographic( double ellipsoidSemiMajorAxis, double ellipsoidFlattening, double centralMeridian, double scaleFactor, char hemisphere, double falseEasting, double falseNorthing ) :
    00263   CoordinateSystem(),
    00264   coordinateType( CoordinateType::polarStereographicScaleFactor ),
    00265   es( 0.08181919084262188000 ),
    00266   es_OVER_2( .040909595421311 ),
    00267   Southern_Hemisphere( 0 ),
    00268   Polar_tc( 1.0 ),
    00269   Polar_k90( 1.0033565552493 ),
    00270   Polar_a_mc( 6378137.0 ),
    00271   two_Polar_a( 12756274.0 ),
    00272   Polar_Central_Meridian( 0.0 ),
    00273   Polar_Standard_Parallel( ((PI * 90) / 180) ),
    00274   Polar_False_Easting( 0.0 ),
    00275   Polar_False_Northing( 0.0 ),
    00276   Polar_Scale_Factor( 1.0 ),
    00277   Polar_Delta_Easting( 12713601.0 ),
    00278   Polar_Delta_Northing( 12713601.0 )
    00279 {
    00280 /*
    00281  * The constructor receives the ellipsoid
    00282  * parameters and Polar Stereograpic (Scale Factor) projection parameters as inputs, and
    00283  * sets the corresponding state variables.  If any errors occur, an
    00284  * exception is thrown with a description of the error.
    00285  *
    00286  *  ellipsoidSemiMajorAxis                : Semi-major axis of ellipsoid, in meters         (input)
    00287  *  ellipsoidFlattening                   : Flattening of ellipsoid                                                     (input)
    00288  *  centralMeridian                       : Longitude down from pole, in radians            (input)
    00289  *  scaleFactor                           : Scale Factor              (input)
    00290  *  falseEasting                          : Easting (X) at center of projection, in meters  (input)
    00291  *  falseNorthing                         : Northing (Y) at center of projection, in meters (input)
    00292  */
    00293
    00294   double es2;
    00295   double sinolat, cosolat;
    00296   double essin;
    00297   double pow_es;
    00298   double mc;
    00299   double one_PLUS_es, one_MINUS_es;
    00300   double one_PLUS_es_sk, one_MINUS_es_sk;
    00301   double sk, sk_PLUS_1;
    00302   double tolerance = 1.0e-15;
    00303   int count = 30;
    00304   double inv_f = 1 / ellipsoidFlattening;
    00305   char errorStatus[500] = "";
    00306
    00307   if (ellipsoidSemiMajorAxis <= 0.0)
    00308   { /* Semi-major axis must be greater than zero */
    00309     strcat( errorStatus, ErrorMessages::semiMajorAxis );
    00310   }
    00311   if ((inv_f < 250) || (inv_f > 350))
    00312   { /* Inverse flattening must be between 250 and 350 */
    00313     strcat( errorStatus, ErrorMessages::ellipsoidFlattening );
    00314   }
    00315   if ((scaleFactor < MIN_SCALE_FACTOR) || (scaleFactor > MAX_SCALE_FACTOR))
    00316   {
    00317     strcat( errorStatus, ErrorMessages::scaleFactor );
    00318   }
    00319   if ((centralMeridian < -PI) || (centralMeridian > TWO_PI))
    00320   { /* Origin Longitude out of range */
    00321     strcat( errorStatus, ErrorMessages::centralMeridian );
    00322   }
    00323   if ((hemisphere != 'N') && (hemisphere != 'S'))
    00324     strcat( errorStatus, ErrorMessages::hemisphere );
    00325
    00326   if( strlen( errorStatus ) > 0)
    00327     throw CoordinateConversionException( errorStatus );
    00328
    00329   semiMajorAxis = ellipsoidSemiMajorAxis;
    00330   flattening = ellipsoidFlattening;
    00331   Polar_Scale_Factor = scaleFactor;
    00332   Polar_False_Easting = falseEasting;
    00333   Polar_False_Northing = falseNorthing;
    00334
    00335   two_Polar_a = 2.0 * semiMajorAxis;
    00336   es2 = 2 * flattening - flattening * flattening;
    00337   es = sqrt(es2);
    00338   es_OVER_2 = es / 2.0;
    00339
    00340   one_PLUS_es = 1.0 + es;
    00341   one_MINUS_es = 1.0 - es;
    00342   Polar_k90 = sqrt(pow(one_PLUS_es, one_PLUS_es) * pow(one_MINUS_es, one_MINUS_es));
    00343
    00344   sk = 0;
    00345   sk_PLUS_1 = -1 + 2 * Polar_Scale_Factor;
    00346   while (fabs(sk_PLUS_1 - sk) > tolerance && count)
    00347   {
    00348     sk = sk_PLUS_1;
    00349     one_PLUS_es_sk = 1.0 + es * sk;
    00350     one_MINUS_es_sk = 1.0 - es * sk;
    00351     sk_PLUS_1 = ((2 * Polar_Scale_Factor * sqrt(pow(one_PLUS_es_sk, one_PLUS_es) * pow(one_MINUS_es_sk, one_MINUS_es))) / Polar_k90) - 1;
    00352     count --;
    00353   }
    00354
    00355   if(!count)
    00356     throw CoordinateConversionException( ErrorMessages::originLatitude );
    00357
    00358   double standardParallel = 0.0;
    00359   if(sk_PLUS_1 >= -1.0 && sk_PLUS_1 <= 1.0)
    00360     standardParallel = asin(sk_PLUS_1);
    00361   else
    00362     throw CoordinateConversionException( ErrorMessages::originLatitude );
    00363
    00364   if (hemisphere == 'S')
    00365     standardParallel *= -1.0;
    00366
    00367   if (centralMeridian > PI)
    00368     centralMeridian -= TWO_PI;
    00369   if (standardParallel < 0)
    00370   {
    00371     Southern_Hemisphere = 1;
    00372     Polar_Standard_Parallel = -standardParallel;
    00373     Polar_Central_Meridian = -centralMeridian;
    00374   }
    00375   else
    00376   {
    00377     Southern_Hemisphere = 0;
    00378     Polar_Standard_Parallel = standardParallel;
    00379     Polar_Central_Meridian = centralMeridian;
    00380   }
    00381
    00382   sinolat = sin(Polar_Standard_Parallel);
    00383
    00384   if (fabs(fabs(Polar_Standard_Parallel) - PI_OVER_2) > 1.0e-10)
    00385   {
    00386     essin = es * sinolat;
    00387     pow_es = polarPow(essin);
    00388     cosolat = cos(Polar_Standard_Parallel);
    00389     mc = cosolat / sqrt(1.0 - essin * essin);
    00390     Polar_a_mc = semiMajorAxis * mc;
    00391     Polar_tc = tan(PI_OVER_4 - Polar_Standard_Parallel / 2.0) / pow_es;
    00392   }
    00393
    00394   /* Calculate Radius */
    00395   GeodeticCoordinates tempGeodeticCoordinates = GeodeticCoordinates( CoordinateType::geodetic, centralMeridian, 0 ) ;
    00396   MapProjectionCoordinates* tempCoordinates = convertFromGeodetic( &tempGeodeticCoordinates );
    00397   Polar_Delta_Northing = tempCoordinates->northing();
    00398   delete tempCoordinates;
    00399
    00400   if(Polar_False_Northing)
    00401     Polar_Delta_Northing -= Polar_False_Northing;
    00402   if (Polar_Delta_Northing < 0)
    00403     Polar_Delta_Northing = -Polar_Delta_Northing;
    00404   Polar_Delta_Northing *= 1.01;
    00405
    00406   Polar_Delta_Easting = Polar_Delta_Northing;
    00407 }
    00408
    00409
    00410 PolarStereographic::PolarStereographic( const PolarStereographic &ps )
    00411 {
    00412   coordinateType = ps.coordinateType;
    00413   semiMajorAxis = ps.semiMajorAxis;
    00414   flattening = ps.flattening;
    00415   es = ps.es;
    00416   es_OVER_2 = ps.es_OVER_2;
    00417   Southern_Hemisphere = ps.Southern_Hemisphere;
    00418   Polar_tc = ps.Polar_tc;
    00419   Polar_k90 = ps.Polar_k90;
    00420   Polar_a_mc = ps.Polar_a_mc;
    00421   two_Polar_a = ps.two_Polar_a;
    00422   Polar_Central_Meridian = ps.Polar_Central_Meridian;
    00423   Polar_Standard_Parallel = ps.Polar_Standard_Parallel;
    00424   Polar_False_Easting = ps.Polar_False_Easting;
    00425   Polar_False_Northing = ps.Polar_False_Northing;
    00426   Polar_Scale_Factor = ps.Polar_Scale_Factor;
    00427   Polar_Delta_Easting = ps.Polar_Delta_Easting;
    00428   Polar_Delta_Northing = ps.Polar_Delta_Northing;
    00429 }
    00430
    00431
    00432 PolarStereographic::~PolarStereographic()
    00433 {
    00434 }
    00435
    00436
    00437 PolarStereographic& PolarStereographic::operator=( const PolarStereographic &ps )
    00438 {
    00439   if( this != &ps )
    00440   {
    00441     coordinateType = ps.coordinateType;
    00442     semiMajorAxis = ps.semiMajorAxis;
    00443     flattening = ps.flattening;
    00444     es = ps.es;
    00445     es_OVER_2 = ps.es_OVER_2;
    00446     Southern_Hemisphere = ps.Southern_Hemisphere;
    00447     Polar_tc = ps.Polar_tc;
    00448     Polar_k90 = ps.Polar_k90;
    00449     Polar_a_mc = ps.Polar_a_mc;
    00450     two_Polar_a = ps.two_Polar_a;
    00451     Polar_Central_Meridian = ps.Polar_Central_Meridian;
    00452     Polar_Standard_Parallel = ps.Polar_Standard_Parallel;
    00453     Polar_False_Easting = ps.Polar_False_Easting;
    00454     Polar_False_Northing = ps.Polar_False_Northing;
    00455     Polar_Scale_Factor = ps.Polar_Scale_Factor;
    00456     Polar_Delta_Easting = ps.Polar_Delta_Easting;
    00457     Polar_Delta_Northing = ps.Polar_Delta_Northing;
    00458   }
    00459
    00460   return *this;
    00461 }
    00462
    00463
    00464 PolarStereographicStandardParallelParameters* PolarStereographic::getStandardParallelParameters() const
    00465 {
    00466 /*
    00467  * The function getStandardParallelParameters returns the current
    00468  * ellipsoid parameters and Polar (Standard Parallel) projection parameters.
    00469  *
    00470  *  ellipsoidSemiMajorAxis          : Semi-major axis of ellipsoid, in meters         (output)
    00471  *  ellipsoidFlattening             : Flattening of ellipsoid                                                   (output)
    00472  *  centralMeridian                 : Longitude down from pole, in radians            (output)
    00473  *  standardParallel                : Latitude of true scale, in radians              (output)
    00474  *  falseEasting                    : Easting (X) at center of projection, in meters  (output)
    00475  *  falseNorthing                   : Northing (Y) at center of projection, in meters (output)
    00476  */
    00477
    00478   return new PolarStereographicStandardParallelParameters( CoordinateType::polarStereographicStandardParallel, Polar_Central_Meridian, Polar_Standard_Parallel, Polar_False_Easting, Polar_False_Northing );
    00479 }
    00480
    00481
    00482 PolarStereographicScaleFactorParameters* PolarStereographic::getScaleFactorParameters() const
    00483 {
    00484 /*
    00485  * The function getScaleFactorParameters returns the current
    00486  * ellipsoid parameters and Polar (Scale Factor) projection parameters.
    00487  *
    00488  *  ellipsoidSemiMajorAxis          : Semi-major axis of ellipsoid, in meters         (output)
    00489  *  ellipsoidFlattening             : Flattening of ellipsoid                                                   (output)
    00490  *  centralMeridian                 : Longitude down from pole, in radians            (output)
    00491  *  scaleFactor                     : Scale factor                                    (output)
    00492  *  falseEasting                    : Easting (X) at center of projection, in meters  (output)
    00493  *  falseNorthing                   : Northing (Y) at center of projection, in meters (output)
    00494  */
    00495
    00496   if(Southern_Hemisphere == 0)
    00497     return new PolarStereographicScaleFactorParameters( CoordinateType::polarStereographicScaleFactor, Polar_Central_Meridian, Polar_Scale_Factor, 'N', Polar_False_Easting, Polar_False_Northing );
    00498   else
    00499     return new PolarStereographicScaleFactorParameters( CoordinateType::polarStereographicScaleFactor, Polar_Central_Meridian, Polar_Scale_Factor, 'S', Polar_False_Easting, Polar_False_Northing );
    00500 }
    00501
    00502
    00503 MSP::CCS::MapProjectionCoordinates* PolarStereographic::convertFromGeodetic( MSP::CCS::GeodeticCoordinates* geodeticCoordinates )
    00504 {
    00505 /*
    00506  * The function convertFromGeodetic converts geodetic
    00507  * coordinates (latitude and longitude) to Polar Stereographic coordinates
    00508  * (easting and northing), according to the current ellipsoid
    00509  * and Polar Stereographic projection parameters. If any errors occur,
    00510  * an exception is thrown with a description of the error.
    00511  *
    00512  *    longitude  :  Longitude, in radians                     (input)
    00513  *    latitude   :  Latitude, in radians                      (input)
    00514  *    easting    :  Easting (X), in meters                    (output)
    00515  *    northing   :  Northing (Y), in meters                   (output)
    00516  */
    00517
    00518   double dlam;
    00519   double slat;
    00520   double essin;
    00521   double t;
    00522   double rho;
    00523   double pow_es;
    00524   double easting, northing;
    00525   char errorStatus[50] = "";
    00526
    00527   double longitude = geodeticCoordinates->longitude();
    00528   double latitude = geodeticCoordinates->latitude();
    00529
    00530   if ((latitude < -PI_OVER_2) || (latitude > PI_OVER_2))
    00531   {   /* latitude out of range */
    00532     strcat( errorStatus, ErrorMessages::latitude );
    00533   }
    00534   else if ((latitude < 0) && (Southern_Hemisphere == 0))
    00535   {   /* latitude and Origin Latitude in different hemispheres */
    00536     strcat( errorStatus, ErrorMessages::latitude );
    00537   }
    00538   else if ((latitude > 0) && (Southern_Hemisphere == 1))
    00539   {   /* latitude and Origin Latitude in different hemispheres */
    00540     strcat( errorStatus, ErrorMessages::latitude );
    00541   }
    00542   if ((longitude < -PI) || (longitude > TWO_PI))
    00543   {  /* longitude out of range */
    00544     strcat( errorStatus, ErrorMessages::longitude );
    00545   }
    00546
    00547   if( strlen( errorStatus ) > 0)
    00548     throw CoordinateConversionException( errorStatus );
    00549
    00550   if (fabs(fabs(latitude) - PI_OVER_2) < 1.0e-10)
    00551   {
    00552     easting = Polar_False_Easting;
    00553     northing = Polar_False_Northing;
    00554   }
    00555   else
    00556   {
    00557     if (Southern_Hemisphere != 0)
    00558     {
    00559       longitude *= -1.0;
    00560       latitude *= -1.0;
    00561     }
    00562     dlam = longitude - Polar_Central_Meridian;
    00563     if (dlam > PI)
    00564     {
    00565       dlam -= TWO_PI;
    00566     }
    00567     if (dlam < -PI)
    00568     {
    00569       dlam += TWO_PI;
    00570     }
    00571     slat = sin(latitude);
    00572     essin = es * slat;
    00573     pow_es = polarPow(essin);
    00574     t = tan(PI_OVER_4 - latitude / 2.0) / pow_es;
    00575
    00576     if (fabs(fabs(Polar_Standard_Parallel) - PI_OVER_2) > 1.0e-10)
    00577       rho = Polar_a_mc * t / Polar_tc;
    00578     else
    00579       rho = two_Polar_a * t / Polar_k90;
    00580
    00581
    00582     if (Southern_Hemisphere != 0)
    00583     {
    00584       easting = -(rho * sin(dlam) - Polar_False_Easting);
    00585       northing = rho * cos(dlam) + Polar_False_Northing;
    00586     }
    00587     else
    00588     {
    00589       easting = rho * sin(dlam) + Polar_False_Easting;
    00590       northing = -rho * cos(dlam) + Polar_False_Northing;
    00591     }
    00592   }
    00593
    00594   return new MapProjectionCoordinates( coordinateType, easting, northing );
    00595 }
    00596
    00597
    00598 MSP::CCS::GeodeticCoordinates* PolarStereographic::convertToGeodetic( MSP::CCS::MapProjectionCoordinates* mapProjectionCoordinates )
    00599 {
    00600 /*
    00601  * The function convertToGeodetic converts Polar
    00602  * Stereographic coordinates (easting and northing) to geodetic
    00603  * coordinates (latitude and longitude) according to the current ellipsoid
    00604  * and Polar Stereographic projection Parameters. If any errors occur,
    00605  * an exception is thrown with a description of the error.
    00606  *
    00607  *  easting          : Easting (X), in meters                   (input)
    00608  *  northing         : Northing (Y), in meters                  (input)
    00609  *  longitude        : Longitude, in radians                    (output)
    00610  *  latitude         : Latitude, in radians                     (output)
    00611  *
    00612  */
    00613
    00614   double dy = 0, dx = 0;
    00615   double rho = 0;
    00616   double t;
    00617   double PHI, sin_PHI;
    00618   double tempPHI = 0.0;
    00619   double essin;
    00620   double pow_es;
    00621   double delta_radius;
    00622   double longitude, latitude;
    00623   char errorStatus[50] = "";
    00624
    00625   double easting = mapProjectionCoordinates->easting();
    00626   double northing = mapProjectionCoordinates->northing();
    00627
    00628   double min_easting = Polar_False_Easting - Polar_Delta_Easting;
    00629   double max_easting = Polar_False_Easting + Polar_Delta_Easting;
    00630   double min_northing = Polar_False_Northing - Polar_Delta_Northing;
    00631   double max_northing = Polar_False_Northing + Polar_Delta_Northing;
    00632
    00633   if (easting > max_easting || easting < min_easting)
    00634   { /* easting out of range */
    00635     strcat( errorStatus, ErrorMessages::easting );
    00636   }
    00637   if (northing > max_northing || northing < min_northing)
    00638   { /* northing out of range */
    00639     strcat( errorStatus, ErrorMessages::northing );
    00640   }
    00641
    00642   if( strlen( errorStatus ) > 0)
    00643     throw CoordinateConversionException( errorStatus );
    00644
    00645     dy = northing - Polar_False_Northing;
    00646     dx = easting - Polar_False_Easting;
    00647
    00648     /* Radius of point with origin of false easting, false northing */
    00649     rho = sqrt(dx * dx + dy * dy);
    00650
    00651     delta_radius = sqrt(Polar_Delta_Easting * Polar_Delta_Easting + Polar_Delta_Northing * Polar_Delta_Northing);
    00652
    00653     if(rho > delta_radius)
    00654     { /* Point is outside of projection area */
    00655       throw CoordinateConversionException( ErrorMessages::radius );
    00656     }
    00657
    00658     if ((dy == 0.0) && (dx == 0.0))
    00659     {
    00660       latitude = PI_OVER_2;
    00661       longitude = Polar_Central_Meridian;
    00662
    00663     }
    00664     else
    00665     {
    00666       if (Southern_Hemisphere != 0)
    00667       {
    00668         dy *= -1.0;
    00669         dx *= -1.0;
    00670       }
    00671
    00672       if (fabs(fabs(Polar_Standard_Parallel) - PI_OVER_2) > 1.0e-10)
    00673         t = rho * Polar_tc / (Polar_a_mc);
    00674       else
    00675         t = rho * Polar_k90 / (two_Polar_a);
    00676       PHI = PI_OVER_2 - 2.0 * atan(t);
    00677       while (fabs(PHI - tempPHI) > 1.0e-10)
    00678       {
    00679         tempPHI = PHI;
    00680         sin_PHI = sin(PHI);
    00681         essin =  es * sin_PHI;
    00682         pow_es = polarPow(essin);
    00683         PHI = PI_OVER_2 - 2.0 * atan(t * pow_es);
    00684       }
    00685       latitude = PHI;
    00686       longitude = Polar_Central_Meridian + atan2(dx, -dy);
    00687
    00688       if (longitude > PI)
    00689         longitude -= TWO_PI;
    00690       else if (longitude < -PI)
    00691         longitude += TWO_PI;
    00692
    00693
    00694       if (latitude > PI_OVER_2)  /* force distorted values to 90, -90 degrees */
    00695         latitude = PI_OVER_2;
    00696       else if (latitude < -PI_OVER_2)
    00697         latitude = -PI_OVER_2;
    00698
    00699       if (longitude > PI)  /* force distorted values to 180, -180 degrees */
    00700         longitude = PI;
    00701       else if (longitude < -PI)
    00702         longitude = -PI;
    00703
    00704     }
    00705     if (Southern_Hemisphere != 0)
    00706     {
    00707       latitude *= -1.0;
    00708       longitude *= -1.0;
    00709     }
    00710
    00711   return new GeodeticCoordinates( CoordinateType::geodetic, longitude, latitude );
    00712 }
    00713
    00714
    00715 double PolarStereographic::polarPow( double esSin )
    00716 {
    00717   return pow((1.0 - esSin) / (1.0 + esSin), es_OVER_2);
    00718 }
    00719
    00720
    00721 // CLASSIFICATION: UNCLASSIFIED