Shuxia Ning
2024-12-03 ce65365b03d49fc6c6961e0c690768b93c4a4c7c
WinFrmUI/Yw.WinFrmUI.Phart.Core/01-pump/01-single/04-variable-speed-view/PumpVariableSpeedViewChart.cs
@@ -17,8 +17,7 @@
        }
        #region Private Variable 
        private List<PumpVariableSpeedViewModel> _vm_list = new List<PumpVariableSpeedViewModel>();
        private readonly string _tag_qh = "QH", _tag_qe = "QE", _tag_qp = "QP";
        private XYDiagram _diagram;
@@ -26,10 +25,8 @@
        private XYDiagramPane _bottom_pane;
        private AxisX _axis_x_flow;
        private AxisY _axis_y_head;
        private SecondaryAxisY _axis_y_eff, _axis_y_power;
        private ConstantLine _query_flow_line;
        private TextAnnotation _anno_txt_query_info;
        private SecondaryAxisY _axis_y_eff, _axis_y_power;
        private PumpCoordinate _coordinate;
        private bool _qe_visible = true;
@@ -38,72 +35,22 @@
        private bool _equip_visible = true;
        private Yw.Geometry.CubicSpline2d _equip_line = null;
        private Yw.Geometry.Point2d _equip_pt = null; 
        private List<Tuple<string, Yw.Geometry.Point2d, Yw.Geometry.Point2d, Yw.Geometry.Point2d>> _equip_sect_pt_list;
        private bool _initial_data = false;
        #endregion
        #region Public Variable
        /// <summary>
        /// 工作线是否可见
        /// </summary>
        public bool LineVisible
        {
            get => _line_visible;
            set
            {
                _line_visible = value;
                this.barCekLineVisible.Checked = _line_visible;
                this.barBtnSetAxisQValue.Enabled = _line_visible;
            }
        }
        private bool _line_visible = false;
        /// <summary>
        /// 曲线名是否可见
        /// </summary>
        public bool LineNameVisible
        {
            get => _line_name_visible;
            set
            {
                _line_name_visible = value;
                this.barCekCurveNameVisible.Checked = _line_name_visible;
            }
        }
        private bool _line_name_visible = true;
        private PumpVariableSpeedViewViewModel _vm = null;
        #endregion
        #region Public Evnet
        /// <summary>
        /// 坐标变换事件
        /// </summary>
        public event Action<PumpCoordinate> CoordinateChangedEvent = null;
        /// <summary>
        /// 并联状态变换事件
        /// </summary>
        public event Action<bool, string> ParallelStatusChangedEvent = null;
        /// <summary>
        /// 查询点变换事件
        /// </summary>
        public event Action<List<PumpQueryPointViewModel>> QueryPointChangedEvent = null;
        /// <summary>
        /// 设计点变换事件
        /// </summary>
        public event Action<List<PumpDesignPointViewModel>> DesignPointChangedEvent = null;
        public event Action AddBySpeedEvent = null;
        public event Action AddByHzEvent = null;
        public event Action AddByPointEvent = null;
        #endregion
        #region Initial
@@ -130,11 +77,7 @@
            _axis_y_power = _diagram.SecondaryAxesY.GetAxisByName("AxisYQP");
            _axis_y_power.SetSecondaryAxisYQPDisplay();
            _query_flow_line = (ConstantLine)_diagram.AxisX.ConstantLines.GetElementByName("WorkPointLine");
            _query_flow_line.SetWorkPointLineDisplay();
            _anno_txt_query_info = this.chartControl1.AnnotationRepository[0] as TextAnnotation;
            _anno_txt_query_info.SetTextAnnoWorkPointDisplay();
            _axis_x_flow.Visibility = DefaultBoolean.False;
            _axis_x_flow.GridLines.Visible = false;
@@ -144,15 +87,7 @@
            _axis_y_eff.GridLines.Visible = false;
            _axis_y_power.Visibility = DefaultBoolean.False;
            _axis_y_power.GridLines.Visible = false;
            _query_flow_line.Visible = false;
            _anno_txt_query_info.Visible = false;
            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;
        }
@@ -161,19 +96,16 @@
        {
            if (e is not DXCustomPaintEventArgs dxArgs)
                return;
            if (_vm_list == null || !_vm_list.Any())
            if (_vm == null)
                return;
            if (_equip_line != null && _equip_visible)
            if (_equip_line != null && _equip_sect_pt_list != null && _equip_sect_pt_list.Any() && _equip_visible)
            {
                using Pen pen = new(Color.Black, 2);
                pen.DashStyle = System.Drawing.Drawing2D.DashStyle.DashDotDot;
                foreach (var vm in _vm_list)
                pen.DashStyle = System.Drawing.Drawing2D.DashStyle.DashDotDot;
                foreach (var tuple in _equip_sect_pt_list)
                {
                    var sect_pt = vm.EquipPoint;
                    if (sect_pt == null)
                        continue;
                    DrawEquipPoint(dxArgs.Cache, pen, sect_pt, vm.CurrentCurveQE, vm.CurrentCurveQP);
                    DrawEquipPoint(dxArgs.Cache, pen, tuple.Item2, tuple.Item3, tuple.Item4);
                }
                DrawEquipLine(dxArgs.Cache, pen, _equip_line);
@@ -199,7 +131,7 @@
            cache.DrawPath(pen, path);
        }
        private void DrawEquipPoint(GraphicsCache cache, Pen pen, Yw.Geometry.Point2d qh_sect_pt, Yw.Geometry.CubicSpline2d qe, Yw.Geometry.CubicSpline2d qp)
        private void DrawEquipPoint(GraphicsCache cache, Pen pen, Yw.Geometry.Point2d qh_sect_pt, Yw.Geometry.Point2d qe_sect_pt, Yw.Geometry.Point2d qp_sect_pt)
        {
            if (qh_sect_pt == null)
                return;
@@ -212,22 +144,21 @@
            var qh_pt_y = qh_pt.Point.Y;
            cache.DrawLine(pen, new Point(qh_pt_x, qh_pt_y - offset_size), new Point(qh_pt_x, qh_pt_y + offset_size));
            if (qe != null && _qe_visible)
            {
                var qe_y = qe.GetPointY(qh_x);
                var qe_pt = _diagram.DiagramToPoint(qh_x, qe_y, _axis_x_flow, _axis_y_eff);
            if (qe_sect_pt != null && _qe_visible)
            {
                var qe_pt = _diagram.DiagramToPoint(qe_sect_pt.X, qe_sect_pt.Y, _axis_x_flow, _axis_y_eff);
                var qe_pt_x = qe_pt.Point.X;
                var qe_pt_y = qe_pt.Point.Y;
                cache.DrawLine(pen, new Point(qe_pt_x, qe_pt_y - offset_size), new Point(qe_pt_x, qe_pt_y + offset_size));
            }
            if (qp != null && _qp_visible)
            if (qp_sect_pt != null && _qp_visible)
            {
                var qp_y = qe.GetPointY(qh_x);
                var qp_pt = _diagram.DiagramToPoint(qh_x, qp_y, _axis_x_flow, _axis_y_power);
                var qp_pt = _diagram.DiagramToPoint(qp_sect_pt.X, qp_sect_pt.Y, _axis_x_flow, _axis_y_power);
                var qp_pt_x = qp_pt.Point.X;
                var qp_pt_y = qp_pt.Point.Y;
                cache.DrawLine(pen, new Point(qp_pt_x, qp_pt_y - offset_size), new Point(qp_pt_x, qp_pt_y + offset_size));
            }
        }
        /// <summary>
@@ -248,10 +179,10 @@
        /// <summary>
        /// 绑定数据
        /// </summary> 
        public void SetBindingData(List<PumpVariableSpeedViewModel> list)
        public void SetBindingData(PumpVariableSpeedViewViewModel vm)
        {
            _vm_list = list;
            _initial_data = list != null && list.Any();
            _vm = vm;
            _initial_data = vm != null;
            UpdateChart(true);
        }
@@ -261,78 +192,83 @@
        public void SetDesignPoint(double x, double y, double? start_head = null)
        {
            _equip_pt = new Geometry.Point2d(x, y);
            _equip_line = null;
            if (_vm_list == null || !_vm_list.Any())
            {
                this.DesignPointChangedEvent?.Invoke(null);
            _equip_line = null;
            _equip_sect_pt_list = null;
            if (_vm == null)
            {
                return;
            }
            }
            start_head ??= _coordinate.DispMinH();
            var max_hz_vm = _vm_list.OrderBy(x => x.CurrentHz).FirstOrDefault();
            var equip_line = Yw.Geometry.EquipCurveHelper.CalcEquipCurve(max_hz_vm.CurrentCurveQH, _equip_pt, start_head.Value, out Yw.Geometry.Point2d sect_pt);
            var equip_line = Yw.Geometry.EquipCurveHelper.CalcEquipCurve(_vm.CurveQH, _equip_pt, start_head.Value, out Yw.Geometry.Point2d sect_pt);
            if (equip_line == null || sect_pt == null)
                return;
            _equip_line = equip_line;
            _equip_line = equip_line;
            _equip_sect_pt_list = new List<Tuple<string, Geometry.Point2d, Geometry.Point2d, Geometry.Point2d>>();
            var design_pt_list = new List<PumpDesignPointViewModel>();
            foreach (var vm in _vm_list)
            Yw.Geometry.Point2d sect_pt_eff=null, sect_pt_power = null;
            if (_vm.CurveQE != null)
            {
                var eff = _vm.CurveQE.GetPointY(sect_pt.X);
                sect_pt_eff = new Geometry.Point2d(sect_pt.X, eff);
            }
            if (_vm.CurveQP != null)
            {
                var power = _vm.CurveQP.GetPointY(sect_pt.X);
                sect_pt_power = new Geometry.Point2d(sect_pt.X, power);
            }
            _equip_sect_pt_list.Add(new(_vm.Id, sect_pt,sect_pt_eff, sect_pt_power));
            foreach (var vm in _vm.Items)
            {
                double flow = 0, head = 0;
                double? eff = null, power = null;
                var pump_equip_line = Yw.Geometry.EquipCurveHelper.CalcEquipCurve(vm.CurrentCurveQH, _equip_pt, start_head.Value, out Yw.Geometry.Point2d pump_sect_pt);
                var pump_equip_line = Yw.Geometry.EquipCurveHelper.CalcEquipCurve(vm.CurveQH, _equip_pt, start_head.Value, out Yw.Geometry.Point2d pump_sect_pt);
                if (pump_equip_line == null || pump_sect_pt == null)
                    return;
                vm.EquipPoint = pump_sect_pt;
                    return;
                Yw.Geometry.Point2d pump_sect_pt_eff = null, pump_sect_pt_power = null;
                flow = pump_sect_pt.X;
                head = vm.CurrentCurveQH.GetPointYUnlimited(flow);
                if (vm.CurrentCurveQP != null)
                head = vm.CurveQH.GetPointYUnlimited(flow);
                if (vm.CurveQP != null)
                {
                    power = vm.CurrentCurveQP.GetPointYUnlimited(flow);
                    power = vm.CurveQP.GetPointYUnlimited(flow);
                    eff = PumpCalcHelper.CalculateE(flow, head, power.Value);
                    pump_sect_pt_eff = new Geometry.Point2d(flow, eff.Value);
                    pump_sect_pt_power = new Geometry.Point2d(flow, power.Value);
                }
                else if (vm.CurrentCurveQE != null)
                else if (vm.CurveQE != null)
                {
                    eff = vm.CurrentCurveQE.GetPointYUnlimited(flow);
                    eff = vm.CurveQE.GetPointYUnlimited(flow);
                    power = PumpCalcHelper.CalculateP(flow, head, eff.Value);
                    pump_sect_pt_eff = new Geometry.Point2d(flow, eff.Value);
                    pump_sect_pt_power = new Geometry.Point2d(flow, power.Value);
                }
                design_pt_list.Add(new PumpDesignPointViewModel
                {
                    Id = vm.Id,
                    Name = vm.Name,
                    Q = flow,
                    H = head,
                    E = eff,
                    P = power,
                    Hz = vm.CurrentHz,
                    N = vm.CurrentN
                });
                _equip_sect_pt_list.Add(new(vm.Id, new Geometry.Point2d(flow, head), pump_sect_pt_eff, pump_sect_pt_power));
            }
            UpdateChart(true);
            this.DesignPointChangedEvent?.Invoke(design_pt_list);
            UpdateChart(true);
        }
        }
        /// <summary>
        /// 清空曲线
        /// </summary> 
        public void Clear()
        {
            _vm_list = new List<PumpVariableSpeedViewModel>();
            _vm = null;
            _initial_data = false;
            UpdateChart(true);
        }
        /// <summary>
        /// 更新图表
        /// </summary>s
        /// </summary>
        public void UpdateChart(bool calc_coordinate = false)
        {
            if (calc_coordinate || _coordinate == null)
@@ -343,11 +279,7 @@
            CalcSeries();
            CalcChartAxis();
            CalcWorkPointByQ();
            //CalcTextAnchorPoint();
            CalcChartAxis();
        }
        #endregion
@@ -364,7 +296,7 @@
        /// </summary>
        private void CalcCoordinate()
        {
            if (_vm_list == null || !_vm_list.Any())
            if (_vm == null)
            {
                //设置成白板坐标
                _coordinate = new PumpCoordinate();
@@ -392,9 +324,8 @@
            double _scaleMinH = 1, _scaleMaxH = 1;
            foreach (var vm in _vm_list)
            {
                var qh_pt_list = vm.CurrentCurveQH.GetPointList();
                var qh_pt_list = _vm.CurveQH.GetPointList();
                var xxx = qh_pt_list.Select(x => x.X);
                var yyy = qh_pt_list.Select(x => x.Y);
@@ -405,23 +336,52 @@
                _max_head = Math.Max(_max_head, yyy.Max());
            }
            foreach (PumpVariableSpeedViewModel vm in _vm_list)
            if (_vm.CurveQE != null)
            {
                if (vm.CurrentCurveQE == null)
                    continue;
                var qe_pt_list = vm.CurrentCurveQE.GetPointList();
                var qe_pt_list = _vm.CurveQE.GetPointList();
                var yyy = qe_pt_list.Select(x => x.Y);
                _min_eff = Math.Min(_min_eff, yyy.Min());
                _max_eff = Math.Max(_max_eff, yyy.Max());
            }
            foreach (PumpVariableSpeedViewModel vm in _vm_list)
            if (_vm.CurveQP != null)
            {
                if (vm.CurrentCurveQP == null)
                    continue;
                var yyy = vm.CurrentCurveQP.GetPointList().Select(x => x.Y);
                var yyy = _vm.CurveQP.GetPointList().Select(x => x.Y);
                _min_power = Math.Min(_min_power, yyy.Min());
                _max_power = Math.Max(_max_power, yyy.Max());
            }
            if (_vm.Items != null && _vm.Items.Any())
            {
                foreach (var vm in _vm.Items)
                {
                    {
                        var qh_pt_list = vm.CurveQH.GetPointList();
                        var xxx = qh_pt_list.Select(x => x.X);
                        var yyy = qh_pt_list.Select(x => x.Y);
                        _min_flow = Math.Min(_min_flow, xxx.Min());
                        _max_flow = Math.Max(_max_flow, xxx.Max());
                        _min_head = Math.Min(_min_head, yyy.Min());
                        _max_head = Math.Max(_max_head, yyy.Max());
                    }
                    if (vm.CurveQE != null)
                    {
                        var qe_pt_list = vm.CurveQE.GetPointList();
                        var yyy = qe_pt_list.Select(x => x.Y);
                        _min_eff = Math.Min(_min_eff, yyy.Min());
                        _max_eff = Math.Max(_max_eff, yyy.Max());
                    }
                    if (vm.CurveQP != null)
                    {
                        var yyy = vm.CurveQP.GetPointList().Select(x => x.Y);
                        _min_power = Math.Min(_min_power, yyy.Min());
                        _max_power = Math.Max(_max_power, yyy.Max());
                    }
                }
            }
            _coordinate = PumpCoordinate.CalcCoordinate(_min_flow,
@@ -440,6 +400,7 @@
            {
                _coordinate.GridNumberX++;
            }
        }
        /// <summary>
@@ -455,8 +416,7 @@
            _axis_y_eff.GridLines.Visible = false;
            _axis_y_power.Visibility = DefaultBoolean.False;
            _axis_y_power.GridLines.Visible = false;
            _query_flow_line.Visible = false;
            _bottom_pane.Visibility = ChartElementVisibility.Hidden;
@@ -562,8 +522,8 @@
            this.chartControl1.BeginInit();
            this.chartControl1.Series.Clear();
            var annotationCount = this.chartControl1.AnnotationRepository.Count;
            for (int i = annotationCount - 1; i > 0; i--)
            var annotation_count = this.chartControl1.AnnotationRepository.Count;
            for (int i = annotation_count - 1; i > 0; i--)
            {
                if (i == 0)
                    break;
@@ -571,111 +531,39 @@
            }
            this.chartControl1.Legend.CustomItems.Clear();
            if (_vm_list.Count > 0)
            if (_vm != null)
            {
                foreach (var vm in _vm_list)
                CreateLineSeries(_vm.Id, _vm.Name, _vm.CurveQH, _vm.CurveQE, _vm.CurveQP);
                if (_vm.Items != null && _vm.Items.Any())
                {
                    CreateLineSeries(vm);
                }
            }
                    foreach (var vm in _vm.Items)
                    {
                        CreateLineSeries(vm.Id, vm.Name, vm.CurveQH, vm.CurveQE, vm.CurveQP);
                    }
                }
            }
            this.chartControl1.EndInit();
        }
        /// <summary>
        /// 计算注释定位
        /// </summary>
        private void CalcTextAnchorPoint()
        {
            var x = this.chartControl1.Location.X + this.chartControl1.Width ;
            var y = this.chartControl1.Location.Y;
            (_anno_txt_query_info.AnchorPoint as ChartAnchorPoint).X = x;
            (_anno_txt_query_info.AnchorPoint as ChartAnchorPoint).Y = y;
        }
        /// <summary>
        /// 计算工作点
        /// </summary>
        public void CalcWorkPointByQ(double? x_flow = null)
        {
            if (!_line_visible)
            {
                _query_flow_line.Visible = false;
                _query_flow_line.Title.Visible = false;
                return;
            }
            else
            {
                _query_flow_line.Visible = true;
                _query_flow_line.Title.Visible = true;
            }
            if (_vm_list == null || !_vm_list.Any())
                return;
            x_flow ??= _equip_pt?.X ?? _max_flow * 0.8;
            if (x_flow < _min_flow || x_flow > _max_flow)
                return;
            var query_pt_list = new List<PumpQueryPointViewModel>();
            foreach (var vm in _vm_list)
            {
                double flow = 0, head = 0;
                double? eff = null, power = null;
                flow = x_flow.Value;
                head = vm.CurrentCurveQH.GetPointY(flow);
                if (vm.CurrentCurveQP != null)
                {
                    power = vm.CurrentCurveQP.GetPointYUnlimited(flow);
                    eff = PumpCalcHelper.CalculateE(flow, head, power.Value);
                }
                else if (vm.CurrentCurveQE != null)
                {
                    eff = vm.CurrentCurveQE.GetPointYUnlimited(flow);
                    power = PumpCalcHelper.CalculateP(flow, head, eff.Value);
                }
                query_pt_list.Add(new()
                {
                    Id = vm.Id,
                    Name = vm.Name,
                    Q = flow,
                    H = head,
                    E = eff,
                    P = power,
                    Hz = vm.CurrentHz,
                    N = vm.CurrentN
                });
            }
            _query_flow_line.AxisValue = x_flow;
            _query_flow_line.Title.Text = $"{x_flow:N1}";
            this.QueryPointChangedEvent?.Invoke(query_pt_list);
        }
         
        /// <summary>
        /// 创建线系列
        /// </summary> 
        private void CreateLineSeries(PumpVariableSpeedViewModel vm)
        private void CreateLineSeries(string id, string curve_name, Yw.Geometry.CubicSpline2d qh, Yw.Geometry.CubicSpline2d qe, Yw.Geometry.CubicSpline2d qp)
        {
            var series_qh = new DevExpress.XtraCharts.Series();
            series_qh.ArgumentScaleType = DevExpress.XtraCharts.ScaleType.Numerical;
            series_qh.LabelsVisibility = DevExpress.Utils.DefaultBoolean.False;
            series_qh.Name = _tag_qh + vm.Id.ToString();
            series_qh.Name = _tag_qh + id;
            series_qh.ShowInLegend = false;
            series_qh.CrosshairEnabled = DefaultBoolean.False;
            series_qh.Tag = vm.Id.ToString();
            series_qh.LegendTextPattern = vm.Name;
            series_qh.LegendTextPattern = curve_name;
            var series_qh_view = new DevExpress.XtraCharts.SplineSeriesView();
            series_qh_view.LineStyle.Thickness = 2;
            series_qh_view.Color = vm.CurrentColor;
            //series_qh_view.Color = vm.Color;
            series_qh_view.EnableAntialiasing = DefaultBoolean.True;
            series_qh_view.LineTensionPercent = 50;
@@ -684,7 +572,7 @@
            series_qh.View = series_qh_view;
            series_qh.Visible = true;
            var pt_qh_list = vm.CurrentCurveQH.GetPointList(12);
            var pt_qh_list = qh.GetPointList(12);
            for (int i = 0; i < pt_qh_list.Count; i++)
            {
                series_qh.Points.Add(new SeriesPoint(pt_qh_list[i].X, new double[] { pt_qh_list[i].Y }));
@@ -706,10 +594,10 @@
            txt_qh.AutoHeight = true;
            txt_qh.AutoWidth = true;
            txt_qh.BackColor = System.Drawing.Color.Transparent;
            txt_qh.Border.Color = vm.CurrentColor;
            //txt_qh.Border.Color = vm.Color;
            txt_qh.ConnectorStyle = DevExpress.XtraCharts.AnnotationConnectorStyle.Line;
            txt_qh.DXFont = PumpChartDisplay.AnnoFontQH;
            txt_qh.Name = _tag_qh + vm.Id.ToString();
            txt_qh.Name = _tag_qh + id;
            txt_qh.Padding.Bottom = 1;
            txt_qh.Padding.Left = 1;
            txt_qh.Padding.Right = 1;
@@ -718,26 +606,26 @@
            txt_qh.RuntimeMoving = true;
            txt_qh.RuntimeResizing = false;
            txt_qh.RuntimeRotation = false;
            txt_qh.Text = vm.Name;
            txt_qh.TextColor = vm.CurrentColor;
            txt_qh.Text = curve_name;
            //txt_qh.TextColor = vm.Color;
            txt_qh.ShapePosition = position_qh;
            txt_qh.Visible = _line_name_visible;
            txt_qh.Visible = true;
            this.chartControl1.AnnotationRepository.Add(txt_qh);
            this.chartControl1.Series.Add(series_qh);
            if (vm.CurrentCurveQE != null)
            if (qe != null)
            {
                var series_qe = new DevExpress.XtraCharts.Series();
                series_qe.ArgumentScaleType = DevExpress.XtraCharts.ScaleType.Numerical;
                series_qe.LabelsVisibility = DevExpress.Utils.DefaultBoolean.False;
                series_qe.Name = _tag_qe + vm.Id.ToString();
                series_qe.Name = _tag_qe + id;
                series_qe.ShowInLegend = false;
                series_qe.CrosshairEnabled = DefaultBoolean.False;
                series_qe.Tag = vm.Id.ToString();
                series_qe.Tag = id;
                var series_qe_view = new DevExpress.XtraCharts.SplineSeriesView();
                series_qe_view.LineStyle.Thickness = 2;
                series_qe_view.Color = vm.CurrentColor;
                //series_qe_view.Color = vm.Color;
                series_qe_view.AxisY = _axis_y_eff;
                series_qe_view.Pane = _default_pane;
                series_qe_view.EnableAntialiasing = DefaultBoolean.True;
@@ -748,7 +636,7 @@
                series_qe.View = series_qe_view;
                series_qe.Visible = _qe_visible;
                var pt_qe_list = vm.CurrentCurveQE.GetPointList(12);
                var pt_qe_list = qe.GetPointList(12);
                for (int i = 0; i < pt_qe_list.Count; i++)
                {
                    series_qe.Points.Add(new SeriesPoint(pt_qe_list[i].X, new double[] { pt_qe_list[i].Y }));
@@ -757,19 +645,19 @@
                this.chartControl1.Series.Add(series_qe);
            }
            if (vm.CurrentCurveQP != null)
            if (qp != null)
            {
                var series_qp = new DevExpress.XtraCharts.Series();
                series_qp.ArgumentScaleType = DevExpress.XtraCharts.ScaleType.Numerical;
                series_qp.LabelsVisibility = DevExpress.Utils.DefaultBoolean.False;
                series_qp.Name = _tag_qp + vm.Id.ToString();
                series_qp.Name = _tag_qp + id;
                series_qp.ShowInLegend = false;
                series_qp.CrosshairEnabled = DefaultBoolean.False;
                series_qp.Tag = vm.Id.ToString();
                series_qp.Tag = id;
                var series_qp_view = new DevExpress.XtraCharts.SplineSeriesView();
                series_qp_view.LineStyle.Thickness = 2;
                series_qp_view.Color = vm.CurrentColor;
                //series_qp_view.Color = vm.Color;
                series_qp_view.AxisY = _axis_y_power;
                series_qp_view.Pane = _bottom_pane;
                series_qp_view.EnableAntialiasing = DefaultBoolean.True;
@@ -780,155 +668,30 @@
                series_qp.View = series_qp_view;
                series_qp.Visible = _qp_visible;
                var pt_qp_list = vm.CurrentCurveQP.GetPointList(12);
                var pt_qp_list = qp.GetPointList(12);
                for (int i = 0; i < pt_qp_list.Count; i++)
                {
                    series_qp.Points.Add(new SeriesPoint(pt_qp_list[i].X, new double[] { pt_qp_list[i].Y }));
                }
                this.chartControl1.Series.Add(series_qp);
            }
            }
        }
        
        #endregion
        #region ChartEvent
        // 右键对象
        private object _rightClickObj = null;
        private bool _onMoveWorkPointLine = 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 == _query_flow_line)
                    {
                        _onMoveWorkPointLine = true;
                    }
                }
                else if (hitInfo.InAnnotation)
                {
                    _rightClickObj = hitInfo.Annotation;
                }
                else
                {
                    _rightClickObj = null;
                }
            }
        }
        private void chartControl1_MouseMove(object sender, MouseEventArgs e)
        {
            if (!_initial_data)
                return;
            if (_onMoveWorkPointLine)
            {
                var diagramCoordinates = _diagram.PointToDiagram(e.Location);
                var axisValue = diagramCoordinates.GetAxisValue(_axis_x_flow);
                if (axisValue == null)
                    return;
                double chartQ = axisValue.NumericalValue;
                CalcWorkPointByQ(chartQ);
            }
            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;
        }
        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 (_vm_list == null || !_vm_list.Any())
                return;
            var dlg = new PumpAxisValueDlg();
            dlg.SetBindingData();
            dlg.VerifyValueChanged += (value) =>
            {
                if (value < _min_flow || value > _max_flow)
                    return false;
                CalcWorkPointByQ(value);
                return true;
            };
            dlg.ShowDialog();
        }
        private void barCekLineVisible_CheckedChanged(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
        {
            SetLineVisible(this.barCekLineVisible.Checked);
        }
        private void barCekCurveNameVisible_CheckedChanged(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
        {
            SetCurveNameVisible(this.barCekCurveNameVisible.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 barBtnSetChartAxis_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
        {
            SetChartAxis();
        }
        private void barCekCurveQHVisible_CheckedChanged(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
        {
            _default_pane.Visibility = _default_pane.Visibility == ChartElementVisibility.Visible ? ChartElementVisibility.Hidden : ChartElementVisibility.Visible;
        }
        }
        private void barCekCurveQEVisible_CheckedChanged(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
        {
             _qe_visible = this.barCekCurveQEVisible.Checked;
@@ -948,71 +711,8 @@
        }
        #endregion
        /// <summary>
        /// 设置工作点显示
        /// </summary>
        public void SetLineVisible(bool visible)
        {
            if (!_initial_data)
                return;
            LineVisible = visible;
            CalcWorkPointByQ();
        }
        /// <summary>
        /// 设置装置曲线显示
        /// </summary>
        public void SetEquipVisible(bool visible)
        {
            if (!_initial_data)
                return;
            _equip_visible = visible;
            UpdateChart(true);
        }
        /// <summary>
        /// 设置效率曲线显示
        /// </summary>
        public void SetQeVisible(bool visible)
        {
            this.barCekCurveQEVisible.Checked = visible;
        }
        /// <summary>
        /// 设置曲线名
        /// </summary>
        public void SetCurveNameVisible(bool visible)
        {
            if (!_initial_data)
                return;
            _line_name_visible = visible;
            for (int i = 1; i < this.chartControl1.AnnotationRepository.Count; i++)
            {
                var anno = this.chartControl1.AnnotationRepository[i];
                anno.Visible = _line_name_visible;
            }
        }
        /// <summary>
        /// 设置图例显示
        /// </summary>
        public void SetLegendVisible(bool visible)
        {
            this.chartControl1.Legend.Visibility = visible ? DefaultBoolean.True : DefaultBoolean.False;
        }
        /// <summary>
        /// 设置轴名称显示
        /// </summary>
        public void SetAxisNameVisible(bool visible)
        {
            _axis_x_flow.Title.Visibility = visible ? DefaultBoolean.True : DefaultBoolean.False;
            _axis_y_head.Title.Visibility = visible ? DefaultBoolean.True : DefaultBoolean.False;
            _axis_y_eff.Title.Visibility = visible ? DefaultBoolean.True : DefaultBoolean.False;
            _axis_y_power.Title.Visibility = visible ? DefaultBoolean.True : DefaultBoolean.False;
        }
        /// <summary>
        /// 设置坐标轴
        /// </summary>
@@ -1031,25 +731,7 @@
        #endregion
        #region Add Event
        private void barBtnAddBySpeed_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
        {
            this.AddBySpeedEvent?.Invoke();
        }
        private void barBtnAddByHz_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
        {
            this.AddByHzEvent?.Invoke();
        }
        private void barBtnAddByPoint_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
        {
            this.AddByPointEvent?.Invoke();
        }
        #endregion
         
    }