subroutine setrem
  use greg_dependencies_interfaces
  use greg_interfaces, except_this=>setrem
  use greg_kernel
  use greg_wcs
  !---------------------------------------------------------------------
  ! @ private
  ! MAP	Computes the coordinates in the absolute system
  !	of the remarkable points of the projection
  !
  ! There are 6 privileged points
  !
  !	2------------4-------------6
  !	|                          |
  !	|                          |	RX,RY	Relative coordinates
  !	|                          |
  !	|                          |	AX,AY	Absolute coordinates
  !	|                          |
  !	1------------3-------------5
  !
  !
  ! En fait en cas d'angle non nul, la methode ci-dessus ne marche plus.
  ! Une astuce COLOSSALE consiste a considerer le plus petit cercle contenant
  ! le rectangle et centre sur le centre de projection. Ce cercle est la
  ! projection de points angulairement equidistants du centre de projection.
  ! Or, en projection GNOMONIC, les points d'elongations extremes
  ! correspondent aux tangentes au cercle passant par le pole.
  ! i.e.	Xgnom	= 	SQRT(Yg(POLE)**2 - D**2) * D / Yg(POLE)
  !	Ygnom	=	D**2 / Yg(POLE)
  ! Les coordonnees absolues s'en deduise trivialement
  !
  ! Pour la declinaison, le probleme est evident.
  !
  ! Bien sur tout ca ne marche pas avec les projections AITOFF et RADIO .
  !---------------------------------------------------------------------
  ! Global
  include 'gbl_pi.inc'
  ! Local
  real*8, parameter :: precision=1.0d-10
  real*8 :: c,w,ax1,ax2,ay1,ay2
  real*8 :: pradius,gradius,radius,gpole,sindec,sinp,sinr,cosr,cosp
  real*8 :: extra
  !
  if (gproj%type.eq.p_none) then
    ax1 = max(gux1,gux2)
    ax2 = min(gux1,gux2)
    ay1 = min(guy1,guy2)
    ay2 = max(guy1,guy2)
    axrem1 = ax1
    ayrem1 = ay1
    axrem2 = ax1
    ayrem2 = ay2
    axrem3 = 0
    ayrem3 = ay1
    axrem4 = 0
    ayrem4 = ay2
    axrem5 = ax2
    ayrem5 = ay1
    axrem6 = ax2
    ayrem6 = ay2
    ramin  = ax2
    ramax  = ax1
    decmin = ay1
    decmax = ay2
    return
  endif
  !
  ! NULL ANGLE CASE
  !----------------------------------------------------------------------
  if (abs(gproj%angle).le.precision) then
    ax1 = max(gux1,gux2)
    ax2 = min(gux1,gux2)
    ay1 = min(guy1,guy2)
    ay2 = max(guy1,guy2)
    !
    ! Gnomonic
    call rel_to_abs (gproj,ax1,ay1,axrem1,ayrem1,1)
    call rel_to_abs (gproj,ax1,ay2,axrem2,ayrem2,1)
    call rel_to_abs (gproj,0.d0,ay1,axrem3,ayrem3,1)
    call rel_to_abs (gproj,0.d0,ay2,axrem4,ayrem4,1)
    call rel_to_abs (gproj,ax2,ay1,axrem5,ayrem5,1)
    call rel_to_abs (gproj,ax2,ay2,axrem6,ayrem6,1)
    !
    ! Orthographic, Lambert and Azimuthal have a finite area
    if (gproj%type.eq.p_ortho) then
      w = ay2**2
      if (w.le.1.d0) then
        c = sqrt(1.d0-w)
        if (-c .gt. ax2) call rel_to_abs(gproj,-c,ay2,axrem6,ayrem6,1)
        if (c .lt. ax1) call rel_to_abs(gproj,c,ay2,axrem2,ayrem2,1)
      endif
      w = ay1**2
      if (w.le.1.d0) then
        c = sqrt(1.d0-w)
        if (-c .gt. ax2) call rel_to_abs(gproj,-c,ay1,axrem5,ayrem5,1)
        if (c .lt. ax1) call rel_to_abs(gproj,c,ay1,axrem1,ayrem1,1)
      endif
      if (ay1+1.d0 .le. 0.d0) ayrem3 = gproj%d0-pi*0.5d0
      if (ay2-1.d0 .ge. 0.d0) ayrem4 = gproj%d0+pi*0.5d0
      !
    elseif (gproj%type.eq.p_azimuthal) then
      w = ay2**2
      if (w.le.pi**2) then
        c = sqrt(pi**2-w)
        if (c .lt. ax2) call rel_to_abs(gproj,c,ay2,axrem6,ayrem6,1)
        if (-c .gt. ax1) call rel_to_abs(gproj,-c,ay2,axrem2,ayrem2,1)
      endif
      w = ay1**2
      if (w.le.pi**2) then
        c = sqrt(pi**2-w)
        if (c .lt. ax2) call rel_to_abs(gproj,c,ay1,axrem5,ayrem5,1)
        if (-c .gt. ax1) call rel_to_abs(gproj,-c,ay1,axrem1,ayrem1,1)
      endif
      if (ay1+0.5d0*pi .le. 0.d0) ayrem3 = gproj%d0-pi*0.5d0
      if (ay2-0.5d0*pi .ge. 0.d0) ayrem4 = gproj%d0+pi*0.5d0
      !
    elseif (gproj%type.eq.p_lambert) then
      w = ay2**2
      if (w.le.4) then
        c = sqrt(4-w)
        if (c .lt. ax2) call rel_to_abs(gproj,c,ay2,axrem6,ayrem6,1)
        if (-c .gt. ax1) call rel_to_abs(gproj,-c,ay2,axrem2,ayrem2,1)
      endif
      w = ay1**2
      if (w.le.4) then
        c = sqrt(4-w)
        if (c .lt. ax2) call rel_to_abs(gproj,c,ay1,axrem5,ayrem5,1)
        if (-c .gt. ax1) call rel_to_abs(gproj,-c,ay1,axrem1,ayrem1,1)
      endif
      if (ay1+1.0 .le. 0.d0) ayrem3 = gproj%d0-pi*0.5d0
      if (ay2-1.0 .ge. 0.d0) ayrem4 = gproj%d0+pi*0.5d0
    endif
    !
    ! Find RA min and RA max
    if (gproj%npole.ge.ay1 .and. gproj%npole.le.ay2) then
      if (gproj%spole.ge.ay1 .and. gproj%spole.le.ay2) then
        ramin = gproj%a0-pi
        ramax = gproj%a0+pi
        decmin = -0.5d0*pi
        decmax = 0.5d0*pi
        ipole = 3
      else
        ramin = gproj%a0-pi
        ramax = gproj%a0+pi
        ipole = 1
      endif
    elseif (gproj%spole.ge.ay1 .and. gproj%spole.le.ay2) then
      ramin = gproj%a0-pi
      ramax = gproj%a0+pi
      ipole = 2
    else
      ipole = 0
      ramin = min(axrem5,axrem6)
      ramax = max(axrem1,axrem2)
      ! This does not work...
      !            IF (RAMIN.GT.RAMAX) RAMIN = RAMIN-2.D0*PI
      ! So select the "equivalent" solution
      if (ramin.gt.ramax) ramax = ramax+2.d0*pi
    endif
    !
    ! Find DEC min and DEC max
    if (ipole.eq.1) then
      decmax = pi*0.5d0
      decmin = min(ayrem1,ayrem2,ayrem3,ayrem4,ayrem5,ayrem6)
    elseif (ipole.eq.2) then
      decmin = -pi*0.5d0
      decmax = max(ayrem1,ayrem2,ayrem3,ayrem4,ayrem5,ayrem6)
    elseif (ipole.ne.3) then
      decmin = min(ayrem1,ayrem3,ayrem5)
      decmax = max(ayrem2,ayrem4,ayrem6)
    endif
    return
  endif
  !----------------------------------------------------------------------
  !
  ! Case ANGLE not zero
  !
  ! Compute radius of projected circle
  pradius = sqrt(max(gux1**2,gux2**2)+max(guy1**2,guy2**2))
  if (gproj%type.eq.p_ortho) then
    if (pradius.lt.1.d0-precision) then
      radius = asin(pradius)
      gradius = tan(radius)
    else
      radius = 0.5d0*pi
      gradius = 1.d38
    endif
  elseif (gproj%type.eq.p_stereo) then
    radius = 2.d0*atan(pradius)
    gradius = tan(radius)
    if (gradius.lt.0.d0) gradius = 1.d38
  elseif (gproj%type.eq.p_azimuthal) then
    if (pradius.lt.pi-precision) then
      radius = pradius
      gradius = tan(radius)
    else
      radius = pi
      gradius = 1.d38
    endif
  elseif (gproj%type.eq.p_gnomonic) then
    radius = atan(pradius)
    gradius = pradius
  endif
  !
  ! Get right ascension extreme
  ! Get Gnomonic pole distance (1.D0/TAN(gproj%d0))
  if (abs(gproj%d0).gt.precision) then
    gpole = abs(1.d0/tan(gproj%d0))
  else
    gpole = 1.d38
  endif
  !
  if (gradius.gt.gpole-precision) then
    ramin = gproj%a0 - pi
    ramax = gproj%a0 + pi
  elseif (gpole.ne.1.d38) then
    if (radius.gt.precision) then
      sinr = sin(radius)
      cosr = cos(radius)
      !		p = atan2 (sqrt(1.d0-(gradius/gpole)**2)),gradius)
      !		cosp = cos(p)
      !		sinp = sin(p)
      cosp = abs(gradius/gpole)
      sinp = sqrt(1.d0-cosp**2)
      sindec = (abs(sin(gproj%d0))*cosr + cos(gproj%d0)*sinr*cosp)
      !		delta = asin (SINDEC)
      !	    	extra = asin ( sinr*sinp/cos(delta) )
      extra = asin ( sinr*sinp/sqrt(1.d0-sindec**2) ) + precision
    else
      extra = 2.d0*precision
    endif
    ramin = gproj%a0 - extra
    ramax = gproj%a0 + extra
  else
    extra = min(radius+precision,pi)   ! RADIUS pas PRADIUS....
    ramin = gproj%a0 - extra
    ramax = gproj%a0 + extra
  endif
  !
  ! Get declination extreme
  if (pradius.gt.abs(gproj%npole)-precision) then
    decmax = 0.5*pi
  else
    decmax = gproj%d0 + radius
  endif
  if (pradius.gt.abs(gproj%spole)-precision) then
    decmin = -0.5*pi
  else
    decmin = gproj%d0 - radius
  endif
end subroutine setrem
