using DevExpress.Utils; using DevExpress.XtraCharts; using System; using System.Collections.Generic; using System.Drawing; using System.Drawing.Drawing2D; using System.Linq; using System.Windows.Forms; namespace TProduct.WinFrmUI.TPump { internal partial class ChartNpshTestIngCtrl : DevExpress.XtraEditors.XtraUserControl { #region 私有字段 //坐标 private TProduct.Model.CoordinateNpsh _coordinateParas = null; private double _coordMaxX = 0; private double _coordMinY = 100000, _coordMaxY = 0; //测试点 private Series SeriesPoint = null; private DevExpress.XtraCharts.ConstantLine _constantLineThreshold = null; // private DevExpress.XtraCharts.XYDiagram mainChartDiagram; // AxisX AxisX = null; AxisY AxisY = null; private List _allRecords = new List(); private TProduct.Model.eNpshTestMethod _npshTestMethod = TProduct.Model.eNpshTestMethod.ByH; #endregion #region 构造函数和加载函数 public ChartNpshTestIngCtrl() { InitializeComponent(); #region 图标控件显示 this.chartControl1.MouseClick += new System.Windows.Forms.MouseEventHandler(this.chartControl_MouseClick); mainChartDiagram = (XYDiagram)chartControl1.Diagram; //设置此属性 this.chartControl1.SelectionMode = ElementSelectionMode.Single;// = true;// 表示可以选择CHART上物体 //this.chartControl1.RuntimeSeriesSelectionMode = SeriesSelectionMode.Point;//系列选择是选择其中的点而不是整个系列 //this.chartControl1.RuntimeSeriesSelectionMode = SeriesSelectionMode.Series; this.chartControl1.SeriesSelectionMode = SeriesSelectionMode.Series; SeriesPoint = chartControl1.Series["SeriesPoint"]; SeriesPoint.ArgumentScaleType = DevExpress.XtraCharts.ScaleType.Numerical; SeriesPoint.CrosshairEnabled = DefaultBoolean.True; SeriesPoint.Visible = false; // AxisX = mainChartDiagram.AxisX; AxisY = mainChartDiagram.AxisY; AxisX.Visibility = DefaultBoolean.False; AxisY.Visibility = DefaultBoolean.False; // _constantLineThreshold = AxisY.ConstantLines[0]; _constantLineThreshold.Visible = false; #endregion this.chartControl1.CustomPaint += new DevExpress.XtraCharts.CustomPaintEventHandler(this.chartControl_CustomPaint); // this.chartControl1.ObjectHotTracked += new DevExpress.XtraCharts.HotTrackEventHandler(this.chartControl_ObjectHotTracked); // ////this.chartControl1.MouseLeave += new System.EventHandler(this.chartControl1_MouseLeave); // this.chartControl1.MouseMove += new System.Windows.Forms.MouseEventHandler(this.chartControl_MouseMove); // this.chartControl1.MouseUp += new System.Windows.Forms.MouseEventHandler(this.chartControl_MouseUp); // this.chartControl1.MouseDown += new System.Windows.Forms.MouseEventHandler(this.chartControl_MouseDown); // this.chartControl1.MouseClick += new System.Windows.Forms.MouseEventHandler(this.chartControl_MouseClick); power_unit = TProduct.UserSetting.Setting.PumpTest.UnitPower; flow_unit = TProduct.UserSetting.Setting.PumpTest.UnitFlow; head_unit = TProduct.UserSetting.Setting.PumpTest.UnitHead; } protected Eventech.Model.UnitP power_unit = Eventech.Model.UnitP.KW; protected Eventech.Model.UnitQ flow_unit = Eventech.Model.UnitQ.M3H; protected Eventech.Model.UnitH head_unit = Eventech.Model.UnitH.M; private void LoadWindow(object sender, EventArgs e) { if (_npshTestMethod == TProduct.Model.eNpshTestMethod.ByE) { AxisY.Title.Text = "效率"; } else { AxisY.Title.Text = "扬程"; } SetChartDisplay(); } //设置显示 private void SetChartDisplay() { // AxisX.Color = Properties.Settings.Default.CoordColorNPSH; // AxisX.Label.TextColor = Properties.Settings.Default.CoordColorNPSH; // AxisX.Title.TextColor = Properties.Settings.Default.CoordColorNPSH; // AxisX.MinorCount = Properties.Settings.Default.MinorCountNPSH; // AxisX.Label.Font = Properties.Settings.Default.AxisLabelFontNPSH; // AxisX.Title.Font = Properties.Settings.Default.AxisTitleFontNPSH; // AxisX.GridLines.Color = Properties.Settings.Default.GridLinesColorX; // AxisX.GridLines.MinorColor = Properties.Settings.Default.GridLinesColorX; // AxisX.GridLines.MinorVisible = Properties.Settings.Default.IsDispMinorLineX; // if (_npshTestMethod == eNpshTestMethod.ByH) // { // AxisY.Color = Properties.Settings.Default.CoordColorH; // AxisY.Label.TextColor = Properties.Settings.Default.CoordColorH; // AxisY.Title.TextColor = Properties.Settings.Default.CoordColorH; // AxisY.MinorCount = Properties.Settings.Default.MinorCountH; // AxisY.Label.Font = Properties.Settings.Default.AxisLabelFontH; // AxisY.Title.Font = Properties.Settings.Default.AxisTitleFontH; // AxisY.GridLines.Color = Properties.Settings.Default.GridLinesColorY; // } // else // { // AxisY.Color = Properties.Settings.Default.CoordColorE; // AxisY.Label.TextColor = Properties.Settings.Default.CoordColorE; // AxisY.Title.TextColor = Properties.Settings.Default.CoordColorE; // AxisY.MinorCount = Properties.Settings.Default.MinorCountE; // AxisY.Label.Font = Properties.Settings.Default.AxisLabelFontH; // AxisY.Title.Font = Properties.Settings.Default.AxisTitleFontH; // AxisY.GridLines.Color = Properties.Settings.Default.GridLinesColorY; // } // SeriesLine.View.Color = Properties.Settings.Default.NpshLineColor; // ((SeriesLine.View as DevExpress.XtraCharts.LineSeriesView).PointMarkerOptions as Marker).Color = Properties.Settings.Default.PointColorNPSH; // (SeriesLine.View as DevExpress.XtraCharts.LineSeriesView).PointMarkerOptions.Size = Properties.Settings.Default.PointSizeNPSH; // (SeriesLine.View as DevExpress.XtraCharts.LineSeriesView).PointMarkerOptions.Kind = (MarkerKind)Properties.Settings.Default.PointKindNPSH; // constantLine1.Color = Properties.Settings.Default.NpshCriticalHColor; // constantLine1.Title.TextColor = Properties.Settings.Default.NpshNoticeColor; // constantLine1.Title.Font = Properties.Settings.Default.NpshNoticeFont; // AxisX.GridLines.LineStyle.DashStyle = (DevExpress.XtraCharts.DashStyle)Properties.Settings.Default.GridLineTypeX; // AxisY.GridLines.LineStyle.DashStyle = (DevExpress.XtraCharts.DashStyle)Properties.Settings.Default.GridLineTypeY; } #endregion // public void SetTestMethod(TProduct.Model.eNpshTestMethod TestMethod) { this._npshTestMethod = TestMethod; } // internal void EmptyAll() { if (_allRecords != null) _allRecords.Clear(); this._thresholdPt = null; //已经汽蚀的点 this._havePoints = null; //没有汽蚀的点 this._nonePoints = null; ReCalcFitPoint(); } internal void RefreshRecordPoint(List pointInfos) { if (pointInfos == null || pointInfos.Count == 0) return; _allRecords = pointInfos; ReCalcFitPoint(); } //计算 private void ReCalcFitPoint() { if (_allRecords == null || _allRecords.Count < 1) { UpdateChart(); return; } UpdateChart(); } /// /// 隐藏临界值线 /// public void HideThresholdLine() { _constantLineThreshold.Visible = false; } /// /// 显示临界值线 /// /// private double _accrodJudgeThresholdAbsolute = 0; public void ShowThresholdLine(double thresholdValve, string thresholdText) { this._accrodJudgeThresholdAbsolute = thresholdValve; _constantLineThreshold.AxisValue = thresholdValve; _constantLineThreshold.Title.Text = thresholdText; _constantLineThreshold.Visible = true; } #region 更新 //更新所有 internal void UpdateChart() { //判断是否要重建坐标系 bool isReBuildCoordinate = CalcCoordinate(); if (isReBuildCoordinate) UpdateCoordinate(); UpdateTestPoints(); } //已经汽蚀的点 List _havePoints = null; //没有汽蚀的点 List _nonePoints = null; TProduct.WinFrmUI.TPump.ViewModel.NpshChartPoint _thresholdPt = null; public void SetThresholdPt(TProduct.WinFrmUI.TPump.ViewModel.NpshChartPoint pt) { this._thresholdPt = pt; } //更新所有点 public void UpdateTestPoints() {//TestPointInfo按气蚀从小到大排序 if (_allRecords == null) { SeriesPoint.Visible = false; _havePoints = null; _nonePoints = null; return; } int i = 0; // SeriesPoint.Visible = true; SeriesPoint.Points.Clear(); for (i = 0; i < _allRecords.Count(); i++) {//_allRecords 已按汽蚀从小到大排序 SeriesPoint.Points.Add(new SeriesPoint(_allRecords[i].NPSH, new double[] { _allRecords[i].Accord })); } //计算是否气蚀 int qishiStartPointIndex = -1; for (i = 0; i < _allRecords.Count(); i++) {//_allRecords 已按汽蚀从小到大排序 if (_allRecords[i].Accord > _accrodJudgeThresholdAbsolute) {//只要超出, 上一个点就是汽蚀点 qishiStartPointIndex = i - 1; break; } //if (_allRecords[i].Accord < _accrodJudgeThresholdAbsolute) //{ // qishiStartPointIndex = i; //} } //已经汽蚀的点 _havePoints = new List(); //没有汽蚀的点 _nonePoints = new List(); for (i = 0; i < _allRecords.Count; i++) { if (i <= qishiStartPointIndex) { _havePoints.Add(_allRecords[i]); } else { _nonePoints.Add(_allRecords[i]); } } } #endregion /* 老方法, 代码备份 * public void UpdateTestPoints() {//TestPointInfo按气蚀从小到大排序 if (_allRecords == null) { SeriesPoint.Visible = false; SeriesSpline.Visible = false; SeriesLine.Visible = false; return; } //计算是否气蚀 int i = 0; int qishiStartPointIndex = -1; SeriesPoint.Visible = true; SeriesPoint.Points.Clear(); for (i = 0; i < _allRecords.Count(); i++) { SeriesPoint.Points.Add(new SeriesPoint(_allRecords[i].CorrectPtNpsh, new double[] { _allRecords[i].CorrectPtAccord })); if (_allRecords[i].CorrectPtAccord < _accrodJudgeThresholdAbsolute) { qishiStartPointIndex = i; } } // bool isFit = false; int minNum = 3; if (isFit) minNum = 4; if (qishiStartPointIndex >= 0 && _allRecords.Count > 3) {//已经气蚀了 int noQiShiPointNum = _allRecords.Count() - 1 - qishiStartPointIndex;//没有气蚀的点 if (noQiShiPointNum >= minNum) {//没有气蚀部分大于4个点 没有气蚀部分用曲线表示 气蚀部分用直线表示 //曲线部分 List splinePoints = new List(); for (i = qishiStartPointIndex + 1; i < _allRecords.Count(); i++) { splinePoints.Add(new Eventech.Model.FeatPoint(_allRecords[i].CorrectPtNpsh, _allRecords[i].CorrectPtAccord)); } var splineCurves = splinePoints;//Eventech.Common.FitCurveHelper.GetFitPoints(splinePoints); if (isFit) { splineCurves = Eventech.Common.FitCurveHelper.GetFitPoints(splinePoints); } SeriesSpline.Visible = true; SeriesSpline.Points.Clear(); for (i = 0; i < splineCurves.Count(); i++) { SeriesSpline.Points.Add(new SeriesPoint(splineCurves[i].X, new double[] { splineCurves[i].Y })); } SeriesLine.Points.Clear(); //气蚀部分用直线表示 SeriesLine.Visible = true; for (i = 0; i <= qishiStartPointIndex; i++) { SeriesLine.Points.Add(new SeriesPoint(_allRecords[i].CorrectPtNpsh, new double[] { _allRecords[i].CorrectPtAccord })); } SeriesLine.Points.Add(new SeriesPoint(splineCurves.First().X, new double[] { splineCurves.First().Y })); } else {//没有气蚀的点小于4个, 用直线表示 SeriesSpline.Visible = false; SeriesLine.Visible = true; SeriesLine.Points.Clear(); for (i = 0; i < _allRecords.Count(); i++) { SeriesLine.Points.Add(new SeriesPoint(_allRecords[i].CorrectPtNpsh, new double[] { _allRecords[i].CorrectPtAccord })); } } } else {//还没有气蚀 if (_allRecords.Count >= minNum) {//点大于4个用曲线表示 List splinePoints = new List(); for (i = 0; i < _allRecords.Count(); i++) { splinePoints.Add(new Eventech.Model.FeatPoint(_allRecords[i].CorrectPtNpsh, _allRecords[i].CorrectPtAccord)); } var splineCurves = splinePoints;//Eventech.Common.FitCurveHelper.GetFitPoints(splinePoints); if (isFit) { splineCurves = Eventech.Common.FitCurveHelper.GetFitPoints(splinePoints); } SeriesSpline.Visible = true; SeriesLine.Visible = false; SeriesLine.Points.Clear(); SeriesSpline.Points.Clear(); for (i = 0; i < splineCurves.Count(); i++) { SeriesSpline.Points.Add(new SeriesPoint(splineCurves[i].X, new double[] { splineCurves[i].Y })); } } else {//小于4个用直线表示 SeriesSpline.Visible = false; SeriesLine.Visible = true; SeriesLine.Points.Clear(); for (i = 0; i < _allRecords.Count(); i++) { SeriesLine.Points.Add(new SeriesPoint(_allRecords[i].CorrectPtNpsh, new double[] { _allRecords[i].CorrectPtAccord })); } } } }*/ #region 坐标 //计算坐标 internal bool CalcCoordinate() { bool isReBuildCoordinate = false; //检查是否需要重建坐标 if (_coordinateParas == null) { isReBuildCoordinate = true;//原来没有,就必须重建坐标系 _coordinateParas = new TProduct.Model.CoordinateNpsh(); _coordinateParas.GridNumberX = 10; _coordinateParas.GridNumberY = 6; } if (_allRecords == null || _allRecords.Count == 0) { return false; } double maxX = (from x in _allRecords select x.NPSH).Max(); double minY = (from x in _allRecords select x.Accord).Min() * 0.9;//保证临界线能显示 double maxY = (from x in _allRecords select x.Accord).Max(); if (maxX > _coordMaxX) { maxX = maxX * 1.02; CalcCoordinateX(0, maxX); isReBuildCoordinate = true; } if (maxY > _coordMaxY) { CalcCoordinateY(minY, maxY); isReBuildCoordinate = true; } else if (minY < _coordMinY) { minY = minY * 0.9; CalcCoordinateY(minY, maxY); isReBuildCoordinate = true; } return isReBuildCoordinate; } //X坐标 private void CalcCoordinateX(double minX, double maxX) { minX = Math.Round(minX, 2); maxX = Math.Round(maxX, 2); //得到最优坐标间隔,还会返回显示的最大最小值,保证minDisplay是比minValue小的最大间隙整数倍 double coordMinX = 0; _coordinateParas.CoordSpaceX = Eventech.Common.CoordinateHelper.GetOptimalSpaceMin(minX, maxX, 8, out coordMinX, out _coordMaxX); _coordinateParas.GridNumberX = 1; _coordinateParas.CoordMinX = 0; double x = 0; while (x < maxX) { x = _coordinateParas.GridNumberX * _coordinateParas.CoordSpaceX; _coordinateParas.GridNumberX++; } } //Y坐标 private void CalcCoordinateY(double minY, double maxY) { _coordinateParas.CoordSpaceY = Eventech.Common.CoordinateHelper.GetOptimalSpaceNum(minY, maxY, ref _coordinateParas.GridNumberY, out _coordMinY, out _coordMaxY); _coordMinY = Math.Max(0, _coordMinY); _coordinateParas.CoordMinY = _coordMinY; _coordMaxY = _coordMinY; _coordinateParas.GridNumberY = 1; while (_coordMaxY < maxY) { _coordMaxY = _coordMaxY + _coordinateParas.CoordSpaceY; _coordinateParas.GridNumberY++; } } //更新图表坐标 internal void UpdateCoordinate() { //先设置为不显示 AxisX.Visibility = DefaultBoolean.False;// = false; AxisY.Visibility = DefaultBoolean.False;//Visible = false; if (_coordinateParas == null) return; //X坐标刻度 List X_Label_List = new List(); AxisX.CustomLabels.Clear(); double dis_npsh = _coordinateParas.CoordMinX; for (int i = 0; i < _coordinateParas.GridNumberX + 1; i++) { var text = TProduct.Common.RoundHelper.GetDispValueFlow(dis_npsh).ToString(); //TProduct.Common.RoundHelper.GetDispValueFlow( // Eventech.Common.UnitQHelper.fromM3H(flow_unit, // disQ < 0 ? 0 : disQ)).ToString() ; X_Label_List.Add(new CustomAxisLabel(text, dis_npsh)); dis_npsh = dis_npsh + _coordinateParas.CoordSpaceX; } AxisX.CustomLabels.AddRange(X_Label_List.ToArray()); //设置显示 TProduct.WinFrmUI.XtraChartHelper.SetAxisRange(AxisX, _coordinateParas.CoordMinX, _coordinateParas.CoordMinX + _coordinateParas.GridNumberX * _coordinateParas.CoordSpaceX); AxisX.GridLines.Visible = true; AxisX.Visibility = DefaultBoolean.True;//Visible = true; //Y坐标刻度 List Y_Label_List = new List(); AxisY.CustomLabels.Clear(); double disY = _coordinateParas.CoordMinY; for (int i = 0; i < _coordinateParas.GridNumberY + 1; i++) { var text = disY.ToString("0.00"); if (disY < 0) { text = ""; } Y_Label_List.Add(new CustomAxisLabel(text, disY)); disY = disY + _coordinateParas.CoordSpaceY; } AxisY.CustomLabels.AddRange(Y_Label_List.ToArray()); //设置显示 TProduct.WinFrmUI.XtraChartHelper.SetAxisRange(AxisY, _coordinateParas.CoordMinY, _coordinateParas.CoordMinY + _coordinateParas.GridNumberY * _coordinateParas.CoordSpaceY); AxisY.GridLines.Visible = true; AxisY.Visibility = DefaultBoolean.True;//true; } #endregion #region 重绘 private bool _isUseSpline = true; void chartControl_CustomPaint(object sender, CustomPaintEventArgs e) { if (_coordinateParas == null) return; Graphics g = e.Graphics; g.SmoothingMode = SmoothingMode.AntiAlias; //已经汽蚀的点 if (_havePoints != null && this._havePoints.Count > 1) { List points = new List(); foreach (var pt in _havePoints) { ControlCoordinates coor = mainChartDiagram.DiagramToPoint(pt.NPSH, pt.Accord); points.Add(coor.Point); } { using (Pen penCurve = new Pen(System.Drawing.Color.PaleVioletRed, 2f)) { g.DrawLines(penCurve, points.ToArray()); } } } //没有汽蚀的点 if (_nonePoints != null) { List points = new List(); foreach (var pt in _nonePoints) { ControlCoordinates coor = mainChartDiagram.DiagramToPoint(pt.NPSH, pt.Accord); points.Add(coor.Point); } if (this._nonePoints.Count > 3 && _isUseSpline) { using (Pen penCurve = new Pen(System.Drawing.Color.DarkSeaGreen, 2f)) { g.DrawCurve(penCurve, points.ToArray(), 0.5f); } } else if (this._nonePoints.Count > 1) { using (Pen penCurve = new Pen(System.Drawing.Color.DarkSeaGreen, 2f)) { g.DrawLines(penCurve, points.ToArray()); } } } //中间部分 if (_havePoints != null && this._havePoints.Count >= 1 && _nonePoints != null && this._nonePoints.Count >= 1) { ControlCoordinates coor1 = mainChartDiagram.DiagramToPoint(_havePoints.Last().NPSH, _havePoints.Last().Accord); ControlCoordinates coor2 = mainChartDiagram.DiagramToPoint(_nonePoints.First().NPSH, _nonePoints.First().Accord); using (Pen penCurve = new Pen(System.Drawing.Color.FromArgb(30, 144, 255), 2f)) { g.DrawLine(penCurve, coor1.Point, coor2.Point); } } if (this._thresholdPt != null) { ControlCoordinates coor_center = mainChartDiagram.DiagramToPoint(_thresholdPt.NPSH, _thresholdPt.Accord); ControlCoordinates coor_bottom = mainChartDiagram.DiagramToPoint(_thresholdPt.NPSH, this._coordinateParas.CoordMinY); using (var brsh = new SolidBrush(System.Drawing.Color.Red)) { Rectangle rc = new Rectangle(coor_center.Point.X - 3, coor_center.Point.Y - 3, 6, 6); g.FillEllipse(brsh, rc); } using (Pen penCurve = new Pen(System.Drawing.Color.Red, 1f)) { g.DrawLine(penCurve, coor_center.Point, coor_bottom.Point); } //写字 using (SolidBrush brush = new SolidBrush(System.Drawing.Color.Red)) using (Font font = TProduct.WinFrmUI.SkinStyleHelper.GetDefaultFont()) { g.DrawString(string.Format("NPSH:{0}m", Math.Round(this._thresholdPt.NPSH, 2)), font, brush, coor_bottom.Point.X + 3, coor_bottom.Point.Y - 23); } } } #endregion #region 右击菜单 private bool isDisplabel = false; private void 显示测量值MenuItem_Click(object sender, EventArgs e) { isDisplabel = !isDisplabel; if (isDisplabel) { 显示测量值MenuItem.Text = "不显示测量值"; } else { 显示测量值MenuItem.Text = "显示测量值"; } SetPointLabel(); } private void SetPointLabel() { if (!isDisplabel) { //SeriesTestPointUI.Label.Visible = false; SeriesPoint.LabelsVisibility = DefaultBoolean.False; } else { //SeriesTestPointUI.Label.Visible = true; SeriesPoint.LabelsVisibility = DefaultBoolean.True; SeriesPoint.Label.TextPattern = "{A},{V}";//.PointOptions.PointView = PointView.ArgumentAndValues; } } private void 设置坐标MenuItem_Click(object sender, EventArgs e) { if (_coordinateParas == null) return; //SetCoordinateNpshDlg theDlg = new SetCoordinateNpshDlg(); //theDlg.OnChangedCoord += new SetCoordinateNpshDlg.ChangeCoordHandler(OnChangedCoord); //theDlg.CoordinateParas = CoordinateParas; //theDlg.Show(); } void OnChangedCoord(TProduct.Model.CoordinateNpsh coordinate) { _coordinateParas = coordinate; UpdateCoordinate(); } private void chartControl_MouseClick(object sender, MouseEventArgs e) { if (e.Button == System.Windows.Forms.MouseButtons.Right) { ChartHitInfo hitInfo = chartControl1.CalcHitInfo(e.Location); if (hitInfo.InConstantLine) { contextMenuContrLine.Show(chartControl1, e.Location); } else { chartRightMenu.Show(chartControl1, e.Location); } } } #endregion } }