因为项目需要做一个电子飞行仪表盘包括地平仪和磁罗盘,网上找了很久,没有找到一个合适的控件,就学习了一些图形处理的开源代码做一个简陋的仪表盘来使用,希望对其他人有帮助,如果有好的建议不妨留言
源程序代码https://download.csdn.net/download/qq_42237381/10877536
目录
一、效果示意
飞行仪表应用于飞行器上主要是飞行姿态角的监测
包括俯仰角,偏航角和滚动角
点击开始按钮,随机生成姿态角
二、原理说明
既然要仿真一些,先从网上找几个机械仪表的样式来学习,再从网上找些图片当做背景来使用
好了,这个就是俯仰角的表盘背景,需要将将它切割成一个圆,通过移动图片的位置在图片框的显示,不同的角度,滚动角可以和这个表放一起,滚动了多少度将图片旋转多少度,在写一圈的刻度值即可。
再找一个磁罗盘的图片,需要代码将它切割成一个圆,里面的表盘也用个截图工具截下来,只需要代码让里面的表盘转动既可以达到效果
三、代码参考
开始编程,创建WINFORM程序,添加两个图片框控件,一个按钮控件,一个时间控件。
程序如下,
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace Dashboard
{
public partial class Form1 : Form
{
public Image imgtmp;
public Image imgori;
public Bitmap bitmp;
public Bitmap bm;
public bool IsSure = false;
double DbPitchAngle = new double(); //俯仰角度[-90,90]
double DbRowAngle = new double(); //滚转角度[-180,180]
double DbYawAngle = new double(); //航向角度[-45,45]
public Form1()
{
InitializeComponent();
}
//重绘旋转后的仪表盘图片
public void Overlap(Bitmap btm, int x, int y, int w, int h)
{
Bitmap image = new Bitmap(btm);
Bitmap hi = new Bitmap(bm);
Graphics g = Graphics.FromImage(hi);
g.DrawImage(image, new Rectangle(x, y, w, h));
bm = hi;
}
//-------------------磁罗盘显示函数-------------------//
//入口参数:
//航向角 dir_angle 范围0~360 度
private void Compass_Disp(double dir_angle)
{
string file = System.IO.Path.Combine(Environment.CurrentDirectory, @"point.jpg");
bitmp = new Bitmap(file);
Bitmap pointImage = new Bitmap(250, 250);
System.Drawing.Graphics gPoint = System.Drawing.Graphics.FromImage(pointImage);
gPoint.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.Bilinear;
gPoint.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
//计算偏移量
Rectangle rectPoint = new Rectangle(0, 0, 250, 250);
gPoint.TranslateTransform(125, 125);
//g.RotateTransform(360 - row_angle);
gPoint.RotateTransform((float)dir_angle);
//恢复图像在水平和垂直方向的平移
gPoint.TranslateTransform(-125, -125);
gPoint.DrawImage(bitmp, rectPoint);
//重至绘图的所有变换
gPoint.ResetTransform();
gPoint.Dispose();
//保存旋转后的图片
bm = pointImage;
Overlap(pointImage, 0, 0, 250, 250);
CompointBox.Image = bm;
// 刻度盘截圆
System.Drawing.Drawing2D.GraphicsPath gp = new System.Drawing.Drawing2D.GraphicsPath();
gp.FillMode = 0;
gp.AddEllipse(new Rectangle(0, 0, 350, 350));
ComshellBox.Region = new Region(gp);
//表盘截圆
System.Drawing.Drawing2D.GraphicsPath gp1 = new System.Drawing.Drawing2D.GraphicsPath();
gp1.FillMode = 0;
gp1.AddEllipse(new Rectangle(0, 0, 250, 250));
CompointBox.Region = new Region(gp1);
gp1.Dispose();
gp.Dispose();
gPoint.Dispose();
bitmp.Dispose();
//Graphics gp1 = CompointBox.CreateGraphics();
//gp1.DrawEllipse()
}
//-------------------地平仪刻度划线函数-------------------//
//入口参数:无
public Image Hori_Line()
{
bitmp = new Bitmap(350, 350);
System.Drawing.Graphics gscale = System.Drawing.Graphics.FromImage(bitmp);
Pen p1 = new Pen(Color.Red, 4);
Pen p2 = new Pen(Color.Green, 3);
//准心绘线
//gscale.DrawEllipse(Pens.Red ,165, 165, 20, 20);
gscale.DrawLine(p2, 145, 175, 205, 175);
gscale.DrawLine(p1, 145, 185, 175, 175);
gscale.DrawLine(p1, 205, 185, 175, 175);
//滚转刻度线
gscale.DrawEllipse(Pens.White, 35, 35, 280, 280);
int i, i1, j, j1, k;
for (k = 0; k < 73; k++)
{
i = Convert.ToInt32(140 * Math.Cos(k * Math.PI / 36) + 175);
j = Convert.ToInt32(140 * Math.Sin(k * Math.PI / 36) + 175);
if (k % 2 == 0)
{
i1 = Convert.ToInt32(155 * Math.Cos(k * Math.PI / 36) + 175);
j1 = Convert.ToInt32(155 * Math.Sin(k * Math.PI / 36) + 175);
}
else
{
i1 = Convert.ToInt32(150 * Math.Cos(k * Math.PI / 36) + 175);
j1 = Convert.ToInt32(150 * Math.Sin(k * Math.PI / 36) + 175);
}
gscale.DrawLine(Pens.White, i, j, i1, j1);
}
gscale.Dispose();
return bitmp;
}
//-------------------地平仪显示函数-------------------//
//入口参数:
//俯仰角 pitch_angle 范围-90~90 度
//滚动角 row_angle 范围-90~90 度
private void Hori_Disp(double pitch_angle, double row_angle)
{
//1地平仪图像载入带平移
int pic_position;
pic_position = Convert.ToInt32(pitch_angle * 3.86);
string file = System.IO.Path.Combine(Environment.CurrentDirectory, @"11.jpg");
try
{
imgtmp = new Bitmap(file);
row_angle = row_angle % 360;
//弧度转换
double ar = 2;
double radian = (row_angle - 90) * Math.PI / 180.0;
double radiana = (row_angle - 90 - ar) * Math.PI / 180.0;
double radianc = (row_angle - 90 + ar) * Math.PI / 180.0;
double cos = Math.Cos(radian);
double cosa = Math.Cos(radiana);
double cosc = Math.Cos(radianc);
double sin = Math.Sin(radian);
double sina = Math.Sin(radiana);
double sinc = Math.Sin(radianc);
//目标位图
Bitmap dsImage = new Bitmap(350, 350);
System.Drawing.Graphics g = System.Drawing.Graphics.FromImage(dsImage);
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.Bilinear;
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
//计算偏移量
Rectangle rect = new Rectangle(-175, -175 + pic_position, 700, 700);
g.TranslateTransform(175, 175);
g.RotateTransform((float)row_angle);
//恢复图像在水平和垂直方向的平移
g.TranslateTransform(-175, -175);
g.DrawImage(imgtmp, rect);
//重至绘图的所有变换
g.ResetTransform();
g.Dispose();
//保存旋转后的图片
bm = dsImage;
//调用imgori 已经是画好的刻度盘
Bitmap bitmp = new Bitmap(imgori);
Overlap(bitmp, 0, 0, 350, 350);
Bitmap pointImage = new Bitmap(350, 350);
// 指针设计 ;
System.Drawing.Graphics gPoint = System.Drawing.Graphics.FromImage(pointImage);
SolidBrush h = new SolidBrush(Color.Red);
Point a = new Point(Convert.ToInt32(175 + 131 * cosa), Convert.ToInt32(180 + 131 * sina));
Point b = new Point(Convert.ToInt32(141 * cos + 175), Convert.ToInt32(141 * sin + 175));
Point c = new Point(Convert.ToInt32(175 + 131 * cosc), Convert.ToInt32(180 + 131 * sinc));
Point[] pointer = { a, b, c };
gPoint.FillPolygon(h, pointer);
Overlap(pointImage, 0, 0, 350, 350);
HoriBox.Image = bm;
g.Dispose();
imgtmp.Dispose();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
System.Drawing.Drawing2D.GraphicsPath gp = new System.Drawing.Drawing2D.GraphicsPath();
gp.FillMode = 0;
gp.AddEllipse(new Rectangle(0, 0, 350, 350));
HoriBox.Region = new Region(gp);
gp.Dispose();
}
/// <summary>
/// 开始按钮点击
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button1_Click(object sender, EventArgs e)
{
if (IsSure == false)
{
timer1.Enabled = true;
IsSure = true;
button1.Text = "停止";
}
else
{
timer1.Enabled = false;
IsSure = false;
button1.Text = "开始";
}
}
private void timer1_Tick(object sender, EventArgs e)
{
double DbPitchAngle = 0; //俯仰角度[-90,90]
double DbRowAngle = 0; //滚转角度[-180,180]
double DbYawAngle = 0; //航向角度[-45,45]
Random pR = new Random();
Random rR = new Random();
Random yR = new Random();
DbPitchAngle = pR.Next(0, 90);
DbRowAngle = rR.Next(-180, 180);
DbYawAngle = yR.Next(-45,45);
Hori_Disp(DbPitchAngle, DbRowAngle);
Compass_Disp(DbYawAngle);
Hori_Line();
}
private void Form1_Load(object sender, EventArgs e)
{
imgori = Hori_Line();
}
}
}