直方图分为坐标系和竖条组成 首先画坐标系 using System; using System.Collections.Generic; using System.Text; using System.Drawing; using System.Collections; namespace Sirc.cem.ZFT { /// <summary> /// 直角坐标系类 /// 用于表示气象自动站时段内降雨量在各个时间的分布 /// </summary> public class ZFTCoordinate { private int jtLength = 20; //箭头的长度 private int valueLent = 4; //刻度线的长度 private Hashtable table = new Hashtable(); //记录直方图X轴各个刻度的坐标,用键值对的形式保存在table中 List<ZFTCell> cellList = null; /// <summary> /// 各个小直方图单元集合 /// </summary> public List<ZFTCell> CellList { get { return cellList; } set { cellList = value; } } private double xCellValue = 0; //X轴一个单元格表示的值 /// <summary> /// X轴一个单元格表示的值 /// </summary> public double XCellValue { get { return xCellValue; } set { xCellValue = value; } } private int xCellCount = 0; //X轴单元格的数目 /// <summary> /// X轴单元格的数目 /// </summary> public int XCellCount { get { return xCellCount; } set { xCellCount = value; } } private int xCellLength = 0; //X轴单元格长度 /// <summary> /// X轴单元格长度 /// </summary> public int XCellLength { get { return xCellLength; } set { xCellLength = value; } } private double yCellValue = 0; //Y轴一个单元格表示的值 /// <summary> /// Y轴一个单元格表示的值 /// </summary> public double YCellValue { get { return yCellValue; } set { yCellValue = value; } } private int yCellCount = 0; //Y轴单元格的数目 /// <summary> /// Y轴单元格的数目 /// </summary> public int YCellCount { get { return yCellCount; } set { yCellCount = value; } } private int yCellLength = 0; //Y轴单元格长度 /// <summary> /// Y轴单元格长度 /// </summary> public int YCellLength { get { return yCellLength; } set { yCellLength = value; } } private int xStyle = 0; //X轴的样式,0表示从08点-08点 1表示20点-20点 2表示近多少小时 /// <summary> /// X轴的样式, /// 0表示从08点-08点 也就是fromHour需要加上8 /// 1表示20点-20点 也就是fromHour需要加上20 /// 2表示近多少小时 fromHour不需要加任何数值 /// 默认是0 /// </summary> public int XStyle { get { return xStyle; } set { xStyle = value; } } private Point coordinatesOrigin; //坐标原点origin of coordinates /// <summary> /// 坐标原点 /// </summary> public Point CoordinatesOrigin { get { return coordinatesOrigin; } set { coordinatesOrigin = value; } } private int fromHour = 0; //起点时间 /// <summary> /// 起点时间 /// X轴的起点时间 /// </summary> public int FromHour { get { return fromHour; } set { fromHour = value; if (fromHour == 8) xStyle = 0; else if (fromHour == 20) xStyle = 1; else xStyle = 2; } } public ZFTCoordinate() { } public ZFTCoordinate(double xCellValue, int xCellCount, double yCellValue, int yCellCount) { this.xCellCount = xCellCount; this.xCellValue = xCellValue; this.yCellCount = yCellCount; this.yCellValue = yCellValue; } /// <summary> /// 依据雨量的最大值 /// 计算Y轴刻度值的分布 /// 保证直方图尽量的大 /// </summary> /// <param name="maxRainfall"></param> public void SetYValue(double maxRainfall) { if (maxRainfall > 5) { //计算Y轴刻度最大值 //计算方法:用最大雨量除以5,取整数加上1,再乘以5 int count1 = Convert.ToInt32(maxRainfall / 5); int count2 = count1 + 1; double maxCellValue = count2 * 5; yCellValue = maxCellValue / 5; } else { yCellValue = 1; } } /// <summary> /// 画直方图 /// 包括坐标系 雨量等 /// </summary> /// <param name="width"></param> /// <param name="height"></param> /// <returns></returns> public Image Draw(int width,int height) { Image img = new Bitmap(width, height); Graphics g = Graphics.FromImage(img); //画坐标系 DrawXLine(g); DrawYLine(g); DrawCell(g, cellList); g.Dispose(); return img; } /// <summary> /// 利用坐标系参数 画坐标系 /// </summary> /// <param name="g"></param> private void DrawXLine(Graphics g) { //坐标原点CoordinatesOrigin //画X轴 //一个单元格一个单元格的画 Point fromPt = coordinatesOrigin; Point toPt = new Point(); Pen pen = new Pen(Color.Black); Font font = new Font("宋体", 9); for (int i = 0; i < xCellCount; i++) { //画单元格 toPt = new Point(fromPt.X + xCellLength, fromPt.Y); g.DrawLine(pen, fromPt, toPt); //画刻度线 Point xCellValuePoint = new Point(toPt.X, toPt.Y + valueLent); g.DrawLine(pen, toPt, xCellValuePoint); //画数值 只画偶数 int hour = i; if (i % 2 == 0) { string s = ""; if (xStyle == 0) { hour = hour + 8; } else if (xStyle == 1) { hour = hour + 20; } else { if (fromHour % 2 != 0) hour = hour + fromHour - 1; else hour = hour + fromHour; } if (hour == 24) { hour = 0; } else if (hour > 24) { hour = hour - 24; } s = (hour < 10) ? ("0" + hour) : hour + ""; //保存刻度点 用来画直方图时使用 if (i > 0) { table.Add(hour, toPt); } else table.Add(-1, toPt);//X轴第一个点 Point sPoint = new Point(xCellValuePoint.X - 7, xCellValuePoint.Y + 5); g.DrawString(s, font, Brushes.Black, sPoint); } fromPt = toPt; } //画箭头 Point jtPoint = new Point(toPt.X + jtLength, toPt.Y); g.DrawLine(pen, toPt, jtPoint); g.DrawLine(pen, jtPoint.X, jtPoint.Y, jtPoint.X - jtLength / 4, jtPoint.Y + jtLength / 4); g.DrawLine(pen, jtPoint.X, jtPoint.Y, jtPoint.X - jtLength / 4, jtPoint.Y - jtLength / 4); //画单位 Point sjtPoint = new Point(jtPoint.X + 5, jtPoint.Y+5); string jts = "时"; g.DrawString(jts, font, Brushes.Black, sjtPoint); pen.Dispose(); font.Dispose(); } /// <summary> /// 利用坐标系参数 画坐标系 /// </summary> /// <param name="g"></param> private void DrawYLine(Graphics g) { //坐标原点CoordinatesOrigin //画X轴 //一个单元格一个单元格的画 Point fromPt = coordinatesOrigin; Point toPt = new Point(); Pen pen = new Pen(Color.Black); Font font = new Font("宋体", 9); for (int i = 0; i < yCellCount; i++) { //画单元格 toPt = new Point(fromPt.X, fromPt.Y - yCellLength); g.DrawLine(pen, fromPt, toPt); //画刻度线 Point yCellValuePoint = new Point(toPt.X - valueLent, toPt.Y); g.DrawLine(pen, toPt, yCellValuePoint); //画数值 Point sPoint = new Point(yCellValuePoint.X - 20, yCellValuePoint.Y - 5); string s = (i + 1) * yCellValue + ""; g.DrawString(s, font, Brushes.Black, sPoint); fromPt = toPt; } //画箭头 Point jtPoint = new Point(toPt.X, toPt.Y - jtLength); g.DrawLine(pen, toPt, jtPoint); g.DrawLine(pen, jtPoint.X, jtPoint.Y, jtPoint.X + jtLength / 4, jtPoint.Y + jtLength / 4); g.DrawLine(pen, jtPoint.X, jtPoint.Y, jtPoint.X - jtLength / 4, jtPoint.Y + jtLength / 4); //画单位 Point sjtPoint = new Point(jtPoint.X + 10, jtPoint.Y); string jts = "毫米"; g.DrawString(jts, font, Brushes.Black, sjtPoint); pen.Dispose(); font.Dispose(); } /// <summary> /// 画直方图 /// </summary> /// <param name="g"></param> private void DrawCell(Graphics g,List<ZFTCell> cellList) { if (cellList == null) return; Pen pen = new Pen(Color.Black); foreach (ZFTCell cell in cellList) { System.Drawing.Point fromPt = new Point(); int hours = cell.Hour; if (hours % 2 != 0) { hours = hours - 1; if(hours == fromHour) fromPt = (Point)table[-1]; else fromPt = (Point)table[hours]; fromPt.X += xCellLength; } else { fromPt = (Point)table[hours]; } int lenth = Convert.ToInt32((cell.Rainfall / yCellValue) * yCellLength); Point leftUp = new Point(fromPt.X - xCellLength / 2, fromPt.Y - lenth); Point rightLow = new Point(fromPt.X + xCellLength / 2, fromPt.Y); Rectangle rect = new Rectangle(leftUp.X, leftUp.Y, rightLow.X - leftUp.X, rightLow.Y - leftUp.Y); g.FillRectangle(Brushes.LightBlue, rect); g.DrawRectangle(pen, rect); } } } } 接下来是构造各个直方图单元格 using System; using System.Collections.Generic; using System.Text; namespace Sirc.cem.ZFT { /// <summary> /// 直方图类 /// 存有雨量值和对应的时间 /// </summary> public class ZFTCell { private int hour = 0; //几点 /// <summary> /// 标志该单元格表示的是几点的雨量 /// </summary> public int Hour { get { return hour; } set { hour = value; } } private double rainfall = 0; //雨量 /// <summary> /// 雨量值 /// </summary> public double Rainfall { get { return rainfall; } set { rainfall = value; } } public ZFTCell(int hour, double rainfall) { this.hour = hour; this.rainfall = rainfall; } } } 最后是使用方法 //分析直方图的值 double maxRainfall = 0;//表示雨量的最大值,用来计算Y轴刻度值的分布 List<ZFTCell> cellList = new List<ZFTCell>(); string[] splitDoller = { "$" }; string[] cellStrArr = s.Split(splitDoller, StringSplitOptions.RemoveEmptyEntries); foreach (string cellStr in cellStrArr) { if (cellStr.IndexOf("-") == -1) continue; string[] splitCellStr = { "-" }; string[] cellInfoArr = cellStr.Split(splitCellStr, StringSplitOptions.RemoveEmptyEntries); int hour = Convert.ToInt32(cellInfoArr[0]); double rainfall = Convert.ToDouble(cellInfoArr[1]); ZFTCell cell = new ZFTCell(hour, rainfall); maxRainfall = Math.Max(maxRainfall, rainfall); cellList.Add(cell); } //画直方图 ZFTCoordinate c = new ZFTCoordinate(1, 25, 0, 5); //fromTime是世界时,而直方图上显示的为北京时,所以要进行一个转换 c.FromHour = fromTime.Hour + 8; c.SetYValue(maxRainfall); c.CoordinatesOrigin = new System.Drawing.Point(30, 120); c.XCellLength = 10; c.YCellLength = 20; c.CellList = cellList; Image img = c.Draw(this.pictureBoxZFT.Width, this.pictureBoxZFT.Height); this.pictureBoxZFT.Image = img;