对于可视化波形图,网上用的最多的是百度的Echarts可视化图形,但对于一些仪器来说,这些图漂亮是漂亮,但不够实用,例如我们的这些仪器监测图:
有时候也是用到的桌面应用程序的,所以需要自己画出这些监测图形效果,下面我自画的效果图:
上代码:
public class Boxing
{
static float move = 100f;//边框宽度
static float Max_X = 30000f;//X轴最大值
static float Max_Y_Left = 4000f;//左Y轴最大值
static float Max_Y_Right = 40f;//右Y轴最大值
static int XscaleCount = 15;//X轴刻度线数量
static int YscaleCount = 4;//Y轴刻度线数量
static string Y_Left_Title = "应力";//左Y轴名称
static string Y_Right_Title = "温度";//右Y轴名称
static string X_Title = "位置";//X轴名称
public byte[] DrawBoxing(int width,int height,List<FPObject> datas)
{
Bitmap image = new Bitmap(width, height);
Graphics gph = Graphics.FromImage(image);
//清空图片背景色
gph.Clear(Color.White);
try
{
//画图片的边框线
gph.DrawRectangle(new Pen(Color.Silver), 0, 0, image.Width - 1, image.Height - 1);
PointF cPt = new PointF(move, height/2f);//中心点(坐标轴原点)
gph.DrawString("2021-12-21 21:12:30", new Font("宋体", 12,FontStyle.Bold), Brushes.Black, new PointF(width / 2f-50,12));//图表标题
DrawY_Left(gph, width, height, Max_Y_Left, YscaleCount);
DrawY_Right(gph, width, height, Max_Y_Right, YscaleCount);
DrawX_Bottom(gph, width, height, Max_X, XscaleCount);
DrawX_Top(gph, width, height, Max_X, XscaleCount);
gph.DrawLine(new Pen(Brushes.DarkGray, 2), cPt.X, cPt.Y, width - move, cPt.Y);//画出中轴线
float X_Between = (width - move * 2f) / Max_X;//水平间距像素
float Y_Left_Between = (image.Height / 2f - move) / Max_Y_Left; //左Y轴间距像素
float Y_Right_Between =(image.Height / 2f - move) / Max_Y_Right;//右Y轴间距像素
PointF[] arrDataPoint1 = new PointF[2];
PointF[] arrDataPoint2 = new PointF[2];
for (int i = 0; i < Max_X; i++)
{
if(i<datas.Count)
{
float stressdata = Convert.ToSingle(datas[i]["stressdata"]);
PointF p = new PointF();
p.X = cPt.X + X_Between * i;
p.Y = cPt.Y - stressdata * Y_Left_Between;
arrDataPoint1[0] = arrDataPoint1[1];
arrDataPoint1[1] = p;
float temprdata = Convert.ToSingle(datas[i]["temprdata"]);
PointF p2 = new PointF();
p2.X = cPt.X + X_Between * i;
p2.Y = cPt.Y - temprdata * Y_Right_Between;
arrDataPoint2[0] = arrDataPoint2[1];
arrDataPoint2[1] = p2;
if (i > 0)
{
gph.DrawLine(Pens.Blue, arrDataPoint1[0].X, arrDataPoint1[0].Y, arrDataPoint1[1].X, arrDataPoint1[1].Y);
gph.DrawLine(Pens.Red, arrDataPoint2[0].X, arrDataPoint2[0].Y, arrDataPoint2[1].X, arrDataPoint2[1].Y);
}
}
}
//保存图片数据
MemoryStream stream = new MemoryStream();
image.Save(stream, ImageFormat.Gif);
//输出图片流
return stream.ToArray();
}
finally
{
gph.Dispose();
image.Dispose();
}
}
/// <summary>
/// 画左边Y轴
/// </summary>
/// <param name="gph"></param>
/// <param name="width"></param>
/// <param name="height"></param>
/// <param name="maxY"></param>
/// <param name="len"></param>
public static void DrawY_Left(Graphics gph,int width,int height, float maxY, int len)
{
float LenY = height / 2f - move;
//画出Y轴
PointF py1 = new PointF(move, move);
PointF py2 = new PointF(move, height - move);
gph.DrawLine(new Pen(Brushes.Black, 2), py1, py2);
StringFormat drawFormat = new StringFormat();
drawFormat.Alignment = StringAlignment.Far;
drawFormat.LineAlignment = StringAlignment.Center;
//画Y轴正刻度
for (int i = 0; i <= len; i++)
{
PointF px1 = new PointF(move, LenY * i / len + move);
PointF px2 = new PointF(move + 4, LenY * i / len + move);
gph.DrawLine(new Pen(Brushes.Black, 2), px1, px2);
PointF _px2 = new PointF(width- move, LenY * i / len + move);
gph.DrawLine(Pens.LightGray, px1, _px2);
string sx = (maxY - maxY * i / len).ToString();
gph.DrawString(sx, new Font("黑体", 10f), Brushes.Black, new PointF(move-15, LenY * i / len + move), drawFormat);
}
//画Y轴负刻度
for (int i = 1; i <= len; i++)
{
PointF px1 = new PointF(move, LenY * i / len + move+ LenY);
PointF px2 = new PointF(move + 4, LenY * i / len + move+ LenY);
gph.DrawLine(new Pen(Brushes.Black, 2), px1, px2);
PointF _px2 = new PointF(width - move, LenY * i / len + move+LenY);
gph.DrawLine(Pens.LightGray, px1, _px2);
string sx = (maxY * i / len*-1).ToString();
gph.DrawString(sx, new Font("黑体", 10f), Brushes.Black, new PointF(move-15, LenY * i / len + move+LenY), drawFormat);
}
Pen pen = new Pen(Color.Black, 1);
gph.DrawString(Y_Left_Title, new Font("宋体 ", 10f,FontStyle.Bold), Brushes.Black, new PointF(move-15, move / 2f), drawFormat);
}
/// <summary>
/// 画右边的Y轴
/// </summary>
/// <param name="gph"></param>
/// <param name="width"></param>
/// <param name="height"></param>
/// <param name="maxY"></param>
/// <param name="len"></param>
public static void DrawY_Right(Graphics gph, int width, int height, float maxY, int len)
{
float LenY = height / 2f - move;
//画出Y轴
PointF py1 = new PointF(width-move, move);
PointF py2 = new PointF(width-move, height - move);
gph.DrawLine(new Pen(Brushes.Black, 2), py1, py2);
StringFormat drawFormat = new StringFormat();
drawFormat.Alignment = StringAlignment.Near;
drawFormat.LineAlignment = StringAlignment.Center;
//画Y轴正刻度
for (int i = 0; i <= len; i++)
{
PointF px1 = new PointF(width-move, LenY * i / len + move);
PointF px2 = new PointF(width- move -4, LenY * i / len + move);
gph.DrawLine(new Pen(Brushes.Black, 2), px1, px2);
string sx = (maxY - maxY * i / len).ToString();
gph.DrawString(sx, new Font("黑体", 10f), Brushes.Black, new PointF(width-move+15, LenY * i / len + move), drawFormat);
}
//画Y轴负刻度
for (int i = 1; i <= len; i++)
{
PointF px1 = new PointF(width-move, LenY * i / len + move + LenY);
PointF px2 = new PointF(width-move - 4, LenY * i / len + move + LenY);
gph.DrawLine(new Pen(Brushes.Black, 2), px1, px2);
string sx = (maxY * i / len * -1).ToString();
gph.DrawString(sx, new Font("黑体", 10f), Brushes.Black, new PointF(width- move+15, LenY * i / len + move + LenY), drawFormat);
}
Pen pen = new Pen(Color.Black, 1);
gph.DrawString(Y_Right_Title, new Font("宋体 ", 10f,FontStyle.Bold), Brushes.Black, new PointF(width - move + 15, move / 2f));
}
/// <summary>
/// 画底部X轴
/// </summary>
/// <param name="gph"></param>
/// <param name="width"></param>
/// <param name="height"></param>
/// <param name="maxY"></param>
/// <param name="len"></param>
public static void DrawX_Bottom(Graphics gph, int width, int height, float maxX, int len)
{
float LenX = width - 2*move;
//画出X轴
PointF py1 = new PointF(move, height - move);
PointF py2 = new PointF(width - move, height - move);
gph.DrawLine(new Pen(Brushes.Black, 2), py1, py2);
//画X轴正刻度
for (int i = 0; i <= len; i++)
{
PointF px1 = new PointF(LenX * i / len + move, height-move);
PointF px2 = new PointF(LenX * i / len + move, height - move - 4);
gph.DrawLine(new Pen(Brushes.Black, 2), px1, px2);
PointF _px2 = new PointF(LenX * i / len + move, move);
gph.DrawLine(Pens.LightGray, px1, _px2);
StringFormat drawFormat = new StringFormat();
drawFormat.Alignment = StringAlignment.Far;
drawFormat.LineAlignment = StringAlignment.Center;
string sx =( maxX * i / len).ToString();
if(i==0)
{
gph.DrawString(sx, new Font("黑体", 10f), Brushes.Black, new PointF(LenX * i / len + move+8f, height - move / 1.2f), drawFormat);
}
else
{
gph.DrawString(sx, new Font("黑体", 10f), Brushes.Black, new PointF(LenX * i / len + move + 16f, height - move / 1.2f), drawFormat);
}
}
//X标题
gph.DrawString(X_Title, new Font("宋体 ", 10f,FontStyle.Bold), Brushes.Black, new PointF(width/2f - 5, height-move+40f));
}
/// <summary>
/// 画出顶部X轴
/// </summary>
/// <param name="gph"></param>
/// <param name="width"></param>
/// <param name="height"></param>
/// <param name="maxX"></param>
/// <param name="len"></param>
public static void DrawX_Top(Graphics gph, int width, int height, float maxX, int len)
{
float LenX = width - 2 * move;
//画出X轴
PointF py1 = new PointF(move, move);
PointF py2 = new PointF(width - move, move);
gph.DrawLine(new Pen(Brushes.Black, 2), py1, py2);
//画X轴正刻度
for (int i = 0; i <= len; i++)
{
PointF px1 = new PointF(LenX * i / len + move, move);
PointF px2 = new PointF(LenX * i / len + move, move +4);
gph.DrawLine(new Pen(Brushes.Black, 2), px1, px2);
}
}
}
代码运行:
源码下载:方配/方配自画仪器监测波形图代码