GPS4Palm

Source Code Documentation


tranmerc.c

Go to the documentation of this file.
00001 /***************************************************************************/
00002 /* RSC IDENTIFIER: TRANSVERSE MERCATOR
00003  *
00004  * ABSTRACT
00005  *
00006  *    This component provides conversions between Geodetic coordinates 
00007  *    (latitude and longitude) and Transverse Mercator projection coordinates
00008  *    (easting and northing).
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  *       TRANMERC_NO_ERROR           : No errors occurred in function
00018  *       TRANMERC_LAT_ERROR          : Latitude outside of valid range
00019  *                                      (-90 to 90 degrees)
00020  *       TRANMERC_LON_ERROR          : Longitude outside of valid range
00021  *                                      (-180 to 360 degrees, and within
00022  *                                        +/-90 of Central Meridian)
00023  *       TRANMERC_EASTING_ERROR      : Easting outside of valid range
00024  *                                      (depending on ellipsoid and
00025  *                                       projection parameters)
00026  *       TRANMERC_NORTHING_ERROR     : Northing outside of valid range
00027  *                                      (depending on ellipsoid and
00028  *                                       projection parameters)
00029  *       TRANMERC_ORIGIN_LAT_ERROR   : Origin latitude outside of valid range
00030  *                                      (-90 to 90 degrees)
00031  *       TRANMERC_CENT_MER_ERROR     : Central meridian outside of valid range
00032  *                                      (-180 to 360 degrees)
00033  *       TRANMERC_A_ERROR            : Semi-major axis less than or equal to zero
00034  *       TRANMERC_INV_F_ERROR        : Inverse flattening outside of valid range
00035  *                                                                                        (250 to 350)
00036  *       TRANMERC_SCALE_FACTOR_ERROR : Scale factor outside of valid
00037  *                                     range (0.3 to 3.0)
00038  *               TM_LON_WARNING              : Distortion will result if longitude is more
00039  *                                       than 9 degrees from the Central Meridian
00040  *
00041  * REUSE NOTES
00042  *
00043  *    TRANSVERSE MERCATOR is intended for reuse by any application that 
00044  *    performs a Transverse Mercator projection or its inverse.
00045  *    
00046  * REFERENCES
00047  *
00048  *    Further information on TRANSVERSE MERCATOR can be found in the 
00049  *    Reuse Manual.
00050  *
00051  *    TRANSVERSE MERCATOR originated from :  
00052  *                      U.S. Army Topographic Engineering Center
00053  *                      Geospatial Information Division
00054  *                      7701 Telegraph Road
00055  *                      Alexandria, VA  22310-3864
00056  *
00057  * LICENSES
00058  *
00059  *    None apply to this component.
00060  *
00061  * RESTRICTIONS
00062  *
00063  *    TRANSVERSE MERCATOR has no restrictions.
00064  *
00065  * ENVIRONMENT
00066  *
00067  *    TRANSVERSE MERCATOR was tested and certified in the following 
00068  *    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  *    10-02-97          Original Code
00078  *    03-02-97          Re-engineered Code
00079  *
00080  */
00081 
00082 
00083 /***************************************************************************/
00084 /*
00085  *                               INCLUDES
00086  */
00087 #include <PalmOS.h>
00088 #include <PalmCompatibility.h>
00089 #include "MathLib.h"
00090 /*
00091 #include <math.h>
00092 */
00093 #include "tranmerc.h"
00094 
00095 /*
00096  *    math.h      - Standard C math library
00097  *    tranmerc.h  - Is for prototype error checking
00098  */
00099 
00100 
00101 /***************************************************************************/
00102 /*                               DEFINES 
00103  *
00104  */
00105 
00106 #define PI              3.14159265358979323e0 /* PI     */
00107 #define PI_OVER         (PI/2.0e0)            /* PI over 2 */
00108 #define MAX_LAT         ((PI * 89.99)/180.0)    /* 90 degrees in radians */
00109 #define MAX_DELTA_LONG  ((PI * 90)/180.0)    /* 90 degrees in radians */
00110 #define MIN_SCALE_FACTOR  0.3
00111 #define MAX_SCALE_FACTOR  3.0
00112 
00113 #define SPHTMD(Latitude) ((double) (TranMerc_ap * Latitude \
00114       - TranMerc_bp * sin(2.e0 * Latitude) + TranMerc_cp * sin(4.e0 * Latitude) \
00115       - TranMerc_dp * sin(6.e0 * Latitude) + TranMerc_ep * sin(8.e0 * Latitude) ) )
00116 
00117 #define SPHSN(Latitude) ((double) (TranMerc_a / sqrt( 1.e0 - TranMerc_es * \
00118       pow(sin(Latitude), 2))))
00119 
00120 #define SPHSR(Latitude) ((double) (TranMerc_a * (1.e0 - TranMerc_es) / \
00121     pow(DENOM(Latitude), 3)))
00122 
00123 #define DENOM(Latitude) ((double) (sqrt(1.e0 - TranMerc_es * pow(sin(Latitude),2))))
00124 
00125 
00126 /**************************************************************************/
00127 /*                               GLOBAL DECLARATIONS
00128  *
00129  */
00130 
00131 /* Ellipsoid Parameters, default to WGS 84  */
00132 static double TranMerc_a = 6378137.0;              /* Semi-major axis of ellipsoid i meters */
00133 static double TranMerc_f = 1 / 298.257223563;      /* Flattening of ellipsoid  */
00134 static double TranMerc_es = 0.0066943799901413800; /* Eccentricity (0.08181919084262188000) squared */
00135 static double TranMerc_ebs = 0.0067394967565869;   /* Second Eccentricity squared */
00136 
00137 /* Transverse_Mercator projection Parameters */
00138 static double TranMerc_Origin_Lat = 0.0;           /* Latitude of origin in radians */
00139 static double TranMerc_Origin_Long = 0.0;          /* Longitude of origin in radians */
00140 static double TranMerc_False_Northing = 0.0;       /* False northing in meters */
00141 static double TranMerc_False_Easting = 0.0;        /* False easting in meters */
00142 static double TranMerc_Scale_Factor = 1.0;         /* Scale factor  */
00143 
00144 /* Isometeric to geodetic latitude parameters, default to WGS 84 */
00145 static double TranMerc_ap = 6367449.1458008;
00146 static double TranMerc_bp = 16038.508696861;
00147 static double TranMerc_cp = 16.832613334334;
00148 static double TranMerc_dp = 0.021984404273757;
00149 static double TranMerc_ep = 3.1148371319283e-005;
00150 
00151 /* Maximum variance for easting and northing values for WGS 84. */
00152 static double TranMerc_Delta_Easting = 40000000.0;
00153 static double TranMerc_Delta_Northing = 40000000.0;
00154 
00155 /* These state variables are for optimization purposes. The only function
00156  * that should modify them is Set_Tranverse_Mercator_Parameters.         */
00157 
00158 
00159 /************************************************************************/
00160 /*                              FUNCTIONS     
00161  *
00162  */
00163 
00164 
00165 long Set_Transverse_Mercator_Parameters(double a,
00166                                         double f,
00167                                         double Origin_Latitude,
00168                                         double Central_Meridian,
00169                                         double False_Easting,
00170                                         double False_Northing,
00171                                         double Scale_Factor)
00172 
00173 { /* BEGIN Set_Tranverse_Mercator_Parameters */
00174   /*
00175    * The function Set_Tranverse_Mercator_Parameters receives the ellipsoid
00176    * parameters and Tranverse Mercator projection parameters as inputs, and
00177    * sets the corresponding state variables. If any errors occur, the error
00178    * code(s) are returned by the function, otherwise TRANMERC_NO_ERROR is
00179    * returned.
00180    *
00181    *    a                 : Semi-major axis of ellipsoid, in meters    (input)
00182    *    f                 : Flattening of ellipsoid                                                      (input)
00183    *    Origin_Latitude   : Latitude in radians at the origin of the   (input)
00184    *                         projection
00185    *    Central_Meridian  : Longitude in radians at the center of the  (input)
00186    *                         projection
00187    *    False_Easting     : Easting/X at the center of the projection  (input)
00188    *    False_Northing    : Northing/Y at the center of the projection (input)
00189    *    Scale_Factor      : Projection scale factor                    (input) 
00190    */
00191 
00192   double tn;        /* True Meridianal distance constant  */
00193   double tn2;
00194   double tn3;
00195   double tn4;
00196   double tn5;
00197   double dummy_northing;
00198   double TranMerc_b; /* Semi-minor axis of ellipsoid, in meters */
00199   double inv_f = 1 / f;
00200   long Error_Code = TRANMERC_NO_ERROR;
00201 
00202   if (a <= 0.0)
00203   { /* Semi-major axis must be greater than zero */
00204     Error_Code |= TRANMERC_A_ERROR;
00205   }
00206   if ((inv_f < 250) || (inv_f > 350))
00207   { /* Inverse flattening must be between 250 and 350 */
00208     Error_Code |= TRANMERC_INV_F_ERROR;
00209   }
00210   if ((Origin_Latitude < -MAX_LAT) || (Origin_Latitude > MAX_LAT))
00211   { /* origin latitude out of range */
00212     Error_Code |= TRANMERC_ORIGIN_LAT_ERROR;
00213   }
00214   if ((Central_Meridian < -PI) || (Central_Meridian > (2*PI)))
00215   { /* origin longitude out of range */
00216     Error_Code |= TRANMERC_CENT_MER_ERROR;
00217   }
00218   if ((Scale_Factor < MIN_SCALE_FACTOR) || (Scale_Factor > MAX_SCALE_FACTOR))
00219   {
00220     Error_Code |= TRANMERC_SCALE_FACTOR_ERROR;
00221   }
00222   if (!Error_Code)
00223   { /* no errors */
00224     TranMerc_a = a;
00225     TranMerc_f = f;
00226     TranMerc_Origin_Lat = 0;
00227     TranMerc_Origin_Long = 0;
00228     TranMerc_False_Northing = 0;
00229     TranMerc_False_Easting = 0; 
00230     TranMerc_Scale_Factor = 1;
00231 
00232     /* Eccentricity Squared */
00233     TranMerc_es = 2 * TranMerc_f - TranMerc_f * TranMerc_f;
00234     /* Second Eccentricity Squared */
00235     TranMerc_ebs = (1 / (1 - TranMerc_es)) - 1;
00236 
00237     TranMerc_b = TranMerc_a * (1 - TranMerc_f);    
00238     /*True meridianal constants  */
00239     tn = (TranMerc_a - TranMerc_b) / (TranMerc_a + TranMerc_b);
00240     tn2 = tn * tn;
00241     tn3 = tn2 * tn;
00242     tn4 = tn3 * tn;
00243     tn5 = tn4 * tn;
00244 
00245     TranMerc_ap = TranMerc_a * (1.e0 - tn + 5.e0 * (tn2 - tn3)/4.e0
00246                                 + 81.e0 * (tn4 - tn5)/64.e0 );
00247     TranMerc_bp = 3.e0 * TranMerc_a * (tn - tn2 + 7.e0 * (tn3 - tn4)
00248                                        /8.e0 + 55.e0 * tn5/64.e0 )/2.e0;
00249     TranMerc_cp = 15.e0 * TranMerc_a * (tn2 - tn3 + 3.e0 * (tn4 - tn5 )/4.e0) /16.0;
00250     TranMerc_dp = 35.e0 * TranMerc_a * (tn3 - tn4 + 11.e0 * tn5 / 16.e0) / 48.e0;
00251     TranMerc_ep = 315.e0 * TranMerc_a * (tn4 - tn5) / 512.e0;
00252     Convert_Geodetic_To_Transverse_Mercator(MAX_LAT,
00253                                             MAX_DELTA_LONG,
00254                                             &TranMerc_Delta_Easting,
00255                                             &TranMerc_Delta_Northing);
00256     Convert_Geodetic_To_Transverse_Mercator(0,
00257                                             MAX_DELTA_LONG,
00258                                             &TranMerc_Delta_Easting,
00259                                             &dummy_northing);
00260     TranMerc_Origin_Lat = Origin_Latitude;
00261     if (Central_Meridian > PI)
00262       Central_Meridian -= (2*PI);
00263     TranMerc_Origin_Long = Central_Meridian;
00264     TranMerc_False_Northing = False_Northing;
00265     TranMerc_False_Easting = False_Easting; 
00266     TranMerc_Scale_Factor = Scale_Factor;
00267   } /* END OF if(!Error_Code) */
00268   return (Error_Code);
00269 }  /* END of Set_Transverse_Mercator_Parameters  */
00270 
00271 
00272 void Get_Transverse_Mercator_Parameters(double *a,
00273                                         double *f,
00274                                         double *Origin_Latitude,
00275                                         double *Central_Meridian,
00276                                         double *False_Easting,
00277                                         double *False_Northing,
00278                                         double *Scale_Factor)
00279 
00280 { /* BEGIN Get_Tranverse_Mercator_Parameters  */
00281   /*
00282    * The function Get_Transverse_Mercator_Parameters returns the current
00283    * ellipsoid and Transverse Mercator projection parameters.
00284    *
00285    *    a                 : Semi-major axis of ellipsoid, in meters    (output)
00286    *    f                 : Flattening of ellipsoid                                                      (output)
00287    *    Origin_Latitude   : Latitude in radians at the origin of the   (output)
00288    *                         projection
00289    *    Central_Meridian  : Longitude in radians at the center of the  (output)
00290    *                         projection
00291    *    False_Easting     : Easting/X at the center of the projection  (output)
00292    *    False_Northing    : Northing/Y at the center of the projection (output)
00293    *    Scale_Factor      : Projection scale factor                    (output) 
00294    */
00295 
00296   *a = TranMerc_a;
00297   *f = TranMerc_f;
00298   *Origin_Latitude = TranMerc_Origin_Lat;
00299   *Central_Meridian = TranMerc_Origin_Long;
00300   *False_Easting = TranMerc_False_Easting;
00301   *False_Northing = TranMerc_False_Northing;
00302   *Scale_Factor = TranMerc_Scale_Factor;
00303   return;
00304 } /* END OF Get_Tranverse_Mercator_Parameters */
00305 
00306 
00307 
00308 long Convert_Geodetic_To_Transverse_Mercator (double Latitude,
00309                                               double Longitude,
00310                                               double *Easting,
00311                                               double *Northing)
00312 
00313 {      /* BEGIN Convert_Geodetic_To_Transverse_Mercator */
00314 
00315   /*
00316    * The function Convert_Geodetic_To_Transverse_Mercator converts geodetic
00317    * (latitude and longitude) coordinates to Transverse Mercator projection
00318    * (easting and northing) coordinates, according to the current ellipsoid
00319    * and Transverse Mercator projection coordinates.  If any errors occur, the
00320    * error code(s) are returned by the function, otherwise TRANMERC_NO_ERROR is
00321    * returned.
00322    *
00323    *    Latitude      : Latitude in radians                         (input)
00324    *    Longitude     : Longitude in radians                        (input)
00325    *    Easting       : Easting/X in meters                         (output)
00326    *    Northing      : Northing/Y in meters                        (output)
00327    */
00328 
00329   double c;       /* Cosine of latitude                          */
00330   double c2;
00331   double c3;
00332   double c5;
00333   double c7;
00334   double dlam;    /* Delta longitude - Difference in Longitude       */
00335   double eta;     /* constant - TranMerc_ebs *c *c                   */
00336   double eta2;
00337   double eta3;
00338   double eta4;
00339   double s;       /* Sine of latitude                        */
00340   double sn;      /* Radius of curvature in the prime vertical       */
00341   double t;       /* Tangent of latitude                             */
00342   double tan2;
00343   double tan3;
00344   double tan4;
00345   double tan5;
00346   double tan6;
00347   double t1;      /* Term in coordinate conversion formula - GP to Y */
00348   double t2;      /* Term in coordinate conversion formula - GP to Y */
00349   double t3;      /* Term in coordinate conversion formula - GP to Y */
00350   double t4;      /* Term in coordinate conversion formula - GP to Y */
00351   double t5;      /* Term in coordinate conversion formula - GP to Y */
00352   double t6;      /* Term in coordinate conversion formula - GP to Y */
00353   double t7;      /* Term in coordinate conversion formula - GP to Y */
00354   double t8;      /* Term in coordinate conversion formula - GP to Y */
00355   double t9;      /* Term in coordinate conversion formula - GP to Y */
00356   double tmd;     /* True Meridional distance                        */
00357   double tmdo;    /* True Meridional distance for latitude of origin */
00358   long    Error_Code = TRANMERC_NO_ERROR;
00359   double temp_Origin;
00360   double temp_Long;
00361 
00362   if ((Latitude < -MAX_LAT) || (Latitude > MAX_LAT))
00363   {  /* Latitude out of range */
00364     Error_Code|= TRANMERC_LAT_ERROR;
00365   }
00366   if (Longitude > PI)
00367     Longitude -= (2 * PI);
00368   if ((Longitude < (TranMerc_Origin_Long - MAX_DELTA_LONG))
00369       || (Longitude > (TranMerc_Origin_Long + MAX_DELTA_LONG)))
00370   {
00371     if (Longitude < 0)
00372       temp_Long = Longitude + 2 * PI;
00373     else
00374       temp_Long = Longitude;
00375     if (TranMerc_Origin_Long < 0)
00376       temp_Origin = TranMerc_Origin_Long + 2 * PI;
00377     else
00378       temp_Origin = TranMerc_Origin_Long;
00379     if ((temp_Long < (temp_Origin - MAX_DELTA_LONG))
00380         || (temp_Long > (temp_Origin + MAX_DELTA_LONG)))
00381       Error_Code|= TRANMERC_LON_ERROR;
00382   }
00383   if (!Error_Code)
00384   { /* no errors */
00385 
00386     /* 
00387      *  Delta Longitude
00388      */
00389     dlam = Longitude - TranMerc_Origin_Long;
00390 
00391     if (fabs(dlam) > (9.0 * PI / 180))
00392     { /* Distortion will result if Longitude is more than 9 degrees from the Central Meridian */
00393       Error_Code |= TRANMERC_LON_WARNING;
00394     }
00395 
00396     if (dlam > PI)
00397       dlam -= (2 * PI);
00398     if (dlam < -PI)
00399       dlam += (2 * PI);
00400     if (fabs(dlam) < 2.e-10)
00401       dlam = 0.0;
00402 
00403     s = sin(Latitude);
00404     c = cos(Latitude);
00405     c2 = c * c;
00406     c3 = c2 * c;
00407     c5 = c3 * c2;
00408     c7 = c5 * c2;
00409     t = tan (Latitude);
00410     tan2 = t * t;
00411     tan3 = tan2 * t;
00412     tan4 = tan3 * t;
00413     tan5 = tan4 * t;
00414     tan6 = tan5 * t;
00415     eta = TranMerc_ebs * c2;
00416     eta2 = eta * eta;
00417     eta3 = eta2 * eta;
00418     eta4 = eta3 * eta;
00419 
00420     /* radius of curvature in prime vertical */
00421     sn = SPHSN(Latitude);
00422 
00423     /* True Meridianal Distances */
00424     tmd = SPHTMD(Latitude);
00425 
00426     /*  Origin  */
00427     tmdo = SPHTMD (TranMerc_Origin_Lat);
00428 
00429     /* northing */
00430     t1 = (tmd - tmdo) * TranMerc_Scale_Factor;
00431     t2 = sn * s * c * TranMerc_Scale_Factor/ 2.e0;
00432     t3 = sn * s * c3 * TranMerc_Scale_Factor * (5.e0 - tan2 + 9.e0 * eta 
00433                                                 + 4.e0 * eta2) /24.e0; 
00434 
00435     t4 = sn * s * c5 * TranMerc_Scale_Factor * (61.e0 - 58.e0 * tan2
00436                                                 + tan4 + 270.e0 * eta - 330.e0 * tan2 * eta + 445.e0 * eta2
00437                                                 + 324.e0 * eta3 -680.e0 * tan2 * eta2 + 88.e0 * eta4 
00438                                                 -600.e0 * tan2 * eta3 - 192.e0 * tan2 * eta4) / 720.e0;
00439 
00440     t5 = sn * s * c7 * TranMerc_Scale_Factor * (1385.e0 - 3111.e0 * 
00441                                                 tan2 + 543.e0 * tan4 - tan6) / 40320.e0;
00442 
00443     *Northing = TranMerc_False_Northing + t1 + pow(dlam,2.e0) * t2
00444                 + pow(dlam,4.e0) * t3 + pow(dlam,6.e0) * t4
00445                 + pow(dlam,8.e0) * t5; 
00446 
00447     /* Easting */
00448     t6 = sn * c * TranMerc_Scale_Factor;
00449     t7 = sn * c3 * TranMerc_Scale_Factor * (1.e0 - tan2 + eta ) /6.e0;
00450     t8 = sn * c5 * TranMerc_Scale_Factor * (5.e0 - 18.e0 * tan2 + tan4
00451                                             + 14.e0 * eta - 58.e0 * tan2 * eta + 13.e0 * eta2 + 4.e0 * eta3 
00452                                             - 64.e0 * tan2 * eta2 - 24.e0 * tan2 * eta3 )/ 120.e0;
00453     t9 = sn * c7 * TranMerc_Scale_Factor * ( 61.e0 - 479.e0 * tan2
00454                                              + 179.e0 * tan4 - tan6 ) /5040.e0;
00455 
00456     *Easting = TranMerc_False_Easting + dlam * t6 + pow(dlam,3.e0) * t7 
00457                + pow(dlam,5.e0) * t8 + pow(dlam,7.e0) * t9;
00458   }
00459   return (Error_Code);
00460 } /* END OF Convert_Geodetic_To_Transverse_Mercator */
00461 
00462 
00463 long Convert_Transverse_Mercator_To_Geodetic (
00464                                              double Easting,
00465                                              double Northing,
00466                                              double *Latitude,
00467                                              double *Longitude)
00468 {      /* BEGIN Convert_Transverse_Mercator_To_Geodetic */
00469 
00470   /*
00471    * The function Convert_Transverse_Mercator_To_Geodetic converts Transverse
00472    * Mercator projection (easting and northing) coordinates to geodetic
00473    * (latitude and longitude) coordinates, according to the current ellipsoid
00474    * and Transverse Mercator projection parameters.  If any errors occur, the
00475    * error code(s) are returned by the function, otherwise TRANMERC_NO_ERROR is
00476    * returned.
00477    *
00478    *    Easting       : Easting/X in meters                         (input)
00479    *    Northing      : Northing/Y in meters                        (input)
00480    *    Latitude      : Latitude in radians                         (output)
00481    *    Longitude     : Longitude in radians                        (output)
00482    */
00483 
00484   double c;       /* Cosine of latitude                          */
00485   double de;      /* Delta easting - Difference in Easting (Easting-Fe)    */
00486   double dlam;    /* Delta longitude - Difference in Longitude       */
00487   double eta;     /* constant - TranMerc_ebs *c *c                   */
00488   double eta2;
00489   double eta3;
00490   double eta4;
00491   double ftphi;   /* Footpoint latitude                              */
00492   int    i;       /* Loop iterator                   */
00493   double s;       /* Sine of latitude                        */
00494   double sn;      /* Radius of curvature in the prime vertical       */
00495   double sr;      /* Radius of curvature in the meridian             */
00496   double t;       /* Tangent of latitude                             */
00497   double tan2;
00498   double tan4;
00499   double t10;     /* Term in coordinate conversion formula - GP to Y */
00500   double t11;     /* Term in coordinate conversion formula - GP to Y */
00501   double t12;     /* Term in coordinate conversion formula - GP to Y */
00502   double t13;     /* Term in coordinate conversion formula - GP to Y */
00503   double t14;     /* Term in coordinate conversion formula - GP to Y */
00504   double t15;     /* Term in coordinate conversion formula - GP to Y */
00505   double t16;     /* Term in coordinate conversion formula - GP to Y */
00506   double t17;     /* Term in coordinate conversion formula - GP to Y */
00507   double tmd;     /* True Meridional distance                        */
00508   double tmdo;    /* True Meridional distance for latitude of origin */
00509   long Error_Code = TRANMERC_NO_ERROR;
00510 
00511   if ((Easting < (TranMerc_False_Easting - TranMerc_Delta_Easting))
00512       ||(Easting > (TranMerc_False_Easting + TranMerc_Delta_Easting)))
00513   { /* Easting out of range  */
00514     Error_Code |= TRANMERC_EASTING_ERROR;
00515   }
00516   if ((Northing < (TranMerc_False_Northing - TranMerc_Delta_Northing))
00517       || (Northing > (TranMerc_False_Northing + TranMerc_Delta_Northing)))
00518   { /* Northing out of range */
00519     Error_Code |= TRANMERC_NORTHING_ERROR;
00520   }
00521 
00522   if (!Error_Code)
00523   {
00524     /* True Meridional Distances for latitude of origin */
00525     tmdo = SPHTMD(TranMerc_Origin_Lat);
00526 
00527     /*  Origin  */
00528     tmd = tmdo +  (Northing - TranMerc_False_Northing) / TranMerc_Scale_Factor; 
00529 
00530     /* First Estimate */
00531     sr = SPHSR(0.e0);
00532     ftphi = tmd/sr;
00533 
00534     for (i = 0; i < 5 ; i++)
00535     {
00536       t10 = SPHTMD (ftphi);
00537       sr = SPHSR(ftphi);
00538       ftphi = ftphi + (tmd - t10) / sr;
00539     }
00540 
00541     /* Radius of Curvature in the meridian */
00542     sr = SPHSR(ftphi);
00543 
00544     /* Radius of Curvature in the meridian */
00545     sn = SPHSN(ftphi);
00546 
00547     /* Sine Cosine terms */
00548     s = sin(ftphi);
00549     c = cos(ftphi);
00550 
00551     /* Tangent Value  */
00552     t = tan(ftphi);
00553     tan2 = t * t;
00554     tan4 = tan2 * tan2;
00555     eta = TranMerc_ebs * pow(c,2);
00556     eta2 = eta * eta;
00557     eta3 = eta2 * eta;
00558     eta4 = eta3 * eta;
00559     de = Easting - TranMerc_False_Easting;
00560     if (fabs(de) < 0.0001)
00561       de = 0.0;
00562 
00563     /* Latitude */
00564     t10 = t / (2.e0 * sr * sn * pow(TranMerc_Scale_Factor, 2));
00565     t11 = t * (5.e0  + 3.e0 * tan2 + eta - 4.e0 * pow(eta,2)
00566                - 9.e0 * tan2 * eta) / (24.e0 * sr * pow(sn,3) 
00567                                        * pow(TranMerc_Scale_Factor,4));
00568     t12 = t * (61.e0 + 90.e0 * tan2 + 46.e0 * eta + 45.E0 * tan4
00569                - 252.e0 * tan2 * eta  - 3.e0 * eta2 + 100.e0 
00570                * eta3 - 66.e0 * tan2 * eta2 - 90.e0 * tan4
00571                * eta + 88.e0 * eta4 + 225.e0 * tan4 * eta2
00572                + 84.e0 * tan2* eta3 - 192.e0 * tan2 * eta4)
00573           / ( 720.e0 * sr * pow(sn,5) * pow(TranMerc_Scale_Factor, 6) );
00574     t13 = t * ( 1385.e0 + 3633.e0 * tan2 + 4095.e0 * tan4 + 1575.e0 
00575                 * pow(t,6))/ (40320.e0 * sr * pow(sn,7) * pow(TranMerc_Scale_Factor,8));
00576     *Latitude = ftphi - pow(de,2) * t10 + pow(de,4) * t11 - pow(de,6) * t12 
00577                 + pow(de,8) * t13;
00578 
00579     t14 = 1.e0 / (sn * c * TranMerc_Scale_Factor);
00580 
00581     t15 = (1.e0 + 2.e0 * tan2 + eta) / (6.e0 * pow(sn,3) * c * 
00582                                         pow(TranMerc_Scale_Factor,3));
00583 
00584     t16 = (5.e0 + 6.e0 * eta + 28.e0 * tan2 - 3.e0 * eta2
00585            + 8.e0 * tan2 * eta + 24.e0 * tan4 - 4.e0 
00586            * eta3 + 4.e0 * tan2 * eta2 + 24.e0 
00587            * tan2 * eta3) / (120.e0 * pow(sn,5) * c  
00588                              * pow(TranMerc_Scale_Factor,5));
00589 
00590     t17 = (61.e0 +  662.e0 * tan2 + 1320.e0 * tan4 + 720.e0 
00591            * pow(t,6)) / (5040.e0 * pow(sn,7) * c 
00592                           * pow(TranMerc_Scale_Factor,7));
00593 
00594     /* Difference in Longitude */
00595     dlam = de * t14 - pow(de,3) * t15 + pow(de,5) * t16 - pow(de,7) * t17;
00596 
00597     /* Longitude */
00598     (*Longitude) = TranMerc_Origin_Long + dlam;
00599     while (*Latitude > (90.0 * PI / 180.0))
00600     {
00601       *Latitude = PI - *Latitude;
00602       *Longitude += PI;
00603       if (*Longitude > PI)
00604         *Longitude -= (2 * PI);
00605     }
00606 
00607     while (*Latitude < (-90.0 * PI / 180.0))
00608     {
00609       *Latitude = - (*Latitude + PI);
00610       *Longitude += PI;
00611       if (*Longitude > PI)
00612         *Longitude -= (2 * PI);
00613     }
00614     if (*Longitude > (2*PI))
00615       *Longitude -= (2 * PI);
00616     if (*Longitude < -PI)
00617       *Longitude += (2 * PI);
00618 
00619     if (fabs(dlam) > (9.0 * PI / 180))
00620     { /* Distortion will result if Longitude is more than 9 degrees from the Central Meridian */
00621       Error_Code |= TRANMERC_LON_WARNING;
00622     }
00623   }
00624   return (Error_Code);
00625 } /* END OF Convert_Transverse_Mercator_To_Geodetic */

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