private static void DrawVOR(ref MySpriteDrawFrame Frame, IMyTextSurface Surface, VORDataSet VORData)
            {
                if (VORData.Rotation == null)
                {
                    DrawCross(ref Frame);
                    return;
                }

                // Vars
                float CircleSize  = Size.Y * 0.95f;
                float ArrowLength = Size.Y * 0.8f;

                float ArrowRotation = (float)VORData.Rotation;
                float Deviation     = (float)VORData.Deviation;


                // Circle
                MySprite Circle1 = MySprite.CreateSprite("Circle", Center, new Vector2(CircleSize, CircleSize));

                Circle1.Color = CockpitFGColor.Alpha(1f);
                Frame.Add(Circle1);

                MySprite Circle2 = MySprite.CreateSprite("Circle", Center, new Vector2(CircleSize, CircleSize) * 0.95f);

                Circle2.Color = CockpitBGColor.Alpha(1f);
                Frame.Add(Circle2);

                // Arrow
                MySprite ArrowBody = MySprite.CreateSprite("SquareSimple", Center, new Vector2(12 * UnitX, ArrowLength));

                ArrowBody.Color           = Color.LawnGreen.Alpha(1f);
                ArrowBody.RotationOrScale = ToRadian(ArrowRotation);
                Frame.Add(ArrowBody);

                float AConstant = ArrowLength / 2.1f;
                float Ax        = (float)Math.Sin(ToRadian(ArrowRotation)) * AConstant;
                float Ay        = (float)Math.Cos(ToRadian(ArrowRotation)) * AConstant * -1;

                MySprite ArrowHead = MySprite.CreateSprite("Triangle", Center + new Vector2(Ax, Ay), Size * 0.2f);

                ArrowHead.Color           = Color.LawnGreen.Alpha(1f);
                ArrowHead.RotationOrScale = ToRadian(ArrowRotation);
                Frame.Add(ArrowHead);


                // Deviation bar
                float DConstant = Deviation / (float)VORFullScaleDeflectionAngle * (Size.Y * 0.4f);
                float Dx        = (float)Math.Sin(ToRadian(ArrowRotation + 90)) * DConstant * -1;
                float Dy        = (float)Math.Cos(ToRadian(ArrowRotation + 90)) * DConstant;

                MySprite DeviationBarMask = MySprite.CreateSprite("SquareSimple", Center, new Vector2(12 * UnitX, ArrowLength / 2.7f));

                DeviationBarMask.Color           = CockpitBGColor.Alpha(1f);
                DeviationBarMask.RotationOrScale = ToRadian(ArrowRotation);
                Frame.Add(DeviationBarMask);

                MySprite DeviationBar = MySprite.CreateSprite("SquareSimple", Center + new Vector2(Dx, Dy), new Vector2(12 * UnitX, ArrowLength / 3));

                DeviationBar.Color           = Color.LawnGreen.Alpha(1f);
                DeviationBar.RotationOrScale = ToRadian(ArrowRotation);
                Frame.Add(DeviationBar);


                // VOR Deviation Scale
                float DSM4 = -1.0f * (Size.Y * 0.4f);
                float DSM3 = -0.75f * (Size.Y * 0.4f);
                float DSM2 = -0.5f * (Size.Y * 0.4f);
                float DSM1 = -0.25f * (Size.Y * 0.4f);
                float DSP1 = 0.25f * (Size.Y * 0.4f);
                float DSP2 = 0.5f * (Size.Y * 0.4f);
                float DSP3 = 0.75f * (Size.Y * 0.4f);
                float DSP4 = 1.0f * (Size.Y * 0.4f);


                float DSM4x = (float)Math.Sin(ToRadian(ArrowRotation + 90)) * DSM4 * -1;
                float DSM4y = (float)Math.Cos(ToRadian(ArrowRotation + 90)) * DSM4;

                float DSM3x = (float)Math.Sin(ToRadian(ArrowRotation + 90)) * DSM3 * -1;
                float DSM3y = (float)Math.Cos(ToRadian(ArrowRotation + 90)) * DSM3;

                float DSM2x = (float)Math.Sin(ToRadian(ArrowRotation + 90)) * DSM2 * -1;
                float DSM2y = (float)Math.Cos(ToRadian(ArrowRotation + 90)) * DSM2;

                float DSM1x = (float)Math.Sin(ToRadian(ArrowRotation + 90)) * DSM1 * -1;
                float DSM1y = (float)Math.Cos(ToRadian(ArrowRotation + 90)) * DSM1;

                float DSP1x = (float)Math.Sin(ToRadian(ArrowRotation + 90)) * DSP1 * -1;
                float DSP1y = (float)Math.Cos(ToRadian(ArrowRotation + 90)) * DSP1;

                float DSP2x = (float)Math.Sin(ToRadian(ArrowRotation + 90)) * DSP2 * -1;
                float DSP2y = (float)Math.Cos(ToRadian(ArrowRotation + 90)) * DSP2;

                float DSP3x = (float)Math.Sin(ToRadian(ArrowRotation + 90)) * DSP3 * -1;
                float DSP3y = (float)Math.Cos(ToRadian(ArrowRotation + 90)) * DSP3;

                float DSP4x = (float)Math.Sin(ToRadian(ArrowRotation + 90)) * DSP4 * -1;
                float DSP4y = (float)Math.Cos(ToRadian(ArrowRotation + 90)) * DSP4;

                MySprite DSM4Sprite = MySprite.CreateSprite("Circle", Center + new Vector2(DSM4x, DSM4y), new Vector2(CircleSize, CircleSize) * 0.05f);
                MySprite DSM3Sprite = MySprite.CreateSprite("Circle", Center + new Vector2(DSM3x, DSM3y), new Vector2(CircleSize, CircleSize) * 0.05f);
                MySprite DSM2Sprite = MySprite.CreateSprite("Circle", Center + new Vector2(DSM2x, DSM2y), new Vector2(CircleSize, CircleSize) * 0.05f);
                MySprite DSM1Sprite = MySprite.CreateSprite("Circle", Center + new Vector2(DSM1x, DSM1y), new Vector2(CircleSize, CircleSize) * 0.05f);
                MySprite DSCSprite  = MySprite.CreateSprite("Circle", Center, new Vector2(CircleSize, CircleSize) * 0.1f);
                MySprite DSP1Sprite = MySprite.CreateSprite("Circle", Center + new Vector2(DSP1x, DSP1y), new Vector2(CircleSize, CircleSize) * 0.05f);
                MySprite DSP2Sprite = MySprite.CreateSprite("Circle", Center + new Vector2(DSP2x, DSP2y), new Vector2(CircleSize, CircleSize) * 0.05f);
                MySprite DSP3Sprite = MySprite.CreateSprite("Circle", Center + new Vector2(DSP3x, DSP3y), new Vector2(CircleSize, CircleSize) * 0.05f);
                MySprite DSP4Sprite = MySprite.CreateSprite("Circle", Center + new Vector2(DSP4x, DSP4y), new Vector2(CircleSize, CircleSize) * 0.05f);

                DSM4Sprite.Color = CockpitFGColor.Alpha(1f);
                DSM3Sprite.Color = CockpitFGColor.Alpha(1f);
                DSM2Sprite.Color = CockpitFGColor.Alpha(1f);
                DSM1Sprite.Color = CockpitFGColor.Alpha(1f);
                DSCSprite.Color  = CockpitFGColor.Alpha(1f);
                DSP1Sprite.Color = CockpitFGColor.Alpha(1f);
                DSP2Sprite.Color = CockpitFGColor.Alpha(1f);
                DSP3Sprite.Color = CockpitFGColor.Alpha(1f);
                DSP4Sprite.Color = CockpitFGColor.Alpha(1f);

                Frame.Add(DSM4Sprite);
                Frame.Add(DSM3Sprite);
                Frame.Add(DSM2Sprite);
                Frame.Add(DSM1Sprite);
                Frame.Add(DSCSprite);
                Frame.Add(DSP1Sprite);
                Frame.Add(DSP2Sprite);
                Frame.Add(DSP3Sprite);
                Frame.Add(DSP4Sprite);
            }
        public VORDataSet HandleVOR()
        {
            string   VORName     = config.Get("VORStation", "Name").ToString();
            Vector3D VORPosition = CreateVectorFromGPSCoordinateString(config.Get("VORStation", "Position").ToString());
            Vector3D NorthVector = CreateVectorFromGPSCoordinateString(config.Get("VORStation", "NorthVector").ToString());
            Vector3D CrossVector = CreateVectorFromGPSCoordinateString(config.Get("VORStation", "CrossVector").ToString());

            VORDataSet VORData = new VORDataSet();

            VORData.Name = VORName;


            Vector3D RadialVector     = Vector3D.Negate(VORPosition) + ShipVector;
            Vector3D RRadialVector    = Vector3D.Reject(RadialVector, GravVectorNorm);
            Vector3D RadialVectorNorm = Vector3D.Normalize(RRadialVector);

            double NorthAngle = ToDegrees(Math.Acos(Vector3D.Dot(RadialVectorNorm, NorthVector)));
            double CrossAngle = ToDegrees(Math.Acos(Vector3D.Dot(RadialVectorNorm, CrossVector)));

            double Radial = NorthAngle;

            if (CrossAngle < 90)
            {
                Radial = 360 - NorthAngle;
            }

            VORData.Radial = Radial;

            double OBS = config.Get("VORNavigation", "OBS").ToDouble();

            // Aircraft North Vector
            Vector3D ACNorthVector     = Vector3D.Reject(new Vector3D(0, -1, 0), GravVectorNorm);
            Vector3D ACNorthVectorNorm = Vector3D.Normalize(ACNorthVector);

            Vector3D ConvVORNorthVector = Vector3D.Normalize(Vector3D.Reject(NorthVector, GravVectorNorm));
            Vector3D ConvVORCrossVector = Vector3D.Normalize(Vector3D.Reject(CrossVector, GravVectorNorm));

            double Convergence      = ToDegrees(Math.Acos(Vector3D.Dot(ACNorthVectorNorm, ConvVORNorthVector)));
            double ConvergenceCross = ToDegrees(Math.Acos(Vector3D.Dot(ACNorthVectorNorm, ConvVORCrossVector)));

            if (ConvergenceCross < 90)
            {
                Convergence = Convergence * -1;
            }

            Vector3D Direction = Vector3D.Normalize(Vector3D.Reject(Vector3D.Normalize(CockpitBlock.WorldMatrix.Forward), GravVectorNorm));
            double   Heading   = ToDegrees(Math.Acos(Vector3D.Dot(Direction, ACNorthVectorNorm)));

            Vector3D CrossDirection;

            if (Math.Acos(Vector3D.Dot(CockpitBlock.WorldMatrix.Down, GravVectorNorm)) < (Math.PI / 2))
            {
                CrossDirection = Vector3D.Reject(CockpitBlock.WorldMatrix.Right, GravVectorNorm);
            }
            else
            {
                CrossDirection = Vector3D.Reject(CockpitBlock.WorldMatrix.Left, GravVectorNorm);
            }

            double AngleCross = ToDegrees(Math.Acos(Vector3D.Dot(CrossDirection, ACNorthVectorNorm)));

            if (AngleCross < 90)
            {
                Heading = 360 - Heading;
            }

            double Rotation = OBS - Heading - Convergence - 180;


            // Deviation
            double Deviation = Radial - OBS;

            Deviation *= -1;
            if (Deviation > 90)
            {
                Deviation -= 180;
                Rotation  -= 180;
            }
            else if (Deviation < -90)
            {
                Deviation += 180;
                Rotation  -= 180;
            }


            VORData.Rotation  = Rotation;
            VORData.Distance  = CalculateShipDistanceFromVector(VORPosition);
            VORData.OBS       = OBS;
            VORData.Heading   = Heading;
            VORData.Deviation = Deviation;

            return(VORData);
        }
        public void DrawToSurfaces(ILSDataSet ILSData, VORDataSet VORData, NDBDataSet NDBData)
        {
            List <IMyTextSurfaceProvider> SurfaceProviders = GetScreens(CockpitTag);

            if (SurfaceProviders == null)
            {
                Echo("No screen found!");
                return;
            }

            CombinedDataSet CombinedData = new CombinedDataSet
            {
                ILSData = ILSData,
                VORData = VORData
            };

            foreach (IMyTextSurfaceProvider _sp in SurfaceProviders)
            {
                IMyTerminalBlock _spTerminal       = _sp as IMyTerminalBlock;
                string           _customDataString = _spTerminal.CustomData;
                MyIni            _customData       = new MyIni();

                MyIniParseResult iniResult;
                if (!_customData.TryParse(_customDataString, out iniResult))
                {
                    throw new Exception(iniResult.ToString());
                }


                if (_customData.Get("NavigationSurfaces", "0").ToString("none") == "none")
                {
                    for (int i = 0; i < _sp.SurfaceCount; i++)
                    {
                        switch (i)
                        {
                        case 1:
                            _customData.Set("NavigationSurfaces", i.ToString(), "ILS");
                            break;

                        case 2:
                            _customData.Set("NavigationSurfaces", i.ToString(), "VOR");
                            break;

                        case 3:
                            _customData.Set("NavigationSurfaces", i.ToString(), "Data");
                            break;

                        default:
                            _customData.Set("NavigationSurfaces", i.ToString(), "N/A");
                            break;
                        }
                    }

                    _spTerminal.CustomData = _customData.ToString();
                    continue;
                }

                string[] DrawSurfaces = new string[_sp.SurfaceCount];
                try
                {
                    for (var i = 0; i < _sp.SurfaceCount; i++)
                    {
                        string value = _customData.Get("NavigationSurfaces", i.ToString()).ToString();
                        DrawSurfaces[i] = value;
                    }
                }
                catch (Exception)
                {
                    Echo("Error in building DrawSurfaces Loop");
                }

                // ILS Screen
                try
                {
                    IMyTextSurface ILSSurface = _sp.GetSurface(Array.IndexOf(DrawSurfaces, "ILS"));
                    Draw.DrawSurface(ILSSurface, Surface.ILS, ILSData);
                }
                catch (Exception)
                {
                    Echo("No ILS Surface found in \"" + _spTerminal.CustomName.ToString() + "\".");
                }


                // VOR Screen
                try
                {
                    IMyTextSurface VORSurface = _sp.GetSurface(Array.IndexOf(DrawSurfaces, "VOR"));
                    Draw.DrawSurface(VORSurface, Surface.VOR, VORData);
                }
                catch (Exception)
                {
                    Echo("No VOR Surface found in \"" + _spTerminal.CustomName.ToString() + "\".");
                }


                // NDB Screen
                try
                {
                    IMyTextSurface VORSurface = _sp.GetSurface(Array.IndexOf(DrawSurfaces, "NDB"));
                    Draw.DrawSurface(VORSurface, Surface.NDB, NDBData);
                }
                catch (Exception)
                {
                    Echo("No NDB Surface found in \"" + _spTerminal.CustomName.ToString() + "\".");
                }


                // Data Screen
                try
                {
                    IMyTextSurface DataSurface = _sp.GetSurface(Array.IndexOf(DrawSurfaces, "Data"));
                    Draw.DrawSurface(DataSurface, Surface.Data, CombinedData);
                }
                catch (Exception)
                {
                    Echo("No Data Surface found in " + _spTerminal.CustomName.ToString());
                }
            }
        }
        public void Main(string argument, UpdateType updateSource)
        {
            if (!SetupComplete)
            {
                Echo("Running setup.");
                Setup();
                InitializeStorage();
            }
            else
            {
                Echo("Skipping setup");
            }

            if (!argument.Equals(""))
            {
                switch (argument.ToLower())
                {
                // General Commands
                case "reset":
                    InitializeStorage();
                    break;

                // ILS Commands
                case "startils":
                    ShipShouldListenForILS = true;
                    break;

                case "stopsearchils":
                    ShipShouldListenForILS = false;
                    break;

                case "stopils":
                    ShipHasSelectedILS     = false;
                    ShipShouldListenForILS = false;
                    // ResetDefaultILSInConfig();
                    break;

                // VOR Commands
                case "startvor":
                    ShipShouldListenForVOR = true;
                    break;

                case "stopsearchvor":
                    ShipShouldListenForVOR = false;
                    break;

                case "stopvor":
                    ShipHasSelectedVOR     = false;
                    ShipShouldListenForVOR = false;
                    // ResetDefaultVORInConfig();
                    break;
                }
                // OBS 90
                if (argument.ToLower().StartsWith("obs "))
                {
                    string[] argPart = argument.Split(' ');
                    double   OBS;
                    if (double.TryParse(argPart[1], out OBS))
                    {
                        config.Set("VORNavigation", "OBS", OBS.ToString());
                        SaveStorage();
                    }
                }

                // SurfaceToggle 0 1
                if (argument.ToLower().StartsWith("surfacetoggle "))
                {
                    string[] argPart = argument.Split(' ');
                    int      SurfaceProviderIndex, SurfaceIndex;

                    int.TryParse(argPart[1], out SurfaceProviderIndex);
                    int.TryParse(argPart[2], out SurfaceIndex);

                    ToggleSurface(SurfaceProviderIndex, SurfaceIndex);
                }
            }

            // Update the ship and gravity vectors.
            UpdateVectors();


            // Main Logic
            if (ShipShouldListenForILS)
            {
                // If ship is connected to an ILS and is listening, another ILS closer by will override
                // the active transmitter. Normally ShipShouldListen will be false once connected.
                SearchForILSMessages();
            }

            if (ShipShouldListenForVOR)
            {
                SearchForVORMessages();
            }

            if (ShipShouldListenForNDB)
            {
                SearchForNDBMessages();
            }

            ILSData = new ILSDataSet();
            if (ShipHasSelectedILS)
            {
                ILSData = HandleILS();
            }

            VORDataSet VORData = new VORDataSet();

            if (ShipHasSelectedVOR)
            {
                VORData = HandleVOR();
            }

            NDBDataSet NDBData = new NDBDataSet();

            if (ShipHasSelectedNDB)
            {
                NDBData = HandleNDB();
            }

            DrawToSurfaces(ILSData, VORData, NDBData);
        }