
	subroutine constants

	common /consts/   PI, FOURTHPI, deg2rad, rad2deg
	common /ellipses/ ellipsnum(24), ellipsname(24), ell_eqrad(24), ell_eccsq(24)

	integer ellipsnum
	character*20 ellipsname
	real*8 ell_eqrad
	real*8 ell_eccsq

	real*8 PI
	real*8 FOURTHPI
	real*8 deg2rad
	real*8 rad2deg

	PI = 3.14159265
	FOURTHPI = PI / 4
	deg2rad = PI / 180
	rad2deg = 180.0 / PI

	data ellipsnum /-1,1,2,3,4,5,6,7,8,9,10,11,
     +                  12,13,14,15,16,17,18,19,20,
     +                  21,22,23/

	data ellipsname /"Placeholder",
     +                   "Airy",
     +                   "Australian National",
     +                   "Bessel 1841",
     +                   "Bessel 1841 (Nambia) ",
     +                   "Clarke 1866",
     +                   "Clarke 1880",
     +                   "Everest",
     +                   "Fischer 1960 (Mercury) ",
     +                   "Fischer 1968",
     +                   "GRS 1967",
     +                   "GRS 1980","Helmert 1906",
     +                   "Hough",
     +                   "International",
     +                   "Krassovsky",
     +                   "Modified Airy",
     +                   "Modified Everest",
     +                   "Modified Fischer 1960",
     +                   "South American 1969",
     +                   "WGS 60",
     +                   "WGS 66",
     +                   "WGS-72",
     +                   "WGS-84"/

	data ell_eqrad / 0.,
     +                   6377563.,
     +                   6378160.,
     +                   6377397.,
     +                   6377484.,
     +                   6378206.,
     +                   6378249.,
     +                   6377276.,
     +                   6378166.,
     +                   6378150.,
     +                   6378160.,
     +                   6378137.,
     +                   6378200.,
     +                   6378270.,
     +                   6378388.,
     +                   6378245.,
     +                   6377340.,
     +                   6377304.,
     +                   6378155.,
     +                   6378160.,
     +                   6378165.,
     +                   6378145.,
     +                   6378135.,
     +                   6378137/

	data ell_eccsq / 0.,
     +                   0.00667054,
     +                   0.006694542,
     +                   0.006674372,
     +                   0.006674372,
     +                   0.006768658,
     +                   0.006803511,
     +                   0.006637847,
     +                   0.006693422,
     +                   0.006693422,
     +                   0.006694605,
     +                   0.00669438,
     +                   0.006693422,
     +                   0.00672267,
     +                   0.00672267,
     +                   0.006693422,
     +                   0.00667054,
     +                   0.006637847,
     +                   0.006693422,
     +                   0.006694542,
     +                   0.006693422,
     +                   0.006694542,
     +                   0.006694318,
     +                   0.00669438/

	return
	end

	subroutine lltoutm (ReferenceEllipsoid, Lat, Long, 
     +             UTMNorthing, UTMEasting, UTMZone, ZoneNumber)

	common /consts/   PI, FOURTHPI, deg2rad, rad2deg
	common /ellipses/ ellipsnum(24), ellipsname(24), ell_eqrad(24), ell_eccsq(24)

	integer ellipsnum
	character*20 ellipsname
	real*8 ell_eqrad
	real*8 ell_eccsq

	real*8 PI
	real*8 FOURTHPI
	real*8 deg2rad
	real*8 rad2deg

	integer ReferenceEllipsoid
	real*8 Lat
	real*8 Long
	real*8 UTMNorthing
	real*8 UTMEasting
	character UTMZone
	character*1 UTMLetterDesignator

c-----converts lat/long to UTM coords.  Equations from USGS Bulletin 1532 
c-----East Longitudes are positive, West longitudes are negative. 
c-----North latitudes are positive, South latitudes are negative
c-----Lat and Long are in decimal degrees

	real*8 a
	real*8 eccSquared
	real*8 k0

	real*8 LongOrigin
	real*8 eccPrimeSquared
	real*8 N, T, C, BA, M
	real*8 LatRad
	real*8 LongRad
	real*8 LongTemp
	real*8 LongOriginRad
	integer ZoneNumber

	a = ell_eqrad(ReferenceEllipsoid)
	eccSquared = ell_eccsq(ReferenceEllipsoid)
	k0 = 0.9996

c-----Make sure the longitude is between -180.00 .. 179.9
	longt = (Long+180)/360
	LongTemp = (Long+180)-longt*360-180
c----- -180.00 .. 179.9

	LatRad = Lat*deg2rad
	LongRad = LongTemp*deg2rad

	longt = (LongTemp + 180)/6
	ZoneNumber = longt + 1
  
	if(Lat.ge.56.0.and.Lat.lt.64.0.and.LongTemp.ge.3.0.and.LongTemp.lt.12.0) ZoneNumber = 32


c----- Special zones for Svalbard
	if(Lat.ge.72.0 .and. Lat.lt.84.0 ) then
	  if(LongTemp.ge.0.0  .and. LongTemp.lt. 9.0 ) ZoneNumber = 31
	  if(LongTemp.ge.9.0  .and. LongTemp.lt.21.0 ) ZoneNumber = 33
	  if(LongTemp.ge.21.0 .and. LongTemp.lt.33.0 ) ZoneNumber = 35
	  if(LongTemp.ge.33.0 .and. LongTemp.lt.42.0 ) ZoneNumber = 37
	 end if

c-----+3 puts origin in middle of zone
	LongOrigin = (ZoneNumber - 1)*6 - 180 + 3
	LongOriginRad = LongOrigin*deg2rad

c-----compute the UTM Zone from the latitude and longitude
	UTMZone = UTMLetterDesignator(Lat)

	eccPrimeSquared = (eccSquared)/(1-eccSquared)

	N = a/sqrt(1-eccSquared*dsin(LatRad)*dsin(LatRad))
	T = tan(LatRad)*tan(LatRad)
	C = eccPrimeSquared*dcos(LatRad)*dcos(LatRad)
	BA = dcos(LatRad)*(LongRad-LongOriginRad)

	M = a*((1 - eccSquared/4 - 3*eccSquared*eccSquared/64 
     +          - 5*eccSquared*eccSquared*eccSquared/256)*LatRad
     +          - (3*eccSquared/8 + 3*eccSquared*eccSquared/32 
     +          + 45*eccSquared*eccSquared*eccSquared/1024)*
     +             dsin(2.d0*LatRad)
     +          + (15*eccSquared*eccSquared/256 
     +          + 45*eccSquared*eccSquared*eccSquared/1024)*
     +             dsin(4.d0*LatRad) 
     +          - (35*eccSquared*eccSquared*eccSquared/3072)*
     +             dsin(6.d0*LatRad))
	
	UTMEasting = k0*N*(BA+(1-T+C)*BA*BA*BA/6
     +          + (5-18*T+T*T+72*C-58*eccPrimeSquared)
     +             *BA*BA*BA*BA*BA/120)
     +          + 500000.0

	UTMNorthing = k0*(M+N*tan(LatRad)*(BA*BA/2+
     +            (5-T+9*C+4*C*C)*BA*BA*BA*BA/24
     +          + (61-58*T+T*T+600*C-330*eccPrimeSquared)
     +             *BA*BA*BA*BA*BA*BA/720))

	if(Lat.lt.0) then
c-----10000000 meter offset for southern hemisphere
	  UTMNorthing = UTMNorthing + 10000000.0
	end if

	return
	end

	function UTMLetterDesignator(Lat)
	real*8 Lat
	character*1 UTMLetterDesignator

c-----This routine determines the correct UTM letter designator for the given latitude
c-----returns 'Z' if latitude is outside the UTM limits of 84N to 80S


	if((84.ge.Lat) .and. (Lat.ge.72)) then
	  UTMLetterDesignator = 'X'
	else if((72.gt.Lat) .and. (Lat.ge.64)) then
          UTMLetterDesignator = 'W'
	else if((64.gt.Lat) .and. (Lat.ge.56)) then
	  UTMLetterDesignator = 'V'
	else if((56.gt.Lat) .and. (Lat.ge.48)) then
	  UTMLetterDesignator = 'U'
	else if((48.gt.Lat) .and. (Lat.ge.40)) then
	  UTMLetterDesignator = 'T'
	else if((40.gt.Lat) .and. (Lat.ge.32)) then
	  UTMLetterDesignator = 'S'
	else if((32.gt.Lat) .and. (Lat.ge.24)) then
	  UTMLetterDesignator = 'R'
	else if((24.gt.Lat) .and. (Lat.ge.16)) then
	  UTMLetterDesignator = 'Q'
	else if((16.gt.Lat) .and. (Lat.ge.8)) then
	  UTMLetterDesignator = 'P'
	else if(( 8.gt.Lat) .and. (Lat.ge.0)) then
	  UTMLetterDesignator = 'N'
	else if(( 0.gt.Lat) .and. (Lat.ge.-8)) then
	  UTMLetterDesignator = 'M'
	else if((-8.gt.Lat) .and. (Lat.ge.-16)) then
	  UTMLetterDesignator = 'L'
	else if((-16.gt.Lat) .and. (Lat.ge.-24)) then
	  UTMLetterDesignator = 'K'
	else if((-24.gt.Lat) .and. (Lat.ge.-32)) then
	  UTMLetterDesignator = 'J'
	else if((-32.gt.Lat) .and. (Lat.ge.-40)) then
	  UTMLetterDesignator = 'H'
	else if((-40.gt.Lat) .and. (Lat.ge.-48)) then
	  UTMLetterDesignator = 'G'
	else if((-48.gt.Lat) .and. (Lat.ge.-56)) then
	  UTMLetterDesignator = 'F'
	else if((-56.gt.Lat) .and. (Lat.ge.-64)) then
	  UTMLetterDesignator = 'E'
	else if((-64.gt.Lat) .and. (Lat.ge.-72)) then
	  UTMLetterDesignator = 'D'
	else if((-72.gt.Lat) .and. (Lat.ge.-80)) then
	  UTMLetterDesignator = 'C'
	else 
c-----This is here as an error flag to show that the Latitude is outside the UTM limits
	  UTMLetterDesignator = 'Z'
	end if


	return 
	end


	subroutine utmtoll (ReferenceEllipsoid, UTMNorthing, UTMEasting, UTMZone,
     +             Lat,  Long, ZoneNumber)

	common /consts/   PI, FOURTHPI, deg2rad, rad2deg
	common /ellipses/ ellipsnum(24), ellipsname(24), ell_eqrad(24), ell_eccsq(24)

	integer ellipsnum
	character*20 ellipsname
	real*8 ell_eqrad
	real*8 ell_eccsq

	real*8 PI
	real*8 FOURTHPI
	real*8 deg2rad
	real*8 rad2deg

	integer ReferenceEllipsoid
	real*8 UTMNorthing
	real*8 UTMEasting
	character UTMZone
	real*8 Lat
	real*8 Long
	integer ZoneNumber

	real*8 N1, T1, C1, R1, D, M
	real*8 LongOrigin
	real*8 mu, phi1, phi1Rad
	real*8 x, y
	character ZoneLetter
c-----1 for northern hemispher, 0 for southern
	integer NorthernHemisphere 
	real*8 k0
	real*8 a
	real*8 eccSquared
	real*8 eccPrimeSquared
	real*8 e1

c-----converts UTM coords to lat/long.  Equations from USGS Bulletin 1532 
c-----East Longitudes are positive, West longitudes are negative. 
c-----North latitudes are positive, South latitudes are negative
c-----Lat and Long are in decimal degrees. 

	k0 = 0.9996
	a = ell_eqrad(ReferenceEllipsoid)
	eccSquared = ell_eccsq(ReferenceEllipsoid)
	e1 = (1-sqrt(1-eccSquared))/(1+sqrt(1-eccSquared))

c-----remove 500,000 meter offset for longitude
	x = UTMEasting - 500000.0 
	y = UTMNorthing

	ZoneLetter = UTMZone
	if((ichar(ZoneLetter) - ichar('N')).ge.0) then
c-----point is in northern hemisphere
	  NorthernHemisphere = 1
	else
c-----point is in southern hemisphere
	  NorthernHemisphere = 0
c-----remove 10,000,000 meter offset used for southern hemisphere
	  y = y - 10000000.0
	end if

c-----+3 puts origin in middle of zone
	LongOrigin = (ZoneNumber - 1)*6 - 180 + 3

	eccPrimeSquared = (eccSquared)/(1-eccSquared)

	M = y / k0
	mu = M/(a*(1-eccSquared/4-3*eccSquared*
     +       eccSquared/64-5*eccSquared*
     +       eccSquared*eccSquared/256))

	phi1Rad = mu + (3*e1/2-27*e1*e1*e1/32)*
     +            dsin(2*mu) + (21*e1*e1/16-55*
     +            e1*e1*e1*e1/32)*dsin(4*mu)
     +            +(151*e1*e1*e1/96)*dsin(6*mu)

	phi1 = phi1Rad*rad2deg

	N1 = a/sqrt(1-eccSquared*dsin(phi1Rad)*
     +       dsin(phi1Rad))
	T1 = tan(phi1Rad)*tan(phi1Rad)
	C1 = eccPrimeSquared*dcos(phi1Rad)*dcos(phi1Rad)
	R1 = a*(1-eccSquared)/((1-eccSquared*
     +       dsin(phi1Rad)*dsin(phi1Rad))**1.5)
	D = x/(N1*k0)

	Lat = phi1Rad - (N1*tan(phi1Rad)/R1)*
     +        (D*D/2-(5+3*T1+10*C1-4*C1*C1-9*
     +        eccPrimeSquared)*D*D*D*D/24
     +        +(61+90*T1+298*C1+45*T1*T1-252*
     +        eccPrimeSquared-3*C1*C1)*D*D*D*D*D*D/720)
	Lat = Lat*rad2deg

	Long = (D-(1+2*T1+C1)*D*D*D/6+
     +         (5-2*C1+28*T1-3*C1*C1+
     +         8*eccPrimeSquared+24*T1*T1)
     +         *D*D*D*D*D/120)/dcos(phi1Rad)

	Long = LongOrigin + Long*rad2deg

	return
	end
