// This is a "copy" of the file ~magics/c/proj_braz.h .
// The reason for this duplicity is to avoid to call
// Magics routines within libUtil.
// For the new Magics version, both files should be
// replaced by a single C++ version.

#pragma once

#ifdef REAL_IS_DOUBLE
typedef double Real;
#else
typedef float Real;
#endif

typedef struct CPoint
{
    Real X, Y; /*  point location */
} CPoint;


typedef struct
{
    CPoint Bll, Bur;

} BBox;

#ifdef FORTRAN_NO_UNDERSCORE
#define pimii1_ pimii1
#define pimii2_ pimii2
#define pimin1_ pimin1
#define pimind_ pimind
#define pimp1_ pimp1
#define pimp2_ pimp2
#define pimg1_ pimg1
#define pimg2_ pimg2
#define pims1_ pims1
#define pims2_ pims2
#define pl2p1_ pl2p1
#define pl2p2_ pl2p2
#define pp2l1_ pp2l1
#define pp2l2_ pp2l2
#define pmvimg_ pmvimg
#define premap_ premap
#define pdeal_ pdeal
#define penqi_ penqi
#define penqc_ penqc
#define penq1i_ penq1i
#endif


#ifndef TRUE
#define TRUE 1
#endif

#ifndef FALSE
#define FALSE 0
#endif

#ifndef NULL
#define NULL 0
#endif

#ifndef ABS
#define ABS(x) (((x) >= 0) ? (x) : -(x))
#endif

#ifndef MIN
#define MIN(x, y) (((x) < (y)) ? (x) : (y))
#endif

#ifndef MAX
#define MAX(x, y) (((x) > (y)) ? (x) : (y))
#endif

#ifndef MAXFLOAT
#define MAXFLOAT 3.4E+35
#endif

#ifndef BIGFLOAT
#define BIGFLOAT 3.4E+35
#endif

/*  Plotting modes for DigitalModel */

#define M_NAME_MAX 100
#define CONTOUR 1
#define SHADING 2
#define GRID_VALUES 4
#define WIND_ARROWS 8
#define WIND_FLAGS 16
#define WIND_STREAM 32
#define WIND_ISOTACHS 64

#define PI 3.14159265358979323846
#define CDR 0.017453293  /*  Conversion factor: degrees to radians */
#define CRD 57.295779513 /*  Conversion factor: radians to degrees */
#define EARTH_RADIUS 6378160.
#define FLATTENING 0.0033528
#define NSTEPS 16.
#define PROJNONE 0
#define PROJUTM 2
#define PROJMERCATOR 3
#define PROJGAUSS 4
#define PROJLAMBERTMILLION 5
#define PROJLAMBERT 6
#define PROJPOLYCONIC 7
#define PROJCYLINDRICAL 0
#define PROJPOLAR 9
#define PROJBIPOLAR 10
#define PROJALBERS 11
#define PROJMILLER 12
#define PROJSATELLITE 90
#define PROJPOLY 254
#define GENERALPROJ 255


#define PDATUM 0x1
#define PHEMISPHERE 0x2
#define PLATITUDE 0x4
#define PLONGITUDE 0x8
#define PFIRSTLAT 0x10
#define PSECDLAT 0x20

// F
#if 0
#define MAGEnqi(par, iv) penqi_(par, iv, strlen(par))
#define MAGEnqc(par, cv)                                \
    {                                                   \
        int i;                                          \
        memset(cv, '\0', sizeof(cv));                   \
        penqc_(par, cv, strlen(par), (sizeof(cv) - 1)); \
        for (i = sizeof(cv) - 1; i > 0; i--)            \
            if (cv[i] == ' ')                           \
                cv[i] = '\0';                           \
    }

#define MAGEnq1i(paramtr, iarray, size, out_size)                    \
    {                                                                \
        int vsize = size;                                            \
        penq1i_(paramtr, iarray, &vsize, out_size, strlen(paramtr)); \
    }
#endif

typedef struct
{
    short Dproj; /* projection code */
    char* Dname; /* planimetric datum name */

    Real 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;

typedef struct
{
    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	*/
} GeneralProjection;

typedef GeneralProjection PolarStereo;
typedef GeneralProjection CylindEquid;
typedef GeneralProjection NoProjection;
typedef GeneralProjection Mercartor;

typedef struct
{
    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.*/
} Satellite;

typedef struct SProjection
{
    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 */

    Real 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*/

    struct SProjection* Pout; /* projection output*/

    union
    {
        GeneralProjection* Gp; /* General Projectioon*/
        Satellite* Sat;        /* Satellite Projectioon */
        PolarStereo* Ps;
        Mercartor* Mc;
        NoProjection* Np;
        CylindEquid* Ce;
    } Proj;

} SProjection;


typedef struct
{
    char id[13]; /* image identifier */

    short satellite, /* satellite identifier xxxx */
        band,        /* spectral band */
        year,
        month,
        day,
        hour,
        minutes,
        seconds,
        nx,     /* number of columns */
        ny,     /* number of lines */
        xp,     /* column of sub-satellite point */
        yp,     /* line of sub-satellite point */
        x0,     /* image origin column */
        y0,     /* image origin line */
        path,   /*  orbit number xxxx */
        row,    /*  image number xxxx */
        plevel, /* processing level */
        vc,
        ac;

    Real lap, /*  latitude of sub-satellite point */
        lop,  /*  longitude of sub-satellite point */
        yaw,  /* orientation angle ... definir grau ou rad */
        nr,   /*  altitude or radius of satellite in meters */
        rx,   /* / horizontal resolution in meters */
        ry;   /*  vertical resolution in meters */
} ImageDoc;

typedef struct
{
    SProjection* IProj; /* pointer to projection */
    BBox* IBBox;        /* image bounding area*/
    short Inx,          /* no. of columns*/
        Iny;            /* no. of lines*/
    Real Irx,           /* horizontal resolution*/
        Iry;            /* vertical resolution*/

    /* Internal controls of the image*/

    unsigned long pixel;        /* pixel out of image*/
    unsigned long outsidevalue; /* Default value to pixels outside Image
                                 */
    unsigned char* tbuf;        /* buffer for transfer data*/

} SImage;


// Functions definitions
Real pWidth(BBox*);
Real pHeight(BBox*);
short pContains(BBox*, CPoint*);
short pIntersects(BBox*, BBox*);
void pInitBBox(BBox*, Real, Real, Real, Real);
void pBBoxRemapInOut(SProjection*, SProjection*, BBox*);
void pBBoxRemap(SProjection*, BBox*);
void pimii1_(Real, Real, Real, Real, int, int, Real, Real, int, int, unsigned char*);
void pimii2_(Real, Real, Real, Real, int, int, Real, Real, int, int, unsigned char*);
void pll2ic(Real&, Real&);
void pl2p1_(Real*, Real*);
void pl2p2_(Real*, Real*);
void pp2l1_(Real*, Real*);
void pp2l2_(Real*, Real*);
void premap_();
void pdeal_();
void pimin1_();
void pimind_(int, char*, Real, Real, Real, double, double);
void pimp1_(char*, char*, int, int, int, int, Real, Real, Real, double, double, double, double);
void pimp2_(char*, char*, int, int, int, int, Real, Real, Real, double, double, double, double);
void pimg1_(int, double, double, double, double);
void pimg2_(int, double, double, double, double);
void pims1_(double, double, double, double, double, double, double, double, double);
void pims2_(double, double, double, double, double, double, double, double, double);

short pTooBig(CPoint*);
short pPointOnLine(SImage*, CPoint*, CPoint*, CPoint*);
CPoint pMaxPoint(CPoint*, CPoint*);
CPoint pMinPoint(CPoint*, CPoint*);
void pInitPoint(CPoint*, Real, Real);
void pInitDatum(Datum*, short, char*, Real, Real, Real, double, double);
void pInitProj(SProjection*, char*, char*, int, short, short, Real, Real, Real, double, double, double, double);
short pProjEq(SProjection*, SProjection*);
void pInitGen(GeneralProjection*, short, double, double, double, double);
void pInitSat(Satellite*, double, double, double, double, double, double, double, double, double);
CPoint pLL2PC(SProjection*, CPoint);
CPoint pPC2LL(SProjection*, CPoint);
void ChangeLL(SProjection*, double*, double*);
CPoint pSatLL2PC(SProjection*, CPoint);
CPoint pSatPC2LL(SProjection*, CPoint);
CPoint pCylLL2PC(SProjection*, CPoint);
CPoint pCylPC2LL(SProjection*, CPoint);
CPoint pPolLL2PC(SProjection*, CPoint);
CPoint pPolPC2LL(SProjection*, CPoint);
CPoint pMerLL2PC(SProjection*, CPoint);
CPoint pMerPC2LL(SProjection*, CPoint);
void pInitImage(SImage*, BBox*, short, short, Real, Real, unsigned long, unsigned long, unsigned char*, SProjection*);
void pInterpolateIn(SImage*, SImage*, CPoint, CPoint, CPoint, CPoint, CPoint, CPoint, CPoint, CPoint);
unsigned char pInterAt(SImage*, CPoint*);
void pPut(SImage*, short, short, unsigned char);
unsigned char pGet(SImage*, short, short);
CPoint pCoord2Index(SImage*, CPoint*);
void pRemapI(SImage*, SImage*);
void pInitRemap(SImage*, BBox*, SProjection*, Real, Real, unsigned char**, SImage*);

// proj_braz_DEFINED
