Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
2233 | - | 1 | /******************************************* |
2 | Original Source by Chootair (http://www.codeproject.com/Articles/27411/C-Avionic-Instrument-Controls) |
||
3 | C# Avionic Instrument Controls |
||
4 | |||
5 | Made some modifications: |
||
6 | --Reduced to the heading indicator |
||
7 | -- & changed class to UserControl |
||
8 | --changed the images |
||
9 | --doublebuffered to reduce flickering |
||
10 | *******************************************/ |
||
11 | |||
12 | using System; |
||
13 | using System.Collections.Generic; |
||
14 | using System.ComponentModel; |
||
15 | using System.Drawing; |
||
16 | using System.Data; |
||
17 | using System.Text; |
||
18 | using System.Windows.Forms; |
||
19 | |||
20 | namespace AvionicsInstrumentControl |
||
21 | { |
||
22 | public partial class HeadingIndicator : UserControl |
||
23 | { |
||
24 | public HeadingIndicator() |
||
25 | { |
||
26 | InitializeComponent(); |
||
27 | this.DoubleBuffered = true; |
||
28 | } |
||
29 | protected void RotateImage(PaintEventArgs pe, Image img, Double alpha, Point ptImg, Point ptRot, float scaleFactor) |
||
30 | { |
||
31 | double beta = 0; // Angle between the Horizontal line and the line (Left upper corner - Rotation point) |
||
32 | double d = 0; // Distance between Left upper corner and Rotation point) |
||
33 | float deltaX = 0; // X componant of the corrected translation |
||
34 | float deltaY = 0; // Y componant of the corrected translation |
||
35 | |||
36 | // Compute the correction translation coeff |
||
37 | if (ptImg != ptRot) |
||
38 | { |
||
39 | // |
||
40 | if (ptRot.X != 0) |
||
41 | { |
||
42 | beta = Math.Atan((double)ptRot.Y / (double)ptRot.X); |
||
43 | } |
||
44 | |||
45 | d = Math.Sqrt((ptRot.X * ptRot.X) + (ptRot.Y * ptRot.Y)); |
||
46 | |||
47 | // Computed offset |
||
48 | deltaX = (float)(d * (Math.Cos(alpha - beta) - Math.Cos(alpha) * Math.Cos(alpha + beta) - Math.Sin(alpha) * Math.Sin(alpha + beta))); |
||
49 | deltaY = (float)(d * (Math.Sin(beta - alpha) + Math.Sin(alpha) * Math.Cos(alpha + beta) - Math.Cos(alpha) * Math.Sin(alpha + beta))); |
||
50 | } |
||
51 | |||
52 | // Rotate image support |
||
53 | pe.Graphics.RotateTransform((float)(alpha * 180 / Math.PI)); |
||
54 | |||
55 | // Dispay image |
||
56 | pe.Graphics.DrawImage(img, (ptImg.X + deltaX) * scaleFactor, (ptImg.Y + deltaY) * scaleFactor, img.Width * scaleFactor, img.Height * scaleFactor); |
||
57 | |||
58 | // Put image support as found |
||
59 | pe.Graphics.RotateTransform((float)(-alpha * 180 / Math.PI)); |
||
60 | |||
61 | } |
||
62 | #region Fields |
||
63 | |||
64 | // Parameters |
||
65 | int Heading; |
||
66 | |||
67 | // Images |
||
68 | Bitmap bmpHedingWeel = new Bitmap(AvionicsInstrumentControl.Properties.Resources.HeadingIndicatorOverlay); |
||
69 | Bitmap bmpAircaft = new Bitmap(AvionicsInstrumentControl.Properties.Resources.HeadingIndicatorBackground); |
||
70 | |||
71 | #endregion |
||
72 | |||
73 | #region Paint |
||
74 | |||
75 | protected override void OnPaint(PaintEventArgs pe) |
||
76 | { |
||
77 | // Calling the base class OnPaint |
||
78 | base.OnPaint(pe); |
||
79 | |||
80 | // Pre Display computings |
||
81 | Point ptRotation = new Point(200, 200); |
||
82 | Point ptImgAircraft = new Point(0, 0); |
||
83 | Point ptImgHeadingWeel = new Point(0, 0); |
||
84 | |||
85 | double alphaHeadingWeel = InterpolPhyToAngle(Heading, 0, 360, 360, 0); |
||
86 | |||
87 | float scale = (float)this.Width / (bmpHedingWeel.Width); |
||
88 | |||
89 | pe.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighSpeed; |
||
90 | |||
91 | // display aircraft |
||
92 | pe.Graphics.DrawImage(bmpAircaft, (int)(ptImgAircraft.X * scale), (int)(ptImgAircraft.Y * scale), (float)(bmpAircaft.Width * scale), (float)(bmpAircaft.Height * scale)); |
||
93 | |||
94 | |||
95 | // display HeadingWeel |
||
96 | RotateImage(pe, bmpHedingWeel, alphaHeadingWeel, ptImgHeadingWeel, ptRotation, scale); |
||
97 | |||
98 | } |
||
99 | |||
100 | #endregion |
||
101 | |||
102 | #region Methods |
||
103 | /// <summary> |
||
104 | /// Convert a physical value in an rad angle used by the rotate function |
||
105 | /// </summary> |
||
106 | /// <param name="phyVal">Physical value to interpol/param> |
||
107 | /// <param name="minPhy">Minimum physical value</param> |
||
108 | /// <param name="maxPhy">Maximum physical value</param> |
||
109 | /// <param name="minAngle">The angle related to the minumum value, in deg</param> |
||
110 | /// <param name="maxAngle">The angle related to the maximum value, in deg</param> |
||
111 | /// <returns>The angle in radian witch correspond to the physical value</returns> |
||
112 | protected float InterpolPhyToAngle(float phyVal, float minPhy, float maxPhy, float minAngle, float maxAngle) |
||
113 | { |
||
114 | float a; |
||
115 | float b; |
||
116 | float y; |
||
117 | float x; |
||
118 | |||
119 | if (phyVal < minPhy) |
||
120 | { |
||
121 | return (float)(minAngle * Math.PI / 180); |
||
122 | } |
||
123 | else if (phyVal > maxPhy) |
||
124 | { |
||
125 | return (float)(maxAngle * Math.PI / 180); |
||
126 | } |
||
127 | else |
||
128 | { |
||
129 | |||
130 | x = phyVal; |
||
131 | a = (maxAngle - minAngle) / (maxPhy - minPhy); |
||
132 | b = (float)(0.5 * (maxAngle + minAngle - a * (maxPhy + minPhy))); |
||
133 | y = a * x + b; |
||
134 | |||
135 | return (float)(y * Math.PI / 180); |
||
136 | } |
||
137 | } |
||
138 | |||
139 | /// <summary> |
||
140 | /// Define the physical value to be displayed on the indicator |
||
141 | /// </summary> |
||
142 | /// <param name="aircraftHeading">The aircraft heading in °deg</param> |
||
143 | public void SetHeadingIndicatorParameters(int aircraftHeading) |
||
144 | { |
||
145 | Heading = aircraftHeading; |
||
146 | |||
147 | this.Refresh(); |
||
148 | } |
||
149 | |||
150 | #endregion |
||
151 | |||
152 | } |
||
153 | } |