/******************************************************************************
 *
 * Purpose: Support for storing and manipulating Orbit information
 *
 ******************************************************************************
 * Copyright (c) 2009
 * PCI Geomatics, 90 Allstate Parkway, Markham, Ontario, Canada.
 *
 * SPDX-License-Identifier: MIT
 ****************************************************************************/
#ifndef INCLUDE_PCIDSK_ORBIT_INFORMATION_H
#define INCLUDE_PCIDSK_ORBIT_INFORMATION_H

#include <string>
#include <cstring>
#include <vector>

namespace PCIDSK
{
/* -------------------------------------------------------------------- */
/*      Structure for ephemeris segment (ORBIT segment, type 160).      */
/* -------------------------------------------------------------------- */
#define EPHEMERIS_BLK           8
#define EPHEMERIS_RADAR_BLK     10
#define EPHEMERIS_ATT_BLK       9
/* -------------------------------------------------------------------- */
/*      Structure for Satellite Radar segment.                          */
/* -------------------------------------------------------------------- */
#define ANC_DATA_PER_BLK        16
#define ANC_DATA_SIZE           32
    /**
     * Ancillary data structure.
     */
    struct AncillaryData_t
    {
        /**
         * Default constructor
         */
        AncillaryData_t() :
            SlantRangeFstPixel(0),
            SlantRangeLastPixel(0),
            FstPixelLat(0.f),
            MidPixelLat(0.f),
            LstPixelLat(0.f),
            FstPixelLong(0.f),
            MidPixelLong(0.f),
            LstPixelLong(0.f)
        {
        }
        /**
         * Copy constructor
         * @param oAD the ancillary data to copy
         */
        AncillaryData_t(const AncillaryData_t& oAD)
        {
            Copy(oAD);
        }

        /**
         * assignment operator
         * @param oAD the ancillary data to assign
         */
        AncillaryData_t& operator=(const AncillaryData_t& oAD)
        {
            Copy(oAD);
            return *this;
        }

        /**
         * Copy function
         * @param oAD the ancillary data to copy
         */
        void Copy(const AncillaryData_t& oAD)
        {
            if(this == &oAD)
            {
                return;
            }
            SlantRangeFstPixel = oAD.SlantRangeFstPixel;
            SlantRangeLastPixel = oAD.SlantRangeLastPixel;
            FstPixelLat = oAD.FstPixelLat;
            MidPixelLat = oAD.MidPixelLat;
            LstPixelLat = oAD.LstPixelLat;
            FstPixelLong = oAD.FstPixelLong;
            MidPixelLong = oAD.MidPixelLong;
            LstPixelLong = oAD.LstPixelLong;
        }

        int   SlantRangeFstPixel;   /* Slant Range to First Pixel (m) */
        int   SlantRangeLastPixel;  /* Slant Range to Last Pixel (m) */
        float FstPixelLat;          /* First Pixel Latitude (millionths degrees) */
        float MidPixelLat;          /* Mid Pixel Latitude (millionths degrees)   */
        float LstPixelLat;          /* Last Pixel Latitude (millionths degrees)  */
        float FstPixelLong;         /* First Pixel Longitude (millionths degrees)*/
        float MidPixelLong;         /* Mid Pixel Longitude (millionths degrees)  */
        float LstPixelLong;         /* Last Pixel Longitude (millionths degrees) */
    } ;

    /**
     * Radar segment information
     */
    struct RadarSeg_t
    {
        /**
         * Default constructor
         */
        RadarSeg_t() :
            EquatorialRadius(0.0),
            PolarRadius(0.0),
            IncidenceAngle(0.0),
            PixelSpacing(0.0),
            LineSpacing(0.0),
            ClockAngle(0.0),
            NumberBlockData(0),
            NumberData(0)
        {
        }
        /**
         * Copy constructor
         * @param oRS the radar segment to copy
         */
        RadarSeg_t(const RadarSeg_t& oRS)
        {
            Copy(oRS);
        }

        /**
         * assignment operator
         * @param oRS the radar segment to assign
         */
        RadarSeg_t& operator=(const RadarSeg_t& oRS)
        {
            Copy(oRS);
            return *this;
        }

        /**
         * Copy function
         * @param oRS the radar segment to copy
         */
        void Copy(const RadarSeg_t& oRS)
        {
            if(this == &oRS)
            {
                return;
            }
            Identifier = oRS.Identifier;
            Facility = oRS.Facility;
            Ellipsoid = oRS.Ellipsoid;
            EquatorialRadius = oRS.EquatorialRadius;
            PolarRadius = oRS.PolarRadius;
            IncidenceAngle = oRS.IncidenceAngle;
            PixelSpacing = oRS.PixelSpacing;
            LineSpacing = oRS.LineSpacing;
            ClockAngle = oRS.ClockAngle;

            NumberBlockData = oRS.NumberBlockData;
            NumberData = oRS.NumberData;

            Line = oRS.Line;
        }

        std::string   Identifier; /* Product identifier */
        std::string   Facility; /* Processing facility */
        std::string   Ellipsoid; /* Ellipsoid designator */
        double EquatorialRadius; /* Equatorial radius of earth */
        double PolarRadius; /* Polar radius of earth */
        double IncidenceAngle; /* Incidence angle */
        double PixelSpacing; /* Nominal pixel spacing in metre */
        double LineSpacing; /* Nominal line spacing in metre */
        double ClockAngle; /* Clock angle in degree */

        int    NumberBlockData; /* Number of blocks of ancillary data */
        int  NumberData; /* Number of ancillary data */

        std::vector<AncillaryData_t> Line; /* Pointer to ancillary line */
    } ;

/* -------------------------------------------------------------------- */
/*       Structure for Satellite attitude segment.                      */
/* -------------------------------------------------------------------- */
#define ATT_SEG_BLK             604
#define ATT_SEG_MAX_LINE        6000
#define ATT_SEG_LINE_PER_BLOCK  10

    /**
     * Attitude line information
     */
    struct AttitudeLine_t
    {
        /**
         * Default constructor
         */
        AttitudeLine_t():
            ChangeInAttitude(0.0),
            ChangeEarthSatelliteDist(0.0)
        {
        }
        /**
         * Copy constructor
         * @param oAL the attitude line to copy
         */
        AttitudeLine_t(const AttitudeLine_t& oAL)
        {
            Copy(oAL);
        }

        /**
         * assignment operator
         * @param oAL the attitude line to assign
         */
        AttitudeLine_t& operator=(const AttitudeLine_t& oAL)
        {
            Copy(oAL);
            return *this;
        }

        /**
         * Copy function
         * @param oAL the attitude line to copy
         */
        void Copy(const AttitudeLine_t& oAL)
        {
            if(this == &oAL)
            {
                return;
            }
            ChangeInAttitude = oAL.ChangeInAttitude;
            ChangeEarthSatelliteDist = oAL.ChangeEarthSatelliteDist;
        }

        double ChangeInAttitude; /* Change in satellite attitude (D22.16) */
        double ChangeEarthSatelliteDist; /* Change in earth-satellite distance
                                         (D22.16) */
    } ;

    /**
     * Attitude segment information
     */
    struct AttitudeSeg_t
    {
        /**
         * Default constructor
         */
        AttitudeSeg_t() :
            Roll(0.0),
            Pitch(0.0),
            Yaw(0.0),
            NumberOfLine(0),
            NumberBlockData(0)
        {
        }
        /**
         * Copy constructor
         * @param oAS the attitude segment to copy
         */
        AttitudeSeg_t(const AttitudeSeg_t& oAS)
        {
            Copy(oAS);
        }

        /**
         * assignment operator
         * @param oAS the avhrr segment to assign
         */
        AttitudeSeg_t& operator=(const AttitudeSeg_t& oAS)
        {
            Copy(oAS);
            return *this;
        }

        /**
         * Copy function
         * @param oAS the avhrr segment to copy
         */
        void Copy(const AttitudeSeg_t& oAS)
        {
            if(this == &oAS)
            {
                return;
            }
            Roll = oAS.Roll;
            Pitch = oAS.Pitch;
            Yaw = oAS.Yaw;
            NumberOfLine = oAS.NumberOfLine;
            NumberBlockData = oAS.NumberBlockData;
            Line = oAS.Line;
        }

        double Roll; /* Roll (D22.16) */
        double Pitch; /* Pitch (D22.16) */
        double Yaw; /* Yaw (D22.16) */
        int  NumberOfLine; /* No. of Lines (I22) */

        int NumberBlockData; /* No. of block of data. */
        std::vector<AttitudeLine_t> Line;

    } ;

/* -------------------------------------------------------------------- */
/*      AVHRR orbit segment. Composed of 11 blocks plus extra blocks    */
/*      for holding per-scanline information.                           */
/* -------------------------------------------------------------------- */
#define AVH_SEG_BASE_NUM_BLK    11

    /**
     * Avhrr line information
     */
    struct AvhrrLine_t
    {
        /**
         * Default constructor
         */
        AvhrrLine_t()
        {
            nScanLineNum = 0;
            nStartScanTimeGMTMsec = 0;
            std::memset(abyScanLineQuality, 0, sizeof(abyScanLineQuality));
            std::memset(aabyBadBandIndicators, 0, sizeof(aabyBadBandIndicators));
            std::memset(abySatelliteTimeCode, 0, sizeof(abySatelliteTimeCode));
            std::memset(anTargetTempData, 0, sizeof(anTargetTempData));
            std::memset(anTargetScanData, 0, sizeof(anTargetScanData));
            std::memset(anSpaceScanData, 0, sizeof(anSpaceScanData));
        }
        /**
         * Copy constructor
         * @param oAL the avhrr line to copy
         */
        AvhrrLine_t(const AvhrrLine_t& oAL)
        {
            Copy(oAL);
        }

        /**
         * assignment operator
         * @param oAL the avhrr line to assign
         */
        AvhrrLine_t& operator=(const AvhrrLine_t& oAL)
        {
            Copy(oAL);
            return *this;
        }

        /**
         * Copy function
         * @param oAL the avhrr line to copy
         */
        void Copy(const AvhrrLine_t& oAL)
        {
            if(this == &oAL)
            {
                return;
            }
            nScanLineNum = oAL.nScanLineNum;
            nStartScanTimeGMTMsec = oAL.nStartScanTimeGMTMsec;
            for(int i=0 ; i < 10 ; i++)
                abyScanLineQuality[i] = oAL.abyScanLineQuality[i];
            for(int i=0 ; i < 5 ; i++)
            {
                aabyBadBandIndicators[i][0] = oAL.aabyBadBandIndicators[i][0];
                aabyBadBandIndicators[i][1] = oAL.aabyBadBandIndicators[i][1];
                anSpaceScanData[i] = oAL.anSpaceScanData[i];
            }
            for(int i=0 ; i < 8 ; i++)
                abySatelliteTimeCode[i] = oAL.abySatelliteTimeCode[i];
            for(int i=0 ; i < 3 ; i++)
            {
                anTargetTempData[i] = oAL.anTargetTempData[i];
                anTargetScanData[i] = oAL.anTargetScanData[i];
            }
        }

        /* For geocoding */
        int   nScanLineNum;
        int   nStartScanTimeGMTMsec;
        unsigned char abyScanLineQuality[10];
        unsigned char aabyBadBandIndicators[5][2];
        unsigned char abySatelliteTimeCode[8];

        /* For thermal/IR calibration */
        int   anTargetTempData[3];
        int   anTargetScanData[3];
        int   anSpaceScanData[5];

    } ;

    /**
     * Avhrr segment information.
     */
    struct AvhrrSeg_t
    {
        /**
         * Default constructor
         */
        AvhrrSeg_t() :
            nImageXSize(0),
            nImageYSize(0),
            bIsAscending(false),
            bIsImageRotated(false),
            nRecordSize(0),
            nBlockSize(0),
            nNumRecordsPerBlock(0),
            nNumBlocks(0),
            nNumScanlineRecords(0)
        {
        }
        /**
         * Copy constructor
         * @param oAS the avhrr segment to copy
         */
        AvhrrSeg_t(const AvhrrSeg_t& oAS)
        {
            Copy(oAS);
        }

        /**
         * assignment operator
         * @param oAS the avhrr segment to assign
         */
        AvhrrSeg_t& operator=(const AvhrrSeg_t& oAS)
        {
            Copy(oAS);
            return *this;
        }

        /**
         * Copy function
         * @param oAS the avhrr segment to copy
         */
        void Copy(const AvhrrSeg_t& oAS)
        {
            if(this == &oAS)
            {
                return;
            }
            szImageFormat = oAS.szImageFormat;
            nImageXSize = oAS.nImageXSize;
            nImageYSize = oAS.nImageYSize;
            bIsAscending = oAS.bIsAscending;
            bIsImageRotated = oAS.bIsImageRotated;
            szOrbitNumber = oAS.szOrbitNumber;
            szAscendDescendNodeFlag = oAS.szAscendDescendNodeFlag;
            szEpochYearAndDay = oAS.szEpochYearAndDay;
            szEpochTimeWithinDay = oAS.szEpochTimeWithinDay;
            szTimeDiffStationSatelliteMsec = oAS.szTimeDiffStationSatelliteMsec;
            szActualSensorScanRate = oAS.szActualSensorScanRate;
            szIdentOfOrbitInfoSource = oAS.szIdentOfOrbitInfoSource;
            szInternationalDesignator = oAS.szInternationalDesignator;
            szOrbitNumAtEpoch = oAS.szOrbitNumAtEpoch;
            szJulianDayAscendNode = oAS.szJulianDayAscendNode;
            szEpochYear = oAS.szEpochYear;
            szEpochMonth = oAS.szEpochMonth;
            szEpochDay = oAS.szEpochDay;
            szEpochHour = oAS.szEpochHour;
            szEpochMinute = oAS.szEpochMinute;
            szEpochSecond = oAS.szEpochSecond;
            szPointOfAriesDegrees = oAS.szPointOfAriesDegrees;
            szAnomalisticPeriod = oAS.szAnomalisticPeriod;
            szNodalPeriod = oAS.szNodalPeriod;
            szEccentricity = oAS.szEccentricity;
            szArgumentOfPerigee = oAS.szArgumentOfPerigee;
            szRAAN = oAS.szRAAN;
            szInclination = oAS.szInclination;
            szMeanAnomaly = oAS.szMeanAnomaly;
            szSemiMajorAxis = oAS.szSemiMajorAxis;
            nRecordSize = oAS.nRecordSize;
            nBlockSize = oAS.nBlockSize;
            nNumRecordsPerBlock = oAS.nNumRecordsPerBlock;
            nNumBlocks = oAS.nNumBlocks;
            nNumScanlineRecords = oAS.nNumScanlineRecords;
            Line = oAS.Line;
        }

        /* Ninth Block Part 1 - General/header information */
        std::string  szImageFormat;
        int   nImageXSize;
        int   nImageYSize;
        bool bIsAscending;
        bool bIsImageRotated;

        /* Ninth Block Part 2 - Ephemeris information */
        std::string  szOrbitNumber;
        std::string  szAscendDescendNodeFlag;
        std::string  szEpochYearAndDay;
        std::string  szEpochTimeWithinDay;
        std::string  szTimeDiffStationSatelliteMsec;
        std::string  szActualSensorScanRate;
        std::string  szIdentOfOrbitInfoSource;
        std::string  szInternationalDesignator;
        std::string  szOrbitNumAtEpoch;
        std::string  szJulianDayAscendNode;
        std::string  szEpochYear;
        std::string  szEpochMonth;
        std::string  szEpochDay;
        std::string  szEpochHour;
        std::string  szEpochMinute;
        std::string  szEpochSecond;
        std::string  szPointOfAriesDegrees;
        std::string  szAnomalisticPeriod;
        std::string  szNodalPeriod;
        std::string  szEccentricity;
        std::string  szArgumentOfPerigee;
        std::string  szRAAN;
        std::string  szInclination;
        std::string  szMeanAnomaly;
        std::string  szSemiMajorAxis;

        /* 10th Block - Empty, reserved for future use */

        /* 11th Block - Needed for indexing 12th block onwards */
        int   nRecordSize;
        int   nBlockSize;
        int   nNumRecordsPerBlock;
        int   nNumBlocks;
        int   nNumScanlineRecords;

        /* 12th Block and onwards - Per-scanline records */
        std::vector<AvhrrLine_t> Line;

    } ;

    /**
     * Possible orbit types.
     */
    typedef enum
    {
        OrbNone,
        OrbAttitude,
        OrbLatLong,
        OrbAvhrr
    } OrbitType;

    /**
     * Ephemeris segment structure
     */
    struct EphemerisSeg_t
    {
        /**
         * Default constructor
         */
        EphemerisSeg_t()
        {
            SupSegExist = false;
            FieldOfView = 0.0;
            ViewAngle = 0.0;
            NumColCentre = 0.0;
            RadialSpeed = 0.0;
            Eccentricity = 0.0;
            Height = 0.0;
            Inclination = 0.0;
            TimeInterval = 0.0;
            NumLineCentre = 0.0;
            LongCentre = 0.0;
            AngularSpd = 0.0;
            AscNodeLong = 0.0;
            ArgPerigee = 0.0;
            LatCentre = 0.0;
            EarthSatelliteDist = 0.0;
            NominalPitch = 0.0;
            TimeAtCentre = 0.0;
            SatelliteArg = 0.0;
            XCentre = 0.0;
            YCentre = 0.0;
            UtmYCentre = 0.0;
            UtmXCentre = 0.0;
            PixelRes = 0.0;
            LineRes = 0.0;
            CornerAvail = false;
            XUL = 0.0;
            YUL = 0.0;
            XUR = 0.0;
            YUR = 0.0;
            XLR = 0.0;
            YLR = 0.0;
            XLL = 0.0;
            YLL = 0.0;
            UtmYUL = 0.0;
            UtmXUL = 0.0;
            UtmYUR = 0.0;
            UtmXUR = 0.0;
            UtmYLR = 0.0;
            UtmXLR = 0.0;
            UtmYLL = 0.0;
            UtmXLL = 0.0;
            LatCentreDeg = 0.0;
            LongCentreDeg = 0.0;
            LatUL = 0.0;
            LongUL = 0.0;
            LatUR = 0.0;
            LongUR = 0.0;
            LatLR = 0.0;
            LongLR = 0.0;
            LatLL = 0.0;
            LongLL = 0.0;
            HtCentre = 0.0;
            HtUL = 0.0;
            HtUR = 0.0;
            HtLR = 0.0;
            HtLL = 0.0;
            std::memset(SPCoeff1B, 0, sizeof(SPCoeff1B));
            std::memset(SPCoeffSg, 0, sizeof(SPCoeffSg));
            ImageRecordLength = 0;
            NumberImageLine = 0;
            NumberBytePerPixel = 0;
            NumberSamplePerLine = 0;
            NumberPrefixBytes = 0;
            NumberSuffixBytes = 0;
            SPNCoeff = 0;
            bDescending = false;
            Type = OrbNone;
            AttitudeSeg = nullptr;
            RadarSeg = nullptr;
            AvhrrSeg = nullptr;
        }

        /**
         * Destructor
         */
        ~EphemerisSeg_t()
        {
            delete AttitudeSeg;
            delete RadarSeg;
            delete AvhrrSeg;
        }

        /**
         * Copy constructor
         * @param oES the ephemeris segment to copy
         */
        EphemerisSeg_t(const EphemerisSeg_t& oES): EphemerisSeg_t()
        {
            Copy(oES);
        }

        /**
         * assignment operator
         * @param oES the ephemeris segment to assign
         */
        EphemerisSeg_t& operator=(const EphemerisSeg_t& oES)
        {
            Copy(oES);
            return *this;
        }

        /**
         * Copy function
         * @param oES the ephemeris segment to copy
         */
        void Copy(const EphemerisSeg_t& oES)
        {
            if(this == &oES)
            {
                return;
            }
            delete AttitudeSeg;
            delete RadarSeg;
            delete AvhrrSeg;
            AttitudeSeg = nullptr;
            RadarSeg = nullptr;
            AvhrrSeg = nullptr;
            if(oES.AttitudeSeg)
                AttitudeSeg = new AttitudeSeg_t(*oES.AttitudeSeg);
            if(oES.RadarSeg)
                RadarSeg = new RadarSeg_t(*oES.RadarSeg);
            if(oES.AvhrrSeg)
                AvhrrSeg = new AvhrrSeg_t(*oES.AvhrrSeg);

            for(int i =0 ; i <39 ; i++)
                SPCoeff1B[i] = oES.SPCoeff1B[i];
            for(int i =0 ; i <4 ; i++)
                SPCoeffSg[i] = oES.SPCoeffSg[i];

            SatelliteDesc = oES.SatelliteDesc;
            SceneID = oES.SceneID;
            SatelliteSensor = oES.SatelliteSensor;
            SensorNo = oES.SensorNo;
            DateImageTaken = oES.DateImageTaken;
            SupSegExist = oES.SupSegExist;
            FieldOfView = oES.FieldOfView;
            ViewAngle = oES.ViewAngle;
            NumColCentre = oES.NumColCentre;
            RadialSpeed = oES.RadialSpeed;
            Eccentricity = oES.Eccentricity;
            Height = oES.Height;
            Inclination = oES.Inclination;
            TimeInterval = oES.TimeInterval;
            NumLineCentre = oES.NumLineCentre;
            LongCentre = oES.LongCentre;
            AngularSpd = oES.AngularSpd;
            AscNodeLong = oES.AscNodeLong;
            ArgPerigee = oES.ArgPerigee;
            LatCentre = oES.LatCentre;
            EarthSatelliteDist = oES.EarthSatelliteDist;
            NominalPitch = oES.NominalPitch;
            TimeAtCentre = oES.TimeAtCentre;
            SatelliteArg = oES.SatelliteArg;
            XCentre = oES.XCentre;
            YCentre = oES.YCentre;
            UtmYCentre = oES.UtmYCentre;
            UtmXCentre = oES.UtmXCentre;
            PixelRes = oES.PixelRes;
            LineRes = oES.LineRes;
            CornerAvail = oES.CornerAvail;
            MapUnit = oES.MapUnit;
            XUL = oES.XUL;
            YUL = oES.YUL;
            XUR = oES.XUR;
            YUR = oES.YUR;
            XLR = oES.XLR;
            YLR = oES.YLR;
            XLL = oES.XLL;
            YLL = oES.YLL;
            UtmYUL = oES.UtmYUL;
            UtmXUL = oES.UtmXUL;
            UtmYUR = oES.UtmYUR;
            UtmXUR = oES.UtmXUR;
            UtmYLR = oES.UtmYLR;
            UtmXLR = oES.UtmXLR;
            UtmYLL = oES.UtmYLL;
            UtmXLL = oES.UtmXLL;
            LatCentreDeg = oES.LatCentreDeg;
            LongCentreDeg = oES.LongCentreDeg;
            LatUL = oES.LatUL;
            LongUL = oES.LongUL;
            LatUR = oES.LatUR;
            LongUR = oES.LongUR;
            LatLR = oES.LatLR;
            LongLR = oES.LongLR;
            LatLL = oES.LatLL;
            LongLL = oES.LongLL;
            HtCentre = oES.HtCentre;
            HtUL = oES.HtUL;
            HtUR = oES.HtUR;
            HtLR = oES.HtLR;
            HtLL = oES.HtLL;
            ImageRecordLength = oES.ImageRecordLength;
            NumberImageLine = oES.NumberImageLine;
            NumberBytePerPixel = oES.NumberBytePerPixel;
            NumberSamplePerLine = oES.NumberSamplePerLine;
            NumberPrefixBytes = oES.NumberPrefixBytes;
            NumberSuffixBytes = oES.NumberSuffixBytes;
            SPNCoeff = oES.SPNCoeff;
            bDescending = oES.bDescending;
            Type = oES.Type;
        }

        /// Satellite description
        std::string SatelliteDesc;
        /// Scene ID
        std::string SceneID;

        /// Satellite sensor
        std::string SatelliteSensor;
        /// Satellite sensor no.
        std::string SensorNo;
        /// Date of image taken
        std::string DateImageTaken;
        /// Flag to indicate supplemental segment
        bool SupSegExist;
        /// Scanner field of view (ALPHA)
        double FieldOfView;
        /// Viewing angle (BETA)
        double ViewAngle;
        /// Number of column at center (C0)
        double NumColCentre;
        /// Radial speed (DELIRO)
        double RadialSpeed;
        /// Eccentricity (ES)
        double Eccentricity;
        /// Height (H0)
        double Height;
        /// Inclination (I)
        double Inclination;
        /// Time interval (K)
        double TimeInterval;
        /// Number of line at center (L0)
        double NumLineCentre;
        /// Longitude of center (LAMBDA)
        double LongCentre;
        /// Angular speed (N)
        double AngularSpd;
        /// Ascending node Longitude (OMEGA-MAJ)
        double AscNodeLong;
        /// Argument Perigee (OMEGA-MIN)
        double ArgPerigee;
        /// Latitude of center (PHI)
        double LatCentre;
        /// Earth Satellite distance (RHO)
        double EarthSatelliteDist;
        /// Nominal pitch (T)
        double NominalPitch;
        /// Time at centre (T0)
        double TimeAtCentre;
        /// Satellite argument (WP)
        double SatelliteArg;

        /// Scene center pixel coordinate
        double XCentre;
        /// Scene center line coordinate
        double YCentre;
        /// Scene centre UTM northing
        double UtmYCentre;
        /// Scene centre UTM easting
        double UtmXCentre;
        /// Pixel resolution in x direction
        double PixelRes;
        /// Pixel resolution in y direction
        double LineRes;
        /// Flag to tell corner coordinate available
        bool CornerAvail;
        /// Map units
        std::string MapUnit;
        /// Pixel coordinate of upper left corner
        double XUL;
        /// Line coordinate of upper left corner
        double YUL;
        /// Pixel coordinate of upper right corner
        double XUR;
        /// Line coordinate of upper right corner
        double YUR;
        /// Pixel coordinate of lower right corner
        double XLR;
        /// Line coordinate of lower right corner
        double YLR;
        /// Pixel coordinate of lower left corner
        double XLL;
        /// Line coordinate of lower left corner
        double YLL;
        /// UTM Northing of upper left corner
        double UtmYUL;
        /// UTM Easting of upper left corner
        double UtmXUL;
        /// UTM Northing of upper right corner
        double UtmYUR;
        /// UTM Easting of upper right corner
        double UtmXUR;
        /// UTM Northing of lower right corner
        double UtmYLR;
        /// UTM Easting of lower right corner
        double UtmXLR;
        /// Utm Northing of lower left corner
        double UtmYLL;
        /// Utm Easting of lower left corner
        double UtmXLL;

        /// Scene centre latitude (deg)
        double LatCentreDeg;
        /// Scene centre longitude (deg)
        double LongCentreDeg;
        /// Upper left latitude (deg)
        double LatUL;
        /// Upper left longitude (deg)
        double LongUL;
        /// Upper right latitude (deg)
        double LatUR;
        /// Upper right longitude (deg)
        double LongUR;
        /// Lower right latitude (deg)
        double LatLR;
        /// Lower right longitude (deg)
        double LongLR;
        /// Lower left latitude (deg)
        double LatLL;
        /// Lower left longitude (deg)
        double LongLL;
        /// Centre Height (m)
        double HtCentre;
        /// UL Height (m)
        double HtUL;
        /// UR Height (m)
        double HtUR;
        /// LR Height (m)
        double HtLR;
        /// LL Height (m)
        double HtLL;

        /// SPOT 1B coefficients
        double SPCoeff1B[39];
        /// SPOT 1B segment coefficients
        int    SPCoeffSg[4];

        /// Image record length
        int    ImageRecordLength;
        /// Number of image line
        int    NumberImageLine;
        /// Number of bytes per pixel
        int    NumberBytePerPixel;
        /// Number of samples per line
        int    NumberSamplePerLine;
        /// Number of prefix bytes
        int    NumberPrefixBytes;
        /// Number of suffix bytes
        int    NumberSuffixBytes;
        /// Number of coefficients for SPOT 1B
        int    SPNCoeff;

        /// Flag to indicate ascending or descending
        bool  bDescending;

        /// Orbit type: None, LatLong, Attitude, Avhrr
        OrbitType   Type;
        AttitudeSeg_t *AttitudeSeg;
        RadarSeg_t    *RadarSeg;
        AvhrrSeg_t    *AvhrrSeg;
    };

    /**
     * List of sensor type
     */
    typedef enum {PLA_1, MLA_1, PLA_2, MLA_2, PLA_3, MLA_3, PLA_4, MLA_4,
                  ASTER, SAR, LISS_1, LISS_2, LISS_3, LISS_L3, LISS_L3_L2,
                  LISS_L4, LISS_L4_L2, LISS_P3, LISS_P3_L2, LISS_W3, LISS_W3_L2,
                  LISS_AWF, LISS_AWF_L2, LISS_M3, EOC, IRS_1, RSAT_FIN,
                  RSAT_STD, ERS_1, ERS_2, TM, ETM, IKO_PAN, IKO_MULTI,
                  ORBVIEW_PAN, ORBVIEW_MULTI, OV3_PAN_BASIC, OV3_PAN_GEO,
                  OV3_MULTI_BASIC, OV3_MULTI_GEO, OV5_PAN_BASIC, OV5_PAN_GEO,
                  OV5_MULTI_BASIC, OV5_MULTI_GEO, QBIRD_PAN, QBIRD_PAN_STD,
                  QBIRD_PAN_STH, QBIRD_MULTI, QBIRD_MULTI_STD, QBIRD_MULTI_STH,
                  FORMOSAT_PAN, FORMOSAT_MULTI, FORMOSAT_PAN_L2,
                  FORMOSAT_MULTIL2, SPOT5_PAN_2_5, SPOT5_PAN_5, SPOT5_HRS,
                  SPOT5_MULTI, MERIS_FR, MERIS_RR, MERIS_LR, ASAR, EROS,
                  MODIS_250, MODIS_500, MODIS_1000, CBERS_HRC, CBERS_HRC_L2,
                  CBERS_CCD, CBERS_CCD_L2, CBERS_IRM_80, CBERS_IRM_80_L2,
                  CBERS_IRM_160, CBERS_IRM_160_L2, CBERS_WFI, CBERS_WFI_L2,
                  CARTOSAT1_L1, CARTOSAT1_L2, ALOS_PRISM_L1, ALOS_PRISM_L2,
                  ALOS_AVNIR_L1, ALOS_AVNIR_L2, PALSAR, DMC_1R, DMC_1T,
                  KOMPSAT2_PAN, KOMPSAT2_MULTI, KOMPSAT3_PAN, KOMPSAT3_MS, KOMPSAT3_PSH,
                  KOMPSAT3A_PAN, KOMPSAT3A_MS, KOMPSAT3A_PSH,
                  TERRASAR, WVIEW_PAN, WVIEW_PAN_STD, WVIEW_MULTI,
                  WVIEW_MULTI_STD, RAPIDEYE_L1B, THEOS_PAN_L1, THEOS_PAN_L2,
                  THEOS_MS_L1, THEOS_MS_L2,
                  GOSAT_500_L1, GOSAT_500_L2, GOSAT_1500_L1, GOSAT_1500_L2,
                  HJ_CCD_1A, HJ_CCD_1B, PLEIADES_PAN_L1, PLEIADES_MS_L1,
                  PLEIADES_PAN_L2, PLEIADES_MS_L2, SSOT_PAN_L1, SSOT_MS_L1,
                  SSOT_PAN_L2, SSOT_MS_L2,
                  SPOT1_PAN, SPOT1_MS, SPOT2_PAN, SPOT2_MS,
                  SPOT3_PAN, SPOT3_MS, SPOT4_PAN, SPOT4_MS,
                  SPOT6_PAN, SPOT6_MS, SPOT6_PSH, SPOT7_PAN, SPOT7_MS, SPOT7_PSH,
                  RASAT_PAN, RASAT_MS, TH01_DGP, TH01_GFB, TH01_SXZ,
                  ZY1_02C_HRC, ZY1_02C_PMS_PAN, ZY1_02C_PMS_MS,
                  ZY3_NAD, ZY3_FWD, ZY3_BWD, ZY3_MUX, ZY3_TLC, GK2_PAN, GK2_MS, HRC,
                  MRC_RED, MRC_GRN, MRC_BLU, MRC_NIR, GF1_PMS_PAN, GF1_PMS_MS, GF1_WFV,
                  GF2_PMS_PAN, GF2_PMS_MS, GF4_PMS_MS, GF4_PMI_Thermal,
                  GF6_PMS_PAN, GF6_PMS_MS, SJ9_PAN, SJ9_MUX, SJ9_PMS_PAN, SJ9_PMS_MS,
                  YG2_1, YG8_1, YG14_1, UAVSAR, HI_RES, MED_RES, ALSAT2_PAN_1A, ALSAT2_MS_1A,
                  ALSAT2_PAN_2A, ALSAT2_MS_2A, DUBAISAT2_PAN, DUBAISAT2_MS,
                  KAZEOSAT1_PAN_1A, KAZEOSAT1_MS_1A, KAZEOSAT1_PAN_2A, KAZEOSAT1_MS_2A, KAZEOSAT2_MS_1G,
                  DEIMOS1_MS_1R, DEIMOS2_PAN_1B, DEIMOS2_MS_1B, DEIMOS2_PSH_1B, HJ1C,
                  TRIPLESAT_PAN, TRIPLESAT_MS, RESOURCESAT, JL101A_PAN, JL101A_MS,
                  CBERS4_PAN_1, CBERS4_MS_1, CBERS4_PAN_2, CBERS4_MS_2,
                  CBERS4_THM_1, CBERS4_THM_2, SV1_PAN_L1, SV1_MS_L1, SV1_PAN_L2, SV1_MS_L2,
                  PER_PAN_2A, PER_MS_2A, FORMOSAT5_PAN, FORMOSAT5_MS,
                  GEOEYE_PAN, GEOEYE_MULTI, GEOEYE_PAN_STD, GEOEYE_MULTI_STD,
                  GOKTURK1_PAN, GOKTURK1_MS,
                  NEW, AVHRR, MSS} TypeDeCapteur;
}

#endif // INCLUDE_PCIDSK_ORBIT_INFORMATION_H
