using DevExpress.Utils; using DevExpress.XtraCharts; using DevExpress.XtraEditors; using System.Text; using Yw.Geometry; namespace Yw.WinFrmUI.Phart { /// /// /// public partial class PumpViewChart : DevExpress.XtraEditors.XtraUserControl { public PumpViewChart() { InitializeComponent(); InitialChart(); } #region Private Variable private XYDiagram _main_diagram; private XYDiagramPane _bottom_panel; private AxisX _axisXQ; private AxisY _axisYQH; private SecondaryAxisY _axis_y_qe, _axis_y_qp; private ConstantLine _work_pt_line; private ConstantLine _work_h_line; private Series _series_qh, _series_qe, _series_qp, _series_cubic_spline_eq; private Series _series_qh_pt, _series_qe_pt, _series_qp_pt; private List _series_eq_pt_list; private TextAnnotation _work_pt_txt_annot; private Yw.Geometry.CubicSpline2d _qh; private Yw.Geometry.CubicSpline2d _qe; private Yw.Geometry.CubicSpline2d _qp; private List _qh_pt_list; private List _qe_pt_list; private List _qp_pt_list; private List _def_qh_pt_list; private List _def_qe_pt_list; private List _def_qp_pt_list; private PumpGroupPt _work_point = new(0, 0, 0, 0, 0); private bool _eq_visible = true; private PumpCoordinate _coordinate_paras; private bool _initial_data = false; #endregion #region Public Variable /// /// 定义点是否可见 /// public bool DefinePointVisible { get => _definePointVisible; set { _definePointVisible = value; this.barCekDefinePointVisible.Checked = _definePointVisible; } } private bool _definePointVisible = false; /// /// 工作线是否可见 /// public bool LineVisible { get => _lineVisible; set { _lineVisible = value; this.barCekLineVisible.Checked = _lineVisible; this.barBtnSetAxisHValue.Enabled = _lineVisible; this.barBtnSetAxisQValue.Enabled = _lineVisible; this.barBtnPositioningMaxE.Enabled = _lineVisible; this.barBtnPositioningMaxQ.Enabled = _lineVisible; } } private bool _lineVisible = false; #endregion #region Public Evnet public event Action OnCurveCoordinateChanged; public event Action OnCalcQueryPoint = null; #endregion #region Initial /// /// 初始化图表 /// private void InitialChart() { this.chartControl1.SetChartDisplay(); this.chartControl1.Legend.Visibility = DevExpress.Utils.DefaultBoolean.False; _main_diagram = (XYDiagram)chartControl1.Diagram; _bottom_panel = (XYDiagramPane)_main_diagram.FindPaneByName("BottomPanel"); _axisXQ = _main_diagram.AxisX; _axisXQ.SetAxisXQDisplay(); _axisYQH = _main_diagram.AxisY; _axisYQH.SetAxisYQHDisplay(); _axis_y_qe = _main_diagram.SecondaryAxesY.GetAxisByName("AxisYQE"); _axis_y_qe.SetSecondaryAxisYQEDisplay(); _axis_y_qp = _main_diagram.SecondaryAxesY.GetAxisByName("AxisYQP"); _axis_y_qp.SetSecondaryAxisYQPDisplay(); _work_pt_line = (ConstantLine)_main_diagram.AxisX.ConstantLines.GetElementByName("WorkPointLine"); _work_pt_line.SetWorkPointLineDisplay(); _work_h_line = (ConstantLine)_main_diagram.AxisY.ConstantLines.GetElementByName("WorkHLine"); _work_h_line.SetWorkHLineDisplay(); _series_qh = this.chartControl1.GetSeriesByName("SeriesCurveQH"); _series_qh.SetCurveQHDisplay(); _series_qe = this.chartControl1.GetSeriesByName("SeriesCurveQE"); _series_qe.SetCurveQEDisplay(); _series_qp = this.chartControl1.GetSeriesByName("SeriesCurveQP"); _series_qp.SetCurveQPDisplay(); _series_cubic_spline_eq = this.chartControl1.GetSeriesByName("SeriesEquipCurve"); ((SplineSeriesView)_series_cubic_spline_eq.View).LineTensionPercent = 40; _series_qh_pt = this.chartControl1.GetSeriesByName("SeriesPointQH"); _series_qh_pt.SetPointQHDisplay(); _series_qe_pt = this.chartControl1.GetSeriesByName("SeriesPointQE"); _series_qe_pt.SetPointQEDisplay(); _series_qp_pt = this.chartControl1.GetSeriesByName("SeriesPointQP"); _series_qp_pt.SetPointQPDisplay(); _work_pt_txt_annot = this.chartControl1.AnnotationRepository[0] as TextAnnotation; _work_pt_txt_annot.SetTextAnnoWorkPointDisplay(); _axisXQ.Visibility = DefaultBoolean.False; _axisXQ.GridLines.Visible = false; _axisYQH.Visibility = DefaultBoolean.False; _axisYQH.GridLines.Visible = false; _axis_y_qe.Visibility = DefaultBoolean.False; _axis_y_qe.GridLines.Visible = false; _axis_y_qp.Visibility = DefaultBoolean.False; _axis_y_qp.GridLines.Visible = false; _work_pt_line.Visible = false; _work_h_line.Visible = false; _work_pt_txt_annot.Visible = false; _series_qh_pt.Visible = false; _series_qe_pt.Visible = false; _series_qp_pt.Visible = false; this.chartControl1.ObjectHotTracked += new DevExpress.XtraCharts.HotTrackEventHandler(this.chartControl1_ObjectHotTracked); 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.Resize += new System.EventHandler(this.chartControl1_Resize); // this.chartControl1.CustomPaint += ChartControl1_CustomPaint; } private void ChartControl1_CustomPaint(object sender, CustomPaintEventArgs e) { if (!(e is DXCustomPaintEventArgs dxArgs)) return; if (_qe == null) { return; } // 使用Graphics绘制样条线 using (var pen = new Pen(Color.Red, 2)) { // dxArgs.Cache.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias; // 创建GraphicsPath对象,并添加样条线 using (var path = new System.Drawing.Drawing2D.GraphicsPath()) { var pts = _qe.GetPointList().Select(x => new PointF((float)x.X, (float)x.Y)).ToArray(); var g_pts = new List(); foreach (var pt in pts) { var x = pt.X; var y = pt.Y; var c_pt = _main_diagram.DiagramToPoint(x, y, _axisXQ, _axis_y_qe); g_pts.Add(new PointF(c_pt.Point.X, c_pt.Point.Y)); } path.AddCurve(g_pts.ToArray()); dxArgs.Cache.DrawPath(pen, path); } } } /// /// 初始化图表数据 /// public void InitialChartData() { _initial_data = false; _qh = null; _qe = null; _qp = null; _qh_pt_list = null; _qe_pt_list = null; _qp_pt_list = null; _def_qh_pt_list = null; _def_qe_pt_list = null; _def_qp_pt_list = null; _coordinate_paras = null; _work_point = new PumpGroupPt(0, 0, 0, 0, 0); UpdateChart(false); } #endregion /// /// 绑定数据 /// /// /// /// /// public void SetBindingData( Yw.Geometry.CubicSpline2d qh, Yw.Geometry.CubicSpline2d qe, Yw.Geometry.CubicSpline2d qp, string coordinate_paras = "", bool calc_coordinate = false) { if (qh == null) { InitialChartData(); return; } List qh_pt_list, qe_pt_list = null, qp_pt_list = null; qh_pt_list = qh.GetPointList(12); if (qe != null) qe_pt_list = qe.GetPointList(12); if (qp != null) qp_pt_list = qp.GetPointList(12); SetBindingData(qh, qe, qp, qh_pt_list, qe_pt_list, qp_pt_list, null, qe_pt_list, null, coordinate_paras, calc_coordinate); } /// /// 绑定数据 /// /// /// /// /// /// public void SetBindingData( Yw.Geometry.CubicSpline2d qh, Yw.Geometry.CubicSpline2d qe, Yw.Geometry.CubicSpline2d qp, List qh_pt_list, List qe_pt_list, List qp_pt_list, List def_qh_pt_list, List def_qe_pt_list, List def_qp_pt_list, string coordinate_paras = null, bool calc_coordinate = false) { if (qh_pt_list == null || !qh_pt_list.Any()) { InitialChartData(); return; } _initial_data = true; _qh = qh; _qe = qe; _qp = qp; _qh_pt_list = qh_pt_list; _qe_pt_list = qe_pt_list; _qp_pt_list = qp_pt_list; _def_qh_pt_list = def_qh_pt_list; _def_qe_pt_list = def_qe_pt_list; _def_qp_pt_list = def_qp_pt_list; _coordinate_paras = PumpCoordinate.ToModel(coordinate_paras); UpdateChart(calc_coordinate); } /// /// 更新图表 /// /// 计算坐标 public void UpdateChart(bool calc_coordinate = false) { if (_qh_pt_list == null || !_qh_pt_list.Any()) { this.barBtnPositioningMaxE.Visibility = DevExpress.XtraBars.BarItemVisibility.Never; } else { this.barBtnPositioningMaxE.Visibility = DevExpress.XtraBars.BarItemVisibility.Always; } if (_qp_pt_list == null || !_qp_pt_list.Any()) { this.barCekSetSplitPanel.Visibility = DevExpress.XtraBars.BarItemVisibility.Never; } else { this.barCekSetSplitPanel.Visibility = DevExpress.XtraBars.BarItemVisibility.Always; } if (calc_coordinate || _coordinate_paras == null) { //不强迫计算,就用上次更新的坐标系 CalcCoordinate(); } CalcChartAxis(this.barCekSetSplitPanel.Checked); CalcSeries(); CalcWorkPointByQ(); CalcDesignPointByQ(); CalcTextAnchorPoint(); } #region Calc /// /// 计算坐标 /// public void CalcCoordinate() { if (_qh_pt_list == null || _qh_pt_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(_qh_pt_list, _qe_pt_list, _qp_pt_list); } /// /// 计算图表轴 /// public void CalcChartAxis(bool splitPanel) { if (_coordinate_paras == null) { _axisXQ.Visibility = DefaultBoolean.False; _axisXQ.GridLines.Visible = false; _axisYQH.Visibility = DefaultBoolean.False; _axisYQH.GridLines.Visible = false; _axis_y_qe.Visibility = DefaultBoolean.False; _axis_y_qe.GridLines.Visible = false; _axis_y_qp.Visibility = DefaultBoolean.False; _axis_y_qp.GridLines.Visible = false; _work_pt_line.Visible = false; _work_h_line.Visible = false; _work_pt_txt_annot.Visible = false; _bottom_panel.Visibility = ChartElementVisibility.Hidden; return; } _bottom_panel.Visibility = splitPanel ? ChartElementVisibility.Visible : ChartElementVisibility.Hidden; PointSeriesView series_eq_p_pt_view = null; if (_series_eq_pt_list != null && _series_eq_pt_list.Any()) { var series = _series_eq_pt_list.Find(x => (Yw.Pump.eCurveType)x.Tag == Yw.Pump.eCurveType.QP); if (series != null) { series_eq_p_pt_view = (PointSeriesView)series.View; } } //流量 if (_qh_pt_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); _work_pt_txt_annot.Visible = _lineVisible; } //扬程 if (_qh_pt_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 (_qe_pt_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; } _axis_y_qe.CustomLabels.Clear(); _axis_y_qe.CustomLabels.AddRange(labels.ToArray()); _axis_y_qe.Visibility = DefaultBoolean.True; _axis_y_qe.GridLines.Visible = true; } //功率 if (_qp_pt_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; } _axis_y_qp.CustomLabels.Clear(); _axis_y_qp.CustomLabels.AddRange(labels.ToArray()); _axis_y_qp.Visibility = DefaultBoolean.True; _axis_y_qp.GridLines.Visible = true; } //是否分割面板:流量效率在上,功率在下 if (splitPanel) { var gridNumH = _coordinate_paras.EndLineNoH - _coordinate_paras.StartLineNoH; var gridNumE = _coordinate_paras.EndLineNoE - _coordinate_paras.StartLineNoE; int gridNumUp = Math.Max(gridNumH, gridNumE) + 2;//多两条 var maxAxisH = _coordinate_paras.CoordMinH + _coordinate_paras.EndLineNoH * _coordinate_paras.CoordSpaceH; var minAxisH = maxAxisH - gridNumUp * _coordinate_paras.CoordSpaceH; _axisYQH.SetAxisRange(minAxisH, maxAxisH); var minAxisE = _coordinate_paras.CoordMinE + _coordinate_paras.StartLineNoE * _coordinate_paras.CoordSpaceE; var maxAxisE = minAxisE + gridNumUp * _coordinate_paras.CoordSpaceE; _axis_y_qe.SetAxisRange(minAxisE, maxAxisE); var gridNumP = _coordinate_paras.EndLineNoP - _coordinate_paras.StartLineNoP; var minAxisP = _coordinate_paras.CoordMinP + _coordinate_paras.StartLineNoP * _coordinate_paras.CoordSpaceP; var maxAxisP = minAxisP + gridNumP * _coordinate_paras.CoordSpaceP; _axis_y_qp.SetAxisRange(minAxisP, maxAxisP); ((PointSeriesView)_series_qp_pt.View).Pane = _bottom_panel; ((SplineSeriesView)_series_qp.View).Pane = _bottom_panel; if (series_eq_p_pt_view != null) { series_eq_p_pt_view.Pane = _bottom_panel; } } else { _axisXQ.SetAxisRange(_coordinate_paras.CoordMinQ, _coordinate_paras.CoordMinQ + _coordinate_paras.GridNumberX * _coordinate_paras.CoordSpaceQ); if ((_qe_pt_list == null || !_qe_pt_list.Any()) && (_qp_pt_list == null || !_qp_pt_list.Any())) { _axisYQH.SetAxisRange(_coordinate_paras.DispMinH(), _coordinate_paras.DispMaxH()); } else { _axisYQH.SetAxisRange(_coordinate_paras.CoordMinH, _coordinate_paras.CoordMinH + _coordinate_paras.GridNumberY * _coordinate_paras.CoordSpaceH); } _axis_y_qe.SetAxisRange(_coordinate_paras.CoordMinE, _coordinate_paras.CoordMinE + _coordinate_paras.GridNumberY * _coordinate_paras.CoordSpaceE); _axis_y_qp.SetAxisRange(_coordinate_paras.CoordMinP, _coordinate_paras.CoordMinP + _coordinate_paras.GridNumberY * _coordinate_paras.CoordSpaceP); ((PointSeriesView)_series_qp_pt.View).Pane = _main_diagram.DefaultPane; ((SplineSeriesView)_series_qp.View).Pane = _main_diagram.DefaultPane; if (series_eq_p_pt_view != null) { series_eq_p_pt_view.Pane = _main_diagram.DefaultPane; } } } /// /// 计算系列 /// public void CalcSeries() { if (_qh_pt_list != null && _qh_pt_list.Count > 3) { _series_qh.Visible = true; _series_qh.Points.Clear(); foreach (var pt in _qh_pt_list) { var series_pt = new SeriesPoint(pt.X, pt.Y); _series_qh.Points.Add(series_pt); } } else { _series_qh.Points.Clear(); _series_qh.Visible = false; _work_pt_line.Visible = false; _work_h_line.Visible = false; _work_pt_txt_annot.Visible = false; _series_cubic_spline_eq.Points.Clear(); _series_cubic_spline_eq.Visible = false; } if (_qe_pt_list != null && _qe_pt_list.Count > 3) { _series_qe.Visible = true; _series_qe.Points.Clear(); foreach (var pt in _qe_pt_list) { var series_pt = new SeriesPoint(pt.X, pt.Y); _series_qe.Points.Add(series_pt); } } else { _series_qe.Points.Clear(); _series_qe.Visible = false; } if (_qp_pt_list != null && _qp_pt_list.Count > 3) { _series_qp.Visible = true; _series_qp.Points.Clear(); foreach (var pt in _qp_pt_list) { var series_pt = new SeriesPoint(pt.X, pt.Y); _series_qp.Points.Add(series_pt); } } else { _series_qp.Points.Clear(); _series_qp.Visible = false; } if (_def_qh_pt_list != null && _def_qh_pt_list.Any()) { _series_qh_pt.Points.Clear(); foreach (var define_pt in _def_qh_pt_list) { var series_pt = new SeriesPoint(define_pt.X, define_pt.Y); _series_qh_pt.Points.Add(series_pt); } } if (_def_qe_pt_list != null && _def_qe_pt_list.Any()) { _series_qe_pt.Points.Clear(); foreach (var define_pt in _def_qe_pt_list) { var series_pt = new SeriesPoint(define_pt.X, define_pt.Y); _series_qe_pt.Points.Add(series_pt); } } if (_def_qp_pt_list != null && _def_qp_pt_list.Any()) { _series_qp_pt.Points.Clear(); foreach (var define_pt in _def_qp_pt_list) { var series_pt = new SeriesPoint(define_pt.X, define_pt.Y); _series_qp_pt.Points.Add(series_pt); } } } /// /// 计算注释定位 /// private void CalcTextAnchorPoint() { var x = this.chartControl1.Location.X + this.chartControl1.Width - (100); var y = this.chartControl1.Height - (200); (_work_pt_txt_annot.AnchorPoint as ChartAnchorPoint).X = x; (_work_pt_txt_annot.AnchorPoint as ChartAnchorPoint).Y = y; } /// /// 计算工作点 /// /// public void CalcWorkPointByQ(double? workQ = null) { if (!_lineVisible) { _work_pt_line.Visible = false; _work_pt_line.Title.Visible = false; _work_h_line.Visible = false; _work_h_line.Title.Visible = false; _work_pt_txt_annot.Visible = false; return; } else { _work_pt_line.Visible = true; _work_pt_line.Title.Visible = true; _work_h_line.Visible = true; _work_h_line.Title.Visible = true; _work_pt_txt_annot.Visible = true; } if (_qh_pt_list == null || !_qh_pt_list.Any()) return; var minQ = _qh_pt_list.Min(x => x.X); var maxQ = _qh_pt_list.Max(x => x.X); if (workQ == null) { //workQ = (minQ + maxQ) / 2; workQ = minQ; } else { if (workQ < minQ || workQ > maxQ) return; } _work_point.Q = workQ.Value; _work_point.H = _qh.GetPointY(_work_point.Q); var workInfoStringBuilder = new StringBuilder(); workInfoStringBuilder.AppendLine($"流量:{_work_point.Q.ToString("N1")} "); workInfoStringBuilder.AppendLine($"扬程:{_work_point.H.ToString("N1")} "); if (_qe != null) { _work_point.E = _qe.GetPointY(_work_point.Q); workInfoStringBuilder.AppendLine($"效率:{_work_point.E.ToString("N1")} "); } if (_qp != null) { _work_point.P = _qp.GetPointY(_work_point.Q); workInfoStringBuilder.Append($"功率:{_work_point.P.ToString("N1")} "); } _work_pt_line.AxisValue = _work_point.Q; _work_pt_line.Title.Text = _work_point.Q.ToString("N1"); _work_h_line.AxisValue = _work_point.H; _work_h_line.Title.Text = _work_point.H.ToString("N1"); //测试展示效果 _work_pt_txt_annot.Text = workInfoStringBuilder.ToString(); _work_pt_txt_annot.AutoSize = true; if (OnCalcQueryPoint != null) { OnCalcQueryPoint(_work_point); } } /// /// 根据扬程计算工作点 /// /// public void CalcWorkPointByH(double workH) { if (!_lineVisible) return; if (_qh == null) return; var minH = _qh_pt_list.Min(x => x.Y); var maxH = _qh_pt_list.Max(x => x.Y); if (workH < minH || workH > maxH) return; var workQ = _qh.GetPointsX(workH)?.LastOrDefault(); CalcWorkPointByQ(workQ); } /// /// 根据最大效率计算工作点 /// public void CalcWorkPointByMaxE() { if (!_lineVisible) return; if (_qe == null) return; var pt_list = _qe.GetPointList(); pt_list = pt_list.OrderBy(x => x.Y).ToList(); var workQ = pt_list.Last().X; CalcWorkPointByQ(workQ); } /// /// 根据最大流量计算工作点 /// public void CalcWorkPointByMaxQ() { if (!_lineVisible) return; if (_qh == null) return; var workQ = _qh.MaxX; CalcWorkPointByQ(workQ); } /// /// 设计点 /// /// public void CalcDesignPointByQ(double? design_pt_q = null, double? design_pt_h = null) { _series_cubic_spline_eq.Visible = false; _series_cubic_spline_eq.Points.Clear(); if (_series_eq_pt_list != null && _series_eq_pt_list.Any()) { this.chartControl1.BeginInit(); foreach (var series in _series_eq_pt_list) { var exist_series = this.chartControl1.GetSeriesByName(series.Name); if (exist_series != null) { this.chartControl1.Series.Remove(exist_series); } } this.chartControl1.EndInit(); } _series_eq_pt_list = new List(); if (_qh_pt_list == null || !_qh_pt_list.Any()) return; if (design_pt_q == null) return; var minQ = _qh_pt_list.Min(x => x.X); var maxQ = _qh_pt_list.Max(x => x.X); if (design_pt_q < minQ || design_pt_q > maxQ) return; double design_flow = 0, design_head = 0; design_flow = design_pt_q.Value; if (design_pt_h.HasValue) { design_head = design_pt_h.Value; } else { design_head = _qh.GetPointY(design_flow); } _series_cubic_spline_eq.Visible = _eq_visible; var design_pt = new Yw.Geometry.Point2d(design_flow, design_head); var eq_paras = EquipCurveHelper.CalcEquipCurve(_qh, design_pt, out Yw.Geometry.Point2d sect_pt); if (eq_paras != null && eq_paras.EquipCurve != null) { var eq_pt_list = eq_paras.EquipCurve.GetPointList(); foreach (var pt in eq_pt_list) { var series_pt = new SeriesPoint(pt.X, pt.Y); _series_cubic_spline_eq.Points.Add(series_pt); } } if (sect_pt == null) return; double flow = 0, head = 0, eff = 0, power = 0; flow = Math.Round(sect_pt.X, 1); head = Math.Round(sect_pt.Y, 2); ; var design_qh_pt = CreatePointSeries(Pump.eCurveType.QH, flow, head); _series_eq_pt_list.Add(design_qh_pt); this.chartControl1.Series.Add(design_qh_pt); if (_qe != null) { eff = _qe.GetPointY(sect_pt.X); var design_qe_pt = CreatePointSeries(Pump.eCurveType.QE, flow, eff); _series_eq_pt_list.Add(design_qe_pt); this.chartControl1.Series.Add(design_qe_pt); } if (_qp != null) { power = _qp.GetPointY(sect_pt.X); var design_qp_pt = CreatePointSeries(Pump.eCurveType.QP, flow, power); _series_eq_pt_list.Add(design_qp_pt); this.chartControl1.Series.Add(design_qp_pt); } } /// /// 创建点系列 /// private Series CreatePointSeries(Yw.Pump.eCurveType curve_type, double x, double y) { string name = string.Empty; Color color = Color.White; AxisYBase axis_y = _axisYQH; switch (curve_type) { case Pump.eCurveType.QH: { name = "流量扬程作用点"; color = Perform2dChartDisplay.PointColorQH; axis_y = _axisYQH; } break; case Pump.eCurveType.QE: { name = "流量效率作用点"; color = Perform2dChartDisplay.PointColorQE; axis_y = _axis_y_qe; } break; case Pump.eCurveType.QP: { name = "流量功率设计点"; color = Perform2dChartDisplay.PointColorQP; axis_y = _axis_y_qp; } break; default: break; } var series_point_view = new DevExpress.XtraCharts.PointSeriesView(); series_point_view.Color = color; series_point_view.PointMarkerOptions.BorderColor = color; series_point_view.PointMarkerOptions.Size = 12; series_point_view.PointMarkerOptions.Kind = MarkerKind.Cross; series_point_view.AxisY = axis_y; var series_point = new DevExpress.XtraCharts.Series(); series_point.Tag = curve_type; series_point.View = series_point_view; series_point.ArgumentScaleType = DevExpress.XtraCharts.ScaleType.Numerical; series_point.LabelsVisibility = DevExpress.Utils.DefaultBoolean.False; series_point.Name = name; series_point.ShowInLegend = false; series_point.CrosshairEnabled = DefaultBoolean.False; series_point.ShowInLegend = true; series_point.SeriesPointsSorting = SortingMode.None; series_point.SeriesPointsSortingKey = SeriesPointKey.Value_1; series_point.Visible = _eq_visible; series_point.LabelsVisibility = DefaultBoolean.True; series_point.Label.TextPattern = "{V:N1}"; //series_point.CrosshairLabelPattern = "{V:N1}"; series_point.CrosshairLabelVisibility = DefaultBoolean.False; series_point.Points.Add(new SeriesPoint(x, new double[] { y })); return series_point; } #endregion #region ChartEvent ToolTipController toolTip = new ToolTipController(); private void chartControl1_ObjectHotTracked(object sender, HotTrackEventArgs e) { if (!_initial_data) return; if (e.AdditionalObject is SeriesPoint series_pt) { var tip = string.Format("X:{0:N1} Y:{1:N1}", series_pt.Argument, series_pt.Values[0]); toolTip.ShowHint(tip); } else { toolTip.HideHint(); } } // 右键对象 private object _rightClickObj = null; private bool _onMoveWorkPointLine = false; private bool _onMoveWorkHLine = false; 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.InSeries) { _rightClickObj = hitInfo.Series; } else if (hitInfo.InAxis) { _rightClickObj = hitInfo.Axis; } else if (hitInfo.InConstantLine) { if (hitInfo.ConstantLine == _work_pt_line) { _onMoveWorkPointLine = true; } else if (hitInfo.ConstantLine == _work_h_line) { _onMoveWorkHLine = true; } } else if (hitInfo.InAnnotation) { _rightClickObj = hitInfo.Annotation; } else { _rightClickObj = null; } } else if (e.Button == MouseButtons.Right) { if (hitInfo.InConstantLine) { this.popMenuLine.ShowPopup(MousePosition); } else { this.popMenuChart.ShowPopup(MousePosition); } } } private void chartControl1_MouseMove(object sender, MouseEventArgs e) { if (!_initial_data) return; if (_onMoveWorkPointLine) { var diagramCoordinates = _main_diagram.PointToDiagram(e.Location); var axisValue = diagramCoordinates.GetAxisValue(_axisXQ); if (axisValue == null) return; double chartQ = axisValue.NumericalValue; CalcWorkPointByQ(chartQ); } else if (_onMoveWorkHLine) { var diagramCoordinates = _main_diagram.PointToDiagram(e.Location); var axisValue = diagramCoordinates.GetAxisValue(_axisYQH); if (axisValue == null) return; double chartH = axisValue.NumericalValue; CalcWorkPointByH(chartH); } else { var hitInfo = chartControl1.CalcHitInfo(e.Location); if (hitInfo.InConstantLine) { this.chartControl1.Cursor = Cursors.Hand; } else if (hitInfo.InAnnotation) { this.chartControl1.Cursor = Cursors.SizeAll; } else { this.chartControl1.Cursor = Cursors.Default; } } } private void chartControl1_MouseUp(object sender, MouseEventArgs e) { if (!_initial_data) return; _onMoveWorkPointLine = false; _onMoveWorkHLine = false; } private void chartControl1_Resize(object sender, EventArgs e) { CalcTextAnchorPoint(); } #endregion #region Right Click Menu #region Event private void barBtnSetAxisQValue_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e) { if (_qh_pt_list == null || !_qh_pt_list.Any()) return; var dlg = new PumpAxisValueDlg(); dlg.SetBindingData(); dlg.VerifyValueChanged += (value) => { var min = _qh_pt_list.Min(x => x.X); var max = _qh_pt_list.Max(x => x.X); if (value < min || value > max) return false; CalcWorkPointByQ(value); return true; }; dlg.ShowDialog(); } private void barBtnSetAxisHValue_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e) { if (_qh_pt_list == null || !_qh_pt_list.Any()) return; var dlg = new PumpAxisValueDlg(); dlg.SetBindingData(); dlg.Text = "扬程"; dlg.VerifyValueChanged += (value) => { var min = _qh_pt_list.Min(x => x.Y); var max = _qh_pt_list.Max(x => x.Y); if (value < min || value > max) return false; CalcWorkPointByH(value); return true; }; dlg.ShowDialog(); } private void barCekEqVisible_CheckedChanged(object sender, DevExpress.XtraBars.ItemClickEventArgs e) { _eq_visible = this.barCekEqVisible.Checked; if (_series_cubic_spline_eq != null) { _series_cubic_spline_eq.Visible = _eq_visible; } if (_series_eq_pt_list != null && _series_eq_pt_list.Any()) { foreach (var item in _series_eq_pt_list) { item.Visible = _eq_visible; } } } private void barBtnPositioningMaxQ_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e) { CalcWorkPointByMaxQ(); } private void barBtnPositioningMaxE_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e) { CalcWorkPointByMaxE(); } private void barCekDefinePointVisible_CheckedChanged(object sender, DevExpress.XtraBars.ItemClickEventArgs e) { SetDefinePointVisible(this.barCekDefinePointVisible.Checked); } private void barCekLineVisible_CheckedChanged(object sender, DevExpress.XtraBars.ItemClickEventArgs e) { SetLineVisible(this.barCekLineVisible.Checked); } 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 barCekSetSplitPanel_CheckedChanged(object sender, DevExpress.XtraBars.ItemClickEventArgs e) { CalcChartAxis(this.barCekSetSplitPanel.Checked); } private void barCekChartDisplay_CheckedChanged(object sender, DevExpress.XtraBars.ItemClickEventArgs e) { SetChartDisplay(this.barCekChartDisplay.Checked); } private void barBtnSetChartAxis_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e) { SetChartAxis(); } private void barBtnSetChartEquation_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e) { XtraMessageBox.Show("待补充"); //SetChartEquation(); } private void barBtnExportXls_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e) { ExportXls(); } private void barBtnExportImage_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e) { ExportImage(); } #endregion /// /// 设置定义点显示 /// public void SetDefinePointVisible(bool visible) { _series_qh_pt.Visible = visible; _series_qe_pt.Visible = visible; _series_qp_pt.Visible = visible; } /// /// 设置工作点显示 /// public void SetLineVisible(bool visible) { if (!_initial_data) return; LineVisible = visible; CalcWorkPointByQ(); } /// /// 设置图例显示 /// 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; _axis_y_qe.Title.Visibility = visible ? DefaultBoolean.True : DefaultBoolean.False; _axis_y_qp.Title.Visibility = visible ? DefaultBoolean.True : DefaultBoolean.False; } /// /// 设置图表显示 /// public void SetChartDisplay(bool monoColor) { if (monoColor) { this.chartControl1.SetChartMonoColorDisplay(); } else { this.chartControl1.SetChartBackColor(); _axisXQ.SetAxisYQColorDisplay(); _axisYQH.SetAxisYQHColorDisplay(_series_qh, _series_qh_pt, true); _axis_y_qe.SetSecondaryAxisYQEColorDisplay(_series_qe, _series_qe_pt, true); _axis_y_qp.SetSecondaryAxisYQPColorDisplay(_series_qp, _series_qp_pt, true); } } /// /// 设置坐标轴 /// public void SetChartAxis() { var dlg = new PumpChartCoordinateDlg(); var onlyQH = _qe == null && _qp == null; dlg.SetBindingData(_coordinate_paras, onlyQH); dlg.OnChangedCoord += (rhs) => { _coordinate_paras = rhs; CalcChartAxis(this.barCekSetSplitPanel.Checked); this.OnCurveCoordinateChanged?.Invoke(_coordinate_paras); }; dlg.ShowDialog(); } ///// ///// 曲线方程 ///// //public void SetChartEquation() //{ // var dlg = new CurveEquationDlg(); // dlg.SetBindingData(_qh, _qe, _qp); // dlg.ShowDialog(); //} /// /// 导出Excel /// public void ExportXls() { Perform2dExportHelper.ExportXLS(_qh, _qe, _qp, 12); } /// /// 导出图片 /// public void ExportImage() { var dlg = new SaveFileDialog(); dlg.Filter = "jpg 图片(*.jpg)|*.jpg"; if (dlg.ShowDialog() != DialogResult.OK) return; this.chartControl1.ExportToImage(dlg.FileName, System.Drawing.Imaging.ImageFormat.Jpeg); } #endregion } }