#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
