#ifndef Grib_H 
#define Grib_H

#include <stdio.h>
#include <memory.h>

#ifndef stypes_H
#include <stypes.hpp>
#endif

#ifndef imagedoc_H
#include <imagedoc.hpp>
#endif

#ifndef griddoc_H
#include <griddoc.hpp>
#endif

//
// .SUMMARY
// Grib file definition
//
// .DESCRIPTION
// The GribFile class is a class for managing files in the GRIB format.
//
// .SEE ALSO
//  GribData
//

#define BUF_IMA                 7680
#define ORIGIN_CENTER           46
#define GRIB_BLOCKSIZE          32      //V0.3
#define MAXGRIBSIZE        8000000L     //V0.4

long ExtractBitField ( short b1, short nb, unsigned char* b );
void InsertBitField (long cv, short b1, short nb, unsigned char* b );
void putint (unsigned char* data, short size, int val);
int  getint (unsigned char*, short);

class GribFile
{
	char	*GFdir;			// directory
	char	*GFname;		// file name
	FILE	*GFfp;			// file pointer
	short	GFnopens;		// number of attempts to open file
	long	GFpos;			// file current position 

public :

	GribFile () {};			// Empty constructor

	GribFile (const char* dir, const char* name);
//		Normal constructor
//		Input :
//			dir   : directory
//			name  : file name

	~GribFile ();			// Normal destructor

	void Init (const char* dir, const char* name);
//		Initialize class GribFile. Called when empty constructor is used.
//		Input :
//			dir   : directory
//			name  : file name

	short Open ();
//		Open an existing grib file.
//		The number of attempts to open file is incremented.
//		Return :
//			TRUE  : grib file opened
//			FALSE : could not open file
	
	short IsGrib ();
//		Search next grib data in the grib file.
//		The file current position is located in the beginning of
//		the grib data, after string "GRIB". 
//		Return :
//			TRUE  : grib data found
//			FALSE : grib data not found

	short Create ();
//		Open an empty grib file for both writing and reading.
//		Return :
//			TRUE  : new grib file opened
//			FALSE : could not open file

	void Close ();
//		Close grib file.
//		The number of attempts to open file is decremented and when it goes
//		to zero the file is really closed.

	short Read (char* buf, int size);
//		Read up size bytes from the grib file and stores them in buf.
//		The file current position is increased by the number of bytes
//		 actually read.
//		Input  :
//			size  : number of bytes to be read
//		Output :
//			buf   : store data read
//		Return :
//			TRUE  : size bytes were read
//			FALSE : read error or the file end is encountered before
//				reaching size bytes

	short Write (char* buf, int size);
//		Write size bytes from buf into the grib file.
//		The file current position is increased by the size bytes
//		Input :
//			buf   : data to be written
//			size  : number of bytes to be written
//		Return :
//			TRUE  : size bytes were written
//			FALSE : write error

	short Skip (long offset);
//		Move the file current position to offset bytes from current position
//		Return :
//			TRUE  : skip operation successful
//			FALSE : skip operation failed

	void Flush () { fflush (GFfp);}
//		Writes any unwritten data for an output  stream  or
//		an  update stream in which the most recent operation was not
//		input to be delivered to the host environment to  the  file;
//		otherwise it is ignored.  The named stream remains open.

	short Seek (short index);
//		Move the file current position to a grib data of number index.
//		The file current position will be positioned after string "GRIB".
//		Input :
//			index : grib data number
//		Return :
//			TRUE  : seek operation successful
//			FALSE : seek operation failed

	void Rewind ();
//		Set the file current position to the beginning of grib file.

	short Eof (short& ind);
//		Set the file current position to the end of grib file and returns the
//		existing files's number of grib data.
//		Return :
//			TRUE  : eof operation successful
//			FALSE : eof operation failed


	const char* Dir () { return GFdir;}
//		Return grib file directory.

	const char* Name () { return GFname;}
//		Return grib file name.

	FILE* Fp () {return GFfp;}
//		Return file pointer associated with grib file.

	long Pos () {return GFpos;}
//		Return the file current position.

};

//
// .SUMMARY
// Grib data definition
//
// .DESCRIPTION
// The GribData class is a class for managing data in the GRIB format. 
//
// .SEE ALSO
//  GribFile
//
#define SEC0_FSIZE 8
typedef	struct
{
	//---------------------------------------------------------
	// Section 0 is the Indicator section, it has a
	// fixed length of 8 octets :
	// Octed No.		Contents	
	// 1-4		Caracter coded according to the
	//		International Telegraphic
	//		Alphabet N0. 5 as GRIB	 	
	// 5-7		Length of the entire GRIB 	
	//		message	expressed in binary
	//		form over the leftmost 3 octets
	//		(i.e., 24 bits)
	// 8		GRIB edition number
	//---------------------------------------------------------

	unsigned
	char	coded[4],	// Coded CCITT-ITA No. 5
		length[3],	// total length of GRIB message
				// (including Section 0)
		ed_number;	// GRIB edition number

} SECTION0;	

#define SEC1_FSIZE 40

typedef struct
{
	//---------------------------------------------------------
	// Section 1 is the Productor definition section,
	// it identifies the centre originating the data
	// and the model used in generating the data. The
	// data itself is described: time, parameter, etc
	// A flag field is also included to indicated the
	// presence or absence of sections 2 and 3
	// This section contain the length of the section
	// in the first 3 octets.
	// Octed No.		Contents
	// 1-3		Length of section
	// 4		Version number (No. 1 for international
	//		exchange)
	// 5		Identification of centre (see
	//		F1F2 Code table 0)
	// 6		Generating process identification
	//		number
	// 7		Grid definition	
	// 8		Flag - 128 (10000000 - section
	//			    2 included)
	// 9		Indicator of parameter (see Code table
	//		2) - 127(Image data)
	// 10		Indicator of type of level (see
	//		Code table 3)
	// 11-12	Channels
	// 13		Year of century
	// 14		Month
	// 15		Day
	// 16		Hour
	// 17		Minutes
	// 18-24	zeros
	// 25		Century of Reference time of data
	// 26-40	Reserved - set to 0
	// 41-nn	Documentation file	
	// 	Meteosat:
	//	Goes:
	//	Lansat/Spot:
	//		41-42	Path
	//		43-44	Row
	//		45	Processing level
	//		46	Reserved
	//---------------------------------------------------------

	unsigned
	char	length[3],		// Length of section
		version_number,		// Version number
		id_centre,		// Identification of centre
		id_process,		// Generating process
					// identification number
		grid_def,		// Grid definition
		flag,			// 128 (10000000 - section 2 included)
		parameter,		// Indicator of parameter
		type_level,		// Indicator of type of level
		channel[2],		// Channels
		year,			// Reference time of data
		month,			// or
		day,			// Date and time of start
		hour,			// of averanging or
		minutes,		// accumulating period
		time_range_unit,
		p1,p2,
		time_range_ind,
		number_fields[2],
		missing_fields,
		century,		// Century of reference time of data
		reserved[15],		// set to 0
		*documentation_file;	// pointer to documentation file

} SECTION1;

// *********************************************************************
// Section 1 optional documentation_file stores satellite documentation
// in a format which depends of the satellite.
// Meteosat :
// Goes:
// Landsat and Spot:
//			41-42	Path
//			43-44	Row
//			45	Processing level
//			46	Reserved
// *********************************************************************

#define SEC1_LND_SIZE 6
#define SEC1_LND_PATH 0
#define SEC1_LND_PATH_SIZE 2
#define SEC1_LND_ROW 2
#define SEC1_LND_ROW_SIZE 2
#define SEC1_LND_PLEVEL 4
#define SEC1_LND_PLEVEL_SIZE 1
#define SEC1_LND_RESERVED 5
#define SEC1_LND_RESERVED_SIZE 1


#define SEC2_FSIZE 6
typedef struct
{
	//---------------------------------------------------------
	// Section 2 is the Grid description section
	// This section is optional, it may be omitted if
	// the grid description is published in Volume B
	// of Publication No. 9
	// Octed No.		Contents
	// 1-3		Length of section
	// 4		Number of unused bits at end of section 2
	// 5		Set to zero (reserved)
	// 6		Data representation type
	//		00  - cylindrical projection
	//		90  - space view perspective
	//		254 - polynomial projection
	//		255 - general projection
	// 7-n		data representation
	//---------------------------------------------------------

	unsigned
	char	length[3], 
		unused_bits,
		zero,
		data_type,
		*data;
} SECTION2;

#define SEC3_FSIZE 6
typedef struct
{
	//---------------------------------------------------------
	// Section 3 is the Grid description section
	// This section is optional, it may be omitted if
	// the grid description is published in Volume B
	// of Publication No. 9
	// Octed No.		Contents
	// 1-3		Length of section
	// 4		Number of unused bits at end of section 3
	// 5-6		Table reference
	// 7-n		Bit map
	//---------------------------------------------------------

	unsigned
	char	length[3],
		unused_bits,
		table_reference[2],
		*bitmap;
} SECTION3;


#define SEC4_FSIZE 11
typedef struct
{
	//---------------------------------------------------------
	// Section 4 is the Binary data section
	// Octed No.		Contents
	// 1-3		Length of section
	// 4		Number of unused bits at end of section 4
	//		(last 4 bits)
	// 5-6		Scale factor
	// 7-10		Reference value
	// 11		Number of bits containing each packed value
	// 12		Variable, depending on the flag value in
	//		octer 4 (matrix mxn - image)
	//---------------------------------------------------------

	unsigned
	char	length[3],	// Length of section
		unused_bits,	// Number of unused bits at end
		scale[2],	// Scale factor	(zero)
		reference[4],	// Reference value (zero)
		bits_number;	// Number of bits packed value

} SECTION4;


#define SEC5_FSIZE 4
typedef struct
{
	unsigned char end[4];
} SECTION5;


//----------------------------------------------------------------------
// Section 2 is the Grid description section.
// This section is optional, it may be omitted if the grid description
// is published in Volume B of Publication No. 9.
// This structure is the variable part of Section 2 for the space view
// perspective (90).
//----------------------------------------------------------------------

#define SAT_NX			0	// Number of columns
#define SAT_NY			2	// Number of lines
#define SAT_LAP			4	// Latitude of sub-satellite point
#define SAT_LOP			7	// Longitude of sub-satellite point
#define SAT_FLAG		10	// Resolution flag (code table 7)
					// 128 - direction increment given
#define SAT_DX			11	// Apparent diameter of earth in grid lengths
#define SAT_DY			14	// Apparent diameter of earth in grid lengths
#define SAT_XP			17	// X-coordinate of sub-satellite point
#define SAT_YP			19	// Y-coordinate of sub-satellite point
#define SAT_SCAN		21	// Scanning mode (code table 8)
#define SAT_ORIENTATION_GRID	22	// The orientation of the grid i.e.,the angle in
					// millidegrees between the increasing y axis
					// and the meridian of the sub-satellite point
					// in the direction of increasing latitude
#define SAT_NR			25	// The altitude of the camera from the earth's
					// centre, measured in earth's (equatorial) radii
#define SAT_X0			28	// Initial column
#define SAT_Y0			30	// Initial line
#define SAT_RESERVED		32	// Reserved - set to 0

#define SEC2_SAT_SIZE		34
#define SAT_NX_SIZE		2	// Octed 7-8
#define SAT_NY_SIZE		2	// Octed 9-10
#define SAT_LAP_SIZE		3	// Octed 11-13
#define SAT_LOP_SIZE		3	// Octed 14-16
#define SAT_FLAG_SIZE		1	// Octed 17
#define SAT_DX_SIZE		3	// Octed 18-20
#define SAT_DY_SIZE		3	// Octed 21-23
#define SAT_XP_SIZE		2	// Octed 24-25
#define SAT_YP_SIZE		2	// Octed 26-27
#define SAT_SCAN_SIZE		1	// Octed 28
#define SAT_ORIENTATION_GRID_SIZE 3	// Octed 29-31
#define SAT_NR_SIZE		3	// Octed 32-34
#define SAT_X0_SIZE		2	// Octed 35-36
#define SAT_Y0_SIZE		2	// Octed 37-38
#define SAT_RESERVED_SIZE	2	// Octed 39-40


//----------------------------------------------------------------------
// Section 2 is the Grid description section.
// This section is optional, it may be omitted if the grid description
// is published in Volume B of Publication No. 9.
// This structure is the variable part of Section 2 for the cylindrical
// grid (00) with resolution less than 100m.	
//----------------------------------------------------------------------

#define CYL_NI			0	// Number of columns
#define CYL_NJ			2	// Number of lines
#define CYL_LA1			4	// Latitude of origin in degrees*10**3
#define CYL_LO1			7	// Longitude of origin in degrees*10**3
#define CYL_FLAG		10	// Resolution flag (code table 7)
					// 128 - direction increment given
#define CYL_LA2			11	// Latitude of extreme point in degrees*10**3
#define CYL_LO2			14	// Longitude of extreme point in degrees*10**3
#define CYL_DI			17	// Direction increment degrees*10**3
#define CYL_DJ			19	// Direction increment degrees*10**3
#define CYL_SCAN		21	// Scanning mode (code table 8)
#define CYL_RESERVED		22	// Reserved - set to 0

#define SEC2_CYL_SIZE		26
#define CYL_NI_SIZE		2	// Octed 7-8
#define CYL_NJ_SIZE		2	// Octed 9-10
#define CYL_LA1_SIZE		3	// Octed 11-13
#define CYL_LO1_SIZE		3	// Octed 14-16
#define CYL_FLAG_SIZE		1	// Octed 17
#define CYL_LA2_SIZE		3	// Octed 18-20
#define CYL_LO2_SIZE		3	// Octed 21-23
#define CYL_DI_SIZE		2	// Octed 24-25
#define CYL_DJ_SIZE		2	// Octed 26-27
#define CYL_SCAN_SIZE		1	// Octed 28
#define CYL_RESERVED_SIZE	4	// Octed 29-32

//----------------------------------------------------------------------
// Section 2 is the Grid description section.
// This section is optional, it may be omitted if the grid description
// is published in Volume B of Publication No. 9.
// This structure is the variable part of Section 2 for the general
// projection grid(255), proposed by INPE-DPI, for local part of table 6
//----------------------------------------------------------------------

#define GP_NI			0	// Number of columns
#define GP_NJ			2	// Number of lines
#define GP_I1			4	// Coordinate of origin on i direction in
					// meters*10**2 of projection 
#define GP_J1			8	// Coordinate of origin on j direction in
					// meters*10**2 of projection
#define GP_FLAG			12	// Resolution flag (code table 7)
					// 128 - direction increment given
#define GP_I2			13	// Coordinate of extreme point on i direction in
					// meters*10**2 of projection
#define GP_J2			17	// Coordinate of extreme point on i direction in
					// meters*10**2 of projection
#define GP_DI			21	// Direction increment in meters *10**3 of
					// projection
#define GP_DJ			25	// Direction increment in meters *10**3 of
					// projection
#define GP_SCAN			29	// Scanning mode (code table 8)
#define GP_PROJ			30	// Projection type (code table 11, proposed by
					// INPE-DPI)			
#define GP_HEMIS		31	// Hemisphere 0-Do not care,1-north,2-south
#define GP_LAT0			32	// Latitude of origin parallel in degrees*10**3
#define GP_LON0			35	// Longitude of origin meridien in degrees*10**3
#define GP_LAT1			38	// Latitude of of first standard parallel in
					// degrees*10**3
#define GP_LAT2			41	// Latitude of of second standard parallel in
					// degrees*10**3
#define GP_RD			44	// Semi-axis of earth ellipsoid in meters
#define GP_FLT			47	// Flatness coeficient of earth ellipsoid
					// multipied by 10**8
#define GP_DX			50	// Translation on X direction of the reference
					// ellipsoid in meters
#define GP_DY			52	// Translation on Y direction of the reference
					// ellipsoid in meters
#define GP_DZ			54	// Translation on Z direction of the reference
					// ellipsoid in meters

#define SEC2_GP_SIZE		56
#define GP_NI_SIZE		2	// Octet 7-8
#define GP_NJ_SIZE		2	// Octet 9-10
#define GP_I1_SIZE		4	// Octet 11-14
#define GP_J1_SIZE		4	// Octet 15-18
#define GP_FLAG_SIZE		1	// Octet 19
#define GP_I2_SIZE		4	// Octet 20-23
#define GP_J2_SIZE		4	// Octet 24-27
#define GP_DI_SIZE		4	// Octet 28-31
#define GP_DJ_SIZE		4	// Octet 32-35
#define GP_SCAN_SIZE		1	// Octet 36
#define GP_PROJ_SIZE		1	// Octet 37
#define GP_HEMIS_SIZE		1	// Octet 38
#define GP_LAT0_SIZE		3	// Octet 39-41	
#define GP_LON0_SIZE		3	// Octet 42-44
#define GP_LAT1_SIZE		3	// Octet 45-47			
#define GP_LAT2_SIZE		3	// Octet 48-50
#define GP_RD_SIZE		3	// Octet 51-53
#define GP_FLT_SIZE		3	// Octet 54-56
#define GP_DX_SIZE		2	// Octet 57-58	
#define GP_DY_SIZE		2	// Octet 59-60
#define GP_DZ_SIZE		2	// Octet 61-62


//----------------------------------------------------------------------
// Section 2 is the Grid description section.
// This section is optional, it may be omitted if the grid description
// is published in Volume B of Publication No. 9.
// This structure is the variable part of Section 2 for the gaussian
// latitude/longitude grid (04) with resolution less than 100m.	
//----------------------------------------------------------------------

#define GSS_NI			0	// Number of columns
#define GSS_NJ			2	// Number of lines
#define GSS_LA1			4	// Latitude of origin in degrees*10**3
#define GSS_LO1			7	// Longitude of origin in degrees*10**3
#define GSS_FLAG		10	// Resolution flag (code table 7)
					// 128 - direction increment given
#define GSS_LA2			11	// Latitude of extreme point in degrees*10**3
#define GSS_LO2			14	// Longitude of extreme point in degrees*10**3
#define GSS_DI			17	// Direction increment degrees*10**3
#define GSS_N			19	// Number of latitude lines between a Pole and
					// the Equator
#define GSS_SCAN		21	// Scanning mode (code table 8)
#define GSS_RESERVED		22	// Reserved - set to 0

#define SEC2_GSS_SIZE		26
#define GSS_NI_SIZE		2	// Octed 7-8
#define GSS_NJ_SIZE		2	// Octed 9-10
#define GSS_LA1_SIZE		3	// Octed 11-13
#define GSS_LO1_SIZE		3	// Octed 14-16
#define GSS_FLAG_SIZE		1	// Octed 17
#define GSS_LA2_SIZE		3	// Octed 18-20
#define GSS_LO2_SIZE		3	// Octed 21-23
#define GSS_DI_SIZE		2	// Octed 24-25
#define GSS_N_SIZE		2	// Octed 26-27
#define GSS_SCAN_SIZE		1	// Octed 28
#define GSS_RESERVED_SIZE	4	// Octed 29-32


//----------------------------------------------------------------------
// Section 2 is the Grid description section.
// This section is optional, it may be omitted if the grid description
// is published in Volume B of Publication No. 9.
// This structure is the variable part of Section 2 for the polynomial
// projection (254) proposed by INPE-DPI, for local part of table 6.
//----------------------------------------------------------------------

#define POL_NX			0	// Number of columns
#define POL_NY			2	// Number of lines
#define POL_LAP			4	// Latitude of sub-satellite point degrees*10**3
#define POL_LOP			7	// Longitude of sub-satellite point degrees*10**3
#define POL_FLAG		10	// Resolution flag (code table 7)
					// 128 - direction increment given
#define POL_RX			11	// Resolution in meters*10**2 in X direction
#define POL_RY			14	// Resolution in meters*10**2 in Y direction
#define POL_XP			17	// X-coordinate of sub-satellite point
#define POL_YP			19	// Y-coordinate of sub-satellite point
#define POL_SCAN		21	// Scanning mode (code table 8)
#define POL_ORIENTATION_GRID	22	// The orientation of the grid i.e.,the angle in
					// millidegrees between the increasing y axis
					// and the meridian of the sub-satellite point
					// in the direction of increasing latitude
#define POL_NR			25	// The altitude of the camera from the earth's
					// centre, measured in earth's (equatorial) radii
#define POL_X0			28	// Initial column
#define POL_Y0			30	// Initial line
#define POL_DEGREE		32	// Polynomial degree
#define POL_NCP			33	// Number of control points
#define POL_CONTROLPOINTS	34	// Buffer to store up to 32 control points in
					// the format:
					// Adjust X coordinate in meters*10**2, 4 bytes
					// Adjust Y coordinate in meters*10**2, 4 bytes
					// Longitude in degrees*10**6, 4 bytes
					// Latitude in degrees*10**6, 4 bytes
#define POL_RESERVED		1058	// Reserved to zeros

#define SEC2_POL_SIZE		1059
#define POL_NX_SIZE		2	// Octet 7-8
#define POL_NY_SIZE		2	// Octet 9-10
#define POL_LAP_SIZE		3	// Octet 11-13
#define POL_LOP_SIZE		3	// Octet 14-16
#define POL_FLAG_SIZE		1	// Octet 17
#define POL_RX_SIZE		3	// Octet 18-20
#define POL_RY_SIZE		3	// Octet 21-23
#define POL_XP_SIZE		2	// Octet 24-25
#define POL_YP_SIZE		2	// Octet 26-27
#define POL_SCAN_SIZE		1	// Octet 28
#define POL_ORIENTATION_GRID_SIZE 3	// Octet 29-31
#define POL_NR_SIZE		3	// Octet 32-34
#define POL_X0_SIZE		2	// Octet 35-36
#define POL_Y0_SIZE		2	// Octet 37-38
#define	POL_DEGREE_SIZE		1	// Octet 39
#define POL_NCP_SIZE		1	// Octet 40
#define POL_CONTROLPOINTS_SIZE	1024	// Octet 41-1064
#define POL_RESERVED_SIZE	1	// Octet 1065


class GribData
{

	short*		GDlookup;		// lookup table
	short		GDtranslated;		// flag
	short		GDnewnx;		// new number of columns
	float*		GDbuf;			// auxiliary buffer

protected :

	GribFile*	GDfile;			// grib file pointer
	short		GDindex;		// grib data number in the grib file
	long		GDpos_inicio_dados;	// initial position of  the grib data
						// representation 
	short		GDnx, GDny;		// size of grib data representation
	float		GDresx,GDresy;		// resolution in meters
	SECTION0	GDsec0;			// Section 0
	SECTION1	GDsec1;			// Section 1
	SECTION2*	GDsec2;			// Section 2
	SECTION3*	GDsec3;			// Section 3        
	SECTION4	GDsec4;			// Section 4
	SECTION5	GDsec5;			// Section 5 
	float		GDzscale,		// scale value
			GDfmin;			// reference value
	short		GDibsiz,		// number of bits
			GDiskip2;		// number of skip bits

public :

	GribData ();
//		Normal constructor

	GribData( GribFile *pgf, GribData *pgd );
//		Constructs a new GribData from another.

	~GribData ();
//		Normal destructor.

	GribFile* GetGribFile () { return GDfile;}
//		Get grib file pointer.

	short Index () { return GDindex;}
//		Get grib data number in the grib file.

	short NumCol () {return GDnx;}
//		Get number of columns of the grib data representation.

	short NumLin () {return GDny;}
//		Get number of rows of the grib data representation.

	short NumBit () {return GDibsiz;}
//		Get number of bits of packed value.

	float ResolutionX () { return GDresx;}
//		Get data horizontal resolution.

	float ResolutionY () { return GDresy;}
//		Get data vertical resolution.

	void	SetReference ( double vmin);
//		Set reference value

	void	SetScale ( double vmin, double vmax, int nbits);
//		Set scale value

	void	PrintGrib ();	//V0.4
//		Prints  the GribData contents

	void Init (GribFile* gf, int index);
//		Initialize GribData class from grib file.
//		It is assumed that the current file position is located in the
//		beginning of the specified grib data, after string "GRIB".
//		Input :
//			gf    : grib file pointer
//			index : grib data number

	void Init (GribFile* gf, GribData* gd, short in, SProjection* pout, SProjection* pin, Box& bout, float resx, float resy);
//		Initialize GribData class from GribData class.
//		Input :
//			gf   : output grib file pointer
//			gd   : input gribdata class
//			in   : grib data index inside grib file
//			pout : output projection class. The grib data will be
//			       initialized in this projection.
//			pin  : input projection class
//			bout : output rectangle
//			resx : output horizontal resolution
//			resy : output vertical resolution

	void Init (GribFile* gf, ImageDoc& id, short index);
//		Initialize GribData class from ImageDoc structure.
//		Input :
//			gf    : output grib file pointer
//			id    : ImageDoc structure
//			index : grib data index inside grib file

	void Init (GribFile* gf, GridDoc& id, short index ,SProjection* sp);
//		Initialize GribData class from GridDoc structure.
//		Input :
//			gf    : output grib file pointer
//			id    : GridDoc structure
//			index : grib data index inside grib file
//			sp    : projection class

	short SkipData ();
//		Skip grib data representation.
//		Put the current file position after Section 4.
//		Return :			
//			TRUE  : skip operation successful
//			FALSE : skip operation failed

	short Open () { return GDfile->Open (); }
//		Open existing grib file.
//		The number of attempts to open file is incremented.
//		Return :
//			TRUE  : grib file opened
//			FALSE : could not open file
		
	void Close () { GDfile->Close (); }
//		Close grib file.
//		The number of attempts to open file is decremented and
//		when it goes to zero the file is really closed.

	short Get (short line, unsigned char* buf);
//		Read from grib data representation a especified line and store it in buf.
//		Input :
//			line : line number to be read
//		Output :
//			buf  : store data
//		Return :
//			TRUE  : line was read
//			FALSE : line was not read

	short Get (short line, float* buf);
//		Read from grib data representation a especified line and store it in buf.
//		The data are in the format float.
//		Input :
//			line : line number to be read
//		Output :
//			buf  : store data
//		Return :
//			TRUE  : line was read
//			FALSE : line was not read

	short Get (short line, unsigned char* buf, short* window);
//		Read from grib data representation a especified virtual line and store
//		it in buf.
//		Input :
//			line   : line to be read
//			window : defines a rectangle region over the data
//		Output :
//			buf  : store data
//		Return :
//			TRUE  : line was read
//			FALSE : line was not read

	short Get (short* rect, short nedge, float fatx, float faty, unsigned char** buf);
//		Read from grib data representation a especified bounding rectangle and
//		store it in buf.
//		Input :
//			rect : defines a bounding rectangle over the data
//			nege : number of lines/columns to be added in the rectangle edge
//			       due to interpolator methods
//			fatx : x sample factor
//			faty : y sample factor      
//		Output :
//			buf  : store data
//		Return :
//			TRUE  : region was read
//			FALSE : region was not read

	short Put (short line, unsigned char* buf);
//		Write data from buf into the grib data representation.
//		The data are represented in unsigned char format.
//		Input :
//			line : line to be written
//			buf  : data to be written
//		Return :
//			TRUE  : data were written
//			FALSE : write error

	short Put (short line, float* buf);
//		Write data from buf into the grib data representation.
//		The data are in represented in floating point format.
//		Input :
//			line : line to be written
//			buf  : data to be written
//		Return :
//			TRUE  : data were written
//			FALSE : write error

	short Put (short line, unsigned char* buf, short* window);
//		Write data from buf into the grib data representation, in a especified
//		virtual line.
//		Input :
//			line   : line to be written
//			buf    : data to be written
//			window : defines a rectangle region over the data
//		Return :
//			TRUE  : data were written
//			FALSE : write error

	short Put (short line, short column, unsigned char** buf, short nline, short ncol);
//		Write data from buf into the grib data representation.
//		The data defines a rectangle region over the grib data representation.
//		The coordinates are : (line,column),(line+nline-1,column+ncol-1).
//		Input :
//			line   : initial line
//			column : initial column
//			buf    : data to be written
//			nline  : number of lines to be written
//			ncol   : number of columns to be written
//		Return :
//			TRUE  : data were written
//			FALSE : write error

	short Put ();
//		Write grib data at the end of grib file. The space for data is allocated.
//		Return :
//			TRUE  : grib data was written
//			FALSE : write error

	short SetTranslation (Box& b, short& n);
//		Set parameters to perform a translation on data from (0,360) to
//		(-180,180) when data is represented in Cylindrical Equidistant
//		projection. Data will be positioned accordingly on buffer when reading
//		data by method Get (short, float*). It returns the new bounding
//		rectangle and the new number of columns.

	short PutSection2 ();
//		Update section 2
//		Return	:
//			  TRUE	: data were written
//			  FALSE	: write error

	short ProjectionCode ();
//		Get the projection code of the grib data.
//		Return :
//			(short) : projection code

	void Rectangle (Box& b);
//		Get the bounding rectangle of the grib data representation.
//		Output :
//			b : defines the bounding rectangle in projection coordinates (meters)

	short Parameter () { return (short)GDsec1.parameter;}
//		Get indicator of parameter.

	short Type () { return (short)GDsec1.type_level;}
//		Get the indicator of type of level.

	short Octet11 () { return (short)GDsec1.channel[0];}
//		Get channel number.

	short Band () { return (short)GDsec1.channel[1];}
//		Get the band number.

	short Height () { return (short)ExtractBitField (0,16,GDsec1.channel);}
//		Get the height value.

	short SubPointCoordX();
//		Get X-coordinate of sub-satellite point.

	short SubPointCoordY();
//		Get Y-coordinate of sub-satellite point.

	short OriginX();
//		Get initial column.

	short OriginY();
//		Get inital line.

	short ApparentDiaX() {return (short)getint(&GDsec2->data[SAT_DX],SAT_DX_SIZE);}
//		Get apparent diameter of earth in grid.

	short ApparentDiaY() {return (short)getint(&GDsec2->data[SAT_DY],SAT_DY_SIZE);}
//		Get apparent diameter of earth in grid.

	double AltitudeSat();
//		Get the altitude of the camera from the earth's centre.

	double SubPointLat();
//		Get latitude of sub-satellite point in radians.

	double SubPointLng();
//		Get longitude of sub-satellite point in radians.

	short ScaningMode() {return (short)getint(&GDsec2->data[SAT_SCAN],SAT_SCAN_SIZE);}
//		Get scanning mode (code table 8).

	double Yaw();
//		Get the orientation of the grid in radians.

	double OriginLat() { return (double)getint (&GDsec2->data[CYL_LA1], CYL_LA1_SIZE) * 0.001*CDR; }
//		Get the latitude of origin in radians.

	double OriginLng() { return (double)getint (&GDsec2->data[CYL_LO1], CYL_LO1_SIZE) * 0.001*CDR; }
//		Get the longitude of origin in radians.

	double EndLat() { return (double)getint (&GDsec2->data[CYL_LA2], CYL_LA2_SIZE) * 0.001*CDR; }
//		Get the latitude of extreme point in radians.

	double EndLng() { return (double)getint (&GDsec2->data[CYL_LO2], CYL_LO2_SIZE) * 0.001*CDR; }
//		Get the longitude of extreme point in radians.

	double IDirectionInc() { return (double)getint (&GDsec2->data[CYL_DI], CYL_DI_SIZE) * 0.001*CDR; }
//		Get the i direction increment in radians.

	double JDirectionInc() { return (double)getint(&GDsec2->data[CYL_DJ], CYL_DJ_SIZE)*0.001*CDR; }
//		Get the j direction increment in radians.

	short Hemisphere();
//		Returns the hemisphere.

	double OriginParallel();
//		Get the origin parallel in radians.

	double OriginMeridian();
//		Get the origin meridian in radians.

	double StandardParallelOne();
//		Get the standard parallel one in radians.

	double StandardParallelTwo();
//		Get the standard parallel two in radians.

	double EarthRadius();
//		Get the earth equatorial radius.

	double Flattening();
//		Get the earth flattening.

	double TranslationX();
//		Get the ellipsoid translation along x axis.

	double TranslationY();
//		Get the ellipsoid translation along y axis.

	double TranslationZ();
//		Get the ellipsoid translation along z axis.

	short OriginCenter() { return (short)GDsec1.id_centre;}
//		Get the origin center.

	short TableVersion() { return (short)GDsec1.version_number; }
//		Get the version table number.

	void SetGribDataLength();
//		Recompute total length size of GribData. The result is stored in GDsec0.length.

// Initialize SECTION0

	void      Set_Section0_coded (){ memcpy (GDsec0.coded, "GRIB", sizeof (GDsec0.coded)); }

	void      Set_Section0_length (int length){ putint ( GDsec0.length, sizeof(GDsec0.length),length);}

	int       Get_Section0_length (){ return getint ( GDsec0.length, sizeof(GDsec0.length) );}

	void      Set_Section0_ed_number (short ed_number){ putint ( &GDsec0.ed_number , sizeof(GDsec0.ed_number), (int)ed_number);}       
    

// Initialize SECTION1
       
	void      Set_Section1_length (int length){ putint ( GDsec1.length,  sizeof(GDsec1.length), length);}

	int       Get_Section1_length (){ return getint ( GDsec1.length,  sizeof(GDsec1.length) );}
      
	void      Set_Section1_version_number (short version_number){ putint ( &GDsec1.version_number, sizeof(GDsec1.version_number), (int)version_number);}

	void      Set_Section1_id_centre (short id_centre){  putint ( &GDsec1.id_centre, sizeof(GDsec1.id_centre), (int)id_centre);}      
    // verificar valores

	void      Set_Section1_id_process (short id_process){ putint ( &GDsec1.id_process, sizeof(GDsec1.id_process), (int)id_process);}

	void      Set_Section1_grid_def (short grid_def){ putint ( &GDsec1.grid_def, sizeof(GDsec1.grid_def), (int)grid_def);}    
     
	void      Set_Section1_flag ( short flag){ putint ( &GDsec1.flag , sizeof(GDsec1.flag), (int)flag);}     
      // podia ser simplificado

	void      Set_Section1_parameter (short parameter){  putint ( &GDsec1.parameter, sizeof(GDsec1.parameter), (int)parameter );}    
        
	void      Set_Section1_type_level (short type_level){ putint ( &GDsec1.type_level, sizeof(GDsec1.type_level), (int)type_level );} 

	void      Set_Section1_channel (short channel) { putint ( GDsec1.channel , sizeof(GDsec1.channel),(int)channel);}     

	void      Set_Section1_year (short year){ putint ( &GDsec1.year , sizeof(GDsec1.year), (int)year);}     

	void      Set_Section1_month (short month){ putint ( &GDsec1.month, sizeof(GDsec1.month), (int)month );}     
            
	void      Set_Section1_day  (short day){ putint ( &GDsec1.day , sizeof(GDsec1.day), (int)day);}     
 
	void      Set_Section1_hour (short hour){ putint ( &GDsec1.hour, sizeof(GDsec1.hour), (int)hour);}

	void	  Set_Section1_minutes (short minutes){ putint ( &GDsec1.minutes, sizeof(GDsec1.minutes), (int)minutes);}

	void      Set_Section1_century  (short century){ putint ( &GDsec1.century, sizeof(GDsec1.century),(int)century );}      

	void 	 Set_Section1_time_range_unit(short time_range_unit) { putint (&GDsec1.time_range_unit , sizeof(GDsec1.time_range_unit), (int)time_range_unit);}  
         
	void      Set_Section1_zeros ();

	void      Set_Section1_reserved  (){ putint ( GDsec1.reserved,sizeof(GDsec1.reserved) ,0 );} 
     
// Initialize  SECTION2 : parameters related to a specific grid

	void      Set_Section2_length (int length){ putint ( GDsec2->length, sizeof(GDsec2->length), length);}

	int       Get_Section2_length (){ return getint ( GDsec2->length, sizeof(GDsec2->length) );}

	 void     Set_Section2_unused_bits (short unused_bits){ putint ( &GDsec2->unused_bits, sizeof(GDsec2->unused_bits), (int)unused_bits );}     

	void      Set_Section2_zero  (){ putint ( &GDsec2->zero, sizeof(GDsec2->zero), 0);} 

	void      Set_Section2_data_type (short data_type ){ putint ( &GDsec2->data_type, sizeof(GDsec2->data_type ) , (int)data_type );}      
	void      Set_Section2_CYL_NI (short ni){ putint ( &GDsec2->data[CYL_NI] , CYL_NI_SIZE, (int)ni);}
 
	void      Set_Section2_CYL_NJ (short nj){ putint ( &GDsec2->data[CYL_NJ] , CYL_NJ_SIZE, (int)nj);}

	void      Set_Section2_CYL_LA1 (float la1){ putint ( &GDsec2->data[CYL_LA1], CYL_LA1_SIZE, (int) (la1*1000*CRD) );} 

	void      Set_Section2_CYL_L01 (float lo1){  putint ( &GDsec2->data[CYL_LO1], CYL_LO1_SIZE, (int)(lo1*1000*CRD));} 

	void      Set_Section2_CYL_FLAG (short flag){ putint (&GDsec2->data[CYL_FLAG] , CYL_FLAG_SIZE, (int)flag);} 

	void      Set_Section2_CYL_LA2 (float la2){ putint ( &GDsec2->data[CYL_LA2], CYL_LA2_SIZE, (int)(la2*1000*CRD));}          
   
	void      Set_Section2_CYL_LO2  (float lo2){ putint ( &GDsec2->data[CYL_LO2], CYL_LO2_SIZE,(int)( lo2*1000*CRD));} 
   
	void      Set_Section2_CYL_DI (float di){ putint ( &GDsec2->data[CYL_DI], CYL_DI_SIZE, (int)(di*1000*CRD));} 
         
	void      Set_Section2_CYL_DJ (float dj){ putint ( &GDsec2->data[CYL_DJ], CYL_DJ_SIZE, (int)(dj*1000*CRD));} 

	void Set_Section2_CYL_SCAN (short scan){ putint ( &GDsec2->data[CYL_SCAN], CYL_SCAN_SIZE, (int)scan );}

	void	  Set_Section2_CYL_RESERVED (short reserved){ putint ( &GDsec2->data[CYL_RESERVED] , CYL_RESERVED_SIZE, (int)reserved);}

// Initialize SECTION3

	void      Set_Section3_length (int length){ putint ( GDsec3->length , sizeof(GDsec3->length), length);} 

	int       Get_Section3_length () { return getint ( GDsec3->length , sizeof(GDsec3->length) );} 

// Initialize SECTION4

	void      Set_Section4_length (int length){ putint ( GDsec4.length , sizeof(GDsec4.length), length);} 

	int       Get_Section4_length () { return getint ( GDsec4.length , sizeof(GDsec4.length) );} 

	void      Set_Section4_unused_bits (short unused_bits){ putint ( &GDsec4.unused_bits, sizeof(GDsec4.unused_bits), (int)unused_bits); } 

	int       Get_Section4_unused_bits (){ return getint ( &GDsec4.unused_bits, sizeof(GDsec4.unused_bits) ); }

	void	  Set_Section4_scale (short scale){ putint ( GDsec4.scale, sizeof(GDsec4.scale), (int)scale); }

	int       Get_Section4_scale (){ return getint ( GDsec4.scale, sizeof(GDsec4.scale) ); } 

	void      Set_Section4_reference  (short reference){  putint ( GDsec4.reference,sizeof(GDsec4.reference), (int)(reference));} 

	int       Get_Section4_reference  (){  return getint ( GDsec4.reference,sizeof(GDsec4.reference) );} 

	void      Set_Section4_bits_number (short bits_number){ putint ( &GDsec4.bits_number, sizeof(GDsec4.bits_number), (int)bits_number); GDibsiz = bits_number; }

	int       Get_Section4_bits_number (){ return getint ( &GDsec4.bits_number, sizeof(GDsec4.bits_number) ); }

// Initialize SECTION5

	void     Set_Section5_message(){memcpy  ( GDsec5.end, "7777", sizeof(GDsec5.end));}

};
#endif
