#ifndef Projection_H
#define Projection_H

#include <string.h>

#ifndef Point_H
#include <Point.hpp>
#endif

class GribData;
class Imagep;

const short PDATUM = 0x1 ;
const short PHEMISPHERE = 0x2 ;
const short PLATITUDE = 0x4 ;
const short PLONGITUDE = 0x8 ;
const short PFIRSTLAT = 0x10 ;
const short PSECDLAT = 0x20 ;

double	Decode(char* string, short flag, short& dg, short& mn, double& sc);
//		Decodes a string that contains geodetic coordinates.
//		Input	:
//			string	: character string
//			flag	: 0 - latitude  1 - longitude
//		Output	:
//			dg 	: degree
//			mn	: minute
//			sc	: second
//		Return	:
//			dd	: decimal degree
//			-1	: failure

void	Encode(double, short, char*);
//		Create a string with geodetic coordinate.
//		Input	:
//			rad	: Latitude or longitude  in radians
//			flag	: 0 - latitude  1 - longitude
//		Return	:
//			string	: String with geodetic coordinate

//
// .SUMMARY
//  Defines the Datum class
//
// .DESCRIPTION
//  Datum class specifies datum parameters which will be used
//  in further projection definitions.  
//  
// .SEE ALSO
//

class Datum
{
public :
	short		Dproj;	// projection code
	char*		Dname;	// planimetric datum name

	float		Ddx,	// ellipsoid translation along x axis
			Ddy,	// ellipsoid translation along y axis
			Ddz;	// ellipsoid translation along z axis
 
	double		Drd,	// earth equatorial radius
			Dflt;	// earth flattening
	
	Datum () { }
//		Empty constructor.

	Datum (short code, char* name,double rd,double flt,float dx,float dy,float dz);
//		Constructs class Datum.
//		Input	:
//			code :  planimetric datum code
//			name :  planimetric datum name
//			rd   :	Earth equatorial radius
//			flt  : 	Earth flattening
//			dx   :	Ellipsoid translation along x axis
//			dy   :	Ellipsoid translation along y axis
//			dz   :	Ellipsoid translation along z axis

	~Datum ();
//		Normal destructor.

	short Load (FILE* fp);
//		Read its contents from file pointed by fp.
//		Input :
//			fp : file pointer.
//		Return :
//			TRUE  : success
//			FALSE : failure

	short Save (FILE* fp);
//		Write its contents into file pointed by fp.
//		Input :
//			fp : file pointer.
//		Return :
//			TRUE  : success
//			FALSE : failure

	char* Name() { return Dname; } 
// 		Return the datum name.

	short Code () { return Dproj;}
//		Return projection code.

};

class SProjection
{
protected :

	char*		Pname;		// projection name
	char*		Pdname;		// datum name
	int		Pid;		// projection id on database
	short		Pcode,		// projection code
			Pgbcode,	// grib projection code
			Pgbcode1,	// grib internal general projection code
			Pbits,		// mask of necessary parameters
			Pdatum;		// planimetric datum

	float		Pdx,		// ellipsoid translation along x axis
			Pdy,		// ellipsoid translation along y axis
			Pdz;		// ellipsoid translation along z axis
 
	double		Prd,		// earth equatorial radius in meters.
			Pflt;		// earth flattening

	double		Poffx,		// x offset
			Poffy;		// y offset

	SProjection* 	Pout;		// projection output

	void		ChangeLL(double &x, double &y); // change the planimetic datum

public :

	SProjection ();
//		Normal constructor.
			
	virtual ~SProjection ();
//		Normal destructor.

	void	Init (short code, char* name,Datum dt);
//		Initialize class SProjection.
//		Input	:
//			code  : Projection code
//			name  : Projection name
//			dt    : datum

	void	Init (short code, char* name, short bits);
//		Initialize class SProjection.
//		Input	:
//			code  : Projection code
//			name  : Projection name
//			bits  : mask of necessary parameters

	void	Init (Datum* dt);
//		Initialize Datum parameters.
//		Input	:
//			dt    : datum

	virtual short Init (GribData* gd) = 0;
//		Initialize class SProjection from GribData.
//		Input	:
//			gd    : GribData class pointer

	char*	DatumName () { return Pdname; }
//		Return datum name

	void	DatumName (char* n);
//		Set datum name.
//		Input	:
//			n    : datum name


	SProjection& operator= (SProjection& p);
//		Assignment operator.
//		Input :
//			p : SProjection

	friend 	short	operator== (SProjection&, SProjection&);

	double	Offx () { return Poffx;}
//		Return the coordinate offset in x direction

	void	Offx (double o) { Poffx = o; }
//		Set the coordinate offset in x direction
//		Input :
//			o : x offset

	double	Offy () { return Poffy;}
//		Return the coordinate offset in y direction

	void	Offy (double o) { Poffy = o; }
//		Set the coordinate offset in y direction
//		Input :
//			o : y offset

	void	SetId (int id) {Pid = id;}
//		Set projection id.
//		Input	:
//			id : Projection identification number.

	int	Id () { return Pid;}
//		Return the projection identification number.

	virtual short	Load (FILE* f);
//		Load parameters from file pointed by f.
//		Input :
//			f : file pointer

	virtual short	Save (FILE* f);
//		Save parameters into file pointed by f.
//		Input :
//			f : file pointer

	char*	Name() { return Pname; } 
// 		Returns the projection name.

	short	PDatum() {return Pdatum;} 
// 		Returns the planimetric datum.

	void 	SetDestinationProjection(SProjection* p) {Pout = p;}
//		Returns a pointer to projection class.

	short Code() { return Pcode; }
//		Returns the projection code.

	void  Code (short c) { Pcode = c; }
//		Set projection code.
//		Input :
//			c : projection code

	short GribCode() { return Pgbcode; }
//		Returns the projection grib code.

	short GribInternalCode() { return Pgbcode1; }
//		Returns the general projection grib code.

	void GribCode(short c) { Pgbcode = c; }
//		Sets the projection grib code.

	void GribInternalCode(short c) { Pgbcode1 =c; }
//		Sets the general projection grib code.

	short Parameters (short p) { return p&Pbits;}
//		Check if parameter p is necessary to define projection.
//		Input	:
//			p : Parameter code.
//		Return	:
//			TRUE : parameter is necessary.
//			FALSE : parameter is not necessary.

	float EllipsoidTranslationX () { return Pdx; }
//		Returns the ellipsoid translation along x axis.

	void  EllipsoidTranslationX (float e) { Pdx = e; }
//		Set the ellipsoid translation along x axis.
//		Input :
//			e : ellipsoid translation

	float EllipsoidTranslationY () { return Pdy; }
//		Returns the ellipsoid translation along y axis.

	void  EllipsoidTranslationY (float e) { Pdy = e; }
//		Set the ellipsoid translation along y axis.
//		Input :
//			e : ellipsoid translation

	float EllipsoidTranslationZ () { return Pdz; }
//		Returns the ellipsoid translation along z axis.

	void  EllipsoidTranslationZ (float e) { Pdz = e; }
//		Set the ellipsoid translation along z axis.
//		Input :
//			e : ellipsoid translation

	double EarthRadius () { return Prd; }
//		Returns the earth equatorial radius.

	void   EarthRadius (double e) { Prd = e; }
//		Set the earth equatorial radius.
//		Input :
//			e : earth radius

	double EarthFlattening () { return Pflt; }
//		Returns the earth flattening.

	void   EarthFlattening (double e) { Pflt = e; }
//		Set the earth flattening.
//		Input :
//			e : earth flattening

	virtual	Point	LL2PC (Point& p) = 0;
//		Geodetic to projection coordinates transformation.
//		Input 	: 
//			ptll : Geodetic coordinates
//		Return	: 
//			ptpc : Corresponding projection coordinates

	virtual	Point	PC2LL (Point& p) = 0;
//		Projection to geodetic coordinates transformation.
//		Input	: 
//			ptpc : Projection coordinates
//		Return 	:
//		ptll : Corresponding geodetic coordinates

	virtual double	SensorResolutionX () = 0;
//		Returns the sensor angle resolution X.

	virtual void    SensorResolutionX (double s) = 0;
//		Set the sensor angle resolution X.
//		Input :
//			s : angle resolution

	virtual double	SensorResolutionY () = 0;
//		Returns the sensor angle resolution Y.

	virtual void    SensorResolutionY (double s) = 0;
//		Set the sensor angle resolution Y.
//		Input :
//			s : angle resolution

	virtual double SubSatelliteX () = 0;
//		Returns the sub-satellite X coordinate.

	virtual void   SubSatelliteX (double s) = 0;
//		Set the sub-satellite X coordinate.
//		Input :
//			s : sub-satellite X coordinate

	virtual double SubSatelliteY () = 0;
//		Returns the sub-satellite Y coordinate.

	virtual void   SubSatelliteY (double s) = 0;
//		Set the sub-satellite Y coordinate.
//		Input :
//			s : sub-satellite Y coordinate

	virtual double OriginX () = 0;
//		Returns inital image x coordinate.

	virtual double OriginY () = 0;
//		Returns inital image y coordinate.

	virtual double SubSatelliteLng () = 0;
//		Returns the sub-satellite longitude in radians.

	virtual void   SubSatelliteLng (double s) = 0;
//		Set the sub-satellite longitude in radians.
//		Input :
//			s : longitude in radians

	virtual double SubSatelliteLat () = 0;
//		Returns the sub-satellite latitude in radians.

	virtual void   SubSatelliteLat (double s) = 0;
//		Set the sub-satellite latitude in radians.
//		Input :
//			s : latitude in radians

	virtual double Radius () = 0;
//		Returns the satellite radius in meters.

	virtual void   Radius (double s) = 0;
//		Set the satellite radius in meters.
//		Input :
//			s : radius

	virtual double Yaw () = 0;
//		Returns the orientation angle in radians.

	virtual void   Yaw (double s) = 0;
//		Set the orientation angle in radians.
//		Input :
//			s : orientation angle

	virtual short Hemisphere () = 0;
//		Returns hemisphere.

	virtual void  Hemisphere (short h) = 0;
//		Set hemisphere.
//		Input :
//			h : hemisphere

	virtual double OriginLatitude () = 0;
//		Returns the origin parallel.

	virtual void   OriginLatitude (double o) = 0;
//		Set the origin parallel.
//		Input :
//			o : origin parallel

	virtual double OriginLongitude () = 0;
//		Returns the origin meridian.

	virtual void   OriginLongitude (double o) = 0;
//		Set the origin meridian.
//		Input :
//			o : origin meridian

	virtual double StandardLatitudeOne () = 0;
//		Returns the standard parallel one.

	virtual void   StandardLatitudeOne (double s) = 0;
//		Set the standard parallel one.
//		Input :
//			s : parallel

	virtual double StandardLatitudeTwo () = 0;
//		Returns the standard parallel two.

	virtual void   StandardLatitudeTwo (double s) = 0;
//		Set the standard parallel two.
//		Input :
//			s : parallel

	virtual double	ScanningMode () { return 0.; }
//		Returns the Scanning Mode.

	virtual void    ScanningMode (double) { }
//		Set the Scanning Mode.
//		Input :
//			y : scanning mode
};

//
// .SUMMARY
//  Defines the general projection class.
//
// .DESCRIPTION
//  GerenalProjection is a general class related to the following
//  projections:utm,mercator,gauss,lambert-million,
//  lambert,polyconic,cilindric equidistance,polar stereo,bipolar,albers,
//  miller.
//  
// .SEE ALSO
//  Point,SProjection

class GeneralProjection : public SProjection
{
protected :

	short		GPhemis;	// hemisphere : polar stereo

				    	// all these parameters must be in
					// radians
	double		GPlat0,		// origin parallel     
			GPlon0,		// origin meridian
			GPstlat1,	// standard parallel
			GPstlat2;	// standard parallel	
		
public :

	GeneralProjection () { Pout = this;}
//		Normal constructor.
//		Input	:
//			p	: projection code
//			n	: projection name
//			gbc	: grib projection code
//			gbc1	: grib internal general projection code

	~GeneralProjection () { }
//		Normal destructor.

	void	Init (Datum* pd, short hemis, double lat0, double lon0, double stlat1, double stlat2);
//		Initialize class GeneralProjection.
//		Input :	
//			pd	: Datum pointer	
//			hemis 	: Hemisphere
//			lat0	: origin parallel
//			lon0	: origin meridian
//			stlat1	: standart parallel
//			stlat2	: standart parallel

	virtual short Init (GribData* gd);
//		Initialize class GeneralProjection from GribData.
//		Input	:
//			gd    : GribData class pointer

	void	Init (double r) {Prd = r;}
// 		Return the earth equatorial radius (Prd) initialized.

	virtual short	Load (FILE* f);
//		Load parameters from file pointed by f.
//		Input :
//			f : file pointer

	virtual short	Save (FILE* f);
//		Save parameters into file pointed by f.
//		Input :
//			f : file pointer

	friend 	short	operator== (GeneralProjection&, GeneralProjection&);

	virtual short Hemisphere () { return GPhemis; }
//		Returns hemisphere.

	virtual void  Hemisphere (short h) { GPhemis = h; }
//		Set hemisphere.
//		Input :
//			h : hemisphere

	virtual double OriginLatitude () { return GPlat0; }
//		Returns the origin parallel.

	virtual void   OriginLatitude (double o)  { GPlat0 = o; }
//		Set the origin parallel.
//		Input :
//			o : origin parallel

	virtual double OriginLongitude () { return GPlon0; }
//		Returns the origin meridian.

	virtual void   OriginLongitude (double o)  { GPlon0 = o; }
//		Set the origin meridian.
//		Input :
//			o : origin meridian

	virtual double StandardLatitudeOne () { return GPstlat1; }
//		Returns the standard parallel one.

	virtual void   StandardLatitudeOne (double s) { GPstlat1 = s; }
//		Set the standard parallel one.
//		Input :
//			s : parallel

	virtual double StandardLatitudeTwo () { return GPstlat2; }
//		Returns the standard parallel two.

	virtual void   StandardLatitudeTwo (double s) { GPstlat2 = s; }
//		Set the standard parallel two.
//		Input :
//			s : parallel

	virtual	Point	LL2PC (Point&) = 0;
//		Geodetic to projection coordinates transformation.
//		Input 	: 
//			ptll : Geodetic coordinates
//		Return	: 
//			ptpc : Corresponding projection coordinates

	virtual	Point	PC2LL (Point&) = 0;
//		Projection to geodetic coordinates transformation.
//		Input	: 
//			ptpc : Projection coordinates
//		Return 	:
//			ptll : Corresponding geodetic coordinates

	virtual double	SensorResolutionX () { return 0.; }
//		Returns the sensor angle resolution X.

	virtual void	SensorResolutionX (double ) { }
//		Set the sensor angle resolution X.
//		Input :
//			s : sensor angle

	virtual double	SensorResolutionY () {return 0.;}
//		Returns the sensor angle resolution Y.

	virtual void	SensorResolutionY (double ) { }
//		Set the sensor angle resolution Y.
//		Input :
//			s : sensor angle

	virtual double SubSatelliteX () {return 0.;}
//		Returns the sub-satellite X coordinate.

	virtual void   SubSatelliteX (double ) { }
//		Set the sub-satellite X coordinate.
//		Input :
//			s : X coordinate

	virtual double SubSatelliteY () {return 0.;}
//		Returns the sub-satellite Y coordinate.

	virtual void   SubSatelliteY (double ) { }
//		Set the sub-satellite Y coordinate.
//		Input :
//			s : Y coordinate

	virtual double OriginX () {return 0.;}
//		Returns inital image x coordinate.

	virtual double OriginY () {return 0.;}
//		Returns inital image y coordinate.

	virtual double SubSatelliteLng () {return 0.;}
//		Returns the sub-satellite longitude in radians.

	virtual void   SubSatelliteLng (double ) { }
//		Set the sub-satellite longitude in radians.
//		Input :
//			s : longitude

	virtual double SubSatelliteLat () {return 0.;}
//		Returns the sub-satellite latitude in radians.

	virtual void   SubSatelliteLat (double ) { }
//		Set the sub-satellite latitude in radians.
//		Input :
//			s : latitude

	virtual double Radius () {return 0.;}
//		Returns the satellite radius in meters.

	virtual void   Radius (double ) { }
//		Set the satellite radius in meters.
//		Input :
//			r : satellite radius

	virtual double Yaw () {return 0.;}
//		Returns the orientation angle in radians.

	virtual void   Yaw (double ) { }
//		Set the orientation angle in radians.
//		Input :
//			y : orientation angle

};


//
// .SUMMARY
//  Defines the Utm class.
//
// .DESCRIPTION
//  Utm is a projection class with planimetric datum
//  Sad69 and Corrego Alegre  (Hayford Ellipsoid).
//
// .SEE ALSO
//  Point, GeneralProjection
//

class Utm : public GeneralProjection
{
public :
	Utm () {}
//		Normal constructor.

	~Utm () { }
//		Normal destructor.

	virtual Point LL2PC(Point&);
//		Geodetic to projection coordinates transformation.
//		Input 	: 
//			ptll : Geodetic coordinates
//		Return	: 
//			ptpc : Corresponding projection coordinates

	virtual Point PC2LL(Point&);
//		Projection to geodetic coordinates transformation.
//		Input	: 
//			ptpc : Projection coordinates
//		Return 	:
//			ptll : Corresponding geodetic coordinates
};


//
// .SUMMARY
//  Defines the VisNoProjection class.
//
// .DESCRIPTION
//  NoProjection does not qualify the data projection, but it provides
//  the virtual methods to keep compatibility with GeneralProjection.
//  Coordinate transformation just return the input value.
//
// .SEE ALSO
//  Point,GeneralProjection
//

class VisNoProjection : public GeneralProjection
{
public :
	VisNoProjection () {}
//		Normal constructor.

	~VisNoProjection () { }
//		Normal destructor.

	virtual Point LL2PC(Point& p) { return p;}
//		Geodetic to projection coordinates transformation.
//		Input 	: 
//			p : Geodetic coordinates
//		Return	: 
//			Point : Same input coordinates.

	virtual Point PC2LL(Point& p) { return p;}
//		Projection to geodetic coordinates transformation.
//		Input	: 
//			p : Projection coordinates
//		Return 	:
//			Point : Corresponding geodetic coordinates
};


//
// .SUMMARY
//  Defines the GeneralLambert class.
//
// .DESCRIPTION
//  GeneralLambert class is a general class related to the following
//  projections : lambert million and lambert.
// 
// .SEE ALSO
//  Point ,GeneralProjection

class GeneralLambert : public GeneralProjection
{
public :
	GeneralLambert () {}
//		Normal constructor.

//	~GeneralLambert () {}
//		Normal destructor.

	virtual Point LL2PC(Point&);
//		Geodetic to projection coordinates transformation.
//		Input 	: 
//			ptll : Geodetic coordinates
//		Return	: 
//			ptpc : Corresponding projection coordinates

	virtual Point PC2LL(Point&);
//		Projection to geodetic coordinates transformation.
//		Input	: 
//			ptpc : Projection coordinates
//		Return 	:
//			ptll : Corresponding geodetic coordinates
};

//
// .SUMMARY
//  Defines the VisMercator class.
//
// .DESCRIPTION
//  Mercator is a projection class which uses the Hayford Ellipsoid.
//  
// .SEE ALSO
//  Point,GeneralProjection
//

class VisMercator : public GeneralProjection
{

public :
	VisMercator ();
//		Normal constructor.

	~VisMercator () { }
//		Normal destructor.

	virtual Point LL2PC(Point&);
//		Geodetic to projection coordinates transformation.
//		Input 	: 
//			ptll : Geodetic coordinates
//		Return	: 
//			ptpc : Corresponding projection coordinates

	virtual Point PC2LL(Point&);
//		Projection to geodetic coordinates transformation.
//		Input	: 
//			ptpc : Projection coordinates
//		Return 	:
//		ptll : Corresponding geodetic coordinates
};

//
// .SUMMARY
//  Defines the Gauss class.
//
// .DESCRIPTION
//  Gauss is a projection class with planimetric datum
//  Corrego Alegre (Hayford Ellipsoid).
//  
// .SEE ALSO
//  Point,GeneralProjection
//

class Gauss : public GeneralProjection
{

public :
	Gauss ();
//		Normal constructor.

	~Gauss () { }
//		Normal destructor.

	virtual Point LL2PC(Point&);
//		Geodetic to projection coordinates transformation.
//		Input 	: 
//			ptll : Geodetic coordinates
//		Return	: 
//			ptpc : Corresponding projection coordinates

	virtual Point PC2LL(Point&);
//		Projection to geodetic coordinates transformation.
//		Input	: 
//			ptpc : Projection coordinates
//		Return 	:
//			ptll : Corresponding geodetic coordinates
//
};


//
// .SUMMARY
//  Defines the LambertMillion class.
//
// .DESCRIPTION
//  LambertMillion is a projection class with calculated projection parameters
//  (Hayford Ellipsoid).
//  
// .SEE ALSO
//  Point,GeneralLambert
//

class LambertMillion : public GeneralLambert
{

public :
	LambertMillion () {}
//		Normal constructor.

	~LambertMillion () { }
//		Normal destructor.

};


//
// .SUMMARY
//  Defines the Lambert class.
//
// .DESCRIPTION
//  Lambert is a projection class with projection parameters given by
//  the user (Hayford Ellipsoid).
//  
// .SEE ALSO
//  Point,GeneralLambert
//

class Lambert : public GeneralLambert
{

public :
	Lambert () {}
//		Normal constructor.

	~Lambert () { }
//		Normal destructor.

};


//
// .SUMMARY
//  Defines the Polyconic class.
//
// .DESCRIPTION
//  Polyconic is a projection class which uses the Hayford Ellipsoid.
//  
// .SEE ALSO
//  Point,GeneralProjection
//

class Polyconic : public GeneralProjection
{

public :
	Polyconic () {}
//		Normal constructor.

	~Polyconic () { }
//		Normal constructor.

	virtual Point LL2PC(Point&);
//		Geodetic to projection coordinates transformation.
//		Input 	: 
//			ptll : Geodetic coordinates
//		Return	: 
//			ptpc : Corresponding projection coordinates

	virtual Point PC2LL(Point&);
//		Projection to geodetic coordinates transformation.
//		Input	: 
//			ptpc : Projection coordinates
//		Return 	:
//			ptll : Corresponding geodetic coordinates
//
};

//
// .SUMMARY
//  Defines the CylindEquid class.
//
// .DESCRIPTION
//  CylindEquid is a projection class which uses the spherical model
//  with earth radius given by the user.
//  
// .SEE ALSO
//  Point,GeneralProjection
//

class CylindEquid : public GeneralProjection
{

public :
	CylindEquid ();
//		Normal constructor.

	~CylindEquid () { }
//		Normal destructor.

	virtual Point LL2PC(Point&);
//		Geodetic to projection coordinates transformation.
//		Input 	: 
//			ptll: Geodetic coordinates
//		Return	: 
//			ptpc : Corresponding projection coordinates

	virtual Point PC2LL(Point&);
//		Projection to geodetic coordinates transformation.
//		Input	: 
//			ptpc : Projection coordinates
//		Return 	:
//			ptll : Corresponding geodetic coordinates
};


//
// .SUMMARY
//  Defines the PolarStereo class.
//
// .DESCRIPTION
//  PolarStereo is a projection class which uses the Hayford Ellipsoid.
//  
// .SEE ALSO
//  Point,GeneralProjection
//

class PolarStereo : public GeneralProjection
{

public :
	PolarStereo (char = 'N', float = 0.0);
//		Normal constructor.
//		Input:
//			hemisphere: 'N' or 'S'
//			vertical longitude

	~PolarStereo () { }
//		Normal destructor.
	
	virtual Point LL2PC(Point&);
//		Geodetic to projection coordinates transformation.
//		Input 	: 
//			ptll : Geodetic coordinates
//		Return	: 
//			ptpc : Corresponding projection coordinates

	virtual Point PC2LL(Point&);
//		Projection to geodetic coordinates transformation.
//		Input	: 
//			ptpc : Projection coordinates
//		Return 	:
//			ptll : Corresponding geodetic coordinates
};


//
// .SUMMARY
//  Defines the Bipolar class.
//
// .DESCRIPTION
//  Bipolar is a projection class which uses the spherical model
//  with earth radius given by the user.
//  
// .SEE ALSO
//  Point,GeneralProjection
//

class Bipolar : public GeneralProjection
{

public :
	Bipolar () {}
//		Normal constructor.

	~Bipolar () { }
//		Normal destructor.

	virtual Point LL2PC(Point&);
//		Geodetic to projection coordinates transformation.
//		Input 	: 
//			ptll : Geodetic coordinates
//		Return	: 
//			ptpc : Corresponding projection coordinates

	virtual Point PC2LL(Point&);
//		Projection to geodetic coordinates transformation.
//		Input	: 
//			ptpc : Projection coordinates
//		Return 	:
//			ptll : Corresponding geodetic coordinates
};


//
// .SUMMARY
//  Defines the Albers class.
//
// .DESCRIPTION
//  Albers is a projection class with projection parameters given by
//  the user (Hayford Ellipsoid).
//  
// .SEE ALSO
//  Point,GeneralProjection
//

class Albers : public GeneralProjection
{

public :
	Albers () {}
//		Normal constructor.

	~Albers () { }
//		Normal destructor.

	virtual Point LL2PC(Point&);
//		Geodetic to projection coordinates transformation.
//		Input 	: 
//			ptll : Geodetic coordinates
//		Return	: 
//			ptpc : Corresponding projection coordinates

	virtual Point PC2LL(Point&);
//		Projection to geodetic coordinates transformation.
//		Input	: 
//			ptpc : Projection coordinates
//		Return 	:
//			ptll : Corresponding geodetic coordinates
};


//
// .SUMMARY
//  Defines the Miller class.
//
// .DESCRIPTION
//  Miller is a projection class which uses the spherical model
//  with earth radius given by the user.
//  
// .SEE ALSO
//  Point,GeneralProjection
//

class Miller : public GeneralProjection	
{

public :
	Miller () {}
//		Normal constructor.

	~Miller () { }
//		Normal destructor.

	virtual Point LL2PC(Point&);
//		Geodetic to projection coordinates transformation.
//		Input 	: 
//			ptll : Geodetic coordinates
//		Return	: 
//			ptpc : Corresponding projection coordinates

	virtual Point PC2LL(Point&);
//		Projection to geodetic coordinates transformation.
//		Input	: 
//			ptpc : Projection coordinates
//		Return 	:
//		ptll : Corresponding geodetic coordinates
};


//
// .SUMMARY
//  Defines the VisSatellite projection class.
//
// .DESCRIPTION
//  SatelliteProjection is a class derived from SProjection that will be
//  used to meteorological images (low resolution images).
//  
// .SEE ALSO
//  Point,SProjection
//

class VisSatellite : public SProjection
{
	double		SPri,	// Sensor angle resolution (y axis, radians)
			SPrj,	// Sensor angle resolution (x axis, radians)
			SPis,	// Y-coordinate of sub-satellite point 
			SPjs,	// X-coordinate of sub-satellite point
			SPla0,	// Latitude of sub-satellite point  (radians)
			SPlo0,	// Longitude of sub-satellite point (radians)
			SPrs,	// Radii of satellite (meters)
			SPscn,	// Scaning mode: 0-WE/NS, 1-SN/EW
			SPyaw;	// The orientation of the grid i.e. the angle
				// in radians between the increasing y axis
				// and the meridian of the sub-satellite point 
				// in the direction of increasing latitude.

public :

	VisSatellite ();
//		Normal constructor.

	~VisSatellite () { }
//		Normal destructor.

	short   Init (VisSatellite* vs);

	virtual short Init (GribData* gd);
//		Initialize class VisSatellite from GribData.
//		Input :
//			gd : GribData pointer

	virtual void Init (float res);
//		Initialize class VisSatellite. Used only for Meteosat images.
//		Input :
//			res : image resolution

	virtual short	Load (FILE* f);
//		Load parameters from file pointed by f.
//		Input :
//			f : file pointer

	virtual short	Save (FILE* f);
//		Save parameters into file pointed by f.
//		Input :
//			f : file pointer

	friend 	short	operator== (VisSatellite&, VisSatellite&);

	virtual double	SensorResolutionX () { return SPrj; }
//		Returns the sensor angle resolution X.

	virtual void	SensorResolutionX (double s) { SPrj = s; }
//		Set the sensor angle resolution X.
//		Input :
//			s : sensor angle

	virtual double	SensorResolutionY () { return SPri; }
//		Returns the sensor angle resolution Y.

	virtual void	SensorResolutionY (double s) { SPri = s; }
//		Set the sensor angle resolution Y.
//		Input :
//			s : sensor angle

	virtual double	SubSatelliteX () { return SPjs; }
//		Returns the sub-satellite X coordinate.

	virtual void   SubSatelliteX (double s) { SPjs = s; }
//		Set the sub-satellite X coordinate.
//		Input :
//			s : X coordinate

	virtual double	SubSatelliteY () { return SPis; }
//		Returns the sub-satellite Y coordinate.

	virtual void   SubSatelliteY (double s) { SPis = s; }
//		Set the sub-satellite Y coordinate.
//		Input :
//			s : Y coordinate

	virtual double	SubSatelliteLng () { return SPlo0; }
//		Returns the sub-satellite longitude in radians.

	virtual void   SubSatelliteLng (double s) { SPlo0 = s; }
//		Set the sub-satellite longitude in radians.
//		Input :
//			s : longitude

	virtual double	SubSatelliteLat () { return SPla0; }
//		Returns the sub-satellite latitude in radians.

	virtual void   SubSatelliteLat (double s) { SPla0 = s; }
//		Set the sub-satellite latitude in radians.
//		Input :
//			s : latitude

	virtual double	Radius () { return SPrs; }
//		Returns the satellite radius in meters.

	virtual void   Radius (double r) { SPrs = r; }
//		Set the satellite radius in meters.
//		Input :
//			r : satellite radius

	virtual double	Yaw () { return SPyaw; }
//		Returns the orientation angle in radians.

	virtual void    Yaw (double y) { SPyaw = y; }
//		Set the orientation angle in radians.
//		Input :
//			y : orientation angle

	virtual double	ScanningMode () { return SPscn; }
//		Returns the Scanning Mode.

	virtual void    ScanningMode (double scn ) { SPscn = scn; }
//		Set the Scanning Mode.
//		Input :
//			y : scanning mode
	virtual double OriginX () { return 0.; }
//		Returns inital image x coordinate.

	virtual double OriginY () { return 0.; }
//		Returns inital image y coordinate.

	virtual short Hemisphere () { return 0; }
//		Returns hemisphere.

	virtual void  Hemisphere (short ) { }
//		Set hemisphere.
//		Input :
//			h : hemisphere

	virtual double OriginLatitude () { return 0L; }
//		Returns the origin parallel.

	virtual void   OriginLatitude (double ) { } 
//		Set the origin parallel.
//		Input :
//			o : origin parallel

	virtual double OriginLongitude () { return 0L; }
//		Returns the origin meridian.

	virtual void   OriginLongitude (double )  { }
//		Set the origin meridian.
//		Input :
//			o : origin meridian

	virtual double StandardLatitudeOne () { return 0L; }
//		Returns the standard parallel one.

	virtual void   StandardLatitudeOne (double )  { }
//		Set the standard parallel one.
//		Input :
//			s : parallel

	virtual double StandardLatitudeTwo () { return 0L; }
//		Returns the standard parallel two.

	virtual void   StandardLatitudeTwo (double )  { }
//		Set the standard parallel two.
//		Input :
//			s : parallel

	virtual	Point	LL2PC (Point&);
//		Geodetic to projection coordinates transformation.
//		Input 	: 
//			ptll : Geodetic coordinates
//		Return	: 
//			ptpc : Corresponding projection coordinates

	virtual	Point	PC2LL (Point&);
//		Projection to geodetic coordinates transformation.
//		Input	: 
//			ptpc : Projection coordinates
//		Return 	:
//			ptll : Corresponding geodetic coordinates
};

	SProjection* NewInstance (short gcod);
//		Get an Instance to a especific projection.
//		Input	:
//			scod	: MMETVIEW projection code (defined in stypes.hpp)


#endif
