/* **********************************************************************
 * *                                                                    *
 * *              Routines to Help With Product Naming                  *
 * *                                                                    *
 * **********************************************************************
 * File: libs/user/ProjectionNames.c
 *
 *                     COPYRIGHT (c) 2003, 2005 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 <stdio.h>
#include <string.h>

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


/* ----------------------------------------------------------------------------
 * Return a projection name used in configuration files less than 16 characters
 * This routine is reentrent.
 */
const char* sProjectionName16( UINT1 iProjectionType_a )    
{
  const char *sPtr ;
  static char sPtrAed[20]         = { "AED"} ;
  static char sPtrMercator[20]    = { "MERCATOR"} ;
  static char sPtrPolstereo[20]   = { "POLSTEREO"} ;
  static char sPtrUtm[20]         = { "UTM"} ;
  static char sPtrPerspective[20] = { "PERSPECTIVE"} ;
  static char sPtrEdc[20]         = { "EDC"} ;
  static char sPtrGnomonic[20]    = { "GNOMONIC"} ;
  static char sPtrGauss[20]       = { "GAUSS"} ;
  static char sPtrLambert[20]     = { "LAMBERT"} ;
  static char sPtrDefault[20]     = { "???"} ;
  
  switch(iProjectionType_a)
    {
    case  MAPROJ_AZIMUTHAL  :  sPtr = sPtrAed;         break ;
    case  MAPROJ_MERCATOR   :  sPtr = sPtrMercator;    break ;
    case  MAPROJ_POLSTEREO  :  sPtr = sPtrPolstereo;   break ;
    case  MAPROJ_UTM        :  sPtr = sPtrUtm;         break ;
    case  MAPROJ_PERSPECTIVE:  sPtr = sPtrPerspective; break ;
    case  MAPROJ_EDC        :  sPtr = sPtrEdc;         break ;
    case  MAPROJ_GNOMONIC   :  sPtr = sPtrGnomonic;    break ;
    case  MAPROJ_GAUSS      :  sPtr = sPtrGauss;       break ;
    case  MAPROJ_LAMBERT    :  sPtr = sPtrLambert;     break ;
    default :                  sPtr = sPtrDefault;     break ;
    }
  return( sPtr ) ;
}
/* =============================================
 * Returns the text used for projection type in projection configuration files
 */
const char* sProjectionName3
( UINT1 iProjectionType_a )
{
  const char *sPtr ;
  static char sPtrAed[8]         = {"AED"} ;
  static char sPtrMercator[8]    = {"MER"} ;
  static char sPtrPolstereo[8]   = {"PSG"} ;
  static char sPtrUtm[8]         = {"UTM"} ;
  static char sPtrPerspective[8] = {"PER"} ;
  static char sPtrEdc[8]         = {"EDC"} ;
  static char sPtrGnomonic[8]    = {"GNO"} ;
  static char sPtrGauss[8]       = {"GAU"} ;
  static char sPtrLambert[8]     = {"LAM"} ;
  static char sPtrDefault[8]     = {"XXX"} ;

  switch(iProjectionType_a)
    {
    case  MAPROJ_AZIMUTHAL  :  sPtr = sPtrAed;         break ;
    case  MAPROJ_MERCATOR   :  sPtr = sPtrMercator;    break ;
    case  MAPROJ_POLSTEREO  :  sPtr = sPtrPolstereo;   break ;
    case  MAPROJ_UTM        :  sPtr = sPtrUtm;         break ;
    case  MAPROJ_PERSPECTIVE:  sPtr = sPtrPerspective; break ;
    case  MAPROJ_EDC        :  sPtr = sPtrEdc;         break ;
    case  MAPROJ_GNOMONIC   :  sPtr = sPtrGnomonic;    break ;
    case  MAPROJ_GAUSS      :  sPtr = sPtrGauss;       break ;
    case  MAPROJ_LAMBERT    :  sPtr = sPtrLambert;     break ;
    default :                  sPtr = sPtrDefault;     break ;
    }
  return( sPtr ) ;
}
/* ----------------------------------------------------------------------------
 * Return a projection name used in documentation using less than 32 characters.
 * This routine is reentrent, description can have imbedded whitespace.
 */
const char* sProjectionName32( UINT1 iProjectionType_a )    
{
  const char *sPtr ;
  static char sPtrAed[40]         = {"Azimuthal Eqdist"} ;
  static char sPtrMercator[40]    = {"Mercator"} ;
  static char sPtrPolstereo[40]   = {"Polar Stereo"} ;
  static char sPtrUtm[40]         = {"UTM"} ;
  static char sPtrPerspective[40] = {"Perspective"} ;
  static char sPtrEdc[40]         = {"Eqdist Cylinder"} ;
  static char sPtrGnomonic[40]    = {"Gnomonic"} ;
  static char sPtrGauss[40]       = {"Gauss Conformal"} ;
  static char sPtrLambert[40]     = {"Lambert Conic"} ;
  static char sPtrDefault[40]     = {"INVALID"} ;

  switch(iProjectionType_a)
    {
    case  MAPROJ_AZIMUTHAL  :  sPtr = sPtrAed;         break ;
    case  MAPROJ_MERCATOR   :  sPtr = sPtrMercator;    break ;
    case  MAPROJ_POLSTEREO  :  sPtr = sPtrPolstereo;   break ;
    case  MAPROJ_UTM        :  sPtr = sPtrUtm;         break ;
    case  MAPROJ_PERSPECTIVE:  sPtr = sPtrPerspective; break ;
    case  MAPROJ_EDC        :  sPtr = sPtrEdc;         break ;
    case  MAPROJ_GNOMONIC   :  sPtr = sPtrGnomonic;    break ;
    case  MAPROJ_GAUSS      :  sPtr = sPtrGauss;       break ;
    case  MAPROJ_LAMBERT    :  sPtr = sPtrLambert;     break ;
    default :                  sPtr = sPtrDefault;     break ;
    }
  return( sPtr ) ;
}

/* ====================================================================
 * Return a projection name used in the proj4 standard.
 */
const char *sProj4Name
(UINT1 iProjectionType_a)
{
  const  char *sPtr ;
  static char sPtrAed[8]         = {"aeqd"} ;
  static char sPtrMercator[8]    = {"merc"} ;
  static char sPtrPolstereo[8]   = {"stere"};
  static char sPtrUtm[8]         = {"tmerc"};
  static char sPtrPerspective[8] = {"nsper"};
  static char sPtrEdc[8]         = {"eqc"};
  static char sPtrGnomonic[8]    = {"gnom"};
  static char sPtrLambert[8]     = {"lcc"};
  static char sPtrDefault[8]     = {"none"};

  switch(iProjectionType_a)
    {
    case  MAPROJ_AZIMUTHAL  :  sPtr = sPtrAed;         break ;
    case  MAPROJ_MERCATOR   :  sPtr = sPtrMercator;    break ;
    case  MAPROJ_POLSTEREO  :  sPtr = sPtrPolstereo;   break ;
    case  MAPROJ_UTM        :  sPtr = sPtrUtm;         break ;
    case  MAPROJ_PERSPECTIVE:  sPtr = sPtrPerspective; break ;
    case  MAPROJ_EDC        :  sPtr = sPtrEdc;         break ;
    case  MAPROJ_GNOMONIC   :  sPtr = sPtrGnomonic;    break ;
    case  MAPROJ_GAUSS      :  sPtr = sPtrUtm;         break ;  /*Same as utm */
    case  MAPROJ_LAMBERT    :  sPtr = sPtrLambert;     break ;
    default :                  sPtr = sPtrDefault;     break ;
    }
  return( sPtr ) ;
}

/* ======================================================
 * Tell me if the projection uses the reference latitude.
 */
UINT1 lProjectionHasRefLat
(UINT1 iProjectionType_a)
{
  switch(iProjectionType_a)
    {
    case  MAPROJ_MERCATOR   : 
    case  MAPROJ_UTM        :
    case  MAPROJ_EDC        :
    case  MAPROJ_GAUSS      :
      return FALSE;
      break ;

    default :  
      return TRUE;
      break;
    }
}
/* ======================================================
 * Tell me if the projection uses standard parallels
 */
UINT1 lProjectionHasStdPar
(UINT1 iProjectionType_a)
{
  switch(iProjectionType_a)
    {
    case  MAPROJ_LAMBERT:
      return TRUE;
      break ;

    default :  
      return FALSE;
      break;
    }
}

/* ======================================================
 * Get name and value for one of the standard geodes.
 * Can produce up to IMAP_EARTH_GEODE_COUNT different values.
 */
FLT8 fGetStandardGeode   /* Returns radius here */
(char sName_a[16],       /* Returns name here */
 FLT8 *fFlattening_a,    /* Returns flattening here */
 UINT4 iIndex_a)
{
  int iIndex;
  const char *sNames[IMAP_EARTH_GEODE_COUNT] = { "Sphere", "intl", "WGS84" };
  FLT8 fRadii[IMAP_EARTH_GEODE_COUNT]  = { FEARTH_MEAN_RADIUS, 6378.388, 6378.137 };
  FLT8 fFlat[IMAP_EARTH_GEODE_COUNT]   = {                0.0, 297.000, 298.257223563 };

  if (iIndex_a<=IMAP_EARTH_GEODE_COUNT)
    iIndex=iIndex_a;
  else
    iIndex=0;

  strcpy( sName_a, sNames[iIndex] );
  *fFlattening_a = fFlat[iIndex];
  return fRadii[iIndex];

}

/*======================================================================
 * Given the projection type in ASCII, convert to value.
 *
 */
UINT1 iProjectionFromName16
( const char* sProjection16_a )   /* Projection type string */
{
  UINT1 iProj ;
  const char *sPtr ;

  for( iProj=0 ; iProj<MAPROJ_COUNT ; iProj++ )
    {
      sPtr = sProjectionName16( iProj ) ;
      if( 0 == strcmp( sProjection16_a, sPtr ) ) return( iProj ) ;
    }
  /* Legacy misspelling: */
  if( 0 == strcmp( sProjection16_a, "POLSTERIO" ) ) return( MAPROJ_POLSTEREO ) ;

  /* Return max value if no match found
   */
  return( 255 ) ;
}

/* ======================================================================
 * Given the projection type in proj4 style ASCII, convert to value.
 */
UINT1 iProjectionFromProj4
( const char* sProj4Name_a )   /* Projection type string */
{
  UINT1 iProj ;
  const char *sPtr ;

  for( iProj=0 ; iProj<MAPROJ_COUNT ; iProj++ )
    {
      sPtr = sProj4Name( iProj ) ;
      if( 0 == strcmp( sProj4Name_a, sPtr ) ) return( iProj ) ;
    }
  /* Return max value if no match found
   */
  return( 255 ) ;
}
