/// <summary>
        /// Calculate the three dimensional geodetic measurement between two positions
        /// measured in reference to a specified ellipsoid.
        /// 
        /// This calculation is performed by first computing a new ellipsoid by expanding or contracting
        /// the reference ellipsoid such that the new ellipsoid passes through the average elevation
        /// of the two positions.  A geodetic curve across the new ellisoid is calculated.  The
        /// point-to-point distance is calculated as the hypotenuse of a right triangle where the length
        /// of one side is the ellipsoidal distance and the other is the difference in elevation.
        /// </summary>
        /// <param name="refEllipsoid">reference ellipsoid to use</param>
        /// <param name="start">starting position</param>
        /// <param name="end">ending position</param>
        /// <returns></returns>
        public GeodeticMeasurement CalculateGeodeticMeasurement(Ellipsoid refEllipsoid, GlobalPosition start, GlobalPosition end)
        {
            // get the coordinates
            GlobalCoordinates startCoords = start.Coordinates;
            GlobalCoordinates endCoords = end.Coordinates;

            // calculate elevation differences
            double elev1 = start.Elevation;
            double elev2 = end.Elevation;
            double elev12 = (elev1 + elev2) / 2.0;

            // calculate latitude differences
            double phi1 = startCoords.Latitude.Radians;
            double phi2 = endCoords.Latitude.Radians;
            double phi12 = (phi1 + phi2) / 2.0;

            // calculate a new ellipsoid to accommodate average elevation
            double refA = refEllipsoid.SemiMajorAxis;
            double f = refEllipsoid.Flattening;
            double a = refA + elev12 * (1.0 + f * Math.Sin(phi12));
            Ellipsoid ellipsoid = Ellipsoid.FromAAndF(a, f);

            // calculate the curve at the average elevation
            GeodeticCurve averageCurve = CalculateGeodeticCurve(ellipsoid, startCoords, endCoords);

            // return the measurement
            return new GeodeticMeasurement(averageCurve, elev2 - elev1);
        }
        /// <summary>
        /// Calculate the destination and final bearing after traveling a specified
        /// distance, and a specified starting bearing, for an initial location.
        /// This is the solution to the direct geodetic problem.
        /// </summary>
        /// <param name="ellipsoid">reference ellipsoid to use</param>
        /// <param name="start">starting location</param>
        /// <param name="startBearing">starting bearing (degrees)</param>
        /// <param name="distance">distance to travel (meters)</param>
        /// <param name="endBearing">bearing at destination (degrees)</param>
        /// <returns></returns>
        public GlobalCoordinates CalculateEndingGlobalCoordinates(Ellipsoid ellipsoid, GlobalCoordinates start, Angle startBearing, double distance, out Angle endBearing)
        {
            double a = ellipsoid.SemiMajorAxis;
            double b = ellipsoid.SemiMinorAxis;
            double aSquared = a * a;
            double bSquared = b * b;
            double f = ellipsoid.Flattening;
            double phi1 = start.Latitude.Radians;
            double alpha1 = startBearing.Radians;
            double cosAlpha1 = Math.Cos(alpha1);
            double sinAlpha1 = Math.Sin(alpha1);
            double s = distance;
            double tanU1 = (1.0 - f) * Math.Tan(phi1);
            double cosU1 = 1.0 / Math.Sqrt(1.0 + tanU1 * tanU1);
            double sinU1 = tanU1 * cosU1;

            // eq. 1
            double sigma1 = Math.Atan2(tanU1, cosAlpha1);

            // eq. 2
            double sinAlpha = cosU1 * sinAlpha1;

            double sin2Alpha = sinAlpha * sinAlpha;
            double cos2Alpha = 1 - sin2Alpha;
            double uSquared = cos2Alpha * (aSquared - bSquared) / bSquared;

            // eq. 3
            double A = 1 + (uSquared / 16384) * (4096 + uSquared * (-768 + uSquared * (320 - 175 * uSquared)));

            // eq. 4
            double B = (uSquared / 1024) * (256 + uSquared * (-128 + uSquared * (74 - 47 * uSquared)));

            // iterate until there is a negligible change in sigma
            double deltaSigma;
            double sOverbA = s / (b * A);
            double sigma = sOverbA;
            double sinSigma;
            double prevSigma = sOverbA;
            double sigmaM2;
            double cosSigmaM2;
            double cos2SigmaM2;

            for (; ; )
            {
                // eq. 5
                sigmaM2 = 2.0 * sigma1 + sigma;
                cosSigmaM2 = Math.Cos(sigmaM2);
                cos2SigmaM2 = cosSigmaM2 * cosSigmaM2;
                sinSigma = Math.Sin(sigma);
                double cosSignma = Math.Cos(sigma);

                // eq. 6
                deltaSigma = B * sinSigma * (cosSigmaM2 + (B / 4.0) * (cosSignma * (-1 + 2 * cos2SigmaM2)
                    - (B / 6.0) * cosSigmaM2 * (-3 + 4 * sinSigma * sinSigma) * (-3 + 4 * cos2SigmaM2)));

                // eq. 7
                sigma = sOverbA + deltaSigma;

                // break after converging to tolerance
                if (Math.Abs(sigma - prevSigma) < 0.0000000000001) break;

                prevSigma = sigma;
            }

            sigmaM2 = 2.0 * sigma1 + sigma;
            cosSigmaM2 = Math.Cos(sigmaM2);
            cos2SigmaM2 = cosSigmaM2 * cosSigmaM2;

            double cosSigma = Math.Cos(sigma);
            sinSigma = Math.Sin(sigma);

            // eq. 8
            double phi2 = Math.Atan2(sinU1 * cosSigma + cosU1 * sinSigma * cosAlpha1,
                                     (1.0 - f) * Math.Sqrt(sin2Alpha + Math.Pow(sinU1 * sinSigma - cosU1 * cosSigma * cosAlpha1, 2.0)));

            // eq. 9
            // This fixes the pole crossing defect spotted by Matt Feemster.  When a path
            // passes a pole and essentially crosses a line of latitude twice - once in
            // each direction - the longitude calculation got messed up.  Using Atan2
            // instead of Atan fixes the defect.  The change is in the next 3 lines.
            //double tanLambda = sinSigma * sinAlpha1 / (cosU1 * cosSigma - sinU1*sinSigma*cosAlpha1);
            //double lambda = Math.Atan(tanLambda);
            double lambda = Math.Atan2(sinSigma * sinAlpha1, cosU1 * cosSigma - sinU1 * sinSigma * cosAlpha1);

            // eq. 10
            double C = (f / 16) * cos2Alpha * (4 + f * (4 - 3 * cos2Alpha));

            // eq. 11
            double L = lambda - (1 - C) * f * sinAlpha * (sigma + C * sinSigma * (cosSigmaM2 + C * cosSigma * (-1 + 2 * cos2SigmaM2)));

            // eq. 12
            double alpha2 = Math.Atan2(sinAlpha, -sinU1 * sinSigma + cosU1 * cosSigma * cosAlpha1);

            // build result
            Angle latitude = new Angle();
            Angle longitude = new Angle();

            latitude.Radians = phi2;
            longitude.Radians = start.Longitude.Radians + L;

            endBearing = new Angle();
            endBearing.Radians = alpha2;

            return new GlobalCoordinates(latitude, longitude);
        }
        /// <summary>
        /// Calculate the destination after traveling a specified distance, and a
        /// specified starting bearing, for an initial location. This is the
        /// solution to the direct geodetic problem.
        /// </summary>
        /// <param name="ellipsoid">reference ellipsoid to use</param>
        /// <param name="start">starting location</param>
        /// <param name="startBearing">starting bearing (degrees)</param>
        /// <param name="distance">distance to travel (meters)</param>
        /// <returns></returns>
        public GlobalCoordinates CalculateEndingGlobalCoordinates(Ellipsoid ellipsoid, GlobalCoordinates start, Angle startBearing, double distance)
        {
            Angle endBearing = new Angle();

            return CalculateEndingGlobalCoordinates(ellipsoid, start, startBearing, distance, out endBearing);
        }
        /// <summary>
        /// Calculate the geodetic curve between two points on a specified reference ellipsoid.
        /// This is the solution to the inverse geodetic problem.
        /// </summary>
        /// <param name="ellipsoid">reference ellipsoid to use</param>
        /// <param name="start">starting coordinates</param>
        /// <param name="end">ending coordinates </param>
        /// <returns></returns>
        public GeodeticCurve CalculateGeodeticCurve(Ellipsoid ellipsoid, GlobalCoordinates start, GlobalCoordinates end)
        {
            //
            // All equation numbers refer back to Vincenty's publication:
            // See http://www.ngs.noaa.gov/PUBS_LIB/inverse.pdf
            //

            // get constants
            double a = ellipsoid.SemiMajorAxis;
            double b = ellipsoid.SemiMinorAxis;
            double f = ellipsoid.Flattening;

            // get parameters as radians
            double phi1 = start.Latitude.Radians;
            double lambda1 = start.Longitude.Radians;
            double phi2 = end.Latitude.Radians;
            double lambda2 = end.Longitude.Radians;

            // calculations
            double a2 = a * a;
            double b2 = b * b;
            double a2b2b2 = (a2 - b2) / b2;

            double omega = lambda2 - lambda1;

            double tanphi1 = Math.Tan(phi1);
            double tanU1 = (1.0 - f) * tanphi1;
            double U1 = Math.Atan(tanU1);
            double sinU1 = Math.Sin(U1);
            double cosU1 = Math.Cos(U1);

            double tanphi2 = Math.Tan(phi2);
            double tanU2 = (1.0 - f) * tanphi2;
            double U2 = Math.Atan(tanU2);
            double sinU2 = Math.Sin(U2);
            double cosU2 = Math.Cos(U2);

            double sinU1sinU2 = sinU1 * sinU2;
            double cosU1sinU2 = cosU1 * sinU2;
            double sinU1cosU2 = sinU1 * cosU2;
            double cosU1cosU2 = cosU1 * cosU2;

            // eq. 13
            double lambda = omega;

            // intermediates we'll need to compute 's'
            double A = 0.0;
            double B = 0.0;
            double sigma = 0.0;
            double deltasigma = 0.0;
            double lambda0;
            bool converged = false;

            for (int i = 0; i < 20; i++)
            {
                lambda0 = lambda;

                double sinlambda = Math.Sin(lambda);
                double coslambda = Math.Cos(lambda);

                // eq. 14
                double sin2sigma = (cosU2 * sinlambda * cosU2 * sinlambda) + Math.Pow(cosU1sinU2 - sinU1cosU2 * coslambda, 2.0);
                double sinsigma = Math.Sqrt(sin2sigma);

                // eq. 15
                double cossigma = sinU1sinU2 + (cosU1cosU2 * coslambda);

                // eq. 16
                sigma = Math.Atan2(sinsigma, cossigma);

                // eq. 17    Careful!  sin2sigma might be almost 0!
                double sinalpha = (sin2sigma == 0) ? 0.0 : cosU1cosU2 * sinlambda / sinsigma;
                double alpha = Math.Asin(sinalpha);
                double cosalpha = Math.Cos(alpha);
                double cos2alpha = cosalpha * cosalpha;

                // eq. 18    Careful!  cos2alpha might be almost 0!
                double cos2sigmam = cos2alpha == 0.0 ? 0.0 : cossigma - 2 * sinU1sinU2 / cos2alpha;
                double u2 = cos2alpha * a2b2b2;

                double cos2sigmam2 = cos2sigmam * cos2sigmam;

                // eq. 3
                A = 1.0 + u2 / 16384 * (4096 + u2 * (-768 + u2 * (320 - 175 * u2)));

                // eq. 4
                B = u2 / 1024 * (256 + u2 * (-128 + u2 * (74 - 47 * u2)));

                // eq. 6
                deltasigma = B * sinsigma * (cos2sigmam + B / 4 * (cossigma * (-1 + 2 * cos2sigmam2) - B / 6 * cos2sigmam * (-3 + 4 * sin2sigma) * (-3 + 4 * cos2sigmam2)));

                // eq. 10
                double C = f / 16 * cos2alpha * (4 + f * (4 - 3 * cos2alpha));

                // eq. 11 (modified)
                lambda = omega + (1 - C) * f * sinalpha * (sigma + C * sinsigma * (cos2sigmam + C * cossigma * (-1 + 2 * cos2sigmam2)));

                // see how much improvement we got
                double change = Math.Abs((lambda - lambda0) / lambda);

                if ((i > 1) && (change < 0.0000000000001))
                {
                    converged = true;
                    break;
                }
            }

            // eq. 19
            double s = b * A * (sigma - deltasigma);
            Angle alpha1;
            Angle alpha2;

            // didn't converge?  must be N/S
            if (!converged)
            {
                if (phi1 > phi2)
                {
                    alpha1 = Angle.Angle180;
                    alpha2 = Angle.Zero;
                }
                else if (phi1 < phi2)
                {
                    alpha1 = Angle.Zero;
                    alpha2 = Angle.Angle180;
                }
                else
                {
                    alpha1 = new Angle(Double.NaN);
                    alpha2 = new Angle(Double.NaN);
                }
            }

            // else, it converged, so do the math
            else
            {
                double radians;
                alpha1 = new Angle();
                alpha2 = new Angle();

                // eq. 20
                radians = Math.Atan2(cosU2 * Math.Sin(lambda), (cosU1sinU2 - sinU1cosU2 * Math.Cos(lambda)));
                if (radians < 0.0) radians += TwoPi;
                alpha1.Radians = radians;

                // eq. 21
                radians = Math.Atan2(cosU1 * Math.Sin(lambda), (-sinU1cosU2 + cosU1sinU2 * Math.Cos(lambda))) + Math.PI;
                if (radians < 0.0) radians += TwoPi;
                alpha2.Radians = radians;
            }

            if (alpha1 >= 360.0) alpha1 -= 360.0;
            if (alpha2 >= 360.0) alpha2 -= 360.0;

            return new GeodeticCurve(s, alpha1, alpha2);
        }
Ejemplo n.º 5
0
        public override void OnRender(Graphics g)
        {
            Pen MyPen = new Pen(new SolidBrush(LabelAttributes.TargetColor), LabelAttributes.TargetSize);

            MyPen.DashStyle = LabelAttributes.TargetStyle;

            // Draw AC Symbol
            g.DrawRectangle(MyPen, LocalPosition.X - 5, LocalPosition.Y - 5, 10, 10);
            AC_SYMB_START_X = LocalPosition.X - 5;
            AC_SYMB_START_Y = LocalPosition.Y - 5;

            /////////////////////////////////////////////////////////////////////////////////////////////////////////////
            // Here handle drawing of Range/Bearing & SEP tool
            if (TargetToMonitor != -1)
            {
                Point StartPosition = new Point(LocalPosition.X, LocalPosition.Y);
                Point EndPosition   = DynamicDisplayBuilder.GetTargetPositionByIndex(TargetToMonitor);
                g.DrawLine(new Pen(Brushes.Yellow, 1), StartPosition, EndPosition);

                // select a reference elllipsoid
                Ellipsoid reference = Ellipsoid.WGS84;
                // instantiate the calculator
                GeodeticCalculator  geoCalc    = new GeodeticCalculator();
                GlobalPosition      Start      = new GlobalPosition(new GlobalCoordinates(this.Position.Lat, this.Position.Lng));
                PointLatLng         End_LatLng = FormMain.FromLocalToLatLng(EndPosition.X, EndPosition.Y);
                GlobalPosition      End        = new GlobalPosition(new GlobalCoordinates(End_LatLng.Lat, End_LatLng.Lng));
                GeodeticMeasurement GM         = geoCalc.CalculateGeodeticMeasurement(reference, End, Start);

                ////////////////////////////////////////////////////////////////////////////////////////////
                // Handle SEP Tool
                double TRK1_SPD = 0.0, TRK2_SPD = 0.0;
                double TRK1_AZ = 0.0, TRK2_AZ = 0.0;
                bool   Sep_Data_Is_Valid = true;

                if (!double.TryParse(CALC_GSPD_STRING, out TRK1_SPD))
                {
                    if (!double.TryParse(DAP_GSPD, out TRK1_SPD))
                    {
                        Sep_Data_Is_Valid = false;
                    }
                }

                if (!double.TryParse(DynamicDisplayBuilder.GetTarget_CALC_GSPD_ByIndex(TargetToMonitor), out TRK2_SPD))
                {
                    if (!double.TryParse(DynamicDisplayBuilder.GetTarget_DAP_GSPD_ByIndex(TargetToMonitor), out TRK2_SPD))
                    {
                        Sep_Data_Is_Valid = false;
                    }
                }

                if (!double.TryParse(CALC_HDG_STRING, out TRK1_AZ))
                {
                    if (!double.TryParse(TRK, out TRK1_AZ))
                    {
                        if (!double.TryParse(DAP_HDG, out TRK1_AZ))
                        {
                            Sep_Data_Is_Valid = false;
                        }
                    }
                }

                if (!double.TryParse(DynamicDisplayBuilder.GetTarget_CALC_HDG_ByIndex(TargetToMonitor), out TRK2_AZ))
                {
                    if (!double.TryParse(DynamicDisplayBuilder.GetTargetTRKByIndex(TargetToMonitor), out TRK2_AZ))
                    {
                        if (!double.TryParse(DynamicDisplayBuilder.GetTargetM_HDGByIndex(TargetToMonitor), out TRK2_AZ))
                        {
                            Sep_Data_Is_Valid = false;
                        }
                    }
                }

                ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
                // If all the necessary data is avilable
                // then pass it on to the SEP tool calculator
                // and then draw the result
                string SepToolActive = "N/A";
                if (Sep_Data_Is_Valid)
                {
                    SEP_Tool_Calculator         SepTool       = new SEP_Tool_Calculator(Start, End, TRK1_SPD, TRK2_SPD, TRK1_AZ, TRK2_AZ, 20);
                    SEP_Tool_Calculator.OutData Sep_Tool_Data = SepTool.GetResult();

                    if (Sep_Tool_Data.Is_Converging)
                    {
                        g.DrawRectangle(new Pen(Brushes.Yellow, LabelAttributes.TargetSize), Sep_Tool_Data.Track_1_Pos_Min.X - 5, Sep_Tool_Data.Track_1_Pos_Min.Y - 5, 10, 10);
                        g.DrawRectangle(new Pen(Brushes.Yellow, LabelAttributes.TargetSize), Sep_Tool_Data.Track_2_Pos_Min.X - 5, Sep_Tool_Data.Track_2_Pos_Min.Y - 5, 10, 10);
                        g.DrawLine(new Pen(Brushes.Yellow, LabelAttributes.TargetSize), new Point(Sep_Tool_Data.Track_1_Pos_Min.X, Sep_Tool_Data.Track_1_Pos_Min.Y), new Point(StartPosition.X, StartPosition.Y));
                        g.DrawLine(new Pen(Brushes.Yellow, LabelAttributes.TargetSize), new Point(Sep_Tool_Data.Track_2_Pos_Min.X, Sep_Tool_Data.Track_2_Pos_Min.Y), new Point(EndPosition.X, EndPosition.Y));
                        TimeSpan T = TimeSpan.FromSeconds(Sep_Tool_Data.SecondsToMinimum);
                        SepToolActive = "min d:" + Math.Round(Sep_Tool_Data.MinDistance, 1).ToString() + "/" + T.Minutes.ToString() + ":" + T.Seconds.ToString();
                    }
                }

                // Now compute position half way between two points.
                double distance = GM.PointToPointDistance / 2.0;
                if (distance > 0.0)
                {
                    GlobalCoordinates GC         = geoCalc.CalculateEndingGlobalCoordinates(reference, new GlobalCoordinates(End_LatLng.Lat, End_LatLng.Lng), GM.Azimuth, distance);
                    GPoint            GP         = FormMain.FromLatLngToLocal(new PointLatLng(GC.Latitude.Degrees, GC.Longitude.Degrees));
                    double            Distane_NM = 0.00053996 * GM.PointToPointDistance;
                    g.DrawString(Math.Round(GM.Azimuth.Degrees).ToString() + "°/" + Math.Round(Distane_NM, 1).ToString() + "nm", new Font(FontFamily.GenericSansSerif, 9), Brushes.Yellow, new PointF(GP.X, GP.Y));

                    if (Sep_Data_Is_Valid && SepToolActive != "N/A")
                    {
                        g.DrawString(SepToolActive, new Font(FontFamily.GenericSansSerif, 9), Brushes.Yellow, new PointF(GP.X, GP.Y + 15));
                    }
                }
            }

            // Here handle history points
            // First draw all previous history points
            int Number_of_Points_Drawn = 0;

            for (int Index = HistoryPoints.Count - 2; Index >= 0; Index--)
            {
                if (Number_of_Points_Drawn < Properties.Settings.Default.HistoryPoints)
                {
                    HistoryPointsType I = HistoryPoints.ElementAt(Index);
                    GPoint            MarkerPositionLocal = FormMain.gMapControl.FromLatLngToLocal(new PointLatLng(I.LatLong.Lat, I.LatLong.Lng));
                    g.DrawEllipse(MyPen, MarkerPositionLocal.X, MarkerPositionLocal.Y, 3, 3);
                    Number_of_Points_Drawn++;
                }
            }


            //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
            // Here draw speed vector
            // // Find out what data should be used for speed vector? IAS, TAS, GSPD, MACH?
            if ((DataItemValidator(CALC_HDG_STRING) || DataItemValidator(DAP_HDG) || DataItemValidator(TRK)) && (DataItemValidator(DAP_GSPD) || DataItemValidator(CALC_GSPD_STRING)))
            {
                double Azimuth = 0.0;
                double Range   = 0.0;

                if (DataItemValidator(CALC_GSPD_STRING))
                {
                    Range = double.Parse(CALC_GSPD_STRING);
                }
                else
                {
                    Range = double.Parse(DAP_GSPD);
                }

                if (DataItemValidator(CALC_HDG_STRING))
                {
                    Azimuth = double.Parse(CALC_HDG_STRING);
                }
                else if (DataItemValidator(TRK))
                {
                    Azimuth = double.Parse(TRK);
                }
                else
                {
                    Azimuth = double.Parse(DAP_HDG);
                }

                Range = (Range / 60) * (double)Properties.Settings.Default.SpeedVector;

                GeoCordSystemDegMinSecUtilities.LatLongClass ResultPosition =
                    GeoCordSystemDegMinSecUtilities.CalculateNewPosition(new GeoCordSystemDegMinSecUtilities.LatLongClass(Position.Lat, Position.Lng), (double)Range, (double)Azimuth);

                GPoint MarkerPositionLocal = FormMain.gMapControl.FromLatLngToLocal(new PointLatLng(ResultPosition.GetLatLongDecimal().LatitudeDecimal, ResultPosition.GetLatLongDecimal().LongitudeDecimal));
                g.DrawLine(MyPen, new Point(LocalPosition.X, LocalPosition.Y), new Point(MarkerPositionLocal.X, MarkerPositionLocal.Y));
            }
            //////////////////////////////////////////////////////////////////////////////////////////////////////////////////

            MyPen           = new Pen(new SolidBrush(LabelAttributes.LineColor), LabelAttributes.LineWidth);
            MyPen.DashStyle = LabelAttributes.LineStyle;

            // Draw leader line
            g.DrawLine(MyPen, new Point(LocalPosition.X, LocalPosition.Y), new Point(LocalPosition.X - LabelOffset.X, LocalPosition.Y - LabelOffset.Y));

            // Draw label box
            Point LabelStartPosition = GetLabelStartingPoint();

            // Recalculate Label Width each cycle to adjust for the possible changes in the number of lines
            // and changes in the text size
            LabelHeight = 0;

            // Draw ModeA and coast indicator
            g.DrawString(ModeA_CI_STRING, ModeA_CI_FONT, ModeA_CI_BRUSH, LabelStartPosition.X + ModeA_CI_OFFSET.X, LabelStartPosition.Y + SpacingIndex);
            LabelHeight = LabelHeight + (int)ModeA_CI_FONT.Size + SpacingIndex * 2;


            if (CALLSIGN_STRING != "--------")
            {
                // Draw CALLSIGN
                g.DrawString(CALLSIGN_STRING, CALLSIGN_FONT, CALLSIGN_BRUSH, LabelStartPosition.X + CALLSIGN_OFFSET.X, LabelStartPosition.Y + LabelHeight);
                LabelHeight = LabelHeight + (int)CALLSIGN_FONT.Size + SpacingIndex * 2;
            }

            // Draw ModeC
            g.DrawString(ModeC_STRING, ModeC_FONT, ModeC_BRUSH, LabelStartPosition.X + ModeC_OFFSET.X, LabelStartPosition.Y + LabelHeight);

            // Draw CFL on the same line
            if (ModeC_STRING == null)
            {
                ModeC_STRING = "---";
            }
            CFL_OFFSET.X = ModeC_STRING.Length * (int)ModeC_FONT.Size;
            CFL_OFFSET.Y = LabelStartPosition.Y + LabelHeight;
            g.DrawString(CFL_STRING, CFL_FONT, CFL_BRUSH, LabelStartPosition.X + CFL_OFFSET.X, CFL_OFFSET.Y);
            CFL_START_X = LabelStartPosition.X + CFL_OFFSET.X;
            CFL_START_Y = CFL_OFFSET.Y;

            // Draw GSPD on the same line
            GSPD_OFFSET.X = (ModeC_STRING.Length * (int)ModeC_FONT.Size) + (CFL_STRING.Length * (int)CFL_FONT.Size);
            GSPD_OFFSET.Y = LabelStartPosition.Y + LabelHeight;

            if (CALC_GSPD_STRING != " ---")
            {
                g.DrawString(CALC_GSPD_STRING, GSPD_FONT, GSPD_BRUSH, LabelStartPosition.X + GSPD_OFFSET.X, GSPD_OFFSET.Y);
            }
            else if (DAP_GSPD != "N/A")
            {
                g.DrawString(DAP_GSPD, GSPD_FONT, GSPD_BRUSH, LabelStartPosition.X + GSPD_OFFSET.X, GSPD_OFFSET.Y);
            }
            else
            {
                g.DrawString(" ---", GSPD_FONT, GSPD_BRUSH, LabelStartPosition.X + GSPD_OFFSET.X, GSPD_OFFSET.Y);
            }

            GSPD_START_X = LabelStartPosition.X + GSPD_OFFSET.X;
            GSPD_START_Y = GSPD_OFFSET.Y;

            LabelHeight = LabelHeight + (int)GSPD_FONT.Size + SpacingIndex * 2;

            if (ShowLabelBox == true)
            {
                /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
                //  DRAW Assigned HDG, SPD and ROC
                /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

                // HDG
                g.DrawString(A_HDG_STRING, A_HDG_FONT, A_HDG_BRUSH, LabelStartPosition.X + A_HDG_OFFSET.X, LabelStartPosition.Y + LabelHeight);
                HDG_START_X = LabelStartPosition.X + A_HDG_OFFSET.X;
                HDG_START_Y = LabelStartPosition.Y + LabelHeight;

                // SPD
                A_SPD_OFFSET.X = A_HDG_STRING.Length * (int)A_HDG_FONT.Size;
                A_SPD_OFFSET.Y = LabelStartPosition.Y + LabelHeight;
                g.DrawString(A_SPD_STRING, A_SPD_FONT, A_SPD_BRUSH, LabelStartPosition.X + A_SPD_OFFSET.X, A_SPD_OFFSET.Y);
                SPD_START_X = LabelStartPosition.X + A_SPD_OFFSET.X;
                SPD_START_Y = A_SPD_OFFSET.Y;

                // ROC
                //A_ROC_OFFSET.X = A_SPD_OFFSET.X + A_SPD_OFFSET.X + A_SPD_STRING.Length * (int)A_SPD_FONT.Size;
                //A_ROC_OFFSET.Y = LabelStartPosition.Y + LabelHeight;
                // g.DrawString(A_ROC_STRING, A_ROC_FONT, A_ROC_BRUSH, LabelStartPosition.X + A_ROC_OFFSET.X, A_ROC_OFFSET.Y);

                LabelHeight = LabelHeight + (int)A_SPD_FONT.Size + SpacingIndex * 2;

                // Add the final spacing index and draw the box
                LabelHeight = LabelHeight + SpacingIndex * 2;
                g.DrawRectangle(MyPen, LabelStartPosition.X, LabelStartPosition.Y, LabelWidth, LabelHeight);
            }
        }