/* FILENAME      : TerrainMap.h
 * AUTHOR        : Debbie Meduna
 * DATE          : 01/01/08
 * DESCRIPTION   : TerrainMap is used to upload, store and access 
 *                 terrain map 
 *                 information from a netcdf, *.grd map file.
 * DEPENDENCIES  : mapio.h, myOutput.h, newmat*.h, structDefs.h, 
 *                 matrixArrayCalcs.h
 *
 * LAST MODIFIED : 07/17/09
 * MODIFIED BY   : Debbie Meduna 
 * ----------------------------------------------------------------------------
 * Modification History:
 * ----------------------------------------------------------------------------
 *****************************************************************************/

#ifndef _TerrainMap_h_
#define _TerrainMap_h_
#include "mapio.h"
#include "myOutput.h"
#include "structDefs.h"
#include "math.h"
#include "matrixArrayCalcs.h"

#include <newmatap.h>
#include <newmatio.h> 

#include <stdlib.h>

//!refMapT struct contains file information on a *.grd netcdf file.
struct refMapT{
  mapbounds* bounds;
  mapsrc* src;
  mapsrc* varSrc;
  mapsrc* lowResSrc;

  refMapT()
  {
    src = NULL;
    varSrc = NULL;
    lowResSrc = NULL;
    bounds = NULL;
  }
  ~refMapT() { clean(); }
  void clean()
  {
    if(src!=NULL)
      {
	mapsrc_free(src);
	src = NULL;
      }
    
    if(varSrc!=NULL)
      {
	mapsrc_free(varSrc);
	varSrc = NULL;
      }
    
   if(lowResSrc!=NULL)
      {
	mapsrc_free(lowResSrc);
	lowResSrc = NULL;
      }

    if(bounds != NULL)
      {
	free(bounds);
	bounds = NULL;
      }
  }
};


//!variogramT struct contains information pertaining to a variogram function
struct variogramT{
  double fractalDim;
  double alpha;

  variogramT()
  {
    fractalDim = 2.234;//2.051;//2.063;
    alpha = 0.0066;//0.0362;//0.012;
  }

  inline double evalVariogram(const double& s){return alpha*pow(s,2.0*(3.0-fractalDim));}
};


/*!
 * Class: TerrainMap
 * 
 * This class is used to upload and store terrain map information to be used
 * with a TerrainNav object. The TerrainMap object contains both a reference 
 * map struct and a local map struct. The reference map contains netcdf id 
 * information for accessing data from a specified netcdf map file.  The local 
 * map is a data structure containing actual map values from a section of the
 * reference map.  
 * 
 * Intended use:
 *
 *		TerrainMap *currMap = new TerrainMap("520mSite.grd");
 *		currMap->map = extractSubMap(location, params);
 */
class TerrainMap
{
 public: 

  /* Constructor: TerrainMap()
   * Usage: currMap = new TerrainMap("canyonmap");
   * ------------------------------------------------------------------------*/
  /*! Initializes a new TerrainMap with the reference terrain map in the file 
   * "mapName.grd";
   */
  TerrainMap(char *mapName);


  /* Destructor: ~TerrainMap
   * Usage: delete currMap;
   * ------------------------------------------------------------------------*/
  /*! Frees all storage associated with the TerrainMap object.
   */
  ~TerrainMap();


  /* Function: extractSubMap
   * Usage: errorCode = currMap->extractSubMap(northPos, eastPos, mapParams);
   * ------------------------------------------------------------------------*/
  /*! Extract map information from a database, centered at (northPos, eastPos)
   * and has properties specified in mapParams. mapParams is an array storing:
   * [numX, numY], i.e. the desired size of the map.
   * The resulting map information is stored in the TerrainMap's mapT struct.
   */
  int extractSubMap(const double north, const double east, double* mapParams);


  /* Function: withinRefMap
   * Usage: terrainMap->withinRefMap(x, y);
   * ------------------------------------------------------------------------*/
  /*! Indicates if given location is within provided reference terrain map
   */
  bool withinRefMap(const double northPos, const double eastPos);	


  /* Function: withinValidMapRegion
   * Usage: terrainMap->withinValidMapRegion(x, y);
   * ------------------------------------------------------------------------*/
  /*! Indicates if given location is within a valid portion of the provided
   * reference terrain map (i.e., a non-NaN location).
   */
  bool withinValidMapRegion(const double northPos, const double eastPos);


  /* Function: withinSubMap
   * Usage: terrainMap->withinSubMap(x, y);
   * ------------------------------------------------------------------------*/
  /*! Indicates if given location is within currently loaded sub-map
   */
  bool withinSubMap(const double northPos, const double eastPos);


  /* Function: setLowResMap
   * Usage: terrainMap->setLowResMap(mapName);
   * -----------------------------------------------------------------------*/
  /*! Load a mapsrc pointer for the low resolution map given by "mapName".
   */
  void setLowResMap(char *mapName);


  /* Function: getNearestLowResMapPoint(x,y)
   * Usage: z = terrainMap->getNearestLowResMapPoint(x,y)
   * -----------------------------------------------------------------------*/
  /*! Returns the nearest depth value to the coordinates (x,y) in the loaded
   * lowResMap.  If no lowResMap is loaded, this function returns 0.
   */
  double getNearestLowResMapPoint(const double north, const double east,
				  double &nearestNorth, double &nearestEast);


  //Structures and components of a TerrainMap object:
  /**************************************************/
  mapT map;

  //stores netcdf reference information for the *.GRD file containing terrain
  //map depth data.
  refMapT* refMap;

  //variogram parameters for given map
  // gamma(s) = alpha*(s)^2*(3-fractalDim)
  variogramT mapVariogram;

 private:
   
  /* Helper Function: setRefMap
   * Usage: currMap->setRefMap(mapName);
   * ------------------------------------------------------------------------*/
  /*! Associate a reference map refMapT structure with current TerrainMap 
   * object.  
   */
  void setRefMap(char *mapName);


  /* Helper Function: convertMapDataToMapT(mapdata* mapStruct)
   * Usage: convertMapDataToMapT(currMapStruct)
   *-------------------------------------------------------------------------*/
  /*! Convert a mapdata structure created in mapio.c to the mapT structure in 
   * TerrainMap.c.
   */
  void convertMapdataToMapT(mapdata* currMapStruct);


  /* Function: extractVarMap
   * Usage: errorCode = currMap->extractVarMap(northPos, eastPos, mapParams);
   * ------------------------------------------------------------------------*/
  /*! Extract variance map information from a database, centered at (northPos, 
   * eastPos) and has properties specified in mapParams. mapParams is an array 
   * storing: [numX, numY], i.e. the desired size of the map.
   * The resulting variance information is stored in map->depthVariance. If 
   * no variance source data has been specified, this function fills in the
   * map->depthVariance matrix with unit variance for all entries.
   */
  int extractVarMap(const double north, const double east, double* mapParams);
	
};

#endif
