using DevExpress.Utils; using DevExpress.XtraCharts; namespace Yw.WinFrmUI.Phart { /// /// /// public partial class PumpPerform2dEditChart : DevExpress.XtraEditors.XtraUserControl { public PumpPerform2dEditChart() { InitializeComponent(); InitialChart(); this.chartControl1.RuntimeHitTesting = true; } #region Private Variable private XYDiagram _mainChartDiagram; private AxisX _axisXQ; private AxisY _axisYQH; private SecondaryAxisY _axisYQE, _axisYQP; private Series _seriesCurveQH, _seriesCurveQE, _seriesCurveQP; private Series _seriesPointQH, _seriesPointQE, _seriesPointQP; private List _def_pt_qh_list; private List _def_pt_qe_list; private List _def_pt_qp_list; private List _pt_qh_list; private List _pt_qe_list; private List _pt_qp_list; private PumpCoordinate _coordinate_paras; private bool _initial_data = false; private Yw.Pump.eCurveType _edit_curve_type = Yw.Pump.eCurveType.QH; #endregion #region Public Evnet public event Action OnCurveCoordinateChanged; public event Action> OnDefinePointChanged; #endregion #region Initial /// /// 初始化图表 /// private void InitialChart() { this.chartControl1.SetChartDisplay(); this.chartControl1.Legend.Visibility = DevExpress.Utils.DefaultBoolean.False; this.chartControl1.SeriesSelectionMode = SeriesSelectionMode.Point; this.chartControl1.SelectionMode = ElementSelectionMode.Single; _mainChartDiagram = (XYDiagram)chartControl1.Diagram; _axisXQ = _mainChartDiagram.AxisX; _axisXQ.SetAxisXQDisplay(); _axisYQH = _mainChartDiagram.AxisY; _axisYQH.SetAxisYQHDisplay(); _axisYQE = _mainChartDiagram.SecondaryAxesY.GetAxisByName("AxisYQE"); _axisYQE.SetSecondaryAxisYQEDisplay(); _axisYQP = _mainChartDiagram.SecondaryAxesY.GetAxisByName("AxisYQP"); _axisYQP.SetSecondaryAxisYQPDisplay(); _seriesCurveQH = this.chartControl1.GetSeriesByName("SeriesCurveQH"); _seriesCurveQH.SetCurveQHDisplay(); _seriesCurveQH.Tag = (int)Yw.Pump.eCurveType.QH; _seriesCurveQE = this.chartControl1.GetSeriesByName("SeriesCurveQE"); _seriesCurveQE.SetCurveQEDisplay(); _seriesCurveQE.Tag = (int)Yw.Pump.eCurveType.QE; _seriesCurveQP = this.chartControl1.GetSeriesByName("SeriesCurveQP"); _seriesCurveQP.SetCurveQPDisplay(); _seriesCurveQP.Tag = (int)Yw.Pump.eCurveType.QP; _seriesPointQH = this.chartControl1.GetSeriesByName("SeriesPointQH"); _seriesPointQH.SetPointQHDisplay(); _seriesPointQH.Tag = (int)Yw.Pump.eCurveType.QH; _seriesPointQE = this.chartControl1.GetSeriesByName("SeriesPointQE"); _seriesPointQE.SetPointQEDisplay(); _seriesPointQE.Tag = (int)Yw.Pump.eCurveType.QE; _seriesPointQP = this.chartControl1.GetSeriesByName("SeriesPointQP"); _seriesPointQP.SetPointQPDisplay(); _seriesPointQP.Tag = (int)Yw.Pump.eCurveType.QP; _axisXQ.Visibility = DefaultBoolean.False; _axisXQ.GridLines.Visible = false; _axisYQH.Visibility = DefaultBoolean.False; _axisYQH.GridLines.Visible = false; _axisYQE.Visibility = DefaultBoolean.False; _axisYQE.GridLines.Visible = false; _axisYQP.Visibility = DefaultBoolean.False; _axisYQP.GridLines.Visible = false; _seriesPointQH.Visible = false; _seriesPointQE.Visible = false; _seriesPointQP.Visible = false; this.chartControl1.SetChartMonoColorDisplay(); this.chartControl1.MouseMove += new System.Windows.Forms.MouseEventHandler(this.chartControl1_MouseMove); this.chartControl1.MouseUp += new System.Windows.Forms.MouseEventHandler(this.chartControl1_MouseUp); this.chartControl1.MouseDown += new System.Windows.Forms.MouseEventHandler(this.chartControl1_MouseDown); this.chartControl1.KeyUp += new System.Windows.Forms.KeyEventHandler(this.chartControl1_KeyUp); } /// /// 初始化图表数据 /// public void InitialChartData() { _initial_data = false; _pt_qh_list = null; _pt_qe_list = null; _pt_qp_list = null; _def_pt_qh_list = null; _def_pt_qe_list = null; _def_pt_qp_list = null; _coordinate_paras = null; UpdateChart(false); } #endregion #region SetBindingData /// /// 绑定数据(目前没有定义点) /// /// /// /// /// public void SetBindingData(Yw.Geometry.CubicSpline2d cubic_spline_qh, Yw.Geometry.CubicSpline2d cubic_spline_qe, Yw.Geometry.CubicSpline2d cubic_spline_qp, string coordinate_paras = null, bool calc_coordinate = false) { if (cubic_spline_qh == null) { InitialChartData(); return; } List pt_qh_list, pt_qe_list = null, pt_qp_list = null; pt_qh_list = cubic_spline_qh.GetPointList(12); if (cubic_spline_qe != null) pt_qe_list = cubic_spline_qe.GetPointList(12); if (cubic_spline_qp != null) pt_qp_list = cubic_spline_qp.GetPointList(12); SetBindingData(pt_qh_list, pt_qe_list, pt_qp_list, pt_qh_list, pt_qe_list, pt_qp_list, coordinate_paras, calc_coordinate); } /// /// 绑定数据 /// /// /// /// /// /// public void SetBindingData( List pt_qh_list, List pt_qe_list, List pt_qp_list, List def_pt_qh_list, List def_pt_qe_list, List def_pt_qp_list, string coordinate_paras = null, bool calc_coordinate = false) { if (pt_qh_list == null || !pt_qh_list.Any()) { InitialChartData(); return; } _initial_data = true; _pt_qh_list = pt_qh_list; _pt_qe_list = pt_qe_list; _pt_qp_list = pt_qp_list; _def_pt_qh_list = def_pt_qh_list; _def_pt_qe_list = def_pt_qe_list; _def_pt_qp_list = def_pt_qp_list; _coordinate_paras = PumpCoordinate.ToModel(coordinate_paras); UpdateChart(calc_coordinate); } #endregion #region Update /// /// 更新曲线 /// /// /// public void UpdateCurve(Yw.Pump.eCurveType curve_type, List fit_point_list) { if (fit_point_list == null || !fit_point_list.Any()) return; _edit_curve_type = curve_type; switch (_edit_curve_type) { case Yw.Pump.eCurveType.QH: { _def_pt_qh_list = fit_point_list; _pt_qh_list = fit_point_list.GetFitPointList(); _axisYQH.SetAxisYQHColorDisplay(_seriesCurveQH, _seriesPointQH, true); _axisYQE.SetSecondaryAxisYQEColorDisplay(_seriesCurveQE, _seriesPointQE, false); _axisYQP.SetSecondaryAxisYQPColorDisplay(_seriesCurveQP, _seriesPointQP, false); } break; case Yw.Pump.eCurveType.QE: { _def_pt_qe_list = fit_point_list; _pt_qe_list = fit_point_list.GetFitPointList(); _axisYQH.SetAxisYQHColorDisplay(_seriesCurveQH, _seriesPointQH, false); _axisYQE.SetSecondaryAxisYQEColorDisplay(_seriesCurveQE, _seriesPointQE, true); _axisYQP.SetSecondaryAxisYQPColorDisplay(_seriesCurveQP, _seriesPointQP, false); } break; case Yw.Pump.eCurveType.QP: { _def_pt_qp_list = fit_point_list; _pt_qp_list = fit_point_list.GetFitPointList(); _axisYQH.SetAxisYQHColorDisplay(_seriesCurveQH, _seriesPointQH, false); _axisYQE.SetSecondaryAxisYQEColorDisplay(_seriesCurveQE, _seriesPointQE, false); _axisYQP.SetSecondaryAxisYQPColorDisplay(_seriesCurveQP, _seriesPointQP, true); } break; default: break; } UpdateChart(true); } /// /// 更新图表 /// /// 计算坐标 public void UpdateChart(bool calc_coordinate = false) { if (calc_coordinate || _coordinate_paras == null) { //不强迫计算,就用上次更新的坐标系 CalcCoordinate(); } CalcChartAxis(); CalcSeries(); } #endregion #region Calc /// /// 计算坐标 /// public void CalcCoordinate() { if (_pt_qh_list == null || _pt_qh_list.Count < 4) { //设置成白板坐标 _coordinate_paras = new PumpCoordinate(); _coordinate_paras.GridNumberX = 30; _coordinate_paras.GridNumberY = 16; //显示的坐标线号 _coordinate_paras.StartLineNoH = 10; _coordinate_paras.EndLineNoH = 15; _coordinate_paras.StartLineNoE = 0; _coordinate_paras.EndLineNoE = 10; _coordinate_paras.StartLineNoP = 2; _coordinate_paras.EndLineNoP = 9; //坐标最小值和间隔 _coordinate_paras.CoordMinQ = 0; _coordinate_paras.CoordSpaceQ = 1000; _coordinate_paras.CoordMinH = 10; _coordinate_paras.CoordSpaceH = 100; _coordinate_paras.CoordMinE = 0; _coordinate_paras.CoordSpaceE = 100; _coordinate_paras.CoordMinP = 10; _coordinate_paras.CoordSpaceP = 100; return; } _coordinate_paras = PumpCoordinate.CalcCoordinate(_pt_qh_list, _pt_qe_list, _pt_qp_list); } /// /// 计算图表轴 /// public void CalcChartAxis() { if (_coordinate_paras == null) { _axisXQ.Visibility = DefaultBoolean.False; _axisXQ.GridLines.Visible = false; _axisYQH.Visibility = DefaultBoolean.False; _axisYQH.GridLines.Visible = false; _axisYQE.Visibility = DefaultBoolean.False; _axisYQE.GridLines.Visible = false; _axisYQP.Visibility = DefaultBoolean.False; _axisYQP.GridLines.Visible = false; return; } //流量 if (_pt_qh_list != null) { //计算刻度 var labels = new List(); var disQ = _coordinate_paras.CoordMinQ; for (int i = 0; i < _coordinate_paras.GridNumberX + 1; i++) { labels.Add(new CustomAxisLabel(disQ.ToString("N0"), disQ)); disQ = disQ + _coordinate_paras.CoordSpaceQ; } //坐标刻度 _axisXQ.CustomLabels.Clear(); _axisXQ.CustomLabels.AddRange(labels.ToArray()); _axisXQ.Visibility = DefaultBoolean.True; _axisXQ.GridLines.Visible = true; _axisXQ.SetAxisRange(_coordinate_paras.CoordMinQ, _coordinate_paras.CoordMinQ + _coordinate_paras.GridNumberX * _coordinate_paras.CoordSpaceQ); } //扬程 if (_pt_qh_list != null) { //计算刻度 var labels = new List(); var disH = _coordinate_paras.CoordMinH + _coordinate_paras.CoordSpaceH * _coordinate_paras.StartLineNoH; for (int i = _coordinate_paras.StartLineNoH; i < _coordinate_paras.EndLineNoH + 1; i++) { labels.Add(new CustomAxisLabel(disH.ToString(), disH)); disH = disH + _coordinate_paras.CoordSpaceH; } _axisYQH.CustomLabels.Clear(); _axisYQH.CustomLabels.AddRange(labels.ToArray()); _axisYQH.Visibility = DefaultBoolean.True; _axisYQH.GridLines.Visible = true; } //效率 if (_pt_qe_list != null) { //计算刻度 var labels = new List(); var disE = _coordinate_paras.CoordMinE + _coordinate_paras.CoordSpaceE * _coordinate_paras.StartLineNoE; for (int i = _coordinate_paras.StartLineNoE; i < _coordinate_paras.EndLineNoE + 1; i++) { labels.Add(new CustomAxisLabel(disE.ToString(), disE)); disE = disE + _coordinate_paras.CoordSpaceE; } _axisYQE.CustomLabels.Clear(); _axisYQE.CustomLabels.AddRange(labels.ToArray()); _axisYQE.Visibility = DefaultBoolean.True; _axisYQE.GridLines.Visible = true; } //功率 if (_pt_qp_list != null) { //计算刻度 var labels = new List(); double disP = _coordinate_paras.CoordMinP + _coordinate_paras.CoordSpaceP * _coordinate_paras.StartLineNoP; for (int i = _coordinate_paras.StartLineNoP; i < _coordinate_paras.EndLineNoP + 1; i++) { labels.Add(new CustomAxisLabel(disP.ToString(), disP)); disP = disP + _coordinate_paras.CoordSpaceP; } _axisYQP.CustomLabels.Clear(); _axisYQP.CustomLabels.AddRange(labels.ToArray()); _axisYQP.Visibility = DefaultBoolean.True; _axisYQP.GridLines.Visible = true; } _axisXQ.SetAxisRange(_coordinate_paras.CoordMinQ, _coordinate_paras.CoordMinQ + _coordinate_paras.GridNumberX * _coordinate_paras.CoordSpaceQ); if (_pt_qe_list == null && _pt_qp_list == null) { _axisYQH.SetAxisRange(_coordinate_paras.DispMinH(), _coordinate_paras.DispMaxH()); } else { _axisYQH.SetAxisRange(_coordinate_paras.CoordMinH, _coordinate_paras.CoordMinH + _coordinate_paras.GridNumberY * _coordinate_paras.CoordSpaceH); } _axisYQE.SetAxisRange(_coordinate_paras.CoordMinE, _coordinate_paras.CoordMinE + _coordinate_paras.GridNumberY * _coordinate_paras.CoordSpaceE); _axisYQP.SetAxisRange(_coordinate_paras.CoordMinP, _coordinate_paras.CoordMinP + _coordinate_paras.GridNumberY * _coordinate_paras.CoordSpaceP); } /// /// 计算系列 /// public void CalcSeries() { if (_pt_qh_list != null && _pt_qh_list.Count > 3) { _seriesCurveQH.Visible = true; _seriesCurveQH.Points.Clear(); foreach (var curvePoint in _pt_qh_list) { var seriesPoint = new SeriesPoint(curvePoint.X, curvePoint.Y); _seriesCurveQH.Points.Add(seriesPoint); } } else { _seriesCurveQH.Points.Clear(); _seriesCurveQH.Visible = false; } if (_pt_qe_list != null && _pt_qe_list.Count > 3) { _seriesCurveQE.Visible = true; _seriesCurveQE.Points.Clear(); foreach (var curvePoint in _pt_qe_list) { var seriesPoint = new SeriesPoint(curvePoint.X, curvePoint.Y); _seriesCurveQE.Points.Add(seriesPoint); } } else { _seriesCurveQE.Points.Clear(); _seriesCurveQE.Visible = false; } if (_pt_qp_list != null && _pt_qp_list.Count > 3) { _seriesCurveQP.Visible = true; _seriesCurveQP.Points.Clear(); foreach (var curvePoint in _pt_qp_list) { var seriesPoint = new SeriesPoint(curvePoint.X, curvePoint.Y); _seriesCurveQP.Points.Add(seriesPoint); } } else { _seriesCurveQP.Points.Clear(); _seriesCurveQP.Visible = false; } if (_def_pt_qh_list != null && _def_pt_qh_list.Any()) { _seriesPointQH.Points.Clear(); for (int i = 0; i < _def_pt_qh_list.Count; i++) { var definePoint = _def_pt_qh_list[i]; var seriesPoint = new SeriesPoint(definePoint.X, definePoint.Y); seriesPoint.Tag = i; _seriesPointQH.Points.Add(seriesPoint); } _seriesPointQH.Visible = true; } else { _seriesPointQH.Visible = false; } if (_def_pt_qe_list != null && _def_pt_qe_list.Any()) { _seriesPointQE.Points.Clear(); for (int i = 0; i < _def_pt_qe_list.Count; i++) { var definePoint = _def_pt_qe_list[i]; var seriesPoint = new SeriesPoint(definePoint.X, definePoint.Y); seriesPoint.Tag = i; _seriesPointQE.Points.Add(seriesPoint); } _seriesPointQE.Visible = true; } else { _seriesPointQE.Visible = false; } if (_def_pt_qp_list != null && _def_pt_qp_list.Any()) { _seriesPointQP.Points.Clear(); for (int i = 0; i < _def_pt_qp_list.Count; i++) { var definePoint = _def_pt_qp_list[i]; var seriesPoint = new SeriesPoint(definePoint.X, definePoint.Y); seriesPoint.Tag = i; _seriesPointQP.Points.Add(seriesPoint); } _seriesPointQP.Visible = true; } else { _seriesPointQP.Visible = false; } } #endregion #region ChartEvent private bool _mouseMode = false;//鼠标模式 private SeriesPoint _pickPoint = null;// 选中点 private void chartControl1_MouseDown(object sender, MouseEventArgs e) { if (!_initial_data) return; var hitInfo = chartControl1.CalcHitInfo(e.Location); if (e.Button == MouseButtons.Left) { if (hitInfo.InSeriesPoint) { if ((int)hitInfo.Series.Tag != (int)_edit_curve_type) { _pickPoint = null; return; } _pickPoint = hitInfo.SeriesPoint; } else { _pickPoint = null; } } else if (e.Button == MouseButtons.Right) { _pickPoint = null; this.popMenuChart.ShowPopup(MousePosition); } } private void chartControl1_MouseMove(object sender, MouseEventArgs e) { if (!_initial_data) return; if (!_mouseMode) return; if (_pickPoint == null) return; var diagramCoordinates = _mainChartDiagram.PointToDiagram(e.Location); switch (_edit_curve_type) { case Yw.Pump.eCurveType.QH: { var axisValue = diagramCoordinates.GetAxisValue(_axisYQH); if (axisValue == null) return; _pickPoint.Values[0] = axisValue.NumericalValue; _pickPoint.NumericalArgument = diagramCoordinates.NumericalArgument; } break; case Yw.Pump.eCurveType.QE: { var axisValue = diagramCoordinates.GetAxisValue(_axisYQE); if (axisValue == null) return; _pickPoint.Values[0] = axisValue.NumericalValue; _pickPoint.NumericalArgument = diagramCoordinates.NumericalArgument; } break; case Yw.Pump.eCurveType.QP: { var axisValue = diagramCoordinates.GetAxisValue(_axisYQP); if (axisValue == null) return; _pickPoint.Values[0] = axisValue.NumericalValue; _pickPoint.NumericalArgument = diagramCoordinates.NumericalArgument; } break; } } private void chartControl1_MouseUp(object sender, MouseEventArgs e) { if (!_initial_data) return; if (_mouseMode) { _pickPoint = null; ChartUpdateCurve(); } } private void chartControl1_KeyUp(object sender, KeyEventArgs e) { if (!_initial_data) return; if (_pickPoint == null) return; double spaceX = _coordinate_paras.CoordSpaceQ / 50; double spaceY = 0; switch (_edit_curve_type) { case Yw.Pump.eCurveType.QH: { spaceY = _coordinate_paras.CoordSpaceH / 50; } break; case Yw.Pump.eCurveType.QE: { spaceY = _coordinate_paras.CoordSpaceE / 50; } break; case Yw.Pump.eCurveType.QP: { spaceY = _coordinate_paras.CoordSpaceP / 50; } break; default: break; } double x = _pickPoint.NumericalArgument; double y = _pickPoint.Values[0]; if (e.KeyCode == Keys.Up) { y += spaceY; } else if (e.KeyCode == Keys.Down) { y -= spaceY; } else if (e.KeyCode == Keys.Left) { x -= spaceX; } else if (e.KeyCode == Keys.Right) { x += spaceX; } _pickPoint.Values[0] = y; _pickPoint.NumericalArgument = x; ChartUpdateCurve(); } /// /// 更新曲线 /// private void ChartUpdateCurve() { switch (_edit_curve_type) { case Yw.Pump.eCurveType.QH: { _def_pt_qh_list = _seriesPointQH.Points.Select(x => new Yw.Geometry.Point2d(x.ArgumentX.NumericalArgument, x.NumericalValue)).ToList(); _pt_qh_list = _def_pt_qh_list.GetFitPointList(); _seriesCurveQH.Points.Clear(); foreach (var curvePoint in _pt_qh_list) { var seriesPoint = new SeriesPoint(curvePoint.X, curvePoint.Y); _seriesCurveQH.Points.Add(seriesPoint); } OnDefinePointChanged?.Invoke(_edit_curve_type, _def_pt_qh_list); } break; case Yw.Pump.eCurveType.QE: { _def_pt_qe_list = _seriesPointQE.Points.Select(x => new Yw.Geometry.Point2d(x.ArgumentX.NumericalArgument, x.NumericalValue)).ToList(); _pt_qe_list = _def_pt_qe_list.GetFitPointList(); _seriesCurveQE.Points.Clear(); foreach (var curvePoint in _pt_qe_list) { var seriesPoint = new SeriesPoint(curvePoint.X, curvePoint.Y); _seriesCurveQE.Points.Add(seriesPoint); } OnDefinePointChanged?.Invoke(_edit_curve_type, _def_pt_qe_list); } break; case Yw.Pump.eCurveType.QP: { _def_pt_qp_list = _seriesPointQP.Points.Select(x => new Yw.Geometry.Point2d(x.ArgumentX.NumericalArgument, x.NumericalValue)).ToList(); _pt_qp_list = _def_pt_qp_list.GetFitPointList(); _seriesCurveQP.Points.Clear(); foreach (var curvePoint in _pt_qp_list) { var seriesPoint = new SeriesPoint(curvePoint.X, curvePoint.Y); _seriesCurveQP.Points.Add(seriesPoint); } OnDefinePointChanged?.Invoke(_edit_curve_type, _def_pt_qp_list); } break; } CalcChartAxis(); } #endregion #region Right Click Menu #region Event private void barCekChartEditMode_CheckedChanged(object sender, DevExpress.XtraBars.ItemClickEventArgs e) { _mouseMode = this.barCekChartEditMode.Checked; var text = "修改模式:鼠标 / 键盘☑"; if (_mouseMode) { text = "修改模式:鼠标☑ / 键盘"; } _mainChartDiagram.DefaultPane.Title.Text = text; } private void BarBtnCalcCoordinate_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e) { CalcCoordinate(); CalcChartAxis(); } private void barCekLegendVisible_CheckedChanged(object sender, DevExpress.XtraBars.ItemClickEventArgs e) { SetLegendVisible(this.barCekLegendVisible.Checked); } private void barCekSetAxisNameVisible_CheckedChanged(object sender, DevExpress.XtraBars.ItemClickEventArgs e) { SetAxisNameVisible(this.barCekSetAxisNameVisible.Checked); } private void barBtnSetChartAxis_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e) { SetChartAxis(); } #endregion /// /// 设置图例显示 /// public void SetLegendVisible(bool visible) { this.chartControl1.Legend.Visibility = visible ? DefaultBoolean.True : DefaultBoolean.False; } /// /// 设置轴名称显示 /// public void SetAxisNameVisible(bool visible) { _axisXQ.Title.Visibility = visible ? DefaultBoolean.True : DefaultBoolean.False; _axisYQH.Title.Visibility = visible ? DefaultBoolean.True : DefaultBoolean.False; _axisYQE.Title.Visibility = visible ? DefaultBoolean.True : DefaultBoolean.False; _axisYQP.Title.Visibility = visible ? DefaultBoolean.True : DefaultBoolean.False; } /// /// 设置坐标轴 /// public void SetChartAxis() { var dlg = new PumpChartCoordinateDlg(); var onlyQH = _pt_qe_list == null && _pt_qp_list == null; dlg.SetBindingData(_coordinate_paras, onlyQH); dlg.OnChangedCoord += (rhs) => { _coordinate_paras = rhs; CalcChartAxis(); this.OnCurveCoordinateChanged?.Invoke(_coordinate_paras); }; dlg.ShowDialog(); } #endregion } }