/******************************************************************************
 *
 * Project:  Spheroid classes
 * Purpose:  Provide spheroid lookup table base classes.
 * Author:   Gillian Walter
 *
 ******************************************************************************
 * Copyright (c) 1999, Frank Warmerdam
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included
 * in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 ****************************************************************************/

#include "atlsci_spheroid.h"
#include "cpl_string.h"


/**********************************************************************/
/* ================================================================== */
/*          Spheroid definitions                                      */
/* ================================================================== */
/**********************************************************************/

SpheroidItem::SpheroidItem() :
    spheroid_name(nullptr),
    equitorial_radius(-1.0),
    polar_radius(-1.0),
    inverse_flattening(-1.0)
{}

SpheroidItem::~SpheroidItem()
{
    CPLFree(spheroid_name);
}

void SpheroidItem::SetValuesByRadii( const char *spheroidname, double eq_radius,
                                     double p_radius )
{
    spheroid_name = CPLStrdup(spheroidname);
    equitorial_radius = eq_radius;
    polar_radius = p_radius;
    inverse_flattening =
        eq_radius == polar_radius ? 0 : eq_radius/(eq_radius - polar_radius);
}

void SpheroidItem::SetValuesByEqRadiusAndInvFlattening(
    const char *spheroidname, double eq_radius, double inverseflattening )
{
    spheroid_name = CPLStrdup(spheroidname);
    equitorial_radius = eq_radius;
    inverse_flattening = inverseflattening;
    polar_radius =
        inverse_flattening == 0 ?
        eq_radius : eq_radius * ( 1.0 - ( 1.0 / inverse_flattening ) );
}

SpheroidList::SpheroidList() :
    num_spheroids(0),
    epsilonR(0.0),
    epsilonI(0.0)
{}

SpheroidList::~SpheroidList() {}

char *SpheroidList::GetSpheroidNameByRadii( double eq_radius, double polar_radius )
{
  for( int index = 0; index < num_spheroids; index++ )
  {
    const double er = spheroids[index].equitorial_radius;
    const double pr = spheroids[index].polar_radius;
    if( (fabs(er - eq_radius) < epsilonR) &&
        (fabs(pr - polar_radius) < epsilonR) )
      return CPLStrdup(spheroids[index].spheroid_name);
  }

  return nullptr;
}

char *SpheroidList::GetSpheroidNameByEqRadiusAndInvFlattening(
    double eq_radius, double inverse_flattening )
{
  for( int index = 0; index < num_spheroids; index++ )
  {
    const double er = spheroids[index].equitorial_radius;
    const double invf = spheroids[index].inverse_flattening;
    if( (fabs(er - eq_radius) < epsilonR) &&
        (fabs(invf - inverse_flattening) < epsilonI) )
      return CPLStrdup(spheroids[index].spheroid_name);
  }

  return nullptr;
}

double SpheroidList::GetSpheroidEqRadius( const char *spheroid_name )
{
  for( int index = 0; index < num_spheroids; index++ )
  {
    if( EQUAL(spheroids[index].spheroid_name, spheroid_name) )
      return spheroids[index].equitorial_radius;
  }

  return -1.0;
}

int SpheroidList::SpheroidInList( const char *spheroid_name )
{
  /* Return 1 if the spheroid name is recognized; 0 otherwise */
  for( int index = 0; index < num_spheroids; index++ )
  {
    if( EQUAL(spheroids[index].spheroid_name, spheroid_name) )
      return 1;
  }

  return 0;
}

double SpheroidList::GetSpheroidInverseFlattening( const char *spheroid_name )
{
  for( int index = 0; index < num_spheroids; index++ )
  {
    if( EQUAL(spheroids[index].spheroid_name, spheroid_name) )
      return spheroids[index].inverse_flattening;
  }

  return -1.0;
}

double SpheroidList::GetSpheroidPolarRadius( const char *spheroid_name )
{
  for( int index = 0; index < num_spheroids; index++ )
  {
    if( strcmp(spheroids[index].spheroid_name, spheroid_name) == 0 )
      return spheroids[index].polar_radius;
  }

  return -1.0;
}
