using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows.Forms.DataVisualization.Charting; using System.Drawing; using System.Data; namespace QMAPP.WinForm.Common.SPCMonitor { /// /// 描述:SPC图表帮助类 /// 作者:单雨春 /// 日期:2015年5月28日11:03:02 /// public class ChartHelper { /// /// 画趋势图 /// /// /// /// public static Chart DrawTendencyChart(Chart chart, DataTable dt, string quota) { //获得坐标的最大值及最小值 ChartValueModel chartValue = GetChartValueForTendency(dt, quota); //设置图表的坐标 chart.ChartAreas.FirstOrDefault().AxisY.Interval = chartValue.Step; chart.ChartAreas.FirstOrDefault().AxisY.Maximum = chartValue.MaxOfCoord; chart.ChartAreas.FirstOrDefault().AxisY.Minimum = chartValue.MinOfCoord; //画上限、下限之间的格线 for (double tempValue = chartValue.Min; tempValue < chartValue.Max; tempValue += chartValue.Step) { StripLine dash = new StripLine(); dash.BackColor = System.Drawing.Color.Silver; dash.BorderDashStyle = ChartDashStyle.Dash; dash.IntervalOffset = Math.Round(tempValue,2); dash.StripWidth = 0.0001; chart.ChartAreas.FirstOrDefault().AxisY.StripLines.Add(dash); } //下限 StripLine minLine = new StripLine(); minLine.BackColor = Color.FromArgb(0, 90, 0); minLine.BorderDashStyle = ChartDashStyle.Dash; minLine.IntervalOffset = Convert.ToDouble(chartValue.Min); minLine.StripWidth = 0.0001; minLine.Text = chartValue.Min.ToString(); minLine.TextAlignment = StringAlignment.Far; chart.ChartAreas.FirstOrDefault().AxisY.StripLines.Add(minLine); //上限 StripLine maxLine = new StripLine(); maxLine.BackColor = Color.FromArgb(0, 90, 0); maxLine.BorderDashStyle = ChartDashStyle.Dash; maxLine.IntervalOffset = Convert.ToDouble(chartValue.Max); maxLine.StripWidth = 0.0001; maxLine.Text = chartValue.Max.ToString(); maxLine.TextAlignment = StringAlignment.Far; chart.ChartAreas.FirstOrDefault().AxisY.StripLines.Add(maxLine); //中值 StripLine midLine = new StripLine(); midLine.BackColor = Color.FromArgb(0, 90, 0); midLine.BorderDashStyle = ChartDashStyle.Dash; midLine.IntervalOffset = Convert.ToDouble(chartValue.Middle); midLine.StripWidth = 0.0001; midLine.Text = chartValue.Middle.ToString(); midLine.TextAlignment = StringAlignment.Far; chart.ChartAreas.FirstOrDefault().AxisY.StripLines.Add(midLine); //去掉X轴的标签 chart.ChartAreas.FirstOrDefault().AxisX.LabelStyle.Enabled = false; return chart; } // /// 画分布 /// /// /// /// public static Chart DrawDistributionChart(Chart chart, DataTable dt,Dictionary dict, string quota) { //获得坐标的最大值及最小值 ChartValueModel chartValue = GetChartValueForDistribution(dt, quota); //设置图表的坐标 chart.ChartAreas.FirstOrDefault().AxisX.Interval = chartValue.Step; chart.ChartAreas.FirstOrDefault().AxisX.Maximum = chartValue.MaxOfCoord; chart.ChartAreas.FirstOrDefault().AxisX.Minimum = chartValue.MinOfCoord; //均值 double avg = dt.AsEnumerable().Average(p => Convert.ToDouble(p[quota])); //均方差 double dev = Math.Sqrt(dt.AsEnumerable().Average(p => Math.Pow(Convert.ToDouble(p[quota]) - avg, 2))); //标题 Title title = new Title("3σ = " + 3 * Math.Round(dev, 6) + "\n" + " ¯x = " + Math.Round(avg, 6), Docking.Right); title.TextOrientation = TextOrientation.Horizontal; title.Alignment = ContentAlignment.TopRight; title.ForeColor = System.Drawing.Color.RoyalBlue; title.IsDockedInsideChartArea = true; title.DockedToChartArea = "ChartA"; chart.Titles.Add(title); //高斯图形 Series seriesGaussian = GetGaussianSeries(dict.Values.Max(), avg, dev); chart.Series.Add(seriesGaussian); //下限 StripLine minLine = new StripLine(); minLine.BackColor = System.Drawing.Color.Green; minLine.BorderDashStyle = ChartDashStyle.Dash; minLine.IntervalOffset = avg - 3 * dev; minLine.StripWidth = 0.0001; minLine.Text = "3σ"; minLine.TextAlignment = StringAlignment.Far; minLine.TextOrientation = TextOrientation.Horizontal; chart.ChartAreas.FirstOrDefault().AxisX.StripLines.Add(minLine); //上限 StripLine maxLine = new StripLine(); maxLine.BackColor = System.Drawing.Color.Green; maxLine.BorderDashStyle = ChartDashStyle.Dash; maxLine.IntervalOffset = avg + 3 * dev; maxLine.StripWidth = 0.0001; maxLine.Text = "3σ"; maxLine.TextAlignment = StringAlignment.Far; maxLine.TextOrientation = TextOrientation.Horizontal; chart.ChartAreas.FirstOrDefault().AxisX.StripLines.Add(maxLine); //中值 StripLine midLine = new StripLine(); midLine.BackColor = System.Drawing.Color.Orange; midLine.BorderDashStyle = ChartDashStyle.Dash; midLine.IntervalOffset = avg; midLine.StripWidth = 0.0001; midLine.Text = "¯x"; midLine.TextOrientation = TextOrientation.Stacked; midLine.TextAlignment = StringAlignment.Far; chart.ChartAreas.FirstOrDefault().AxisX.StripLines.Add(midLine); //去掉Y轴的标签 chart.ChartAreas.FirstOrDefault().AxisY.LabelStyle.Enabled = false; return chart; } /// /// 趋势图-设置坐标及间隔 /// /// /// public static ChartValueModel GetChartValueForTendency(DataTable dt, string quota) { ChartValueModel chartValue = new ChartValueModel(); DataRow dr = dt.AsEnumerable().FirstOrDefault(); //取得最大值和最小值 chartValue.Min = Convert.ToDouble(dr["MIN"]); chartValue.Max = Convert.ToDouble(dr["MAX"]); chartValue.Middle = Convert.ToDouble(chartValue.Min + chartValue.Max) / 2; //计算间隔 chartValue.Step = (chartValue.Max - chartValue.Min) / 10.0; //计算最大坐标和最小坐标 chartValue.MaxOfCoord = chartValue.Max + chartValue.Step * 5; chartValue.MinOfCoord = chartValue.Min - chartValue.Step * 5; return chartValue; } /// /// 分布图-设置坐标及间隔 /// /// /// public static ChartValueModel GetChartValueForDistribution(DataTable dt, string quota) { ChartValueModel chartValue = new ChartValueModel(); DataRow dr = dt.AsEnumerable().FirstOrDefault(); //取得最大值和最小值 chartValue.Min = dt.AsEnumerable().Min(p => Convert.ToDouble(p[quota])); chartValue.Max = dt.AsEnumerable().Max(p => Convert.ToDouble(p[quota])); //计算间隔 chartValue.Step = double.Parse(dr["STEP"].ToString()); //计算最大坐标和最小坐标 chartValue.MaxOfCoord = chartValue.Max + chartValue.Step * 3; chartValue.MinOfCoord = chartValue.Min - chartValue.Step * 3; return chartValue; } /// /// 获取高斯函数图形 /// /// Y轴最大 /// 均值 /// 均方差 /// private static Series GetGaussianSeries(int yMax, double avg, double dev) { #region 高斯算法 List gass = new List(); double min = avg - 6 * dev; double max = avg + 6 * dev; double step = (max - min) / 100; if (step == 0) step = Int32.MaxValue; for (double m = min; m <= max; m += step) { GaussianModel model = new GaussianModel(); double y = (1 / (Math.Sqrt(2 * Math.PI) * dev)) * Math.Pow(Math.E, 0 - (Math.Pow(m - avg, 2) / (2 * Math.Pow(dev, 2)))); model.X = m; model.Y = y; gass.Add(model); } #endregion #region 画高斯图形 Series seriesGass = new Series(); seriesGass.ChartType = SeriesChartType.Spline; double pram = 0; double temp = 0; pram = yMax * 1.1; //double gassMax = gass[50].Y; double gassMax = gass.Max(o => o.Y); temp = pram / gassMax; foreach (GaussianModel item in gass) { seriesGass.Points.AddXY(item.X, temp * item.Y); } #endregion return seriesGass; } /// /// 取Bar图的所有坐标 /// /// /// public static Dictionary GetBarValue(DataTable dt, string quota) { Type type = dt.Columns[quota].DataType; Dictionary dict = new Dictionary(); double min = dt.AsEnumerable().Min(p => Convert.ToDouble(p[quota])); double max = dt.AsEnumerable().Max(p => Convert.ToDouble(p[quota])); double step = Convert.ToDouble(dt.AsEnumerable().FirstOrDefault()["STEP"]); for (double tempValue = min; tempValue <= max; tempValue += step) { var rowCount = dt.AsEnumerable().Where(p => Convert.ToDouble(p[quota]) > tempValue - step/2 && Convert.ToDouble(p[quota]) <= tempValue + step/2).Count(); dict.Add(tempValue, rowCount); } return dict; } } }