- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

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

Go to the documentation of this file.

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