!
! projections
!
!
! Copyright © 2011 F.Hroch (hroch@physics.muni.cz)
!
! This file is part of Munipack.
!
! Munipack is free software: you can redistribute it and/or modify
! it under the terms of the GNU General Public License as published by
! the Free Software Foundation, either version 3 of the License, or
! (at your option) any later version.
! 
! Munipack is distributed in the hope that it will be useful,
! but WITHOUT ANY WARRANTY; without even the implied warranty of
! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
! GNU General Public License for more details.
! 
! You should have received a copy of the GNU General Public License
! along with Munipack.  If not, see <http://www.gnu.org/licenses/>.
!

module projections

  implicit none
  integer, private, parameter :: dp = selected_real_kind(15)
  real(dp), private, parameter :: rad = 180.0_dp/3.1415926535897931160_dp

contains

  subroutine identity(alpha, delta, alpha0, delta0, x,y)

    real(dp),intent(in) :: alpha, delta, alpha0, delta0
    real(dp),intent(out) :: x,y

    x = alpha - alpha0
    y = delta - delta0

  end subroutine identity

  subroutine invidentity(x,y,alpha0,delta0,alpha,delta)

    implicit none
    real(dp),intent(in) :: alpha0, delta0, x, y
    real(dp),intent(out) :: alpha, delta

    alpha = x + alpha0
    delta = y + delta0

  end subroutine invidentity


  subroutine gnomon(alpha, delta, alpha0, delta0, x,y)

    implicit none
    real(dp),intent(in) :: alpha, delta, alpha0, delta0
    real(dp),intent(out) :: x,y
    real(dp) :: c,p,q,r,v,w,s

    c = cos(delta)
    p = sin(delta)
    q = c*sin(alpha - alpha0)
    r = c*cos(alpha - alpha0)
    v = sin(delta0)
    w = cos(delta0)
    s = p*v + r*w

    x = -q/s
    y = (w*p - v*r)/s

  end subroutine gnomon

  subroutine invgnomon(x,y,alpha0,delta0,alpha,delta)

    implicit none
    real(dp),intent(in) :: alpha0, delta0, x, y
    real(dp),intent(out) :: alpha, delta
    real(dp) :: p,q,r,v,w,t

    v = sin(delta0)
    w = cos(delta0) 
    t = sqrt(1.0_dp + x**2 + y**2)
    p = (v + w*y)/t
    q = -x/t
    r = (w - v*y)/t

    delta = asin(p)
    alpha = atan2(q,r) + alpha0

  end subroutine invgnomon

  subroutine gnomond(alpha, delta, alpha0, delta0, x,y)

    implicit none
    real(dp),intent(in) :: alpha, delta, alpha0, delta0
    real(dp),intent(out) :: x,y

    call gnomon(alpha/rad, delta/rad,alpha0/rad,delta0/rad,x,y)
    x = rad*x
    y = rad*y

  end subroutine gnomond

  subroutine invgnomond(x,y,alpha0,delta0,alpha,delta)

    implicit none
    real(dp),intent(in) :: alpha0, delta0, x, y
    real(dp),intent(out) :: alpha, delta

    call invgnomon(x/rad,y/rad,alpha0/rad,delta0/rad,alpha,delta)
    alpha = rad*alpha
    delta = rad*delta

  end subroutine invgnomond

end module projections

