Subversion Repositories Projects

Rev

Blame | Last modification | View Log | RSS feed

/*******************************************
Original Source by Chootair (http://www.codeproject.com/Articles/27411/C-Avionic-Instrument-Controls)
C# Avionic Instrument Controls

Made some modifications:
--Reduced to the heading indicator
-- & changed class to UserControl
--changed the images
--doublebuffered to reduce flickering
*******************************************/


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;

namespace AvionicsInstrumentControl
{
    public partial class HeadingIndicator : UserControl
    {
        public HeadingIndicator()
        {
            InitializeComponent();
            this.DoubleBuffered = true;
        }
        protected void RotateImage(PaintEventArgs pe, Image img, Double alpha, Point ptImg, Point ptRot, float scaleFactor)
        {
            double beta = 0;    // Angle between the Horizontal line and the line (Left upper corner - Rotation point)
            double d = 0;               // Distance between Left upper corner and Rotation point)              
            float deltaX = 0;   // X componant of the corrected translation
            float deltaY = 0;   // Y componant of the corrected translation

            // Compute the correction translation coeff
            if (ptImg != ptRot)
            {
                //
                if (ptRot.X != 0)
                {
                    beta = Math.Atan((double)ptRot.Y / (double)ptRot.X);
                }

                d = Math.Sqrt((ptRot.X * ptRot.X) + (ptRot.Y * ptRot.Y));

                // Computed offset
                deltaX = (float)(d * (Math.Cos(alpha - beta) - Math.Cos(alpha) * Math.Cos(alpha + beta) - Math.Sin(alpha) * Math.Sin(alpha + beta)));
                deltaY = (float)(d * (Math.Sin(beta - alpha) + Math.Sin(alpha) * Math.Cos(alpha + beta) - Math.Cos(alpha) * Math.Sin(alpha + beta)));
            }

            // Rotate image support
            pe.Graphics.RotateTransform((float)(alpha * 180 / Math.PI));

            // Dispay image
            pe.Graphics.DrawImage(img, (ptImg.X + deltaX) * scaleFactor, (ptImg.Y + deltaY) * scaleFactor, img.Width * scaleFactor, img.Height * scaleFactor);

            // Put image support as found
            pe.Graphics.RotateTransform((float)(-alpha * 180 / Math.PI));

        }
        #region Fields

        // Parameters
        int Heading;

        // Images
        Bitmap bmpHedingWeel = new Bitmap(AvionicsInstrumentControl.Properties.Resources.HeadingIndicatorOverlay);
        Bitmap bmpAircaft = new Bitmap(AvionicsInstrumentControl.Properties.Resources.HeadingIndicatorBackground);

        #endregion

        #region Paint

        protected override void OnPaint(PaintEventArgs pe)
        {
            // Calling the base class OnPaint
            base.OnPaint(pe);

            // Pre Display computings
            Point ptRotation = new Point(200, 200);
            Point ptImgAircraft = new Point(0, 0);
            Point ptImgHeadingWeel = new Point(0, 0);

            double alphaHeadingWeel = InterpolPhyToAngle(Heading, 0, 360, 360, 0);

            float scale = (float)this.Width / (bmpHedingWeel.Width);

            pe.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighSpeed;

            // display aircraft
            pe.Graphics.DrawImage(bmpAircaft, (int)(ptImgAircraft.X * scale), (int)(ptImgAircraft.Y * scale), (float)(bmpAircaft.Width * scale), (float)(bmpAircaft.Height * scale));


            // display HeadingWeel
            RotateImage(pe, bmpHedingWeel, alphaHeadingWeel, ptImgHeadingWeel, ptRotation, scale);

        }

        #endregion

        #region Methods
        /// <summary>
        /// Convert a physical value in an rad angle used by the rotate function
        /// </summary>
                /// <param name="phyVal">Physical value to interpol/param>
                /// <param name="minPhy">Minimum physical value</param>
                /// <param name="maxPhy">Maximum physical value</param>
                /// <param name="minAngle">The angle related to the minumum value, in deg</param>
                /// <param name="maxAngle">The angle related to the maximum value, in deg</param>
                /// <returns>The angle in radian witch correspond to the physical value</returns>
        protected float InterpolPhyToAngle(float phyVal, float minPhy, float maxPhy, float minAngle, float maxAngle)
        {
            float a;
            float b;
            float y;
            float x;

            if (phyVal < minPhy)
            {
                return (float)(minAngle * Math.PI / 180);
            }
            else if (phyVal > maxPhy)
            {
                return (float)(maxAngle * Math.PI / 180);
            }
            else
            {

                x = phyVal;
                a = (maxAngle - minAngle) / (maxPhy - minPhy);
                b = (float)(0.5 * (maxAngle + minAngle - a * (maxPhy + minPhy)));
                y = a * x + b;

                return (float)(y * Math.PI / 180);
            }
        }

        /// <summary>
        /// Define the physical value to be displayed on the indicator
        /// </summary>
        /// <param name="aircraftHeading">The aircraft heading in °deg</param>
        public void SetHeadingIndicatorParameters(int aircraftHeading)
        {
            Heading = aircraftHeading;

            this.Refresh();
        }

        #endregion

    }
}