using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows.Forms.DataVisualization.Charting; using System.Drawing; namespace FLY.ControlLibrary { public class GraphRange_coslight : GraphRange { public GraphRange_coslight() : base() { this.chart1.SizeChanged += new EventHandler(chart1_SizeChanged); } /// /// 解决右边坐标显示问题 /// /// /// void chart1_SizeChanged(object sender, EventArgs e) { ChartArea area = chart1.ChartAreas[0]; Graphics g = chart1.CreateGraphics(); SizeF size = g.MeasureString("目标值", area.AxisY.LabelStyle.Font);//获取字符串尺寸 float pw = 100 * (chart1.Width - size.Width - 10) / chart1.Width; chart1.ChartAreas[0].Position.Width = (int)pw; chart1.ChartAreas[0].Position.Height = 100F; chart1.ChartAreas[0].Position.X = 0F; chart1.ChartAreas[0].Position.Y = 0F; g.Dispose(); } /// /// 获取实际应用的目标值,公差 /// /// /// /// /// /// void GetActualTargetAlarm( out double target, out double alarm, out double yrange, out double ctrlline, out bool ispercent) { double multi = Multi; if (IsAutoTarget) target = AutoTarget / multi;//AutoTarget 计算得到的平均值 else target = Target / multi; ispercent = IsPercent; if ((ispercent) && (Target <= 0) || (Alarm < 0) || (target <= 0)) ispercent = false; if (ispercent) { alarm = target * Alarm / Target; } else { alarm = Alarm / multi; } yrange = alarm * YRangePercent; if ((alarm < 0.1) || (yrange < 0.3)) { alarm = 0.1; yrange = 0.3; } ctrlline = CtrlLine / multi; } /// /// 画虚线 与 右坐标 /// /// /// protected override void Chart1_PrePaint(object sender, System.Windows.Forms.DataVisualization.Charting.ChartPaintEventArgs e) { if (e.ChartElement is ChartArea) { ChartArea area = (ChartArea)e.ChartElement; if (Double.IsNaN(area.AxisY.Minimum)) return; double alarm; double yrange; double target; double ctrlline; bool ispercent; GetActualTargetAlarm(out target, out alarm, out yrange, out ctrlline, out ispercent); //画目标值 System.Drawing.Pen pen = new System.Drawing.Pen(System.Drawing.Color.Green, 2); DrawYGridTick(e.ChartGraphics, pen, target); //画规格线 if (alarm < yrange) { pen.Color = System.Drawing.Color.Red; DrawYGridTick(e.ChartGraphics, pen, target + alarm); DrawYGridTick(e.ChartGraphics, pen, target - alarm); } //画控制线 if (HasCtrlLine) { if (ctrlline < yrange) { pen.Color = System.Drawing.Color.Orange; pen.DashStyle = System.Drawing.Drawing2D.DashStyle.Custom; pen.DashPattern = new float[] { 5, 5 }; DrawYGridTick(e.ChartGraphics, pen, target + ctrlline); if (Type == GraphRangeType.All) { pen.Color = System.Drawing.Color.Orange; DrawYGridTick(e.ChartGraphics, pen, target - ctrlline); } else { pen.Color = System.Drawing.Color.Blue; DrawYGridTick(e.ChartGraphics, pen, target - ctrlline); } } } //写字 //if (y > area.AxisY.Maximum || y < area.AxisY.Minimum) // return; ChartGraphics cg = e.ChartGraphics; Graphics graph = cg.Graphics; RectangleF rectangele_target = new RectangleF(); RectangleF rectangele_alarm_min = new RectangleF(); RectangleF rectangele_alarm_max = new RectangleF(); RectangleF rectangele_ctrlline_min = new RectangleF(); RectangleF rectangele_ctrlline_max = new RectangleF(); rectangele_target.Size = graph.MeasureString("目标值", area.AxisY.LabelStyle.Font);//获取字符串尺寸 double XMax = cg.GetPositionFromAxis(area.Name, AxisName.X, area.AxisX.Maximum); cg.GetAbsolutePoint( new System.Drawing.PointF() { X = (float)(XMax), Y = 0 }); // Convert relative coordinates to absolute coordinates. rectangele_target.Location = cg.GetAbsolutePoint(new System.Drawing.PointF() { X = (float)(XMax), Y = (float)cg.GetPositionFromAxis(area.Name, AxisName.Y, target) }); rectangele_target.X += 2; rectangele_target.Y -= rectangele_target.Height / 2;//移到中间 graph.DrawString( "目标值", area.AxisY.LabelStyle.Font, new System.Drawing.SolidBrush(System.Drawing.Color.Green), rectangele_target); //画控制线 if (HasCtrlLine) { if ((ctrlline < yrange) && (ctrlline < alarm)) { rectangele_ctrlline_min.Size = graph.MeasureString("控制线", area.AxisY.LabelStyle.Font);//获取字符串尺寸 // Convert relative coordinates to absolute coordinates. rectangele_ctrlline_min.Location = cg.GetAbsolutePoint( new System.Drawing.PointF() { X = (float)(XMax), Y = (float)cg.GetPositionFromAxis(area.Name, AxisName.Y, target - ctrlline) }); rectangele_ctrlline_min.X += 2; rectangele_ctrlline_min.Y -= rectangele_ctrlline_min.Height / 2;//移到中间 if (rectangele_ctrlline_min.Top < rectangele_target.Bottom) { rectangele_ctrlline_min.Y = rectangele_target.Bottom; } if (Type == GraphRangeType.All) { graph.DrawString( "控制线", area.AxisY.LabelStyle.Font, new System.Drawing.SolidBrush(System.Drawing.Color.Orange), rectangele_ctrlline_min); } else { graph.DrawString( "控制线", area.AxisY.LabelStyle.Font, new System.Drawing.SolidBrush(System.Drawing.Color.Blue), rectangele_ctrlline_min); } rectangele_ctrlline_max.Size = graph.MeasureString("控制线", area.AxisY.LabelStyle.Font);//获取字符串尺寸 // Convert relative coordinates to absolute coordinates. rectangele_ctrlline_max.Location = cg.GetAbsolutePoint( new System.Drawing.PointF() { X = (float)(XMax), Y = (float)cg.GetPositionFromAxis(area.Name, AxisName.Y, target + ctrlline) }); rectangele_ctrlline_max.X += 2; rectangele_ctrlline_max.Y -= rectangele_ctrlline_max.Height / 2;//移到中间 if (rectangele_ctrlline_max.Bottom > rectangele_target.Top) { rectangele_ctrlline_max.Y = rectangele_target.Top - rectangele_ctrlline_max.Height; } graph.DrawString( "控制线", area.AxisY.LabelStyle.Font, new System.Drawing.SolidBrush(System.Drawing.Color.Orange), rectangele_ctrlline_max); } } //规格线 if (alarm < yrange) { rectangele_alarm_min.Size = graph.MeasureString("规格线", area.AxisY.LabelStyle.Font);//获取字符串尺寸 // Convert relative coordinates to absolute coordinates. rectangele_alarm_min.Location = cg.GetAbsolutePoint( new System.Drawing.PointF() { X = (float)(XMax), Y = (float)cg.GetPositionFromAxis(area.Name, AxisName.Y, target - alarm) }); rectangele_alarm_min.X += 2; rectangele_alarm_min.Y -= rectangele_alarm_min.Height / 2;//移到中间 if (HasCtrlLine && (ctrlline < alarm)) { if (rectangele_alarm_min.Top < rectangele_ctrlline_min.Bottom) { rectangele_alarm_min.Y = rectangele_ctrlline_min.Bottom; } } else { if (rectangele_alarm_min.Top < rectangele_target.Bottom) { rectangele_alarm_min.Y = rectangele_target.Bottom; } } graph.DrawString( "规格线", area.AxisY.LabelStyle.Font, new System.Drawing.SolidBrush(System.Drawing.Color.Red), rectangele_alarm_min); rectangele_alarm_max.Size = graph.MeasureString("规格线", area.AxisY.LabelStyle.Font);//获取字符串尺寸 // Convert relative coordinates to absolute coordinates. rectangele_alarm_max.Location = cg.GetAbsolutePoint( new System.Drawing.PointF() { X = (float)(XMax), Y = (float)cg.GetPositionFromAxis(area.Name, AxisName.Y, target + alarm) }); rectangele_alarm_max.X += 2; rectangele_alarm_max.Y -= rectangele_alarm_max.Height / 2;//移到中间 if (HasCtrlLine && (ctrlline < alarm)) { if (rectangele_alarm_max.Bottom > rectangele_ctrlline_max.Top) { rectangele_alarm_max.Y = rectangele_ctrlline_max.Top - rectangele_alarm_max.Height; } } else { if (rectangele_alarm_max.Bottom > rectangele_target.Top) { rectangele_alarm_max.Y = rectangele_target.Top - rectangele_alarm_max.Height; } } graph.DrawString( "规格线", area.AxisY.LabelStyle.Font, new System.Drawing.SolidBrush(System.Drawing.Color.Red), rectangele_alarm_max); } } } void DrawYGridTick(ChartGraphics cg, System.Drawing.Pen pen, double y) { ChartArea area = chart1.ChartAreas[0]; if (y > area.AxisY.Maximum || y < area.AxisY.Minimum) return; // Take Graphics object from chart Graphics graph = cg.Graphics; // Convert X and Y values to screen position double py = cg.GetPositionFromAxis(area.Name, AxisName.Y, y); double XMin = cg.GetPositionFromAxis(area.Name, AxisName.X, area.AxisX.Minimum); double XMax = cg.GetPositionFromAxis(area.Name, AxisName.X, area.AxisX.Maximum); System.Drawing.PointF[] points = new System.Drawing.PointF[2]; points[0].X = (float)XMin; points[1].X = (float)XMax; points[0].Y = points[1].Y = (float)py; // Convert relative coordinates to absolute coordinates. points[0] = cg.GetAbsolutePoint(points[0]); points[1] = cg.GetAbsolutePoint(points[1]); graph.DrawLine(pen, points[0], points[1]); } #region 2sigma protected override void UpdateAxisY_2sigma() { double multi = Multi; double alarm; double yrange; if (IsPercent) { alarm = 100.0 * Alarm / Target; yrange = alarm * YRangePercent; } else { alarm = Alarm / multi; yrange = alarm * YRangePercent; } if ((alarm < 0.1) || (yrange < 0.3)) { alarm = 0.1; yrange = 0.3; } Axis axisY = chart1.ChartAreas["chartArea1"].AxisY; //TODO axisY.Crossing = 0; // Set manual minimum and maximum values. axisY.Minimum = -yrange; axisY.Maximum = yrange; axisY.CustomLabels.Clear(); //上下限 SetCustomLabel_2sigma(axisY, alarm, GridTickTypes.All, System.Drawing.Color.Red, IsPercent, null); SetCustomLabel_2sigma(axisY, -alarm, GridTickTypes.All, System.Drawing.Color.Red, IsPercent, null); //显示范围数值 SetCustomLabel_2sigma(axisY, axisY.Minimum, GridTickTypes.TickMark, System.Drawing.Color.DarkViolet, IsPercent, null); SetCustomLabel_2sigma(axisY, axisY.Maximum, GridTickTypes.TickMark, System.Drawing.Color.DarkViolet, IsPercent, null); //显示范围数值 if ((yrange != 2 * alarm)) { SetCustomLabel_2sigma(axisY, alarm * 2, GridTickTypes.TickMark, System.Drawing.Color.Black, IsPercent, null); SetCustomLabel_2sigma(axisY, -alarm * 2, GridTickTypes.TickMark, System.Drawing.Color.Black, IsPercent, null); } //显示范围太小,多加纵坐标 if (yrange <= alarm) { SetCustomLabel_2sigma(axisY, (axisY.Maximum + axisY.Minimum) / 2 - (axisY.Maximum - axisY.Minimum) / 4, GridTickTypes.All, System.Drawing.Color.Black, IsPercent, null); SetCustomLabel_2sigma(axisY, (axisY.Maximum + axisY.Minimum) / 2 + (axisY.Maximum - axisY.Minimum) / 4, GridTickTypes.All, System.Drawing.Color.Black, IsPercent, null); } } protected override void UpdateOnePoint_2sigma(int index) { double multi = Multi; int emptyvalue = EmptyValue; DataPoint point; double sigma2 = 2 * DataSource[index].Sigma / multi; double avg = DataSource[index].Avg / multi; if (IsPercent) { if (avg <= 0) { //异常 sigma2 = 0; } else { sigma2 = sigma2 / avg * 100; } } if (index >= chart1.Series["series_sigma"].Points.Count) { chart1.Series["series_sigma"].Points.AddXY(index, sigma2, -sigma2); point = chart1.Series["series_sigma"].Points[index]; } else { point = chart1.Series["series_sigma"].Points[index]; point.YValues[0] = sigma2; point.YValues[1] = -sigma2; point.XValue = index; } //设定空数据 if (DataSource[index].Avg == emptyvalue) { point.IsEmpty = true; } else { point.IsEmpty = false; double threshold05; double threshold1; double threshold2; if (IsPercent) { threshold1 = 100.0 * Alarm / Target; threshold05 = 100.0 * CtrlLine / Target; threshold2 = threshold1 * YRangePercent; } else { threshold1 = Alarm / multi; threshold05 = CtrlLine / Target; threshold2 = threshold1 * YRangePercent; } System.Drawing.Color c; if (sigma2 > threshold2) c = System.Drawing.Color.Violet; else if (sigma2 > threshold1) c = System.Drawing.Color.Red; else if (sigma2 > threshold05) c = System.Drawing.Color.Orange; else c = System.Drawing.Color.Green; point.BorderColor = c; point.Color = c; } } #endregion #region all protected override void UpdateOnePoint_all(int index) { double multi = Multi; int emptyvalue = EmptyValue; DataPoint point_sigma; DataPoint point_avg; double sigma2 = 2 * DataSource[index].Sigma / multi; double avg = DataSource[index].Avg / multi; if (index >= chart1.Series["series_sigma"].Points.Count) { chart1.Series["series_sigma"].Points.AddXY(index, avg + sigma2, avg - sigma2); point_sigma = chart1.Series["series_sigma"].Points[index]; chart1.Series["series_avg"].Points.AddXY(index, avg); point_avg = chart1.Series["series_avg"].Points[index]; } else { point_sigma = chart1.Series["series_sigma"].Points[index]; point_sigma.YValues[0] = avg + sigma2; point_sigma.YValues[1] = avg - sigma2; point_sigma.XValue = index; point_avg = chart1.Series["series_avg"].Points[index]; point_avg.YValues[0] = avg; point_avg.XValue = index; } //设定空数据 if (DataSource[index].Avg == emptyvalue) { point_sigma.IsEmpty = true; point_avg.IsEmpty = true; } else { point_sigma.IsEmpty = false; double alarm; double yrange; double target; double ctrlline; bool ispercent; GetActualTargetAlarm(out target, out alarm, out yrange, out ctrlline, out ispercent); double threshold05 = ctrlline; double threshold1 = alarm; double threshold2 = yrange; System.Drawing.Color c; if (((avg + sigma2) > (target + threshold2)) || ((avg + sigma2) < (target - threshold2))) { c = System.Drawing.Color.Violet; } else if (((avg - sigma2) > (target + threshold2)) || ((avg - sigma2) < (target - threshold2))) { c = System.Drawing.Color.Violet; } else if (((avg + sigma2) > (target + threshold1)) || ((avg + sigma2) < (target - threshold1))) { c = System.Drawing.Color.Red; } else if (((avg - sigma2) > (target + threshold1)) || ((avg - sigma2) < (target - threshold1))) { c = System.Drawing.Color.Red; } else { if (((avg + sigma2) > (target + threshold05)) || ((avg + sigma2) < (target - threshold05))) { c = System.Drawing.Color.Orange; } else if (((avg - sigma2) > (target + threshold05)) || ((avg - sigma2) < (target - threshold05))) { c = System.Drawing.Color.Orange; } else { c = System.Drawing.Color.Green; } } point_sigma.BorderColor = c; point_sigma.Color = c; point_avg.Color = System.Drawing.Color.FromArgb(((int)(((byte)(220)))), ((int)(((byte)(65)))), ((int)(((byte)(140)))), ((int)(((byte)(240))))); point_avg.BorderColor = System.Drawing.Color.FromArgb(((int)(((byte)(180)))), ((int)(((byte)(26)))), ((int)(((byte)(59)))), ((int)(((byte)(105))))); } } #endregion #region avg protected override void UpdateAxisY_avg() { double alarm; double yrange; double target; double ctrlline; bool ispercent; GetActualTargetAlarm(out target, out alarm, out yrange, out ctrlline, out ispercent); Axis axisY = chart1.ChartAreas["chartArea1"].AxisY; axisY.Crossing = target; // Set manual minimum and maximum values. axisY.Minimum = target - yrange; axisY.Maximum = target + yrange; axisY.CustomLabels.Clear(); //目标值 SetCustomLabel(axisY, target, GridTickTypes.All, System.Drawing.Color.Green, false, null); //上下限 SetCustomLabel(axisY, target + alarm, GridTickTypes.All, System.Drawing.Color.Red, ispercent, null); SetCustomLabel(axisY, target - alarm, GridTickTypes.All, System.Drawing.Color.Red, ispercent, null); //显示范围数值 SetCustomLabel(axisY, axisY.Minimum, GridTickTypes.All, System.Drawing.Color.DarkViolet, ispercent, null); SetCustomLabel(axisY, axisY.Maximum, GridTickTypes.All, System.Drawing.Color.DarkViolet, ispercent, null); //显示范围数值 if (yrange != 2 * alarm) { SetCustomLabel(axisY, target + alarm * 2, GridTickTypes.TickMark, System.Drawing.Color.Black, ispercent, null); SetCustomLabel(axisY, target - alarm * 2, GridTickTypes.TickMark, System.Drawing.Color.Black, ispercent, null); } //显示范围太小,多加纵坐标 if (yrange <= alarm) { SetCustomLabel(axisY, target - yrange / 2, GridTickTypes.All, System.Drawing.Color.Black, ispercent, null); SetCustomLabel(axisY, target + yrange / 2, GridTickTypes.All, System.Drawing.Color.Black, ispercent, null); } } protected override void UpdateOnePoint_avg(int index) { double multi = Multi; int emptyvalue = EmptyValue; DataPoint point_avg; double avg = DataSource[index].Avg / multi; if (index >= chart1.Series["series_avg"].Points.Count) { chart1.Series["series_avg"].Points.AddXY(index, avg); point_avg = chart1.Series["series_avg"].Points[index]; } else { point_avg = chart1.Series["series_avg"].Points[index]; point_avg.YValues[0] = avg; point_avg.XValue = index; } //设定空数据 if (DataSource[index].Avg == emptyvalue) { point_avg.IsEmpty = true; } else { point_avg.IsEmpty = false; double alarm; double yrange; double target; double ctrlline; bool ispercent; GetActualTargetAlarm(out target, out alarm, out yrange, out ctrlline, out ispercent); double data = avg; System.Drawing.Color c; if (data > (target + yrange)) { c = System.Drawing.Color.Violet; } else if (data > (target + alarm)) { c = System.Drawing.Color.Red; } else if (data >= (target - alarm)) { if (HasCtrlLine) { if (data > (target + ctrlline)) { c = System.Drawing.Color.Orange; } else if (data >= (target - ctrlline)) { c = System.Drawing.Color.Green; } else { c = System.Drawing.Color.FromArgb(0x00, 0x8B, 0xE5); } } else { c = System.Drawing.Color.Green; } } else if (data >= (target - yrange)) { c = System.Drawing.Color.Red; } else { c = System.Drawing.Color.Violet; } point_avg.BorderColor = c; point_avg.Color = c; } } #endregion } }