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