!****************************************************************
SUBROUTINE limb_plane(plat,plon,pazim1,kobtype,kprof,plat_2d,plon_2d,kerror)

! Routine to calculate a series of points to define the viewing
! plane for a limb instrument, given the latitude and longitude
! of the sub-tangent point, the angle pazim1 between the plane and
! a longitude line, and an array of angles defining the points
! relative to the tangent point. The definition of the viewing 
! plane is invalid if the sub-tangent point is at the pole, so the
! routine returns error=1.
! Formulae derived by considering that
!  cos(theta) = DOT_PRODUCT(sub tangent vector, vector to calculate)
! and
!  cos(pazim1) = DOT_PRODUCT(normalised vector orthogonal to longitude plane,
!                            normalised vector orthogonal to viewing plane)

! Conventions: pazim1 clockwise (ie eastward is positive)
!              theta  positive is northward if pazim1 is between -90 and 90 deg

! Niels Bormann, 11 March 2004
!-------------------------------------------------------------

USE PARKIND1  ,ONLY : JPIM     ,JPRB
USE YOMHOOK   ,ONLY : LHOOK,   DR_HOOK
USE YOMLIMB   ,ONLY : dtheta
USE YOMCST   , ONLY : RPI

IMPLICIT NONE

REAL(KIND=JPRB), INTENT(IN)     :: plat      ! Lat of sub-tangent pt [deg]
REAL(KIND=JPRB), INTENT(IN)     :: plon      ! Lon of sub-tangent pt [deg]
REAL(KIND=JPRB), INTENT(IN)     :: pazim1    ! Angle [deg to north] of                                                   ! viewing plane, positive                                                  ! is eastward
INTEGER(KIND=JPIM), INTENT(IN)  :: kobtype   ! Number of points 
INTEGER(KIND=JPIM), INTENT(IN)  :: kprof     ! Number of points                                                              ! to calculat
REAL(KIND=JPRB), INTENT(OUT)    :: plat_2d(kprof)   ! Lats of points [deg] 
REAL(KIND=JPRB), INTENT(OUT)    :: plon_2d(kprof)   ! Lons of points [deg]
INTEGER(KIND=JPIM), INTENT(OUT) :: kerror ! Error code

! local

REAL(KIND=JPRB)          :: ztheta(kprof)
REAL(KIND=JPRB)          :: zcos_pazim
REAL(KIND=JPRB)          :: zcos_plon
REAL(KIND=JPRB)          :: zcos_plat
REAL(KIND=JPRB)          :: zsin_plon
REAL(KIND=JPRB)          :: zsin_plat
REAL(KIND=JPRB)          :: zsin_theta
REAL(KIND=JPRB)          :: zcos_theta
REAL(KIND=JPRB)          :: zsin_plat_2d
REAL(KIND=JPRB)          :: zcos_delta
REAL(KIND=JPRB)          :: zrplat
REAL(KIND=JPRB)          :: zazim
INTEGER(KIND=JPIM)       :: i,imid
REAL(KIND=JPRB) :: ZHOOK_HANDLE


!-------------------------------------------------------------------

IF (LHOOK) CALL DR_HOOK('LIMB_PLANE',0,ZHOOK_HANDLE)



! set the initial theta values

imid = kprof/2 + 1  ! the central profile

! calculate the theta values in the plane

DO i = 1, kprof
   ztheta(i) = REAL(i-imid)*dtheta  ! dtheta in radians
ENDDO   

kerror = 0
IF ( ABS(plat) == 0.5_JPRB*RPI ) THEN
  kerror = 1

  IF (LHOOK) CALL DR_HOOK('LIMB_PLANE',1,ZHOOK_HANDLE)
  RETURN
ENDIF


 
zazim = pazim1
IF (pazim1 > RPI ) zazim =  pazim1 - 2.0_JPRB*RPI  
  
zcos_pazim = COS(zazim)
zcos_plon  = COS(plon)
zcos_plat  = COS(plat)
zsin_plon  = SIN(plon)
zsin_plat  = SIN(plat)

DO i = 1, kprof

  zsin_theta = SIN(ztheta(i))  ! dtheta in radians
  zcos_theta = COS(ztheta(i))

  zsin_plat_2d = zsin_theta * zcos_pazim * zcos_plat + zsin_plat * zcos_theta
  
  zrplat = ASIN(zsin_plat_2d)

  IF( ABS(zrplat) == RPI/2.0_jprb ) THEN
    zcos_delta = 1.0_jprb
  ELSE
    zcos_delta = ( zcos_theta - zsin_plat * zsin_plat_2d ) / ( zcos_plat * COS(zrplat) )
    IF( zcos_delta > 1.0_JPRB)  zcos_delta = 1.0_JPRB
    IF( zcos_delta < -1.0_JPRB) zcos_delta = -1.0_JPRB
  ENDIF
  
  IF( SIGN(1.0_JPRB,ztheta(i)) == SIGN(1.0_JPRB,zazim) ) THEN
    plon_2d(i) = plon + ACOS(zcos_delta)
  ELSE
    plon_2d(i) = plon - ACOS(zcos_delta)
  ENDIF

  plat_2d(i) = zrplat 
  
  plon_2d(i) = MODULO(plon_2d(i)+RPI,2.0_JPRB*RPI) - RPI
  
ENDDO

IF (LHOOK) CALL DR_HOOK('LIMB_PLANE',1,ZHOOK_HANDLE)

END SUBROUTINE limb_plane
