!> \~japanese
!! \brief 三次元の座標変換を行なう手続きを提供するモジュール.
!! \~english
!! \brief This module provides some subroutines which perform 3D coordinate conversion.
!! \~
!!
!! <br><br>
!! \b Copyright (C) GFD Dennou Club, 2011-2012. All rights reserved. <br>
!! \b license ?? <br>
!! \author Yuta Kawai
!!
module igmcore_coordinate_conversion
  
  ! モジュール引用 ; Use statements
  !

  ! 種類型パラメタ
  ! Kind type parameter
  !
  use dc_types, only: DP         ! 倍精度実数型. Double precision. 
  
  ! 数学
  ! Mathematic.
  !
  use igmcore_math, only: PI   ! 円周率. PI.

  ! 宣言文 ; Declaration statements
  !
  implicit none
  private

  ! 公開手続き
  ! Public procedure
  !
  public :: orth_to_geo_pos, geo_to_orth_pos, geo_to_orth_vec, orth_to_geo_vec


contains

!
!> \~japanese
!! \brief 直交座標系から地理座標系への位置ベクトルの座標変換を行う.
!!
!! @param[in] orth_p 直交座標系における位置ベクトル\f$(x,y,z)\f$.
!! @return           地理座標系における位置ベクトル(\f$\phi\f$(経度), \f$\theta\f$(緯度), \f$r\f$(中心からの距離)).
!!
!! \~english
!! \brief Performs a coordinate conversion of a position vector given in a cartesian coordinate to a geographic coordinate.
!!
!! @param[in] orth_p A position vector in a cartesian coordinate system\f$(x,y,z)\f$.
!! @return           A position vector in a geographic coordinate system(\f$\phi\f$(longitude), \f$\theta\f$(latitude), \f$r\f$(distance)).
!!
function orth_to_geo_pos( &
  & orth_p                & ! (in)
  & ) result(geo_p)

  ! 宣言文 ; Declaration statements
  !

  real(DP), intent(in) :: orth_p(3)
  real(DP) geo_p(3)
  
  ! 実行文 ; Executable statements
  !

  geo_p(3) = sqrt( orth_p(1)**2 + orth_p(2)**2 + orth_p(3)**2 )
  geo_p(2) = asin( orth_p(3) / geo_p(3) )
  geo_p(1) = atan( orth_p(2) / orth_p(1) )
  
  ! 位置ベクトルの終点が xy 平面上において第三象限にあるときは西経 90 度から 180度, 
  ! 第二象限にあるときは東経　90 度から 180 度となるように調節する. 
  
  if ( geo_p(1) < 0 .and. orth_p(1) < 0 ) then
    geo_p(1) = geo_p(1) + PI
  else if ( geo_p(1) > 0 .and. orth_p(1) < 0 ) then
    geo_p(1) = geo_p(1) - PI
  end if

end function orth_to_geo_pos

!
!> \~japanese
!! \brief 地理座標系から直交座標系へ位置ベクトルの座標変換を行う.
!!
!! @param[in] geo_p 地理座標系における位置ベクトル(\f$\phi\f$(経度), \f$\theta\f$(緯度), \f$r\f$(中心からの距離))
!! @return          直交座標系における位置ベクトル\f$(x,y,z)\f$.
!!
!! \~english
!! Performs a coordinate conversion of a position vector given in a geographic coordinate to a cartesian coordinate. 
!!
!! @param[in] geo_p A position vector in a geographic coordinate system(\f$\phi\f$(longitude), \f$\theta\f$(latitude), \f$r\f$(distance)).
!! @return  A position vector in a cartesian coordinate system \f$(x,y,z)\f$.
!         
function geo_to_orth_pos( &
  & geo_p                 &  ! (in)
  & ) result(orth_p)

  ! 宣言文 ; Declaration statements
  !

  real(DP), intent(in) :: geo_p(3)   ! 地理座標系における位置ベクトル(\f$\phi\f$(経度), \f$\theta\f$(緯度), \f$r\f$(中心からの距離))
  real(DP) orth_p(3)                 ! 直交座標系における位置ベクトル\f$(x,y,z)\f$. 

  ! 実行文 ; Executable statements
  !
 
  orth_p(1) = geo_p(3) * cos(geo_p(2)) * cos(geo_p(1))
  orth_p(2) = geo_p(3) * cos(geo_p(2)) * sin(geo_p(1))
  orth_p(3) = geo_p(3) * sin(geo_p(2))

end function geo_to_orth_pos

!
!> \~japanese
!! \brief ベクトルを直交座標系から地球座標系へ変換する.
!!
!! @param[in] orth_v 直交座標系におけるベクトル\f$(A_x,A_y,A_z)\f$.
!! @param[in] geo_p  地理座標系における位置ベクトル(\f$\phi\f$(経度), \f$\theta\f$(緯度), \f$r\f$(中心からの距離)).
!! @return           地理座標系におけるベクトル\f$(A_{\phi}, A_{\theta}, A_r)\f$.
!!
!! \~english
!! \brief Converts a vector  from cartesian to geographic coordinate system.
!!
!! @param[in] orth_v A vector in cartesian coordinate system\f$(A_x,A_y,A_z)\f$.
!! @param[in] geo_p  A position vector in geographic coordinate system(\f$\phi\f$(longitude), \f$\theta\f$(latitude), \f$r\f$(distance)).
!! @return           A vector in geographic coordinate system\f$(A_{\phi}, A_{\theta}, A_r)\f.
!
function orth_to_geo_vec( &
  & orth_v, geo_p         &  ! (in) 
  & ) result(geo_v)

  ! 宣言文 ; Declaration statements
  ! 
  real(DP), intent(in) :: orth_v(3)    ! 直交座標系におけるベクトル\f$(A_x,A_y,A_z)\f$. 
  real(DP), intent(in) :: geo_p(3)     ! 地理座標系における位置ベクトル(\f$\phi\f$(経度), \f$\theta\f$(緯度), \f$r\f$(中心からの距離))
  real(DP) geo_v(3)                    ! 地理座標系におけるベクトル\f$(A_{\phi}, A_{\theta}, A_r)\f$. 

  ! 実行文 ; Executable statements
  !

  geo_v(3) =  orth_v(1) * cos(geo_p(2)) * cos(geo_p(1))  &
    &        + orth_v(2) * cos(geo_p(2)) * sin(geo_p(1)) &
    &        + orth_v(3) * sin(geo_p(2))

  geo_v(2) = - orth_v(1) * sin(geo_p(2)) * cos(geo_p(1)) &
    &        - orth_v(2) * sin(geo_p(2)) * sin(geo_p(1)) &
    &        + orth_v(3) * cos(geo_p(2))

  geo_v(1) = - orth_v(1) * sin(geo_p(1)) &
    &        + orth_v(2) * cos(geo_p(1))

end function orth_to_geo_vec

!
!> \~japanese
!! \brief ベクトルを地理座標系から直交座標系へ座標変換する.
!! @param[in] geo_v 地理座標系におけるベクトル\f$(A_{\phi}, A_{\theta}, A_r)\f$.
!! @param[in] geo_p  地理座標系における位置ベクトル(\f$\phi\f$(経度), \f$\theta\f$(緯度), \f$r\f$(中心からの距離)).
!! @return           直交座標系におけるベクトル\f$(A_x,A_y,A_z)\f$.
!!
!! \~english
!! \brief Converts a vector from geographic to cartesian coordinate system.
!!
!! @param[in] geo_v A vector in geographic coordinate system\f$(A_{\phi}, A_{\theta}, A_r)\f$.
!! @param[in] geo_p  A position vector in geographic coordinate system(\f$\phi\f$(longitude), \f$\theta\f$(latitude), \f$r\f$(distance)).
!! @return           A vector in cartesian coordinate system\f$(A_x,A_y,A_z)\f.
!
function geo_to_orth_vec( &
  & geo_v, geo_p          &  ! (in)
  & ) result(orth_v)

  ! 宣言文 ; Declaration statements
  !
  real(DP), intent(in) :: geo_v(3)  ! 地理座標系におけるベクトル\f$(A_{\phi}, A_{\theta}, A_r)\f$.
  real(DP), intent(in) :: geo_p(3)  ! 地理座標系における位置ベクトル($\phi$(経度), $\theta$(緯度), $r$(中心からの距離))
  real(DP) orth_v(3)                ! 直交座標系におけるベクトル\f$(A_x,A_y,A_z)\f$. 

  ! 実行文 ; Executable statements
  !

  orth_v(1) =   geo_v(3) * cos(geo_p(1)) * cos(geo_p(2)) &
    &         - geo_v(2) * cos(geo_p(1)) * sin(geo_p(2)) &
    &         - geo_v(1) * sin(geo_p(1))

  orth_v(2) =   geo_v(3) * sin(geo_p(1)) * cos(geo_p(2)) &
    &         - geo_v(2) * sin(geo_p(1)) * sin(geo_p(2)) &
    &         + geo_v(1) * cos(geo_p(1))

  orth_v(3) = geo_v(3) * dsin(geo_p(2)) + geo_v(2) * dcos(geo_p(2))

end function geo_to_orth_vec

end module igmcore_coordinate_conversion
