- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

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

Go to the documentation of this file.

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