GPS4Palm

Source Code Documentation


utm.c

Go to the documentation of this file.
00001 /***************************************************************************/
00002 /* RSC IDENTIFIER: UTM
00003  *
00004  * ABSTRACT
00005  *
00006  *    This component provides conversions between geodetic coordinates 
00007  *    (latitude and longitudes) and Universal Transverse Mercator (UTM)
00008  *    projection (zone, hemisphere, easting, and northing) coordinates.
00009  *
00010  * ERROR HANDLING
00011  *
00012  *    This component checks parameters for valid values.  If an invalid value
00013  *    is found, the error code is combined with the current error code using 
00014  *    the bitwise or.  This combining allows multiple error codes to be
00015  *    returned. The possible error codes are:
00016  *
00017  *          UTM_NO_ERROR           : No errors occurred in function
00018  *          UTM_LAT_ERROR          : Latitude outside of valid range
00019  *                                    (-80.5 to 84.5 degrees)
00020  *          UTM_LON_ERROR          : Longitude outside of valid range
00021  *                                    (-180 to 360 degrees)
00022  *          UTM_EASTING_ERROR      : Easting outside of valid range
00023  *                                    (100,000 to 900,000 meters)
00024  *          UTM_NORTHING_ERROR     : Northing outside of valid range
00025  *                                    (0 to 10,000,000 meters)
00026  *          UTM_ZONE_ERROR         : Zone outside of valid range (1 to 60)
00027  *          UTM_HEMISPHERE_ERROR   : Invalid hemisphere ('N' or 'S')
00028  *          UTM_ZONE_OVERRIDE_ERROR: Zone outside of valid range
00029  *                                    (1 to 60) and within 1 of 'natural' zone
00030  *          UTM_A_ERROR            : Semi-major axis less than or equal to zero
00031  *          UTM_INV_F_ERROR        : Inverse flattening outside of valid range
00032  *                                                                                      (250 to 350)
00033  *
00034  * REUSE NOTES
00035  *
00036  *    UTM is intended for reuse by any application that performs a Universal
00037  *    Transverse Mercator (UTM) projection or its inverse.
00038  *    
00039  * REFERENCES
00040  *
00041  *    Further information on UTM can be found in the Reuse Manual.
00042  *
00043  *    UTM originated from :  U.S. Army Topographic Engineering Center
00044  *                           Geospatial Information Division
00045  *                           7701 Telegraph Road
00046  *                           Alexandria, VA  22310-3864
00047  *
00048  * LICENSES
00049  *
00050  *    None apply to this component.
00051  *
00052  * RESTRICTIONS
00053  *
00054  *    UTM has no restrictions.
00055  *
00056  * ENVIRONMENT
00057  *
00058  *    UTM was tested and certified in the following environments:
00059  *
00060  *    1. Solaris 2.5 with GCC, version 2.8.1
00061  *    2. MSDOS with MS Visual C++, version 6
00062  *
00063  * MODIFICATIONS
00064  *
00065  *    Date              Description
00066  *    ----              -----------
00067  *    10-02-97          Original Code
00068  *
00069  */
00070 
00071 
00072 /***************************************************************************/
00073 /*
00074  *                              INCLUDES
00075  */
00076 #include "tranmerc.h"
00077 #include "utm.h"
00078 /*
00079  *    tranmerc.h    - Is used to convert transverse mercator coordinates
00080  *    utm.h         - Defines the function prototypes for the utm module.
00081  */
00082 
00083 
00084 /***************************************************************************/
00085 /*
00086  *                              DEFINES
00087  */
00088 
00089 #define PI           3.14159265358979323e0    /* PI                        */
00090 #define MIN_LAT      ( (-80.5 * PI) / 180.0 ) /* -80.5 degrees in radians    */
00091 #define MAX_LAT      ( (84.5 * PI) / 180.0 )  /* 84.5 degrees in radians     */
00092 #define MIN_EASTING  100000
00093 #define MAX_EASTING  900000
00094 #define MIN_NORTHING 0
00095 #define MAX_NORTHING 10000000
00096 
00097 /***************************************************************************/
00098 /*
00099  *                              GLOBAL DECLARATIONS
00100  */
00101 
00102 static double UTM_a = 6378137.0;         /* Semi-major axis of ellipsoid in meters  */
00103 static double UTM_f = 1 / 298.257223563; /* Flattening of ellipsoid                 */
00104 static long   UTM_Override = 0;          /* Zone override flag                      */
00105 
00106 
00107 /***************************************************************************/
00108 /*
00109  *                                FUNCTIONS
00110  *
00111  */
00112 
00113 long Set_UTM_Parameters(double a,      
00114                         double f,
00115                         long   override)
00116 {
00117 /*
00118  * The function Set_UTM_Parameters receives the ellipsoid parameters and
00119  * UTM zone override parameter as inputs, and sets the corresponding state
00120  * variables.  If any errors occur, the error code(s) are returned by the 
00121  * function, otherwise UTM_NO_ERROR is returned.
00122  *
00123  *    a                 : Semi-major axis of ellipsoid, in meters       (input)
00124  *    f                 : Flattening of ellipsoid                                                           (input)
00125  *    override          : UTM override zone, zero indicates no override (input)
00126  */
00127 
00128   double inv_f = 1 / f;
00129   long Error_Code = UTM_NO_ERROR;
00130 
00131   if (a <= 0.0)
00132   { /* Semi-major axis must be greater than zero */
00133     Error_Code |= UTM_A_ERROR;
00134   }
00135   if ((inv_f < 250) || (inv_f > 350))
00136   { /* Inverse flattening must be between 250 and 350 */
00137     Error_Code |= UTM_INV_F_ERROR;
00138   }
00139   if ((override < 0) || (override > 60))
00140   {
00141     Error_Code |= UTM_ZONE_OVERRIDE_ERROR;
00142   }
00143   if (!Error_Code)
00144   { /* no errors */
00145     UTM_a = a;
00146     UTM_f = f;
00147     UTM_Override = override;
00148   }
00149   return (Error_Code);
00150 } /* END OF Set_UTM_Parameters */
00151 
00152 
00153 void Get_UTM_Parameters(double *a,
00154                         double *f,
00155                         long   *override)
00156 {
00157 /*
00158  * The function Get_UTM_Parameters returns the current ellipsoid
00159  * parameters and UTM zone override parameter.
00160  *
00161  *    a                 : Semi-major axis of ellipsoid, in meters       (output)
00162  *    f                 : Flattening of ellipsoid                                                           (output)
00163  *    override          : UTM override zone, zero indicates no override (output)
00164  */
00165 
00166   *a = UTM_a;
00167   *f = UTM_f;
00168   *override = UTM_Override;
00169 } /* END OF Get_UTM_Parameters */
00170 
00171 
00172 long Convert_Geodetic_To_UTM (double Latitude,
00173                               double Longitude,
00174                               long   *Zone,
00175                               char   *Hemisphere,
00176                               double *Easting,
00177                               double *Northing)
00178 { 
00179 /*
00180  * The function Convert_Geodetic_To_UTM converts geodetic (latitude and
00181  * longitude) coordinates to UTM projection (zone, hemisphere, easting and
00182  * northing) coordinates according to the current ellipsoid and UTM zone
00183  * override parameters.  If any errors occur, the error code(s) are returned
00184  * by the function, otherwise UTM_NO_ERROR is returned.
00185  *
00186  *    Latitude          : Latitude in radians                 (input)
00187  *    Longitude         : Longitude in radians                (input)
00188  *    Zone              : UTM zone                            (output)
00189  *    Hemisphere        : North or South hemisphere           (output)
00190  *    Easting           : Easting (X) in meters               (output)
00191  *    Northing          : Northing (Y) in meters              (output)
00192  */
00193 
00194   long Lat_Degrees;
00195   long Long_Degrees;
00196   long temp_zone;
00197   long Error_Code = UTM_NO_ERROR;
00198   double Origin_Latitude = 0;
00199   double Central_Meridian = 0;
00200   double False_Easting = 500000;
00201   double False_Northing = 0;
00202   double Scale = 0.9996;
00203 
00204   if ((Latitude < MIN_LAT) || (Latitude > MAX_LAT))
00205   { /* Latitude out of range */
00206     Error_Code |= UTM_LAT_ERROR;
00207   }
00208   if ((Longitude < -PI) || (Longitude > (2*PI)))
00209   { /* Longitude out of range */
00210     Error_Code |= UTM_LON_ERROR;
00211   }
00212   if (!Error_Code)
00213   { /* no errors */
00214     if (Longitude < 0)
00215       Longitude += (2*PI);
00216     Lat_Degrees = (long)(Latitude * 180.0 / PI);
00217     Long_Degrees = (long)(Longitude * 180.0 / PI);
00218 
00219     if (Longitude < PI)
00220       temp_zone = (long)(31 + ((Longitude * 180.0 / PI) / 6.0));
00221     else
00222       temp_zone = (long)(((Longitude * 180.0 / PI) / 6.0) - 29);
00223     if (temp_zone > 60)
00224       temp_zone = 1;
00225     /* UTM special cases */
00226     if ((Lat_Degrees > 55) && (Lat_Degrees < 64) && (Long_Degrees > -1)
00227         && (Long_Degrees < 3))
00228       temp_zone = 31;
00229     if ((Lat_Degrees > 55) && (Lat_Degrees < 64) && (Long_Degrees > 2)
00230         && (Long_Degrees < 12))
00231       temp_zone = 32;
00232     if ((Lat_Degrees > 71) && (Long_Degrees > -1) && (Long_Degrees < 9))
00233       temp_zone = 31;
00234     if ((Lat_Degrees > 71) && (Long_Degrees > 8) && (Long_Degrees < 21))
00235       temp_zone = 33;
00236     if ((Lat_Degrees > 71) && (Long_Degrees > 20) && (Long_Degrees < 33))
00237       temp_zone = 35;
00238     if ((Lat_Degrees > 71) && (Long_Degrees > 32) && (Long_Degrees < 42))
00239       temp_zone = 37;
00240 
00241     if (UTM_Override)
00242     {
00243       if ((temp_zone == 1) && (UTM_Override == 60))
00244         temp_zone = UTM_Override;
00245       else if ((temp_zone == 60) && (UTM_Override == 1))
00246         temp_zone = UTM_Override;
00247       else if (((temp_zone-1) <= UTM_Override) && (UTM_Override <= (temp_zone+1)))
00248         temp_zone = UTM_Override;
00249       else
00250         Error_Code = UTM_ZONE_OVERRIDE_ERROR;
00251     }
00252     if (!Error_Code)
00253     {
00254       if (temp_zone >= 31)
00255         Central_Meridian = (6 * temp_zone - 183) * PI / 180.0;
00256       else
00257         Central_Meridian = (6 * temp_zone + 177) * PI / 180.0;
00258       *Zone = temp_zone;
00259       if (Latitude < 0)
00260       {
00261         False_Northing = 10000000;
00262         *Hemisphere = 'S';
00263       }
00264       else
00265         *Hemisphere = 'N';
00266       Set_Transverse_Mercator_Parameters(UTM_a, UTM_f, Origin_Latitude,
00267                                          Central_Meridian, False_Easting, False_Northing, Scale);
00268       Convert_Geodetic_To_Transverse_Mercator(Latitude, Longitude, Easting,
00269                                               Northing);
00270       if ((*Easting < MIN_EASTING) || (*Easting > MAX_EASTING))
00271         Error_Code = UTM_EASTING_ERROR;
00272       if ((*Northing < MIN_NORTHING) || (*Northing > MAX_NORTHING))
00273         Error_Code |= UTM_NORTHING_ERROR;
00274     }
00275   } /* END OF if (!Error_Code) */
00276   return (Error_Code);
00277 } /* END OF Convert_Geodetic_To_UTM */
00278 
00279 
00280 long Convert_UTM_To_Geodetic(long   Zone,
00281                              char   Hemisphere,
00282                              double Easting,
00283                              double Northing,
00284                              double *Latitude,
00285                              double *Longitude)
00286 {
00287 /*
00288  * The function Convert_UTM_To_Geodetic converts UTM projection (zone, 
00289  * hemisphere, easting and northing) coordinates to geodetic(latitude
00290  * and  longitude) coordinates, according to the current ellipsoid
00291  * parameters.  If any errors occur, the error code(s) are returned
00292  * by the function, otherwise UTM_NO_ERROR is returned.
00293  *
00294  *    Zone              : UTM zone                               (input)
00295  *    Hemisphere        : North or South hemisphere              (input)
00296  *    Easting           : Easting (X) in meters                  (input)
00297  *    Northing          : Northing (Y) in meters                 (input)
00298  *    Latitude          : Latitude in radians                    (output)
00299  *    Longitude         : Longitude in radians                   (output)
00300  */
00301   long Error_Code = UTM_NO_ERROR;
00302   double Origin_Latitude = 0;
00303   double Central_Meridian = 0;
00304   double False_Easting = 500000;
00305   double False_Northing = 0;
00306   double Scale = 0.9996;
00307 
00308   if ((Zone < 1) || (Zone > 60))
00309     Error_Code |= UTM_ZONE_ERROR;
00310   if ((Hemisphere != 'S') && (Hemisphere != 'N'))
00311     Error_Code |= UTM_HEMISPHERE_ERROR;
00312   if ((Easting < MIN_EASTING) || (Easting > MAX_EASTING))
00313     Error_Code |= UTM_EASTING_ERROR;
00314   if ((Northing < MIN_NORTHING) || (Northing > MAX_NORTHING))
00315     Error_Code |= UTM_NORTHING_ERROR;
00316   if (!Error_Code)
00317   { /* no errors */
00318     if (Zone >= 31)
00319       Central_Meridian = ((6 * Zone - 183) * PI / 180.0 + 0.00000005);
00320     else
00321       Central_Meridian = ((6 * Zone + 177) * PI / 180.0 + 0.00000005);
00322     if (Hemisphere == 'S')
00323       False_Northing = 10000000;
00324     Set_Transverse_Mercator_Parameters(UTM_a, UTM_f, Origin_Latitude,
00325                                        Central_Meridian, False_Easting, False_Northing, Scale);
00326     if (Convert_Transverse_Mercator_To_Geodetic(Easting,
00327                                                 Northing,
00328                                                 Latitude, 
00329                                                 Longitude))
00330       Error_Code |= UTM_NORTHING_ERROR;
00331     if ((*Latitude < MIN_LAT) || (*Latitude > MAX_LAT))
00332     { /* Latitude out of range */
00333       Error_Code |= UTM_NORTHING_ERROR;
00334     }
00335   }
00336   return (Error_Code);
00337 } /* END OF Convert_UTM_To_Geodetic */

Created: Mon, 08 Oct 2007 22:33:16 +0200
Copyright ©2004 M. Prinke