cb::forwrd3d
c
      program forwrd3d
c
c********1*********2*********3*********4*********5*********6*********7**
c
c name:      forwrd3d
c version:   200208.19 
c author:    stephen j. frakes
c purpose:   to compute a geodetic 3d forward (direct problem)
c            and then display output information
c
c input parameters:
c -----------------
c
c output parameters:
c ------------------
c
c local variables and constants:
c ------------------------------
c answer           user prompt response
c arc              meridional arc distance latitude p1 to p2 (meters)      
c baz              azimuth back (in radians)
c blimit           geodetic distance allowed on ellipsoid (in meters)
c buff             input char buffer array
c dd,dm,ds         temporary values for degrees, minutes, seconds
c delta            temporary variable                                   
c dh               ellipsoidal difference          (eht2-eht1 in meters)
c distmm           mark to mark distance                     (in meters)
c dmt,d_mt         char constants for units (in meters)        
c dd_max           maximum ellipsoid distance -1 (in meters)   
c dn,de,du         cooridnate differences  (NORTH,EAST,UP     in meters)
c dx,dy,dz         cooridnate differences  (X2-X1,Y2-Y1,Z2-Z1 in meters)
c edist            ellipsoid distance (in meters)
c faz              azimuth forward (in radians)
c filout           output file name
c finv             reciprocal flattening
c hem              hemisphere flag for lat & lon entry  
c ierror           error condition flag with d,m,s conversion
c iter             loop counter 
c lgh              length of buff() array                          
c nq               temporary subroutine flag               
c r1,r2            temporary variables    
c ss               temporary value for ellipsoid distance
c tol0             tolerance for conversion of azimuth seconds    
c tol1             tolerance for values less than 0.00005 meters
c tol2             tolerance for conversion of zenith seconds    
c twopi            two times the constant pi
c izd,mzd,szd      computed zenith distance d,m,s                
c isignz           computed zenith distance - flag  (+/- 1)
c izn,mzn,szn      apparent zenith distance d,m,s                
c isignn           apparent zenith distance - flag  (+/- 1)
c zenith           zenith distance flag 
c
c name1            name of station one
c ld1,lm1,sl1      latitude  sta one - degrees,minutes,seconds
c ald1,alm1,sl1    latitude  sta one - degrees,minutes,seconds
c lat1sn           latitude  sta one - sign (+/- 1)
c d_ns1            latitude  sta one - char ('N','S')
c lod1,lom1,slo1   longitude sta one - degrees,minutes,seconds
c alod1,alom1,slo1 longitude sta one - degrees,minutes,seconds
c lon1sn           longitude sta one - sign (+/- 1)
c d_ew1            longitude sta one - char ('E','W')
c iaz1,maz1,saz1   forward azimuth   - degrees,minutes,seconds
c isign1           forward azimuth   - flag  (+/- 1)
c azd1,azm1,saz1   forward azimuth   - degrees,minutes,seconds
c iazsn            forward azimuth   - flag  (+/- 1)
c glat1,glon1      station one       - (lat & lon in radians )
c eht1             station one       - (ellipsoid hgt meters )
c x1,y1,z1         station one       - (X, Y, Z,  in  meters )
c p1,e1            standpoint one    - (lat & lon in radians )
c
c name2            name of station two
c ld2,lm2,sl2      latitude  sta two - degrees,minutes,seconds
c lat2sn           latitude  sta two - sign (+/- 1)
c d_ns2            latitude  sta two - char ('N','S')
c lod2,lom2,slo2   longitude sta two - degrees,minutes,seconds
c lon2sn           longitude sta two - sign (+/- 1)
c d_ew2            longitude sta two - char ('E','W')
c iaz2,maz2,saz2   back azimuth      - degrees,minutes,seconds
c isign2           back azimuth      - flag  (+/- 1)
c glat2,glon2      station two       - (lat & lon in radians )
c eht2             station two       - (ellipsoid hgt meters )
c x2,y2,z2         station two       - (X, Y, Z,  in  meters )
c p2,e2            forepoint two     - (lat & lon in radians )
c
c global variables and constants:
c -------------------------------
c a                semimajor axis equatorial (in meters)
c b                semiminor axis polar (in meters)
c f                flattening
c esq              1st eccentricity squared for reference ellipsoid
c ep2              2nd eccentricity squared for reference ellipsoid
c pi               constant 3.14159....
c rad              constant 180.0/pi  
c
c    this module called by:  n/a
c
c    this module calls:      getrad, dirct2, todmsp, frmxyz, toxyz, 
c    gethem, trim,   bufdms, gvalr8, gvali4, fixdms, gpnarc, gpn2xyz
c    gpnhri, gpnloa, xyzneu, neuxyz, mmdist, zvalue
c    datan,  write,  read,   dabs,   dsqrt,  open,   stop
c
c    include files used:     n/a
c
c    common blocks used:     const, ellips  
c
c    references:             see comments within subroutines
c
c    comments:
c
c********1*********2*********3*********4*********5*********6*********7**
c::modification history
c::1990mm.dd, sjf, creation of program           
c::199412.15, bmt, creation of program on viper
c::200203.08, crs, modified by c.schwarz to correct spelling of Clarke
c::                at request of Dave Doyle
c::200208.09, rws, modified i/o & standardized program documentation
c::               -added subs trim, bufdms, gethem, gvali4, gvalr8     
c::               -added sub gpnarc
c::200208.13, rws, modified dx,dy,dz & dn,de,du print outs
c::200208.15, rws, fixed an error in bufdms
c::              - added FAZ & BAZ to printed output 
c::200208.19, rws, added more error flags for web interface
c::              - added logical nowebb                      
c::200208.xx, sjf, program version number 2.0                   
c********1*********2*********3*********4*********5*********6*********7**
ce::forwrd3d
c
      implicit double precision (a-h, o-z)
      implicit integer (i-n)
c
      logical  frmxyz
      logical  zenith
      logical  nowebb
c
      character*1  answer,dmt,buff(50),hem
      character*6  d_ns1, d_ew1, d_ns2, d_ew2, d_mt
      character*30 filout,name1,name2
c
      integer*4    nq
      integer*4    ierror
      integer*4    lgh
      real*8       zvalue
c
      common/const/pi,rad
      common/ellips/a,b,f,esq,ep2
c
c     ms_unix      0 = web version
c                  1 = ms_dos or unix
c
      parameter   ( ms_unix = 0 )
c
      pi   = 4.d0*datan(1.d0)
      rad  = 180.d0/pi
c
      dmt  = 'm'
      d_mt = 'Meters'
c
      if( ms_unix.eq.1 )then
        nowebb = .true.
      else
        nowebb = .false.
      endif
c
      tol0 = 0.00005d0
      tol1 = 0.00005d0
      tol2 = 0.005d0
c
      a     = 6378137.d0
      finv  = 298.257222101d0
c
c     b     = 6356752.31414d0
c     esq   = 6.694380022903416d-3
c     ep2   = 6.73949677548169d-3
c
      f     = 1.d0/finv
      esq   = f*(2.0d0-f)
      ss    = 1.0d0-esq
      b     = a*dsqrt( ss )
      ep2   = esq/ss
      twopi = 2.0d0*pi
c
c     compute the geodetic limit distance (blimit), it is equal
c     to twice the arc distance to the pole minus one meter
c
      r1 = 0.0d0
      r2 = pi/2.0d0
      call gpnarc ( a, f, esq, pi, r1, r2, arc )
c
c     maximum distance allowed on ellipsoid
c
      blimit = 2.0d0*arc-1.0d0
      dd_max = blimit                  
c
    1 do 2 i=1,25
        write(*,*) '  '
    2 continue
c
    5 write(*,*) '  '
      write(*,*) '  Program Forwrd3d  -  Version 2.0'
      write(*,*) '  '
      write(*,*) '  Three dimensional forward computation.'
      write(*,*) '  First Station position can be entered in either : '
      write(*,*) '  '
      write(*,*) '  1) Geodetic coordinates - (LAT,LON,EHT) or '
      write(*,*) '  2) Rectangular coordinates - (X,Y,Z) '
      write(*,*) '  '
      write(*,*) '  Select option (1 or 2) : '
      read(*,10) answer
      write(*,*) '  '
      write(*,*) '  '
      irlat1 = 0
      irlon1 = 0
 
   10 format(a1)

      if( answer.eq.'1' )then
c
c   *** input first station latitude, longitude, ellipsoid height
c
        write(*,*) '  Enter First Station '
        write(*,16)
   16   format(18x,'(Separate D,M,S by blanks or commas)')
        write(*,*)'hDD MM SS.sssss  Latitude :        (h default = N )'
c
   11   format(50a1)
c
   22   hem='N'
        read(*,11) buff
        call trim (buff,lgh,hem)
        call bufdms (buff,lgh,hem,dd,dm,ds,ierror)
c
        if( ierror.eq.0 )then
          irlat1 = 0
        else
          irlat1 = 1
          write(*,*) ' Invalid Latitude ... Please re-enter it '
          write(*,*) '  '
          if( nowebb )then
            goto 22
          endif
        endif
c
        ald1 = dd
        alm1 = dm
        sl1  = ds
c
        if( hem.eq.'N' ) then
          lat1sn = +1
        else
          lat1sn = -1
        endif
c
        write(*,*)'hDDD MM SS.sssss Longitude :       (h default = W )'
c
   23   hem='W'
        read(*,11) buff
        call trim (buff,lgh,hem)
        call bufdms (buff,lgh,hem,dd,dm,ds,ierror)
c
        if( ierror.eq.0 )then
          irlon1 = 0
        else
          irlon1 = 1
          write(*,*) ' Invalid Longitude ... Please re-enter it '
          write(*,*) '  '
          if( nowebb )then
            goto 23
          endif
        endif
c
        alod1 = dd
        alom1 = dm
        slo1  = ds
c
        if( hem.eq.'E' ) then
          lon1sn = +1
        else
          lon1sn = -1
        endif
c
        write(*,*)'DDDDD.ddd        Ellipsoid Height :      ( meters )'
        read(*,*) eht1
c
        call getrad(ald1,  alm1,  sl1,  lat1sn, glat1)
        call getrad(alod1, alom1, slo1, lon1sn, glon1)
        call toxyz(glat1,  glon1, eht1, x1, y1, z1)

      elseif( answer.eq.'2' )then
c
c   *** input first station x,y,z coordinates
c
        write(*,*) '  Enter First Station '
        write(*,*) '  '
        write(*,*) 'sDDDDDDD.dddd  X Coordinate :            ( meters )'
        read(*,*) x1
        write(*,*) 'sDDDDDDD.dddd  Y Coordinate :            ( meters )'
        read(*,*) y1
        write(*,*) 'sDDDDDDD.dddd  Z Coordinate :            ( meters )'
        read(*,*) z1
c
        if( .not.frmxyz(x1,y1,z1,glat1,glon1,eht1) )then
          stop 666
        endif
c
        eht1 = zvalue ( eht1, tol1 )
      else
        write(*,*) '  Enter 1 or 2 !   Try again --'
        go to 5
      endif
 
c
   15 write(*,*) '  '
      write(*,*) '  '
      write(*,*) '  '
      write(*,*) '  1) Input DN,DE,DU  or'
      write(*,*) '  2) Input DX,DY,DZ  or'
      write(*,*) '  3) Delta height, azimuth, Ellipsoidal distance or'
      write(*,*) '  4) Delta height, azimuth, Mark to mark distance. '
      write(*,*) '  '
      write(*,*) '  Enter choice : '
      read(*,10) answer
      write(*,*) '  '
      irdst1 = 0
      irmrk1 = 0
      irazi1 = 0

      if( answer.eq.'1' )then
c
c   *** do the forward computation. given dn, de, du
c
        write(*,*) '  Enter DN, DE, DU from First Station '
        write(*,*) '  '
        write(*,*) 'sDDDDD.dddd   DN :                       ( meters )'
        read(*,*) dn
        write(*,*) 'sDDDDD.dddd   DE :                       ( meters )'
        read(*,*) de
        write(*,*) 'sDDDDD.dddd   DU :                       ( meters )'
        read(*,*) du
c
        call neuxyz(dn,de,du,glat1,glon1,dx,dy,dz)
c
        dx = zvalue ( dx, tol1 )
        dy = zvalue ( dy, tol1 )
        dz = zvalue ( dz, tol1 )
c
        x2 = x1+dx
        y2 = y1+dy
        z2 = z1+dz
        if( .not.frmxyz(x2,y2,z2,glat2,glon2,eht2) )then
          stop 666
        endif
c
        eht2 = zvalue ( eht2, tol1 )
c
c       convert e1 & e2 to  0 -> 2*pi radians
c
        p1 = glat1
        e1 = glon1
        p2 = glat2
        e2 = glon2
c
        if( e1.lt.0.0d0 )then
          e1 = e1+twopi
        endif
        if( e2.lt.0.0d0 )then
          e2 = e2+twopi
        endif
c
c       compute the geodetic inverse
c
c ************************************************************
c *     replaced subroutine inver2 with gpnhri
c *  
c *     call inver2 (glat1,glon1,glat2,glon2,faz,baz,edist)
c *
c ************************************************************
c
        call gpnhri (a,f,esq,pi,p1,e1,p2,e2,faz,baz,edist)
c
c       check for a non distance ... p1,e1 & p2,e2 equal zero ?
c
        if( edist.lt.0.00005d0 )then
          faz = 0.0d0
          baz = 0.0d0
        endif
c
c       set the azimuth seconds tolerance
c
        call todmsp(faz,iaz1,maz1,saz1,isign1)
        if(isign1.lt.0) then
          iaz1=359-iaz1
          maz1=59-maz1
          saz1=60.d0-saz1
        endif
        call fixdms ( iaz1, maz1, saz1, tol0 )
c
        call todmsp(baz,iaz2,maz2,saz2,isign2)
        if(isign2.lt.0) then
          iaz2=359-iaz2
          maz2=59-maz2
          saz2=60.d0-saz2
        endif
        call fixdms ( iaz2, maz2, saz2, tol0 )
c
        dh=eht2-eht1
        distmm=dsqrt(dx*dx+dy*dy+dz*dz)

      elseif( answer.eq.'2' )then
c
c   *** do the forward computation. given dx, dy, dz
c
        write(*,*) '  Enter DX, DY, DZ from First Station '
        write(*,*) '  '
        write(*,*) 'sDDDDDD.dddd  DX :                       ( meters )'
        read(*,*) dx
        write(*,*) 'sDDDDDD.dddd  DY :                       ( meters )'
        read(*,*) dy
        write(*,*) 'sDDDDDD.dddd  DZ :                       ( meters )'
        read(*,*) dz
C
        call xyzneu(dx,dy,dz,glat1,glon1,dn,de,du)
c
        dn = zvalue ( dn, tol1 )
        de = zvalue ( de, tol1 )
        du = zvalue ( du, tol1 )
c
        x2 = x1+dx
        y2 = y1+dy
        z2 = z1+dz

        if( .not.frmxyz(x2,y2,z2,glat2,glon2,eht2) )then
          stop 666
        endif
c
        eht2 = zvalue ( eht2, tol1 )
c
c       convert e1 & e2 to  0 -> 2*pi radians
c
        p1 = glat1
        e1 = glon1
        p2 = glat2
        e2 = glon2
c
        if( e1.lt.0.0d0 )then
          e1 = e1+twopi
        endif
        if( e2.lt.0.0d0 )then
          e2 = e2+twopi
        endif
c
c       compute the geodetic inverse
c
c ************************************************************
c *     replaced subroutine inver2 with gpnhri
c *  
c *     call inver2 (glat1,glon1,glat2,glon2,faz,baz,edist)
c *
c ************************************************************
c
        call gpnhri (a,f,esq,pi,p1,e1,p2,e2,faz,baz,edist)
c
c       check for a non distance ... p1,e1 & p2,e2 equal zero ?
c
        if( edist.lt.0.00005d0 )then
          faz = 0.0d0
          baz = 0.0d0
        endif
c
c       set the azimuth seconds tolerance
c
        call todmsp(faz,iaz1,maz1,saz1,isign1)
        if(isign1.lt.0) then
          iaz1=359-iaz1
          maz1=59-maz1
          saz1=60.d0-saz1
        endif
        call fixdms ( iaz1, maz1, saz1, tol0 )
c
        call todmsp(baz,iaz2,maz2,saz2,isign2)
        if(isign2.lt.0) then
          iaz2=359-iaz2
          maz2=59-maz2
          saz2=60.d0-saz2
        endif
        call fixdms ( iaz2, maz2, saz2, tol0 )
c
        dh=eht2-eht1
        distmm=dsqrt(dx*dx+dy*dy+dz*dz)

      elseif( answer.eq.'3' )then
c
c   *** do the forward comutation. given ellips dist, azimuth, delta ht
c
        write(*,*)'sDDDD.ddd        Delta Height :          ( meters )'
        read(*,*) dh
        eht2 = eht1+dh
c
        write(*,*)'DDD MM SS.sss    Forward Azimuth :     (from north)'
c
   24   hem='A'
        read(*,11) buff
        call trim (buff,lgh,hem)
        call bufdms (buff,lgh,hem,dd,dm,ds,ierror)
c
        if( ierror.eq.0 )then
          iazsn  = 1
          irazi1 = 0
        else
          irazi1 = 1
          write(*,*) ' Invalid Azimuth  ... Please re-enter it '
          write(*,*) '  '
          if( nowebb )then
            goto 24
          endif
        endif
c
        azd1 = dd
        azm1 = dm
        saz1 = ds
c
        call getrad (azd1,azm1,saz1,iazsn,faz)
c
        write(*,*)'DDDDDD.dddd      Ellipsoidal Distance : (in meters)'
c
   28   ss = 0.0d0
        read(*,*) ss
        ss = dabs(ss)
c
        if( ss.lt.dd_max )then
          edist  = ss
          irdst1 = 0
        else
          irdst1 = 1
          write(*,*) ' Invalid Distance ... Please re-enter it '
          write(*,*) '  '
          if( nowebb )then
            goto 28
          endif
          edist  = 1.0d0
        endif
c
        call dirct2 (glat1,glon1,glat2,glon2,faz,baz,edist)
        call toxyz (glat2,glon2,eht2,x2,y2,z2)
        dx = x2-x1
        dy = y2-y1
        dz = z2-z1
c
        dx = zvalue ( dx, tol1 )
        dy = zvalue ( dy, tol1 )
        dz = zvalue ( dz, tol1 )
c
        call xyzneu(dx,dy,dz,glat1,glon1,dn,de,du)
        distmm=dsqrt(dx*dx+dy*dy+dz*dz)
c
c       set the azimuth seconds tolerance
c
        call todmsp(faz,iaz1,maz1,saz1,isign1)
        if(isign1.lt.0) then
          iaz1=359-iaz1
          maz1=59-maz1
          saz1=60.d0-saz1
        endif
        call fixdms ( iaz1, maz1, saz1, tol0 )
c
        call todmsp(baz,iaz2,maz2,saz2,isign2)
        if(isign2.lt.0) then
          iaz2=359-iaz2
          maz2=59-maz2
          saz2=60.d0-saz2
        endif
        call fixdms ( iaz2, maz2, saz2, tol0 )
c
      elseif( answer.eq.'4' )then
c
c   *** do the forward computation. given mark-mark dist, az, ellips ht
c
        write(*,*)'sDDDD.ddd        Delta Height :          ( meters )'
        read(*,*) dh
        eht2 = eht1+dh
c
        write(*,*)'DDD MM SS.sss    Forward Azimuth :     (from north)'
c
   26   hem='A'
        read(*,11) buff
        call trim (buff,lgh,hem)
        call bufdms (buff,lgh,hem,dd,dm,ds,ierror)
c
        if( ierror.eq.0 )then
          iazsn  = 1
          irazi1 = 0
        else
          irazi1 = 1
          write(*,*) ' Invalid Azimuth  ... Please re-enter it '
          write(*,*) '  '
          if( nowebb )then
            goto 26
          endif
        endif
c
        azd1 = dd
        azm1 = dm
        saz1 = ds
c
        call getrad(azd1,azm1,saz1,iazsn,faz)
c
        write(*,*)'DDDDD.dddd      Mark-to-Mark Distance : (in meters)'
   29   read(*,*) ss    
        ss = dabs(ss)
c
        if( ss.lt.11.1d+6 )then
          distmm = ss
          irmrk1 = 0
        else
          irmrk1 = 1
          write(*,*) ' Invalid Mk-to-Mk ... Please re-enter it '
          write(*,*) '  '
          if( nowebb )then
            goto 29
          endif
          distmm = 1.0d0
        endif
c
        iter = 0
        call mmdist (glat1,faz,eht1,eht2,distmm,edist)
   27   call dirct2 (glat1,glon1,glat2,glon2,faz,baz,edist)
        call toxyz  (glat2,glon2,eht2,x2,y2,z2)
        dx = x2-x1
        dy = y2-y1
        dz = z2-z1
c
        dx = zvalue ( dx, tol1 )
        dy = zvalue ( dy, tol1 )
        dz = zvalue ( dz, tol1 )
c
        call xyzneu (dx,dy,dz,glat1,glon1,dn,de,du)
        distm2 = dsqrt(dx*dx+dy*dy+dz*dz)
        delta  = distmm-distm2
c
        if( dabs(delta).gt.0.00006d0 )then
          edist = edist+delta
          iter  = iter+1
          if( iter.gt.30 )then
            write(*,*) '  The mark-to-mark distance is too long!'
            stop 666
          endif
          go to 27
        endif
c
c       set the azimuth seconds tolerance
c
        call todmsp(faz,iaz1,maz1,saz1,isign1)
        if(isign1.lt.0) then
          iaz1=359-iaz1
          maz1=59-maz1
          saz1=60.d0-saz1
        endif
        call fixdms ( iaz1, maz1, saz1, tol0 )
c
        call todmsp(baz,iaz2,maz2,saz2,isign2)
        if(isign2.lt.0) then
          iaz2=359-iaz2
          maz2=59-maz2
          saz2=60.d0-saz2
        endif
        call fixdms ( iaz2, maz2, saz2, tol0 )
c
      else
        write(*,*) '  Enter 1 , 2, 3, or 4 !  Try again --'
        go to 15
      endif
c
c     check for small negative numbers
c
      dh   = zvalue ( dh, tol1 )
      eht2 = zvalue ( eht2, tol1 )
c
      call todmsp(glat1, ld1,  lm1,  sl1,  lat1sn)
      call todmsp(glon1, lod1, lom1, slo1, lon1sn)
      call todmsp(glat2, ld2,  lm2,  sl2,  lat2sn)
      call todmsp(glon2, lod2, lom2, slo2, lon2sn)
c
      call hem_ns ( lat1sn, d_ns1 )
      call hem_ns ( lat2sn, d_ns2 )
      call hem_ew ( lon1sn, d_ew1 )
      call hem_ew ( lon2sn, d_ew2 )
c
c     180 miles * (5280 ft/mile) / (3.28083333... ft/meter) 
c
      if( distmm.lt.289682.5d0 )then
        ss = dabs(du/distmm)
        if( ss.gt.0.99985d0 )then
          zenith = .false.
        else
          zenith = .true.

c         compute the real zenith distance (zd)

          zd = dasin(du/distmm)
          zd = pi/2.0d0 - zd

c         compute the apparent zenith distance (zen)

          nq = 0
          ss = 0.0d0
          call gpn2xyz ( a,f,esq,pi,nq,p1,faz,ss,r1,r2,raz)
          refr = (( edist/raz )/2.0d0)/7.0d0
          zen  = zd-refr
c
          call todmsp (zd, izd,mzd,szd,isignz)
          call fixdms (    izd,mzd,szd, tol2 ) 
          call todmsp (zen,izn,mzn,szn,isignn)
          call fixdms (    izn,mzn,szn, tol2 )
        endif 
      else  
        zenith = .false.
      endif
c
      write(*,*) '  '
      write(*,*) '  '
      write(*,*) '  '
      write(*,*) '  '
      write(*,*) '  First  Station : '
c     write(*,*) '  ---------------- '
      write(*,18) x1,ld1, lm1, sl1, d_ns1
      write(*,19) y1,lod1,lom1,slo1,d_ew1
      write(*,25) z1,eht1,d_mt
c
      write(*,*) '  '
      write(*,*) '  Second Station : '
c     write(*,*) '  ---------------- '
      write(*,18) x2,ld2, lm2, sl2, d_ns2
      write(*,19) y2,lod2,lom2,slo2,d_ew2
      write(*,25) z2,eht2,d_mt
c
      write(*,*) '  '
      write(*,34) iaz1,maz1,saz1
      write(*,35) iaz2,maz2,saz2
      write(*,32) edist
      write(*,31) dh
      write(*,33) distmm
      write(*,*) '  '
      write(*,36) dx,dn
      write(*,37) dy,de
      write(*,38) dz,du
c
      if( zenith )then
        write(*,*) '  '
        write(*,68) izd,mzd,szd
        write(*,69) izn,mzn,szn
      endif
c
c
   18 format('  X = ',f15.4,' m  LAT = ',i3,1x,i2,1x,f8.5,1x,a6)
   19 format('  Y = ',f15.4,' m  LON = ',i3,1x,i2,1x,f8.5,1x,a6)
   25 format('  Z = ',f15.4,' m  EHT = ',4x,f10.4,2x,a6)
   31 format('  Delta height            dh = ',f14.4,' m')
   32 format('  Ellipsoidal distance     S = ',f14.4,' m')
   33 format('  Mark-to-mark distance    D = ',f14.4,' m')
   34 format('  Forward azimuth        FAZ = ',i3,1x,i2,1x,f7.4,
     1       ' From North')
   35 format('  Back azimuth           BAZ = ',i3,1x,i2,1x,f7.4,
     1       ' From North')
   68 format('  Zenith (mk-to-mk)       ZD = ',i3,1x,i2,1x,f5.2)
   69 format('  Apparent zenith distance   = ',i3,1x,i2,1x,f5.2)
   36 format('  DX = ',f14.4,' m   DN = ',f14.4,' m')
   37 format('  DY = ',f14.4,' m   DE = ',f14.4,' m')
   38 format('  DZ = ',f14.4,' m   DU = ',f14.4,' m')

      write(*,*) '  '
      write(*,*) '  Do you want to save this output into a file (y/n)?'
      read(*,10) answer
c
      if( answer.eq.'Y'.or.answer.eq.'y' )then
   39   write(*,*) '  Enter the output filename : '
        read(*,40) filout
   40   format(a30)
        open(3,file=filout,status='new',err=99)
        goto 98

   99   write(*,*) '  File already exists, try again.'
        goto 39

   98   continue
        write(*,*) '  Enter the First Station name : '
        read(*,40) name1
        write(*,*) '  Enter the Second Station name : '
        read(*,40) name2
c
   41   format('  First  Station : ',a30)
   42   format('  Second Station : ',a30)
   70   format('  ---------------- ')
   84   format('  Error:  First  Station ... Invalid Latitude  ')
   85   format('  Error:  First  Station ... Invalid Longitude ')
   86   format('  Error:  Forward Azimuth ... Invalid Entry    ')
   87   format('  Error:  Ellipsoid Distance ... Invalid Entry ')
   88   format(1x,65(1h*))
   83   format('  Error:  Mark-to-mark Distance ... Invalid Entry ')
   91   format('          DD(0-89) MM(0-59) SS(0-59.999...)    ')
   92   format('          DDD(0-359) MM(0-59) SS(0-59.999...)  ')
   93   format('          Geodetic distance is too long.       ')
   94   format('          Mark-to-mark distance is too long.   ')
c
        write(3,*) '  '
        write(3,41) name1
        write(3,70)
c
        if( irlat1.eq.0 )then 
          write(3,18) x1,ld1, lm1, sl1, d_ns1
        else
          write(3,88)
          write(3,84)
          write(3,91)                              
          write(3,88)
        endif
c
        if( irlon1.eq.0 )then
          write(3,19) y1,lod1,lom1,slo1,d_ew1
        else
          write(3,88)
          write(3,85)
          write(3,92)                          
          write(3,88)
        endif
c
        write(3,25) z1,eht1,d_mt
c
        write(3,*) '  '
        write(3,42) name2
        write(3,70) 
        write(3,18) x2,ld2, lm2, sl2, d_ns2
        write(3,19) y2,lod2,lom2,slo2,d_ew2
        write(3,25) z2,eht2,d_mt
c
        write(3,*) '  '
c
        if( irazi1.eq.0 )then
          write(3,34) iaz1,maz1,saz1
        else
          write(3,88)
          write(3,86)
          write(3,92)                  
          write(3,88)
        endif
c
        write(3,35) iaz2,maz2,saz2
c
        if( irdst1.eq.0 )then
          write(3,32) edist
        else
          write(3,88)
          write(3,87)
          write(3,93)      
          write(3,88)
        endif
c
        write(3,31) dh
c
        if( irmrk1.eq.0 )then
          write(3,33) distmm
        else
          write(3,88)
          write(3,83)
          write(3,94)          
          write(3,88)
        endif
c
        write(3,*) '  '
        write(3,36) dx,dn
        write(3,37) dy,de
        write(3,38) dz,du
c
        if( zenith )then
          write(3,*) '  '
          write(3,68) izd,mzd,szd
          write(3,69) izn,mzn,szn
        endif
      endif
c
      write(*,*) '  '
      write(*,*) '  '
      write(*,*) '  '
      write(*,*) '  1) Another forward, two new stations.'
      write(*,*) '  2) Another forward, same First Station.'
      write(*,*) '  3) Done.'
      write(*,*) '  '
      write(*,*) '  Enter choice : '
      read(*,10) answer
c
      if(     answer.eq.'1' )then
        goto 1
      elseif( answer.eq.'2' )then
        goto 15
      else
        write(*,*) '  Thats all folks! '
      endif

c     stop
      end

      subroutine bufdms (buff,lgh,hem,dd,dm,ds,ierror)
      implicit double precision (a-h, o-z)
      implicit integer (i-n)
c
      logical     done,flag
c
      character*1 buff(*),abuf(21)
      character*1 ch
      character*1 hem
      integer*4   ll,lgh
      integer*4   i4,id,im,is,icond,ierror
      real*8      x(5)
c
c     set the "error flag" 
c
      ierror = 0
      icond  = 0
c
c     set defaults for dd,dm,ds
c
      dd = 0.0d0
      dm = 0.0d0
      ds = 0.0d0
c
c     set default limits for "hem" flag
c
      if(     hem.eq.'N' .or. hem.eq.'S' )then
        ddmax = 90.0d0
      elseif( hem.eq.'E' .or. hem.eq.'W' )then
        ddmax = 360.0d0
      elseif( hem.eq.'A' )then
        ddmax = 360.0d0
      elseif( hem.eq.'Z' )then
        ddmax = 180.0d0
      elseif( hem.eq.'*' )then
        ddmax  = 0.0d0
        ierror = 1
      else
        ddmax = 360.0d0
      endif
c
      do 1 i=1,5
        x(i) = 0.0d0
    1 continue
c
      icolon = 0
      ipoint = 0
      icount = 0
      flag   = .true.
      jlgh   = lgh
c
      do 2 i=1,jlgh
        if( buff(i).eq.':' )then
          icolon = icolon+1
        endif
        if( buff(i).eq.'.' )then
          ipoint = ipoint+1
          flag   = .false.
        endif
        if( flag )then
          icount = icount+1
        endif
    2 continue
c
      if( ipoint.eq.1 .and. icolon.eq.0 )then
c
c       load temp buffer
c
        do 3 i=1,jlgh
          abuf(i) = buff(i)
    3   continue
        abuf(jlgh+1) = '$'
        ll = jlgh
c
        call gvalr8 (abuf,ll,r8,icond)
c
        if( icount.ge.5 )then
c
c         value is a packed decimal of ==>  DDMMSS.sssss       
c
          ss = r8/10000.0d0
          id = idint( ss )
c
          r8 = r8-10000.0d0*dble(float(id))
          ss = r8/100.0d0
          im = idint( ss )
c
          r8 = r8-100.0d0*dble(float(im))
        else
c
c         value is a decimal of ==>  .xx   X.xxx   X.  
c
          id = idint( r8 )
          r8 = (r8-id)*60.0d0
          im = idint( r8 )
          r8 = (r8-im)*60.0d0
        endif
c
c       account for rounding error
c
        is = idnint( r8*1.0d5 )
        if( is.ge.6000000 )then
           r8 = 0.0d0
           im = im+1
        endif
c
        if( im.ge.60 )then
          im = 0
          id = id+1
        endif
c
        dd = dble( float( id ) )
        dm = dble( float( im ) )
        ds = r8
      else
c
c       buff() value is a d,m,s of ==>  NN:NN:XX.xxx    
c
        k    = 0
        next = 1
        done = .false.
        ie   = jlgh
c
        do 100 j=1,5
          ib = next
          do 90 i=ib,ie
            ch   = buff(i)
            last = i
            if( i.eq.jlgh .or. ch.eq.':' )then
              if( i.eq.jlgh )then
                done = .true.
              endif
              if( ch.eq.':' )then
                last = i-1
              endif
              goto 91
            endif
   90     continue
          goto 98
c
   91     ipoint = 0
          ik     = 0
          do 92 i=next,last
            ik = ik+1
            ch = buff(i)
            if( ch.eq.'.' )then
              ipoint = ipoint+1
            endif
            abuf(ik) = buff(i) 
   92     continue
          abuf(ik+1) = '$' 
c
          ll = ik
          if( ipoint.eq.0 )then
            call gvali4 (abuf,ll,i4,icond)
            r8 = dble(float( i4 )) 
          else
            call gvalr8 (abuf,ll,r8,icond)
          endif
c
          k    = k+1
          x(k) = r8
c
   98     if( done )then
            goto 101
          endif
c
          next = last
   99     next = next+1     
          if( buff(next).eq.':' )then
            goto 99
          endif
  100   continue
c
c       load dd,dm,ds
c
  101   if( k.ge.1 )then
          dd = x(1)
        endif
c
        if( k.ge.2 )then
          dm = x(2)
        endif
c
        if( k.ge.3 )then
          ds = x(3)
        endif
      endif
c
      if( dd.gt.ddmax  .or.
     1    dm.ge.60.0d0 .or.
     1    ds.ge.60.0d0 )then
        ierror = 1
        dd = 0.0d0
        dm = 0.0d0
        ds = 0.0d0
      endif
c
      if( icond.ne.0 )then
        ierror = 1
      endif
c
      return
      end

      SUBROUTINE DIRCT2 (GLAT1,GLON1,GLAT2,GLON2,FAZ,BAZ,S)
C
C *** SOLUTION OF THE GEODETIC DIRECT PROBLEM AFTER T.VINCENTY
C *** MODIFIED RAINSFORD'S METHOD WITH HELMERT'S ELLIPTICAL TERMS
C *** EFFECTIVE IN ANY AZIMUTH AND AT ANY DISTANCE SHORT OF ANTIPODAL
C
C *** A IS THE SEMI-MAJOR AXIS OF THE REFERENCE ELLIPSOID
C *** F IS THE FLATTENING OF THE REFERENCE ELLIPSOID
C *** LATITUDES AND LONGITUDES IN RADIANS POSITIVE NORTH AND EAST
C *** AZIMUTHS IN RADIANS CLOCKWISE FROM NORTH
C *** GEODESIC DISTANCE S ASSUMED IN UNITS OF SEMI-MAJOR AXIS A
C
C *** PROGRAMMED FOR CDC-6600 BY LCDR L.PFEIFER NGS ROCKVILLE MD 20FEB75
C *** MODIFIED FOR SYSTEM 360 BY JOHN G GERGEN NGS ROCKVILLE MD 750608
C
      IMPLICIT REAL*8 (A-H,O-Z)
      COMMON/CONST/PI,RAD
      COMMON/ELLIPS/A,B,F,E2,EP2
      DATA EPS/0.5D-13/
      R=1.-F
      TU=R*DSIN(GLAT1)/DCOS(GLAT1)
      SF=DSIN(FAZ)
      CF=DCOS(FAZ)
      BAZ=0.
      IF(CF.NE.0.) BAZ=DATAN2(TU,CF)*2.
      CU=1./DSQRT(TU*TU+1.)
      SU=TU*CU
      SA=CU*SF
      C2A=-SA*SA+1.
      X=DSQRT((1./R/R-1.)*C2A+1.)+1.
      X=(X-2.)/X
      C=1.-X
      C=(X*X/4.+1)/C
      D=(0.375D0*X*X-1.)*X
      TU=S/R/A/C
      Y=TU
  100 SY=DSIN(Y)
      CY=DCOS(Y)
      CZ=DCOS(BAZ+Y)
      E=CZ*CZ*2.-1.
      C=Y
      X=E*CY
      Y=E+E-1.
      Y=(((SY*SY*4.-3.)*Y*CZ*D/6.+X)*D/4.-CZ)*SY*D+TU
      IF(DABS(Y-C).GT.EPS)GO TO 100
      BAZ=CU*CY*CF-SU*SY
      C=R*DSQRT(SA*SA+BAZ*BAZ)
      D=SU*CY+CU*SY*CF
      GLAT2=DATAN2(D,C)
      C=CU*CY-SU*SY*CF
      X=DATAN2(SY*SF,C)
      C=((-3.*C2A+4.)*F+4.)*C2A*F/16.
      D=((E*CY*C+CZ)*SY*C+Y)*SA
      GLON2=GLON1+X-(1.-C)*D*F
      BAZ=DATAN2(SA,BAZ)+PI
      RETURN
      END

      subroutine fixdms (ideg, min, sec, tol )
c
      implicit double precision (a-h, o-z)
      implicit integer (i-n)
c
c     test for seconds near 60.0-tol
c
      if( sec.ge.( 60.0d0-tol ) )then
        sec  = 0.0d0
        min  = min+1
      endif
c
c     test for minutes near 60
c
      if( min.ge.60 )then
        min  = 0
        ideg = ideg+1
      endif 
c
c     test for degrees near 360
c
      if( ideg.ge.360 )then
        ideg = 0
      endif 
c
      return
      end 
      logical function frmxyz(x,y,z,glat,glon,eht)
 
*** convert x,y,z into geodetic lat, lon, and ellip. ht
*** ref: eq a.4b, p. 132, appendix a, osu #370
*** ref: geom geod notes gs 658, rapp
 
      implicit double precision(a-h,o-z)
      parameter(maxint=10,tol=1.d-13)
      common/ellips/a,b,f,e2,ep2
 
      ae2=a*e2
 
*** compute initial estimate of reduced latitude  (eht=0)
 
      p=dsqrt(x*x+y*y)
      icount=0
      tgla=z/p/(1.d0-e2)
 
*** iterate to convergence, or to max # iterations
 
    1 if(icount.le.maxint) then
        tglax=tgla
        tgla=z/(p-(ae2/dsqrt(1.d0+(1.d0-e2)*tgla*tgla)))
        icount=icount+1
        if(dabs(tgla-tglax).gt.tol) go to 1
 
*** convergence achieved
 
        frmxyz=.true.
        glat=datan(tgla)
        slat=dsin(glat)
        clat=dcos(glat)
        glon=datan2(y,x)
        w=dsqrt(1.d0-e2*slat*slat)
        en=a/w
        if(dabs(glat).le.0.7854d0) then
          eht=p/clat-en
        else
          eht=z/slat-en+e2*en
        endif
        glon=datan2(y,x)
 
*** too many iterations
 
      else
        frmxyz=.false.
        glat=0.d0
        glon=0.d0
        eht=0.d0
      endif
 
      return
      end
      subroutine hem_ns ( lat_sn, hem )
      implicit integer (i-n)
      character*6  hem
c
      if( lat_sn.eq.1 ) then
        hem = 'North '
      else
        hem = 'South '
      endif
c
      return
      end
      subroutine hem_ew ( lon_sn, hem )
      implicit integer (i-n)
      character*6  hem
c
      if( lon_sn.eq.1 ) then
        hem = 'East  '
      else
        hem = 'West  '
      endif
c
      return
      end
      subroutine getrad(d,m,sec,isign,val)
 
*** comvert deg, min, sec to radians
 
      implicit double precision(a-h,j-z)
      common/const/pi,rad
 
      val=(d+m/60.d0+sec/3600.d0)/rad
      val=dble(isign)*val
 
      return
      end
CB::GPN2XYZ
C
      SUBROUTINE GPN2XYZ (A,F,ESQ,PI,N,X,Y,Z,T1,T2,T3)
C
C********1*********2*********3*********4*********5*********6*********7*
C
C NAME:        GPN2XYZ
C VERSION:     200005.26
C WRITTEN BY:  ROBERT (Sid) SAFFORD
C PURPOSE:     SUBROUTINE TO COMPUTE THE GEODETIC OPTIONS: N=0,1,2
C
C INPUT PARAMETERS:
C -----------------
C 
C A            MAJOR AXIS
C F            FLATTENING
C ESQ          0.006768658...
C PI           3.141592653...
C N            CASE TO SOLVE
C X,Y,Z        SEE BELOW
C
C OUTPUT PARAMETERS:
C ------------------
C T1,T2,T3     SEE BELOW
C
C ------------<ENTRIES IN METERS OR RADIANS>-------------------------
C
C            CASE   N=0
C
C     X (LATITUDE)     -->    T1 =  RN
C     Y (AZIMUTH)      -->    T2 =  RM
C     Z (ZERO)         -->    T3 =  RAZ
C
C            CASE   N=1
C
C     X (LATITUDE)     -->    T1 =  X (SPACE RECTANGLUAR COORDINATES)
C     Y (LONGITUDE)    -->    T2 =  Y
C     Z (HEIGHT)       -->    T3 =  Z
C
C            CASE   N=2
C
C     X (COORDINATE)   -->    T1 =  LATITUDE   
C     Y (COORDINATE)   -->    T2 =  LONGITUDE  
C     Z (COORDINATE)   -->    T3 =  ELLIPSOID HEIGHT
C                             N  =  TOTAL # OF ITERATIONS (N)
C
C LOCAL VARIABLES AND CONSTANTS:
C ------------------------------
C GLOBAL VARIABLES AND CONSTANTS:
C -------------------------------
C
C    MODULE CALLED BY:    GENERAL 
C
C    THIS MODULE CALLS:   
C       LLIBFORE/ DSIN,   DCOS,   DABS,   DSQRT,  DATAN 
C
C    INCLUDE FILES USED:
C    COMMON BLOCKS USED:  
C
C    REFERENCES: Microsoft FORTRAN 4.10 Optimizing Compiler, 1988
C                MS-DOS Operating System
C    COMMENTS:
C********1*********2*********3*********4*********5*********6*********7*
C::MODIFICATION HISTORY
C::199705.01, RWS, CODE   CREATED FROM MTEN GPNXYZ
C::200005.26, RWS, CODE   RESTRUCTURED & DOCUMENTATION ADDED             
C::200012.31, RWS, VER 23 MTEN5 RELEASED                                 
C********1*********2*********3*********4*********5*********6*********7*
CE::GPN2XYZ
C
      IMPLICIT REAL*8  (A-H,O-Z)
      INTEGER*4    N
C
      DATA TOL / 1.0D-13 /
C 
      E = (1.0D0-ESQ)
C
      IF( N.NE.2 )THEN  
        P1 = X
        E1 = Y
        H  = DSIN(P1)
        W  = DSQRT(1.0D0-ESQ*H*H)
        R  = A/W
C
        IF( N.EQ.1 )THEN
C
C         LAT,LON,HGT   TO  X,Y,Z
C
          IF( E1.LT.0.0D0 )THEN
            E1 = 2.0D0*PI+E1
          ENDIF
C
          EH = Z
          W  = (R+EH)*DCOS(P1)
          T1 = W*DCOS(E1)
          T2 = W*DSIN(E1)
          T3 = H*(R*E+EH)
        ELSE 
C
C         LAT,AZI      TO  RN,RM,RAZ
C
          S  = DCOS(E1)
          H  = A*E/(W*W*W)
          W  = DSIN(E1)
          T1 = R
          T2 = H
          T3 = (T1*T2)/(T1*S*S+T2*W*W)
        ENDIF 
      ELSE 
C
C       X,Y,Z          TO  LAT,LON,HGT
C
        N  = 1
        W  = DSQRT(X*X+Y*Y)
        C  = Z/W
        W  = C/E
        T2 = DATAN2(Y,X)
        S  = DATAN(W)
C 
C       START ITERATION
C
    1   H  = DSIN(S)
        W  = DSQRT(1.0D0-ESQ*H*H)
        R  = A/W
        T  = C*(1.0D0+(R*ESQ*H)/Z)
        T  = DATAN(T)
        IF( DABS(S-T).GT.TOL )THEN
          S = T
          N = N+1
          IF( N.LE.10 )THEN
            GOTO 1
          ENDIF
        ENDIF
C
        T1 = T
        T3 = Z/H-R*E
      ENDIF
C
      RETURN
      END
CB::GPNARC
C
      SUBROUTINE GPNARC (AMAX,FLAT,ESQ,PI,P1,P2,ARC)
C
C********1*********2*********3*********4*********5*********6*********7*
C
C NAME:        GPNARC
C VERSION:     200005.26
C WRITTEN BY:  ROBERT (Sid) SAFFORD
C PURPOSE:     SUBROUTINE TO COMPUTE THE LENGTH OF A MERIDIONAL ARC 
C              BETWEEN TWO LATITUDES
C
C INPUT PARAMETERS:
C -----------------
C AMAX         SEMI-MAJOR AXIS OF REFERENCE ELLIPSOID
C FLAT         FLATTENING (0.0033528 ... )
C ESQ          ECCENTRICITY SQUARED FOR REFERENCE ELLIPSOID
C PI           3.14159...
C P1           LAT STATION 1
C P2           LAT STATION 2
C
C OUTPUT PARAMETERS:
C ------------------
C ARC          GEODETIC DISTANCE 
C
C LOCAL VARIABLES AND CONSTANTS:
C ------------------------------
C GLOBAL VARIABLES AND CONSTANTS:
C -------------------------------
C
C    MODULE CALLED BY:    GENERAL 
C
C    THIS MODULE CALLS:   
C       LLIBFORE/ OPEN,   CLOSE,  READ,   WRITE,  INQUIRE
C                 DABS,   DBLE,   FLOAT,  IABS,   CHAR,   ICHAR
C
C    INCLUDE FILES USED:
C    COMMON BLOCKS USED:  
C
C    REFERENCES: Microsoft FORTRAN 4.10 Optimizing Compiler, 1988
C                MS-DOS Operating System
C    COMMENTS:
C********1*********2*********3*********4*********5*********6*********7*
C::MODIFICATION HISTORY
C::197507.05, RWS, VER 00 TENCOL RELEASED FOR FIELD USE
C::198311.20, RWS, VER 01 MTEN   RELEASED TO FIELD
C::198411.26, RWS, VER 07 MTEN2  RELEASED TO FIELD
C::1985xx.xx, RWS, CODE   CREATED               
C::198506.10, RWS, WRK    ENHANCEMENTS RELEASED TO FIELD
C::198509.01, RWS, VER 11 MTEN3  RELEASED TO FIELD
C::198512.18, RWS, CODE   MODIFIED FOR MTEN3
C::198708.10, RWS, CODE   MODIFIED TO USE NEW MTEN4 GPN RECORD FORMAT
C::199112.31, RWS, VER 20 MTEN4 RELEASED TO FIELD
C::200001.13, RWS, VER 21 MTEN4 RELEASED TO FIELD
C::200005.26, RWS, CODE   RESTRUCTURED & DOCUMENTATION ADDED             
C::200012.31, RWS, VER 23 MTEN5 RELEASED                                 
C********1*********2*********3*********4*********5*********6*********7*
CE::GPNARC
C ---------------------------
C     M T E N  (VERSION 3)
C     M T E N  (VERSION 5.23)
C ---------------------------
C 
      IMPLICIT REAL*8 (A-H,O-Z)
C
      LOGICAL  FLAG
C
      DATA TT/5.0D-15/
C
C     CHECK FOR A 90 DEGREE LOOKUP
C
      FLAG = .FALSE.
C
      S1 = DABS(P1)
      S2 = DABS(P2)
C
      IF( (PI/2.0D0-TT).LT.S2 .AND. S2.LT.(PI/2.0D0+TT) )THEN
        FLAG = .TRUE.
      ENDIF
C
      IF( S1.GT.TT )THEN
        FLAG = .FALSE.
      ENDIF
C
      DA = (P2-P1)
      S1 = 0.0D0
      S2 = 0.0D0
C
C     COMPUTE THE LENGTH OF A MERIDIONAL ARC BETWEEN TWO LATITUDES
C
      E2 = ESQ
      E4 = E2*E2
      E6 = E4*E2
      E8 = E6*E2
      EX = E8*E2
C
      T1 = E2*(003.0D0/4.0D0)
      T2 = E4*(015.0D0/64.0D0)
      T3 = E6*(035.0D0/512.0D0)
      T4 = E8*(315.0D0/16384.0D0)
      T5 = EX*(693.0D0/131072.0D0)
C
      A  = 1.0D0+T1+3.0D0*T2+10.0D0*T3+35.0D0*T4+126.0D0*T5
C
      IF( FLAG )THEN
        GOTO 1
      ENDIF
C
      B  = T1+4.0D0*T2+15.0D0*T3+56.0D0*T4+210.0D0*T5
      C  = T2+06.0D0*T3+28.0D0*T4+120.0D0*T5
      D  = T3+08.0D0*T4+045.0D0*T5
      E  = T4+010.0D0*T5
      F  = T5
C
      DB = DSIN(P2*2.0D0)-DSIN(P1*2.0D0)
      DC = DSIN(P2*4.0D0)-DSIN(P1*4.0D0)
      DD = DSIN(P2*6.0D0)-DSIN(P1*6.0D0)
      DE = DSIN(P2*8.0D0)-DSIN(P1*8.0D0)
      DF = DSIN(P2*10.0D0)-DSIN(P1*10.0D0)
C
C     COMPUTE THE S2 PART OF THE SERIES EXPANSION
C
      S2 = -DB*B/2.0D0+DC*C/4.0D0-DD*D/6.0D0+DE*E/8.0D0-DF*F/10.0D0
C
C     COMPUTE THE S1 PART OF THE SERIES EXPANSION
C
    1 S1 = DA*A
C
C     COMPUTE THE ARC LENGTH
C
      ARC = AMAX*(1.0D0-ESQ)*(S1+S2)
C
      RETURN
      END
cb::gpnhri
c
      subroutine gpnhri (a,f,esq,pi,p1,e1,p2,e2,az1,az2,s)      
c
c********1*********2*********3*********4*********5*********6*********7*
c
c name:        gpnhri
c version:     200208.09
c written by:  robert (sid) safford
c purpose:     subroutine to compute helmert rainsford inverse problem 
c 
c     solution of the geodetic inverse problem after t. vincenty
c     modified rainsford's method with helmert's elliptical terms
c     effective in any azimuth and at any distance short of antipocal
c     from/to stations must not be the geographic pole.
c     parameter a is the semi-major axis of the reference ellipsoid
c     finv=1/f is the inverse flattening of the reference ellipsoid
c     latitudes and longitudes in radians positive north and west
c     forward and back azimuths returned in radians clockwise from south
c     geodesic distance s returned in units of semi-major axis a
c     programmed for ibm 360-195   09/23/75
c
c     note - note - note -
c     1. do not use for meridional arcs and be careful on the equator.
c     2. azimuths are from north(+) clockwise and 
c     3. longitudes are positive east(+) 
c
c input parameters:
c -----------------
c a            semi-major axis of reference ellipsoid      meters
c f            flattening (0.0033528...)
c esq          eccentricity squared 
c pi           3.14159...
c p1           lat station 1                               radians
c e1           lon station 1                               radians
c p2           lat station 2                               radians
c e2           lon station 2                               radians
c
c output parameters:
c ------------------
c az1          azi at sta 1 -> sta 2                       radians
c az2          azi at sta 2 -> sta 1                       radians
c s            geodetic dist between sta(s) 1 & 2          meters
c
c local variables and constants:
c ------------------------------
c aa               constant from subroutine gpnloa                    
c alimit           equatorial arc distance along the equator   (radians)
c arc              meridional arc distance latitude p1 to p2 (in meters)      
c az1              azimuth forward                          (in radians)
c az2              azimuth back                             (in radians)
c bb               constant from subroutine gpnloa                    
c dlon             temporary value for difference in longitude (radians)   
c equ              equatorial distance                       (in meters)
c r1,r2            temporary variables    
c s                ellipsoid distance                        (in meters)
c sms              equatorial - geodesic distance (S - s) "Sms"       
c ss               temporary variable     
c tol0             tolerance for checking computation value         
c tol1             tolerance for checking a real zero value         
c tol2             tolerance for close to zero value  
c twopi            two times constant pi               
c
c global variables and constants:
c -------------------------------
c
c    module called by:    general 
c
c    this module calls:   gpnarc, gpnloa
c       llibfore/ dsin,   dcos,   dsqrt,  dabs,  datan2, write
c
c    include files used:
c    common blocks used:  
c
c    references: microsoft fortran 4.10 optimizing compiler, 1988
c                ms-dos operating system
c    comments:
c********1*********2*********3*********4*********5*********6*********7*
c::modification history
c::197507.05, rws, ver 00 tencol released for field use
c::198311.20, rws, ver 01 mten   released to field
c::198411.26, rws, ver 07 mten2  released to field
c::198506.10, rws, wrk    enhancements released to field
c::198507.22, rws, code   modified for mten3
c::198509.01, rws, ver 11 mten3  released to field
c::198708.10, rws, code   modified to use new mten4 gpn record format
c::199112.31, rws, ver 20 mten4 released to field
c::200001.13, rws, ver 21 mten4 released to field
c::200005.26, rws, code   restructured & documentation added             
c::200012.31, rws, ver 23 mten5 released                                 
c::200104.09, rws, code   added to calblin program                       
c::200208.09, rws, code   added subroutines gpnarc & gpnloa              
c********1*********2*********3*********4*********5*********6*********7*
ce::gpnhri
c  -------------------------------
c     m t e n  (version 3)
c              (version 4.22)
c              (version 5.23)
c  -------------------------------
c
      implicit real*8 (a-h,o-z)
c
      data tol0 /5.0d-15/
      data tol1 /5.0d-14/
      data tol2 /7.0d-03/
c
      twopi = 2.0d0*pi
c
c     test the longitude difference with tol1
c     tol1 is approximately 0.000000001 arc seconds
c
      ss = e2-e1
      if( dabs(ss).lt.tol1 )then
        e2 = e2+tol1
        write(*,*) ' longitudal difference is near zero '
c                 
        r2 = p2
        r1 = p1
        call gpnarc ( a, f, esq, pi, r1, r2, arc )
        s  = dabs( arc )
c
        if( p2.gt.p1 )then
          az1 = 0.0d0
          az2 = pi
        else
          az1 = pi   
          az2 = 0.0d0
        endif
        return 
      endif
c
c     test for longitude over 180 degrees
c
      dlon = e2-e1
c
      if( dlon.ge.0.0d0 )then
        if( pi.le.dlon .and. dlon.lt.twopi )then
          dlon = dlon-twopi
        endif
      else
        ss = dabs(dlon)
        if( pi.le.ss .and. ss.lt.twopi )then
          dlon = dlon+twopi
        endif
      endif
c
      ss = dabs( dlon )
      if( ss.gt.pi )then
c::     write(*,*) '  '
c::     write(*,*) ' Longitude difference over 180 degrees  '  
c::     write(*,*) ' Turn it around '
        ss = twopi-ss
      endif
c
c     compute the limit in longitude (alimit), it is equal 
c     to twice the distance from the equator to the pole,
c     as measured along the equator (east/ewst)
c
      alimit = pi*(1.0d0-f)
c
c     test for anti-nodal difference      
c
      if( ss.ge.alimit )then
        r1 = dabs(p1)
        r2 = dabs(p2)
c
c       latitudes r1 & r2 are not near the equator
c
        if( r1.gt.tol2 .and. r2.gt.tol2 )then
          goto 60
        endif
c
c       longitude difference is greater than lift-off point
c       now check to see if  "both"  r1 & r2 are on equator
c
        if( r1.lt.tol1 .and. r2.gt.tol2 )then
          goto 60
        endif
        if( r2.lt.tol1 .and. r1.gt.tol2 )then
          goto 60
        endif
c
c       check for either r1 or r2 just off the equator but < tol2
c
        if( r1.gt.tol1. or. r2.gt.tol1 )then
          az1 = 0.0d0
          az2 = 0.0d0
          s   = 0.0d0
          return 
        endif
c
c       compute the azimuth to anti-nodal point
c
c::     write(*,*) '  '
c::     write(*,*) ' Longitude difference beyond lift-off point '  
c::     write(*,*) '  '
c
        call gpnloa (a,f,esq,pi,dlon,az1,az2,aa,bb,sms)
c
c       compute the equatorial distance & geodetic
c
        equ = a*dabs(dlon)
        s   = equ-sms
        return 
      endif
c
   60 continue
c
      f0   = (1.0d0-f)
      b    = a*f0
      epsq = esq/(1.0d0-esq)
      f2   = f*f     
      f3   = f*f2    
      f4   = f*f3    
c
c     the longitude difference 
c
      dlon  = e2-e1   
      ab    = dlon      
      kount = 0    
c
c     the reduced latitudes    
c
      u1    = f0*dsin(p1)/dcos(p1)     
      u2    = f0*dsin(p2)/dcos(p2)
c
      u1    = datan(u1)
      u2    = datan(u2)
c
      su1   = dsin(u1)    
      cu1   = dcos(u1)    
c
      su2   = dsin(u2)
      cu2   = dcos(u2)
c
c     counter for the iteration operation
c
    1 kount = kount+1     
c
      clon  = dcos(ab)   
      slon  = dsin(ab)   
c
      csig  = su1*su2+cu1*cu2*clon  
      ssig  = dsqrt((slon*cu2)**2+(su2*cu1-su1*cu2*clon)**2)  
c
      sig   = datan2(ssig,csig)
      sinalf=cu1*cu2*slon/ssig
c
      w   = (1.0d0-sinalf*sinalf)
      t4  = w*w   
      t6  = w*t4   
c
c     the coefficients of type a      
c
      ao  = f-f2*(1.0d0+f+f2)*w/4.0d0+3.0d0*f3*(1.0d0+
     1        9.0d0*f/4.0d0)*t4/16.0d0-25.0d0*f4*t6/128.0d0
      a2  = f2*(1.0d0+f+f2)*w/4.0d0-f3*(1.0d0+9.0d0*f/4.0d0)*t4/4.0d0+
     1        75.0d0*f4*t6/256.0d0
      a4  = f3*(1.0d0+9.0d0*f/4.0d0)*t4/32.0d0-15.0d0*f4*t6/256.0d0
      a6  = 5.0d0*f4*t6/768.0d0
c
c     the multiple angle functions    
c
      qo  = 0.0d0
      if( w.gt.tol0 )then
        qo = -2.0d0*su1*su2/w
      endif     
c
      q2  = csig+qo
      q4  = 2.0d0*q2*q2-1.0d0    
      q6  = q2*(4.0d0*q2*q2-3.0d0)      
      r2  = 2.0d0*ssig*csig      
      r3  = ssig*(3.0d0-4.0d0*ssig*ssig) 
c
c     the longitude difference 
c
      s   = sinalf*(ao*sig+a2*ssig*q2+a4*r2*q4+a6*r3*q6)    
      xz  = dlon+s   
c
      xy  = dabs(xz-ab)    
      ab  = dlon+s   
c
      if( xy.lt.0.5d-13 )then
        goto 4
      endif
c
      if( kount.le.7 )then
        goto 1
      endif
c
c     the coefficients of type b      
c
    4 z   = epsq*w
c
      bo  = 1.0d0+z*(1.0d0/4.0d0+z*(-3.0d0/64.0d0+z*(5.0d0/256.0d0-
     1         z*175.0d0/16384.0d0)))      
      b2  = z*(-1.0d0/4.0d0+z*(1.0d0/16.0d0+z*(-15.0d0/512.0d0+
     1         z*35.0d0/2048.0d0)))  
      b4  = z*z*(-1.0d0/128.0d0+z*(3.0d0/512.0d0-z*35.0d0/8192.0d0))
      b6  = z*z*z*(-1.0d0/1536.0d0+z*5.0d0/6144.0d0)    
c
c     the distance in meters   
c
      s   = b*(bo*sig+b2*ssig*q2+b4*r2*q4+b6*r3*q6) 
c
c     first compute the az1 & az2 for along the equator
c
      if( dlon.gt.pi )then
        dlon = (dlon-2.0d0*pi)
      endif
c
      if( dabs(dlon).gt.pi )then
        dlon = (dlon+2.0d0*pi)
      endif
c
      az1 = pi/2.0d0
      if( dlon.lt.0.0d0 )then
        az1 = 3.0d0*az1
      endif
c
      az2 = az1+pi
      if( az2.gt.2.0d0*pi )then
        az2 = az2-2.0d0*pi
      endif
c
c     now compute the az1 & az2 for latitudes not on the equator
c
      if( .not.(dabs(su1).lt.tol0 .and. dabs(su2).lt.tol0) )then
        tana1 =  slon*cu2/(su2*cu1-clon*su1*cu2)  
        tana2 =  slon*cu1/(su1*cu2-clon*su2*cu1)  
        sina1 =  sinalf/cu1
        sina2 = -sinalf/cu2      
c
c       azimuths from north,longitudes positive east  
c
        az1   = datan2(sina1,sina1/tana1)   
        az2   = pi-datan2(sina2,sina2/tana2)
      endif
c
      if( az1.lt.0.0d0 )then
        az1 = az1+2.0d0*pi   
      endif
c
      if( az2.lt.0.0d0 )then
        az2 = az2+2.0d0*pi
      endif
c
      return     
      end 

CB::GPNLOA
C
      SUBROUTINE GPNLOA (AMAX,FLAT,ESQ,PI,DL,AZ1,AZ2,AO,BO,SMS)
C
C********1*********2*********3*********4*********5*********6*********7*
C
C NAME:        GPNLOA
C VERSION:     200005.26
C WRITTEN BY:  ROBERT (Sid) SAFFORD
C PURPOSE:     SUBROUTINE TO COMPUTE THE LIFF-OFF-AZIMUTH CONSTANTS
C
C INPUT PARAMETERS:
C -----------------
C AMAX         SEMI-MAJOR AXIS OF REFERENCE ELLIPSOID
C FLAT         FLATTENING (0.0033528 ... )
C ESQ          ECCENTRICITY SQUARED FOR REFERENCE ELLIPSOID
C PI           3.14159...
C DL           LON DIFFERENCE
C AZ1          AZI AT STA 1 -> STA 2
C
C OUTPUT PARAMETERS:
C ------------------
C AZ2          AZ2 AT STA 2 -> STA 1
C AO           CONST
C BO           CONST
C SMS          DISTANCE ... EQUATORIAL - GEODESIC  (S - s)   "SMS"
C
C LOCAL VARIABLES AND CONSTANTS:
C ------------------------------
C GLOBAL VARIABLES AND CONSTANTS:
C -------------------------------
C
C    MODULE CALLED BY:    GENERAL 
C
C    THIS MODULE CALLS:   
C       LLIBFORE/ DSIN,   DCOS,   DABS,   DASIN 
C
C    INCLUDE FILES USED:
C    COMMON BLOCKS USED:  
C
C    REFERENCES: Microsoft FORTRAN 4.10 Optimizing Compiler, 1988
C                MS-DOS Operating System
C    COMMENTS:
C********1*********2*********3*********4*********5*********6*********7*
C::MODIFICATION HISTORY
C::1985xx.xx, RWS, CODE   CREATED               
C::198506.10, RWS, WRK    ENHANCEMENTS RELEASED TO FIELD
C::198509.01, RWS, VER 11 MTEN3  RELEASED TO FIELD
C::198512.18, RWS, CODE   MODIFIED FOR MTEN3
C::198708.10, RWS, CODE   MODIFIED TO USE NEW MTEN4 GPN RECORD FORMAT
C::199112.31, RWS, VER 20 MTEN4 RELEASED TO FIELD
C::200001.13, RWS, VER 21 MTEN4 RELEASED TO FIELD
C::200005.26, RWS, CODE   RESTRUCTURED & DOCUMENTATION ADDED             
C::200012.31, RWS, VER 23 MTEN5 RELEASED                                 
C********1*********2*********3*********4*********5*********6*********7*
CE::GPNLOA
C ---------------------------
C     M T E N  (VERSION 3)
C              (VERSION 4.22)
C              (VERSION 5.23)
C ---------------------------
C
      IMPLICIT REAL*8 (A-H,O-Z)
C
      DATA TT/5.0D-13/
C
      DLON = DABS(DL)
      CONS = (PI-DLON)/(PI*FLAT)
      F    = FLAT
C
C     COMPUTE AN APPROXIMATE AZ
C
      AZ   = DASIN(CONS)
C
      T1   =    1.0D0
      T2   =  (-1.0D0/4.0D0)*F*(1.0D0+F+F*F)
      T4   =    3.0D0/16.0D0*F*F*(1.0D0+(9.0D0/4.0D0)*F)
      T6   = (-25.0D0/128.0D0)*F*F*F
C
      ITER = 0
    1 ITER = ITER+1
      S    = DCOS(AZ)
      C2   = S*S
C
C     COMPUTE NEW AO
C
      AO   = T1 + T2*C2 + T4*C2*C2 + T6*C2*C2*C2
      CS   = CONS/AO
      S    = DASIN(CS)
      IF( DABS(S-AZ).LT.TT )THEN
        GOTO 2
      ENDIF
C
      AZ   = S
      IF( ITER.LE.6 )THEN
        GOTO 1
      ENDIF
C
    2 AZ1  = S
      IF( DL.LT.0.0D0 )THEN
        AZ1 = 2.0D0*PI-AZ1
      ENDIF
C
      AZ2  = 2.0D0*PI-AZ1
C
C     EQUATORIAL - GEODESIC  (S - s)   "SMS"
C
      ESQP = ESQ/(1.0D0-ESQ)
      S    = DCOS(AZ1)
C
      U2   = ESQP*S*S
      U4   = U2*U2
      U6   = U4*U2
      U8   = U6*U2
C
      T1   =     1.0D0
      T2   =    (1.0D0/4.0D0)*U2
      T4   =   (-3.0D0/64.0D0)*U4
      T6   =    (5.0D0/256.0D0)*U6
      T8   = (-175.0D0/16384.0D0)*U8
C
      BO   = T1 + T2 + T4 + T6 + T8
      S    = DSIN(AZ1)
      SMS  = AMAX*PI*(1.0D0 - FLAT*DABS(S)*AO - BO*(1.0D0-FLAT))
C
      RETURN
      END
      subroutine gvali4 (buff,ll,vali4,icond)
      implicit     integer (i-n)
c
      logical      plus,sign,done,error
      character*1  buff(*)
      character*1  ch
c
c     integer*2    i
c     integer*2    l1
c
      integer*4    ich,icond
      integer*4    ll    
      integer*4    vali4
c
      l1    = ll
      vali4 = 0
      icond = 0
      plus  = .true.
      sign  = .false.
      done  = .false.
      error = .false.
c
      i = 0
   10 i = i+1
      if( i.gt.l1 .or. done )then
        go to 1000
      else
        ch  = buff(i)
        ich = ichar( buff(i) )
      endif
c
      if(     ch.eq.'+' )then
c
c       enter on plus sign
c
        if( sign )then
          goto 150
        else 
          sign = .true.
          goto 10
        endif
      elseif( ch.eq.'-' )then
c
c       enter on minus sign
c
        if( sign )then
          goto 150
        else
          sign = .true.
          plus = .false.
          goto 10
        endif
      elseif( ch.ge.'0' .and. ch.le.'9' )then
        goto 100
      elseif( ch.eq.' ' )then
c
c       enter on space -- ignore leading spaces
c
        if( .not.sign )then
          goto 10
        else
          buff(i) = '0'
          ich = 48
          goto 100
        endif
      elseif( ch.eq.':' )then
c
c       enter on colon -- ignore 
c
        if( .not.sign )then
          goto 10
        else
          goto 1000
        endif
      elseif( ch.eq.'$' )then
c
c       enter on dollar "$"      
c
        done = .true.
        goto 10
      else
c
c       something wrong
c
        goto 150
      endif
c
c     enter on numeric
c
  100 vali4 = 10*vali4+(ich-48)
      sign  = .true.
      goto 10
c
c     treat illegal character
c
  150 buff(i) = '0'
      vali4 = 0
      icond = 1
c
 1000 if( .not.plus )then
        vali4 = -vali4
      endif
c
      return
      end
      subroutine gvalr8 (buff,ll,valr8,icond)
      implicit     integer (i-n)
c
      logical      plus,sign,dpoint,done
c
      character*1  buff(*)
      character*1  ch
c
c     integer*2    i, ip
c     integer*2    l1
c     integer*2    nn, num, n48
c
      integer*4    ich,icond
      integer*4    ll
c
      real*8       ten
      real*8       valr8
      real*8       zero
c
      data zero,ten/0.0d0,10.0d0/
c
      n48     =  48
      l1      =  ll
      icond   =   0
      valr8   =  zero  
      plus    = .true.
      sign    = .false.
      dpoint  = .false.
      done    = .false.
c
c     start loop thru buffer
c
      i = 0
   10 i = i+1
      if( i.gt.l1 .or. done )then
        go to 1000
      else 
        ch  = buff(i)
        nn  = ichar( ch )
        ich = nn
      endif 
c
      if(     ch.eq.'+' )then
c
c       enter on plus sign
c
        if( sign )then
          goto 150
        else
          sign = .true.
          goto 10
        endif
      elseif( ch.eq.'-' )then
c
c       enter on minus sign
c
        if( sign )then
          goto 150
        else
          sign = .true.
          plus = .false.
          goto 10
        endif
      elseif( ch.eq.'.' )then
c
c       enter on decimal point
c
        ip     = 0
        sign   = .true.
        dpoint = .true.
        goto 10
      elseif( ch.ge.'0' .and. ch.le.'9' )then
        goto 100
      elseif( ch.eq.' ' )then
c
c       enter on space
c
        if( .not.sign )then
          goto 10
        else
          buff(i) = '0'
          ich = 48
          goto 100
        endif
      elseif( ch.eq.':' .or. ch.eq.'$' )then
c
c       enter on colon or "$" sign
c
        done = .true.
        goto 10
      else
c
c       something wrong
c
        goto 150
      endif
c
c     enter on numeric
c
  100 sign = .true.
      if( dpoint )then
        ip = ip+1
      endif
c
      num   = ich
      valr8 = ten*valr8+dble(float( num-n48 ))
      goto 10
c
c     treat illegal character
c
  150 buff(i) = '0'
      valr8   =  0.0d0
      icond   =  1
c
 1000 if( dpoint )then
        valr8 =  valr8/(ten**ip)
      endif
c
      if( .not.plus )then
        valr8 = -valr8
      endif
c
      return
      end
      subroutine mmdist(glat,az,ht1,ht2,d2,d6)
 
*** convert mmdist to ellipsoid distance
*** formulas from 'Use of calibration baselines', nos ngs 10
 
      implicit double precision (a-h,o-z)
      common/ellips/a,b,f,e2,ep2
      cl2=dcos(glat)*dcos(glat)
      ca2=dcos(az)*dcos(az)
      c=a*a/b
      n=c/dsqrt(1.d0+ep2*cl2)
      r=n/(1.d0+ep2*cl2*ca2)
      dh=ht2-ht1
      d7=dsqrt((d2*d2-dh*dh)/((1.d0+ht1/r)*(1.d0+ht2/r)))
      d6=2.d0*r*(dasin(d7/(2.d0*r)))
c
      return
      end
      subroutine neuxyz(dn,de,du,glat,glon,dx,dy,dz)
 
*** convert dn,de,du to dx,dy,dz
*** input glat,glon are positive north and east in radians
 
      implicit double precision (a-z)
      common/const/pi,rad
c
c *** reverse sign of delta North
c
      ds = -dn
c
c *** rotate by s = (LAT-90 degrees)
c
      s  = glat-pi/2.0d0
      x  = ds*dcos(s)-du*dsin(s)
      y  = de
      z  = du*dcos(s)+ds*dsin(s)
c
c *** rotate by s = -(LON degrees)
c
      s  = -glon
      dx = x*dcos(s)+y*dsin(s)
      dy = y*dcos(s)-x*dsin(s)
      dz = z
 
      return
      end
      subroutine todmsp(val,id,im,s,isign)
 
*** convert position radians to deg,min,sec
*** range is [-pi to +pi]
 
      implicit double precision(a-h,o-z)
      common/const/pi,rad
 
    1 if(val.gt.pi) then
        val=val-pi-pi
        go to 1
      endif
 
    2 if(val.lt.-pi) then
        val=val+pi+pi
        go to 2
      endif
 
      if(val.lt.0.d0) then
        isign=-1
      else
        isign=+1
      endif
 
      s=dabs(val*rad)
      id=idint(s)
      s=(s-id)*60.d0
      im=idint(s)
      s=(s-im)*60.d0
 
*** account for rounding error
 
      is=idnint(s*1.d5)
      if(is.ge.6000000) then
        s=0.d0
        im=im+1
      endif
      if(im.ge.60) then
        im=0
        id=id+1
      endif
 
      return
      end
      subroutine toxyz(glat,glon,eht,x,y,z)
 
*** compute x,y,z
*** ref p.17 geometric geodesy notes vol 1, osu, rapp
 
      implicit double precision(a-h,o-z)
      common/ellips/a,b,f,e2,ep2

      slat=dsin(glat)
      clat=dcos(glat)
      w=dsqrt(1.d0-e2*slat*slat)
      en=a/w
 
      x=(en+eht)*clat*dcos(glon)
      y=(en+eht)*clat*dsin(glon)
      z=(en*(1.d0-e2)+eht)*slat
 
      return
      end

      subroutine trim (buff,lgh,hem)
      implicit integer (i-n)
      character*1 ch,hem
      character*1 buff(*)
      integer*4   lgh
c
      ibeg = 1
      do 10 i=1,50
        if( buff(i).ne.' ' )then
          goto 11
        endif
        ibeg = ibeg+1
   10 continue
   11 continue
      if( ibeg.ge.50 )then
        ibeg = 1
        buff(ibeg) = '0'
      endif
c
      iend = 50
      do 20 i=1,50
        j = 51-i
        if( buff(j).eq.' ' )then
          iend = iend-1
        else
          goto 21
        endif
   20 continue
   21 continue
c
      ch = buff(ibeg)
      if( hem.eq.'N' )then
        if( ch.eq.'N' .or. ch.eq.'n' .or. ch.eq.'+' )then
          hem = 'N'
          ibeg = ibeg+1
        endif
        if( ch.eq.'S' .or. ch.eq.'s' .or. ch.eq.'-' )then
          hem = 'S'
          ibeg = ibeg+1
        endif
c
c       check for wrong hemisphere entry
c
        if( ch.eq.'E' .or. ch.eq.'e' )then
          hem = '*'
          ibeg = ibeg+1
        endif
        if( ch.eq.'W' .or. ch.eq.'w' )then
          hem = '*'
          ibeg = ibeg+1
        endif
      elseif( hem.eq.'W' )then
        if( ch.eq.'E' .or. ch.eq.'e' .or. ch.eq.'+' )then
          hem = 'E'
          ibeg = ibeg+1
        endif
        if( ch.eq.'W' .or. ch.eq.'w' .or. ch.eq.'-' )then
          hem = 'W'
          ibeg = ibeg+1
        endif
c
c       check for wrong hemisphere entry
c
        if( ch.eq.'N' .or. ch.eq.'n' )then
          hem = '*'
          ibeg = ibeg+1
        endif
        if( ch.eq.'S' .or. ch.eq.'s' )then
          hem = '*'
          ibeg = ibeg+1
        endif
      elseif( hem.eq.'A' )then
        if( .not.('0'.le.ch .and. ch.le.'9') )then
          hem = '*'
          ibeg = ibeg+1
        endif
      else
c        do nothing
      endif
c
c
      do 30 i=ibeg,iend
        ch = buff(i)
c
        if(     ch.eq.':' .or. ch.eq.'.' )then
          goto 30
        elseif( ch.eq.' ' .or. ch.eq.',' )then
          buff(i) = ':'
        elseif( '0'.le.ch .and. ch.le.'9' )then
          goto 30      
        else
          buff(i) = ':'
        endif
c
   30 continue
c
c     left justify buff() array to its first character position
c     also check for a ":" char in the starting position,
c     if found!!  skip it
c
      j  = 0
      ib = ibeg
      ie = iend
c
      do 40 i=ib,ie
        if( i.eq.ibeg .and. buff(i).eq.':' )then
c
c         move the 1st position pointer to the next char &
c         do not put ":" char in buff(j) array where j=1    
c
          ibeg = ibeg+1
          goto 40
        endif
        j = j+1
        buff(j) = buff(i)
   40 continue
c
c
      lgh = iend-ibeg+1
      j   = lgh+1
      buff(j) = '$'
c
c     clean-up the rest of the buff() array
c
      do 50 i=j+1,50   
        buff(i) = ' '    
   50 continue
c
c     save a maximum of 20 characters
c
      if( lgh.gt.20 )then
        lgh = 20
        j   = lgh+1
        buff(j) = '$'
      endif
c
      return
      end
      subroutine xyzneu(dx,dy,dz,glat,glon,dn,de,du)

*** convert dx,dy,dz to dn,de,du
*** input glat,glon are positive north and east in radians

      implicit double precision(a-z)
      common/const/pi,rad

*** rotate by glon

      x=dx*dcos(glon)+dy*dsin(glon)
      y=dy*dcos(glon)-dx*dsin(glon)
      z=dz

*** rotate by glat

      ds=x*dcos(pi/2.d0-glat)-z*dsin(pi/2.d0-glat)
      de=y
      du=z*dcos(pi/2.d0-glat)+x*dsin(pi/2.d0-glat)

      dn=-ds

      return
      end
      real*8 function zvalue ( ss, tol )
c
      implicit double precision (a-z)
c
c     to check for dx,dy,dz or 
c     dn,de,du values below tol.
c
      if( dabs(ss).lt.tol )then
        ss = 0.0d0
      endif
c
      zvalue = ss
c
      return
      end

