Cartography-Projection-GCTP

 view release on metacpan or  search on metacpan

gctpc/utminv.c  view on Meta::CPAN

double r_min;			/* minor axis				*/
double scale_fact;		/* scale factor				*/
long zone;			/* zone number				*/
{
double temp;			/* temprorary variables			*/

if ((abs(zone) < 1) || (abs(zone) > 60))
   {
   p_error("Illegal zone number","utm-invint");
   return(11);
   }
r_major = r_maj;
r_minor = r_min;
scale_factor = scale_fact;
lat_origin = 0.0;
lon_center = ((6 * abs(zone)) - 183) * D2R;
false_easting = 500000.0;
false_northing = (zone < 0) ? 10000000.0 : 0.0;

temp = r_minor / r_major;
es = 1.0 - SQUARE(temp);
e = sqrt(es);
e0 = e0fn(es);
e1 = e1fn(es);
e2 = e2fn(es);
e3 = e3fn(es);
ml0 = r_major * mlfn(e0, e1, e2, e3, lat_origin);
esp = es / (1.0 - es);

if (es < .00001)
   ind = 1;
else 
   ind = 0;

/* Report parameters to the user
  -----------------------------*/
ptitle("UNIVERSAL TRANSVERSE MERCATOR (UTM)"); 
genrpt_long(zone,   "Zone:     ");
radius2(r_major, r_minor);
genrpt(scale_factor,"Scale Factor at C. Meridian:     ");
cenlonmer(lon_center);
return(OK);
}

/* Universal Transverse Mercator inverse equations--mapping x,y to lat,long 
   Note:  The algorithm for UTM is exactly the same as TM and therefore
	  if a change is implemented, also make the change to TMINV.c
  -----------------------------------------------------------------------*/
long utminv(x, y, lon, lat)
double x;		/* (I) X projection coordinate 			*/
double y;		/* (I) Y projection coordinate 			*/
double *lon;		/* (O) Longitude 				*/
double *lat;		/* (O) Latitude 				*/
{
double con,phi;		/* temporary angles				*/
double delta_phi;	/* difference between longitudes		*/
long i;			/* counter variable				*/
double sin_phi, cos_phi, tan_phi;	/* sin cos and tangent values	*/
double c, cs, t, ts, n, r, d, ds;	/* temporary variables		*/
double f, h, g, temp;			/* temporary variables		*/
long max_iter = 6;			/* maximun number of iterations	*/

/* fortran code for spherical form 
--------------------------------*/
if (ind != 0)
   {
   f = exp(x/(r_major * scale_factor));
   g = .5 * (f - 1/f);
   temp = lat_origin + y/(r_major * scale_factor);
   h = cos(temp);
   con = sqrt((1.0 - h * h)/(1.0 + g * g));
   *lat = asinz(con);
   if (temp < 0)
     *lat = -*lat;
   if ((g == 0) && (h == 0))
     {
     *lon = lon_center;
     return(OK);
     }
   else
     {
     *lon = adjust_lon(atan2(g,h) + lon_center);
     return(OK);
     }
   }

/* Inverse equations
  -----------------*/
x = x - false_easting;
y = y - false_northing;

con = (ml0 + y / scale_factor) / r_major;
phi = con;
for (i=0;;i++)
   {
   delta_phi=((con + e1 * sin(2.0*phi) - e2 * sin(4.0*phi) + e3 * sin(6.0*phi))
               / e0) - phi;
/*
   delta_phi = ((con + e1 * sin(2.0*phi) - e2 * sin(4.0*phi)) / e0) - phi;
*/
   phi += delta_phi;
   if (fabs(delta_phi) <= EPSLN) break;
   if (i >= max_iter) 
      { 
      p_error("Latitude failed to converge","UTM-INVERSE"); 
      return(95);
      }
   }
if (fabs(phi) < HALF_PI)
   {
   sincos(phi, &sin_phi, &cos_phi);
   tan_phi = tan(phi);
   c    = esp * SQUARE(cos_phi);
   cs   = SQUARE(c);
   t    = SQUARE(tan_phi);
   ts   = SQUARE(t);
   con  = 1.0 - es * SQUARE(sin_phi); 
   n    = r_major / sqrt(con);
   r    = n * (1.0 - es) / con;
   d    = x / (n * scale_factor);
   ds   = SQUARE(d);



( run in 0.890 second using v1.01-cache-2.11-cpan-71847e10f99 )