/* **********************************************************************
 * *	                                                                *
 * *         Routines to Help With Angle string formatting              *
 * *                                                                    *
 * **********************************************************************
 * File: libs/user/AngleNames.c
 *
 *                         COPYRIGHT (c) 2004 BY
 *         SIGMET INCORPORATED, WESTFORD MASSACHUSETTS, U.S.A.
 *
 * THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED AND  COPIED
 * ONLY  IN  ACCORDANCE WITH  THE  TERMS  OF  SUCH  LICENSE  AND WITH THE
 * INCLUSION OF THE ABOVE COPYRIGHT NOTICE.  THIS SOFTWARE  OR  ANY OTHER
 * COPIES  THEREOF MAY NOT BE PROVIDED OR OTHERWISE MADE AVAILABLE TO ANY
 * OTHER PERSON.  NO TITLE TO AND OWNERSHIP OF  THE  SOFTWARE  IS  HEREBY
 * TRANSFERED.
 */
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "sigtypes.h"
#include "user_lib.h"

/* ------------------------------
 * Convert an angle in radians to latitude format.  There are both
 * reentrent and non-reentrent versions.
 */
char* sLatFromRadian
( FLT8 fAngle_a, char *sBuffer_a, int  iBufLen_a )
{
  char sresult[20] ; FLT8 fDegrees, fminutes ;
  SINT4 idegrees, itenth_minute ;

  fDegrees = (180.0/FPI) * fAngle_a ;
  if (fAngle_a < 0.0)
    {
      fDegrees = -fDegrees ;
    }
  fDegrees = MIN(fDegrees, 90.0) ;

  /* Round to the nearest 1/10 of a minute of arc
   */
  itenth_minute = NINT( 600.0 * fDegrees ) ;
  idegrees = itenth_minute/600 ;
  fminutes = ((FLT8)(itenth_minute%600))/10.0 ;
  sprintf( sresult,"%3d %4.1f'S",idegrees, fminutes ) ;
  ((UINT1 *)sresult)[3] = 176 ;

  if (fAngle_a >= 0.0) sresult[9]='N' ;
  sresult[10] = 0 ;
  strncpy( sBuffer_a, sresult, iBufLen_a ) ;
  return( sBuffer_a ) ;
}

char* srdeg_to_lat( FLT4 fangle_a )
{
  static char sresult[20] ;
  sLatFromRadian( (FPI/180.0)*(FLT8)fangle_a, sresult, 20 ) ;
  return( sresult ) ;
}

/* ------------------------------
 * Convert an angle in radians to longitude format.  There are both
 * reentrent and non-reentrent versions.
 */
char* sLonFromRadian
( FLT8 fAngle_a, char *sBuffer_a, int  iBufLen_a )
{
  char sresult[20] ; FLT8 fDegrees, fminutes ;
  SINT4 idegrees, itenth_minute ;

  fDegrees = (180.0/FPI) * fAngle_a ;
  if (fAngle_a < 0.0)
    {
      fDegrees = -fDegrees ;
    }
  fDegrees = MIN(fDegrees, 180.0) ;

  /* Round to the nearest 1/10 of a minute of arc
   */
  itenth_minute = NINT( 600.0 * fDegrees ) ;
  idegrees = itenth_minute/600 ;
  fminutes = ((FLT8)(itenth_minute%600))/10.0 ;
  sprintf( sresult,"%3d %4.1f'W",idegrees, fminutes ) ;
  ((UINT1 *)sresult)[3] = 176 ;
  if (fAngle_a >= 0.0) sresult[9]='E' ;
  sresult[10] = 0 ;
  strncpy( sBuffer_a, sresult, iBufLen_a ) ;
  return( sBuffer_a ) ;
}

char* srdeg_to_lon( FLT4 fangle_a )
{
  static char sresult[20] ;
  sLonFromRadian( (FPI/180.0)*(FLT8)fangle_a, sresult, 20 ) ;
  return( sresult ) ;
}

/* ------------------------------
 * Convert an ASCII degrees and minutes and seconds to floating degrees.
 * A floating point input of just degrees, or just degrees and minutes
 * will also work.
 */
FLT8 fDegFromText( const char *sAngle_a )
{
  FLT8 fResult, fDegrees, fMinutes, fSeconds ;
  char sAngle[80], strtokstr[8], *stok, *sState ;
  UINT2 lNegativeSign ;

  strncpy( sAngle, sAngle_a, 79 ) ;
  sAngle[79] = 0 ;

  /* Do not use STR_TOUPPER because it will change the \176 character 
   * on some platforms.
   */
  if ( (strchr(sAngle, 'W') != NULL)||(strchr(sAngle, 'S') != NULL)||
       (strchr(sAngle, 'w') != NULL)||(strchr(sAngle, 's') != NULL) )
    lNegativeSign = TRUE ;
  else
    lNegativeSign = FALSE ;

  /* Parse the string for degrees and minutes
   */
  sprintf(strtokstr, " %c'\"", 176) ;

  stok = strtok_r( sAngle, strtokstr, &sState ) ;
  if (stok)
    fDegrees = atof(stok) ;
  else
    fDegrees = 0.0 ;

  stok = strtok_r( NULL, strtokstr, &sState ) ;
  if (stok)
    fMinutes = atof(stok) ;
  else
    fMinutes = 0.0 ;

  stok = strtok_r( NULL, strtokstr, &sState ) ;
  if (stok)
    fSeconds = atof(stok) ;
  else
    fSeconds = 0.0 ;

  /* Add degrees and minutes
   */
  fResult = fDegrees + (fMinutes/60.0) + (fSeconds/3600.0) ;
  if (lNegativeSign) fResult = -fResult ;
  return( fResult ) ;
}
