Shuxia Ning
2025-01-14 0f99d4d12f2eae29bbe343f4b3131f2faeccda5d
WinFrmUI/Yw.WinFrmUI.Phart.Core/01-pump/01-view/PumpViewChart.cs
@@ -1,5 +1,8 @@
using DevExpress.Utils;
using DevExpress.Utils.Drawing;
using DevExpress.XtraCharts;
using Yw.Ahart;
using Yw.Geometry;
namespace Yw.WinFrmUI.Phart
{
@@ -26,19 +29,63 @@
        private ConstantLine _const_line_x;
        private ConstantLine _const_line_y;
        private TextAnnotation _const_txt_annotation;
        private TextAnnotation _anno_txt_query_info;
        private PumpCoordinate _coordinate = null;
        private PumpCurveViewModel _vm = null;
        private List<PumpViewChartViewModel> _vm_list = null;
        private List<(List<Yw.Geometry.Point2d> FitPointList, bool IsClosed, double Tension)> _equal_eff_list = null;
        private (List<Yw.Geometry.Point2d> FitPointList, PumpSectPointViewModel SectPoint)? _equip = null;
        private bool _default_visible = false;
        private bool _power_visible = false;
        private bool _eff_visible = false;
        private bool _equal_eff_visible = false;
        private bool _split_panel = false;
        private bool _line_visible = false;
        private bool _initial_data = false;
        #endregion
        #region Public Variable
        /// <summary>
        ///
        /// </summary>
        public bool LineVisible
        {
            get
            {
                return _line_visible;
            }
            set
            {
                _line_visible = value;
                _const_line_x.Visible = value;
                _const_line_y.Visible = value;
                SetAxisXValue();
            }
        }
        /// <summary>
        ///
        /// </summary>
        public bool SplitPanel
        {
            get
            {
                return _split_panel;
            }
            set
            {
                _split_panel = value;
            }
        }
        #endregion
        #region Private Initial
        /// <summary>
        /// 初始化图表
@@ -114,9 +161,9 @@
        #endregion
        #region Chart Event
        #region Private Chart Event
        ToolTipController toolTip = new ToolTipController();
        ToolTipController _tool_tip = new();
        private void chartControl1_ObjectHotTracked(object sender, HotTrackEventArgs e)
        {
            //if (!_initial_data)
@@ -124,53 +171,34 @@
            //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);
            //    _tool_tip.ShowHint(tip);
            //}
            //else
            //{
            //    toolTip.HideHint();
            //    _tool_tip.HideHint();
            //}
        }
        // 右键对象
        private object _rightClickObj = null;
        private bool _onMoveWorkPointLine = false;
        private bool _onMoveWorkHLine = false;
        private bool _on_move_x_line = false;
        private bool _on_move_y_line = 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.InConstantLine)
                {
                    if (hitInfo.ConstantLine == _const_line_x)
                    {
                        _onMoveWorkPointLine = true;
                        _on_move_x_line = true;
                    }
                    else if (hitInfo.ConstantLine == _const_line_y)
                    {
                        _onMoveWorkHLine = true;
                        _on_move_y_line = true;
                    }
                }
                else if (hitInfo.InAnnotation)
                {
                    _rightClickObj = hitInfo.Annotation;
                }
                else
                {
                    _rightClickObj = null;
                }
            }
@@ -178,53 +206,53 @@
        private void chartControl1_MouseMove(object sender, MouseEventArgs e)
        {
            //if (!_initial_data)
            //    return;
            if (!_initial_data)
                return;
            //if (_onMoveWorkPointLine)
            //{
            //    var diagram_coordinates = _diagram.PointToDiagram(e.Location);
            //    var axisValue = diagram_coordinates.GetAxisValue(_axis_x_flow);
            //    if (axisValue == null)
            //        return;
            //    double chartQ = axisValue.NumericalValue;
            //    CalcWorkPointByQ(chartQ);
            if (_on_move_x_line)
            {
                var diagram_coordinates = _diagram.PointToDiagram(e.Location);
                var axis_value = diagram_coordinates.GetAxisValue(_axis_x_flow);
                if (axis_value == null)
                    return;
                double chartQ = axis_value.NumericalValue;
                SetAxisXValue(chartQ);
            //}
            //else if (_onMoveWorkHLine)
            //{
            //    var diagram_coordinates = _diagram.PointToDiagram(e.Location);
            //    var axisValue = diagram_coordinates.GetAxisValue(_axis_y_head);
            //    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 if (_on_move_y_line)
            {
                var diagram_coordinates = _diagram.PointToDiagram(e.Location);
                var axis_value = diagram_coordinates.GetAxisValue(_axis_y_head);
                if (axis_value == null)
                    return;
                double chartH = axis_value.NumericalValue;
                SetAxisYValue(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;
            //    }
            //}
                }
                else
                {
                    this.chartControl1.Cursor = Cursors.Default;
                }
            }
        }
        private void chartControl1_MouseUp(object sender, MouseEventArgs e)
        {
            if (!_initial_data)
                return;
            _onMoveWorkPointLine = false;
            _onMoveWorkHLine = false;
            _on_move_x_line = false;
            _on_move_y_line = false;
        }
        private void chartControl1_Resize(object sender, EventArgs e)
@@ -236,7 +264,7 @@
        {
            if (!_initial_data)
                return;
            if (_vm == null)
            if (_vm_list == null)
                return;
            if (_axis_x_flow.Visibility == DefaultBoolean.False)
                return;
@@ -244,16 +272,15 @@
                return;
            var cache = dx_args.Cache;
            cache.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
            if (_equal_eff_visible && _vm.EqualEffList != null && _vm.EqualEffList.Any())
            if (_equal_eff_list != null && _equal_eff_list.Any())
            {
                using Pen pen = new(Color.Green, 2);
                foreach (var eq_eff in _vm.EqualEffList)
                foreach (var vm in _equal_eff_list)
                {
                    if (!eq_eff.IsValid())
                        continue;
                    var eq_eff_pt_list = eq_eff.CurveEqualEff;
                    var fit_pt_list = vm.FitPointList;
                    var pic_eq_eff_pt_list = new List<Point>();
                    foreach (var eq_eff_pt in eq_eff_pt_list)
                    foreach (var eq_eff_pt in fit_pt_list)
                    {
                        var x = eq_eff_pt.X;
                        var y = eq_eff_pt.Y;
@@ -267,16 +294,16 @@
                    var pt_count = pic_eq_eff_pt_list.Count;
                    if (pt_count > 2)
                    {
                        if (eq_eff.IsClosed)
                        if (vm.IsClosed)
                        {
                            var path = cache.CreatePath();
                            path.AddClosedCurve(pic_eq_eff_pt_list.ToArray(), (float)eq_eff.Tension);
                            path.AddClosedCurve(pic_eq_eff_pt_list.ToArray(), (float)vm.Tension);
                            cache.DrawPath(pen, path);
                        }
                        else
                        {
                            var path = cache.CreatePath();
                            path.AddCurve(pic_eq_eff_pt_list.ToArray(), (float)eq_eff.Tension);
                            path.AddCurve(pic_eq_eff_pt_list.ToArray(), (float)vm.Tension);
                            cache.DrawPath(pen, path);
                        }
                    }
@@ -287,45 +314,74 @@
                    else if (pt_count == 1)
                    {
                        Rectangle rc = new Rectangle(pic_eq_eff_pt_list[0].X - 2, pic_eq_eff_pt_list[0].Y - 2, 4, 4);
                        using (Brush b = new SolidBrush(pen.Color))
                            cache.FillEllipse(b, rc);
                        using Brush b = new SolidBrush(pen.Color);
                        cache.FillEllipse(b, rc);
                    }
                }
            }
            if (_vm.Equip != null && _vm.Equip.IsValid())
            if (_equip.HasValue)
            {
                using Pen pen = new(Color.Black, 2);
                pen.DashStyle = System.Drawing.Drawing2D.DashStyle.DashDotDot;
                DrawEquipLine(dx_args.Cache, pen, _equip.Value.FitPointList);
                DrawEquipPoint(dx_args.Cache, pen, _equip.Value.SectPoint);
            }
        }
                var offset_size = 10;
                var qh_pt = _diagram.DiagramToPoint(_vm.Equip.SectQ, _vm.Equip.SectH, _axis_x_flow, _axis_y_head);
                var qh_pt_x = qh_pt.Point.X;
                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));
        private void DrawEquipPoint(GraphicsCache cache, Pen pen, PumpSectPointViewModel sect_pt)
        {
            if (sect_pt == null)
                return;
                if (_eff_visible && _vm.Equip.SectE != null)
                {
                    var qe_pt = _diagram.DiagramToPoint(_vm.Equip.SectQ, _vm.Equip.SectE.Value, _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 (_power_visible && _vm.Equip.SectP != null)
                {
                    var qp_pt = _diagram.DiagramToPoint(_vm.Equip.SectQ, _vm.Equip.SectP.Value, _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));
                }
            double Q = sect_pt.Q;
            double H = sect_pt.H;
            double? E = sect_pt.E;
            double? P = sect_pt.P;
            var offset_size = 10;
            var qh_pt = _diagram.DiagramToPoint(Q, H, _axis_x_flow, _axis_y_head);
            var qh_pt_x = qh_pt.Point.X;
            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 (E.HasValue && _eff_visible)
            {
                var qe_pt = _diagram.DiagramToPoint(Q, E.Value, _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 (P.HasValue && _power_visible)
            {
                var qp_pt = _diagram.DiagramToPoint(Q, P.Value, _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));
            }
        }
        private void DrawEquipLine(GraphicsCache cache, Pen pen, List<Yw.Geometry.Point2d> pt_list)
        {
            if (pt_list == null || !pt_list.Any())
                return;
            var pt_f_list = new List<PointF>();
            foreach (var pt in pt_list)
            {
                var x = pt.X;
                var y = pt.Y;
                var c_pt = _diagram.DiagramToPoint(x, y, _axis_x_flow, _axis_y_head);
                pt_f_list.Add(new PointF(c_pt.Point.X, c_pt.Point.Y));
            }
            using var path = new System.Drawing.Drawing2D.GraphicsPath();
            path.AddCurve(pt_f_list.ToArray());
            cache.DrawPath(pen, path);
        }
        #endregion
        #region  Set  
@@ -333,10 +389,12 @@
        /// <summary>
        /// 清空图表
        /// </summary>
        public void ClearBindingData()
        public void Clear()
        {
            _vm = null;
            _default_visible = false;
            _vm_list = null;
            _equal_eff_list = null;
            _equip = null;
            _coordinate = null;
            _split_panel = false;
            _eff_visible = false;
            _power_visible = false;
@@ -351,197 +409,125 @@
        /// <summary>
        /// 设置图表
        /// </summary>
        public void SetBindingData(PumpCurveViewModel vm, bool default_visible = true, bool split_panel = false, bool eff_visible = false, bool power_visible = true, bool equal_eff_visible = false)
        public void SetBindingData(List<PumpViewChartViewModel> vm_list, string coordinate = null, bool split_panel = false, bool eff_visible = false, bool power_visible = true, bool equal_eff_visible = false)
        {
            _vm = vm;
            _default_visible = default_visible;
            _vm_list = vm_list;
            _equal_eff_list = null;
            _equip = null;
            _coordinate = PumpCoordinate.ToModel(coordinate);
            _split_panel = split_panel;
            _eff_visible = eff_visible;
            _power_visible = power_visible;
            _equal_eff_visible = equal_eff_visible;
            this.chartControl1.BeginInit();
            this.chartControl1.Series.Clear();
            this.chartControl1.AnnotationRepository.Clear();
            this.chartControl1.Legend.CustomItems.Clear();
            if (vm == null)
            if (IsInvalidData())
            {
                _initial_data = false;
                this.chartControl1.EndInit();
                return;
            }
            AxisXBase axis_x = null;
            AxisYBase axis_y = null;
            XYDiagramPaneBase pane = null;
            if (default_visible)
                AddDefault(vm);
            AddEquip(vm.Equip);
            AddVariableSpeedList(vm.VariableSpeedList);
            if (_equal_eff_visible)
                AddEqualEffList(vm.EqualEffList);
            AddEqualPowerList(vm.EqualPowerList);
            if (vm.Coordinate == null)
            _equal_eff_list = new List<(List<Point2d> FitPointList, bool IsClosed, double Tension)>();
            foreach (var vm in _vm_list)
            {
                if (vm.CurveType == Ahart.eCurveType.EqualE)
                {
                    axis_x = _axis_x_flow;
                    axis_y = _axis_y_head;
                    pane = _default_pane;
                    var paras = PhartGraphHelper.GetGraphParas<EqualEGraphParasViewModel>(vm.CurveType, vm.GraphParas);
                    if (paras.Tension<=0)
                    {
                        paras.Tension = 0.7;
                    }
                    _equal_eff_list.Add((vm.FitPointList, paras.IsClosed, paras.Tension));
                }
                else if (vm.CurveType == Ahart.eCurveType.QH)
                {
                    axis_x = _axis_x_flow;
                    axis_y = _axis_y_head;
                    pane = _default_pane;
                }
                else if (vm.CurveType == Ahart.eCurveType.QE)
                {
                    axis_x = _axis_x_flow;
                    axis_y = _axis_y_eff;
                    pane = _default_pane;
                }
                else if (vm.CurveType == Ahart.eCurveType.QP)
                {
                    axis_x = _axis_x_flow;
                    axis_y = _axis_y_power;
                    pane = _split_panel? _bottom_pane: _default_pane;
                }
                if (vm.AnnotationList != null && vm.AnnotationList.Any())
                {
                    foreach (var name in vm.AnnotationList)
                    {
                        AddAnnotation(vm.Id, name.Text, vm.Color, axis_y, pane, new Geometry.Point2d(name.X, name.Y), -40);
                    }
                }
                if (vm.CurveType == Ahart.eCurveType.EqualE)
                    continue;
                var dash_style = DashStyle.Solid;
                if (vm.Hz == 50)
                    dash_style = DashStyle.Dot;
                AddLineSeries(vm.Id, vm.Color, axis_x, axis_y, pane, vm.FitPointList, dash_style);
            }
            if (_coordinate == null)
                SetCoordinate();
            }
            else
            {
                _coordinate = vm.Coordinate;
            }
            SetChartAxis();
            this.chartControl1.EndInit();
            _initial_data = true;
        }
        #region Add Data
        private void AddDefault(PumpCurveViewModel vm)
        /// <summary>
        /// 设置图表
        /// </summary>
        public void SetEquip(List<Yw.Geometry.Point2d> fit_pt_list, PumpSectPointViewModel sect_pt)
        {
            var id = vm.Id;
            var caption_qh = vm.CurveQHName;
            var caption_qp = vm.CurveQPName;
            var color_qh = vm.ColorQH ?? PumpChartDisplay.CurveColorQH;
            var color_qe = vm.ColorQE ?? PumpChartDisplay.CurveColorQE;
            var color_qp = vm.ColorQP ?? PumpChartDisplay.CurveColorQP;
            var qh = vm.CurveQH;
            var qe = vm.CurveQE;
            var qp = vm.CurveQP;
            XYDiagramPaneBase bottom_pane = _split_panel ? _bottom_pane : _default_pane;
            AddLineSeries(id, color_qh, _axis_x_flow, _axis_y_head, _default_pane, qh, DevExpress.XtraCharts.DashStyle.Dash);
            if (!string.IsNullOrEmpty(caption_qh))
                AddAnnotation(id, caption_qh, color_qh, _axis_y_head, _default_pane, qh.Last());
            if (qe != null && qe.Any() && _eff_visible)
            _equip = null;
            if (fit_pt_list != null && fit_pt_list.Any() && sect_pt != null)
            {
                AddLineSeries(id, color_qe, _axis_x_flow, _axis_y_eff, _default_pane, qe, DevExpress.XtraCharts.DashStyle.Dash);
                _equip = (fit_pt_list, sect_pt);
            }
            if (qp != null && qp.Any() && _power_visible)
            {
                AddLineSeries(id, color_qp, _axis_x_flow, _axis_y_power, bottom_pane, qp, DevExpress.XtraCharts.DashStyle.Dash);
                if (!string.IsNullOrEmpty(caption_qp))
                {
                    AddAnnotation(id, caption_qp, color_qp, _axis_y_power, bottom_pane, qp.Last());
                }
            }
            SetCoordinate();
            SetChartAxis();
        }
        private void AddEquip(PumpCurveEquipViewModel vm)
        //是否是无效数据
        private bool IsInvalidData()
        {
            if (vm == null)
                return;
            var id = vm.Id;
            var caption = vm.CurveName;
            var color = vm.Color ?? Color.Black;
            var equip = vm.CurveEquip;
            var equip_pt = new Yw.Geometry.Point2d(vm.PipeQ, vm.PipeH);
            AddLineSeries(id, color, _axis_x_flow, _axis_y_head, _default_pane, equip, DevExpress.XtraCharts.DashStyle.DashDotDot);
            // AddPointSeries(id, color, _axis_x_flow, _axis_y_head, _default_pane, new List<Geometry.Point2d>() { equip_pt }, MarkerKind.ThinCross);
            if (!string.IsNullOrEmpty(caption))
                AddAnnotation(id, caption, color, _axis_y_head, _default_pane, equip.Last());
        }
        private void AddVariableSpeedList(List<PumpCurveVariableSpeedViewModel> vm_list)
        {
            if (vm_list == null || !vm_list.Any())
                return;
            XYDiagramPaneBase bottom_pane = _split_panel ? _bottom_pane : _default_pane;
            foreach (var vm in vm_list)
            if (_vm_list == null || !_vm_list.Any())
            {
                if (!vm.IsValid())
                    continue;
                var id = vm.Id;
                var caption_qh = vm.CurveQHName;
                var caption_qp = vm.CurveQPName;
                var color_qh = vm.ColorQH ?? PumpChartDisplay.CurveColorQH;
                var color_qe = vm.ColorQE ?? PumpChartDisplay.CurveColorQE;
                var color_qp = vm.ColorQP ?? PumpChartDisplay.CurveColorQP;
                var qh = vm.CurveQH;
                var qe = vm.CurveQE;
                var qp = vm.CurveQP;
                AddLineSeries(id, color_qh, _axis_x_flow, _axis_y_head, _default_pane, qh);
                if (!string.IsNullOrEmpty(caption_qh))
                    AddAnnotation(id, caption_qh, color_qh, _axis_y_head, _default_pane, qh.Last());
                if (qe != null && qe.Any() && _eff_visible)
                {
                    AddLineSeries(id, color_qe, _axis_x_flow, _axis_y_eff, _default_pane, qe);
                }
                if (qp != null && qp.Any() && _power_visible)
                {
                    AddLineSeries(id, color_qp, _axis_x_flow, _axis_y_power, bottom_pane, qp);
                    if (!string.IsNullOrEmpty(caption_qp))
                    {
                        AddAnnotation(id, caption_qp, color_qp, _axis_y_power, bottom_pane, qp.Last());
                    }
                }
                return true;
            }
        }
        private void AddEqualEffList(List<PumpCurveEqualEffViewModel> vm_list)
        {
            if (vm_list == null || !vm_list.Any())
                return;
            foreach (var vm in vm_list)
            if (!_vm_list.Exists(x => x.CurveType == Ahart.eCurveType.QH))
            {
                if (!vm.IsValid())
                    continue;
                var id = vm.Id;
                var caption = vm.CurveName;
                var color = vm.Color ?? Color.Green;
                var equif_eff = vm.CurveEqualEff;
                if (!string.IsNullOrEmpty(caption))
                {
                    if (equif_eff.Count > 2)
                    {
                        AddAnnotation(id, caption, color, _axis_y_head, _default_pane, equif_eff.First(), 60);
                    }
                    AddAnnotation(id, caption, color, _axis_y_head, _default_pane, equif_eff.Last(), 60);
                }
                return true;
            }
            return false;
        }
        private void AddEqualPowerList(List<PumpCurveEqualPowerViewModel> vm_list)
        {
            if (vm_list == null || !vm_list.Any())
                return;
            foreach (var vm in vm_list)
            {
                if (!vm.IsValid())
                    continue;
                var id = vm.Id;
                var caption = vm.CurveName;
                var color = vm.Color ?? Color.Green;
                var equif_power = vm.CurveEqualPower;
                if (equif_power.Count < 2)
                {
                    AddPointSeries(id, color, _axis_x_flow, _axis_y_head, _default_pane, equif_power);
                }
                else
                {
                    AddLineSeries(id, color, _axis_x_flow, _axis_y_head, _default_pane, equif_power, DashStyle.Dash);
                }
                if (!string.IsNullOrEmpty(caption))
                    AddAnnotation(id, caption, color, _axis_y_head, _default_pane, equif_power.Last());
            }
        }
        #endregion
        #region Add Chart Data 
@@ -586,6 +572,10 @@
            view.LineStyle.DashStyle = dash;
            view.LineStyle.LineJoin = System.Drawing.Drawing2D.LineJoin.Round;
            view.LineStyle.Thickness = 2;
            if (dash!= DashStyle.Solid)
            {
                view.LineStyle.Thickness =3;
            }
            view.Color = color;
            view.EnableAntialiasing = DefaultBoolean.True;
            view.MarkerVisibility = DefaultBoolean.False;
@@ -652,6 +642,7 @@
        }
        #endregion
        #endregion
        #region Set Axis
@@ -666,12 +657,7 @@
        /// </summary>
        private void SetCoordinate()
        {
            if (_vm == null)
            {
                InitialCoordinate();
                return;
            }
            if (_vm.CurveQH == null || !_vm.CurveQH.Any())
            if (IsInvalidData())
            {
                InitialCoordinate();
                return;
@@ -687,60 +673,28 @@
            var e_list_list = new List<List<double>>();
            var p_list_list = new List<List<double>>();
            if (_default_visible)
            foreach (var vm in _vm_list)
            {
                q_list_list.Add(_vm.CurveQH.Select(x => x.X).ToList());
                h_list_list.Add(_vm.CurveQH.Select(x => x.Y).ToList());
                if (_vm.CurveQE != null)
                if (vm.CurveType == Ahart.eCurveType.QH || vm.CurveType == Ahart.eCurveType.EqualE)
                {
                    e_list_list.Add(_vm.CurveQE.Select(x => x.Y).ToList());
                    q_list_list.Add(vm.FitPointList.Select(x => x.X).ToList());
                    h_list_list.Add(vm.FitPointList.Select(x => x.Y).ToList());
                }
                if (_vm.CurveQP != null)
                else if (vm.CurveType == Ahart.eCurveType.QE)
                {
                    p_list_list.Add(_vm.CurveQP.Select(x => x.Y).ToList());
                    e_list_list.Add(vm.FitPointList.Select(x => x.Y).ToList());
                }
                else if (vm.CurveType == Ahart.eCurveType.QP)
                {
                    p_list_list.Add(vm.FitPointList.Select(x => x.Y).ToList());
                }
            }
            if (_vm.Equip != null)
            if (_equip.HasValue)
            {
                var item = _vm.Equip;
                q_list_list.Add(item.CurveEquip.Select(x => x.X).ToList());
                h_list_list.Add(item.CurveEquip.Select(x => x.Y).ToList());
            }
            if (_vm.VariableSpeedList != null && _vm.VariableSpeedList.Any())
            {
                foreach (var item in _vm.VariableSpeedList)
                {
                    q_list_list.Add(item.CurveQH.Select(x => x.X).ToList());
                    h_list_list.Add(item.CurveQH.Select(x => x.Y).ToList());
                    if (item.CurveQE != null)
                    {
                        e_list_list.Add(item.CurveQE.Select(x => x.Y).ToList());
                    }
                    if (item.CurveQP != null)
                    {
                        p_list_list.Add(item.CurveQP.Select(x => x.Y).ToList());
                    }
                }
            }
            if (_vm.EqualEffList != null && _vm.EqualEffList.Any())
            {
                foreach (var item in _vm.EqualEffList)
                {
                    q_list_list.Add(item.CurveEqualEff.Select(x => x.X).ToList());
                    h_list_list.Add(item.CurveEqualEff.Select(x => x.Y).ToList());
                }
            }
            if (_vm.EqualPowerList != null && _vm.EqualPowerList.Any())
            {
                foreach (var item in _vm.EqualPowerList)
                {
                    q_list_list.Add(item.CurveEqualPower.Select(x => x.X).ToList());
                    h_list_list.Add(item.CurveEqualPower.Select(x => x.Y).ToList());
                }
                var fit_pt_list = _equip.Value.FitPointList;
                q_list_list.Add(fit_pt_list.Select(x => x.X).ToList());
                h_list_list.Add(fit_pt_list.Select(x => x.Y).ToList());
            }
@@ -869,99 +823,316 @@
            _axis_x_flow.SetAxisRange(_coordinate.CoordMinQ, _coordinate.CoordMinQ + _coordinate.GridNumberX * _coordinate.CoordSpaceQ);
            //是否分割面板:流量效率在上,功率在下
            if (_split_panel)
            {
                if (_power_visible)
                var grid_count_head = _coordinate.EndLineNoH - _coordinate.StartLineNoH;
                var grid_count_eff = _coordinate.EndLineNoE - _coordinate.StartLineNoE;
                int grid_count_up = Math.Max(grid_count_head, grid_count_eff);
                if (_eff_visible)
                {
                    var grid_count_head = _coordinate.EndLineNoH - _coordinate.StartLineNoH;
                    var grid_count_eff = _coordinate.EndLineNoE - _coordinate.StartLineNoE;
                    int grid_count_add = Math.Max(grid_count_head, grid_count_eff);
                    if (_eff_visible)
                        grid_count_add += +5;//多两条
                    var max_axis_head = _coordinate.CoordMinH + _coordinate.EndLineNoH * _coordinate.CoordSpaceH;
                    var min_axis_head = max_axis_head - grid_count_add * _coordinate.CoordSpaceH;
                    _axis_y_head.SetAxisRange(min_axis_head, max_axis_head);
                    var min_axis_eff = _coordinate.CoordMinE + _coordinate.StartLineNoE * _coordinate.CoordSpaceE;
                    var max_axis_eff = min_axis_eff + grid_count_add * _coordinate.CoordSpaceE;
                    _axis_y_eff.SetAxisRange(min_axis_eff, max_axis_eff);
                    _bottom_pane.Visibility = ChartElementVisibility.Visible;
                    grid_count_up += 4;//多两条
                }
                else
                {
                    var grid_count_power = _coordinate.EndLineNoP - _coordinate.StartLineNoP;
                    var grid_delete_head = grid_count_power * _coordinate.CoordSpaceH;
                    grid_delete_head = _coordinate.CoordMinH < 0 ? -grid_delete_head : grid_delete_head;
                    var grid_delete_eff = grid_count_power * _coordinate.CoordSpaceE;
                    grid_delete_eff = _coordinate.CoordMinE < 0 ? -grid_delete_eff : grid_delete_eff;
                var max_axis_head = _coordinate.CoordMinH + _coordinate.EndLineNoH * _coordinate.CoordSpaceH;
                var min_axis_head = max_axis_head - grid_count_up * _coordinate.CoordSpaceH;
                _axis_y_head.SetAxisRange(min_axis_head, max_axis_head);
                    _axis_y_head.SetAxisRange(_coordinate.CoordMinH - grid_delete_head, _coordinate.CoordMinH + _coordinate.GridNumberY * _coordinate.CoordSpaceH);
                    _axis_y_eff.SetAxisRange(_coordinate.CoordMinE - grid_delete_eff, _coordinate.CoordMinE + _coordinate.GridNumberY * _coordinate.CoordSpaceE);
                    _bottom_pane.Visibility = ChartElementVisibility.Hidden;
                }
                var min_axis_eff = _coordinate.CoordMinE + _coordinate.StartLineNoE * _coordinate.CoordSpaceE;
                var max_axis_eff = min_axis_eff + grid_count_up * _coordinate.CoordSpaceE;
                _axis_y_eff.SetAxisRange(min_axis_eff, max_axis_eff);
                if ((!_eff_visible) && (!_power_visible))
                {
                    _axis_y_head.SetAxisRange(_coordinate.DispMinH(), _coordinate.DispMaxH());
                }
                _axis_y_power.SetAxisRange(_coordinate.DispMinP(), _coordinate.DispMaxP());
                _axis_y_power.SetAxisRange(_coordinate.DispMinP(), _coordinate.DispMaxP());
                _bottom_pane.Visibility = ChartElementVisibility.Visible;
            }
            else
            {
                if ((!_eff_visible) && (!_power_visible))
                {
                    _axis_y_head.SetAxisRange(_coordinate.DispMinH(), _coordinate.DispMaxH());
                }
                else if ((!_eff_visible) && _power_visible)
                {
                    var grid_count_eff = _coordinate.EndLineNoE - _coordinate.StartLineNoE;
                    if (_coordinate.EndLineNoH - _coordinate.StartLineNoH < 6)
                        grid_count_eff++;
                    var grid_delete_head = grid_count_eff * _coordinate.CoordSpaceH;
                    grid_delete_head = _coordinate.CoordMinH < 0 ? -grid_delete_head : grid_delete_head;
                    var grid_delete_power = grid_count_eff * _coordinate.CoordSpaceP;
                    _axis_y_head.SetAxisRange(_coordinate.CoordMinH - grid_delete_head, _coordinate.CoordMinH + _coordinate.GridNumberY * _coordinate.CoordSpaceH);
                    _axis_y_power.SetAxisRange(_coordinate.CoordMinP, _coordinate.CoordMinP + _coordinate.GridNumberY * _coordinate.CoordSpaceP - grid_delete_power);
                }
                else if (_eff_visible && (!_power_visible))
                {
                    var grid_count_power = _coordinate.EndLineNoP - _coordinate.StartLineNoP;
                    var grid_delete_head = grid_count_power * _coordinate.CoordSpaceH;
                    grid_delete_head = _coordinate.CoordMinH < 0 ? -grid_delete_head : grid_delete_head;
                    var grid_delete_eff = grid_count_power * _coordinate.CoordSpaceE;
                    grid_delete_eff = _coordinate.CoordMinE < 0 ? -grid_delete_eff : grid_delete_eff;
                    _axis_y_head.SetAxisRange(_coordinate.CoordMinH - grid_delete_head, _coordinate.CoordMinH + _coordinate.GridNumberY * _coordinate.CoordSpaceH);
                    _axis_y_eff.SetAxisRange(_coordinate.CoordMinE - grid_delete_eff, _coordinate.CoordMinE + _coordinate.GridNumberY * _coordinate.CoordSpaceE);
                }
                else
                if (_eff_visible)
                {
                    _axis_y_head.SetAxisRange(_coordinate.CoordMinH, _coordinate.CoordMinH + _coordinate.GridNumberY * _coordinate.CoordSpaceH);
                    _axis_y_eff.SetAxisRange(_coordinate.CoordMinE, _coordinate.CoordMinE + _coordinate.GridNumberY * _coordinate.CoordSpaceE);
                    _axis_y_power.SetAxisRange(_coordinate.CoordMinP, _coordinate.CoordMinP + _coordinate.GridNumberY * _coordinate.CoordSpaceP);
                }
                else
                {
                    var grid_count_eff = _coordinate.GridNumberY - (_coordinate.EndLineNoH - _coordinate.StartLineNoH+ _coordinate.EndLineNoP - _coordinate.StartLineNoP);
                    var grid_delete_head = grid_count_eff * _coordinate.CoordSpaceH;
                    double min_head = _coordinate.CoordMinH;
                    if (true)
                    {
                        if (_coordinate.CoordMinH<0)
                        {
                            min_head=_coordinate.CoordMinH - -grid_delete_head;
                        }
                        else
                        {
                            min_head = _coordinate.CoordMinH+grid_delete_head;
                        }
                    }
                    var grid_delete_power = grid_count_eff * _coordinate.CoordSpaceP;
                    _axis_y_head.SetAxisRange(min_head, _coordinate.CoordMinH + _coordinate.GridNumberY * _coordinate.CoordSpaceH);
                    _axis_y_power.SetAxisRange(_coordinate.CoordMinP, _coordinate.CoordMinP + _coordinate.GridNumberY * _coordinate.CoordSpaceP - grid_delete_power);
                }
                _bottom_pane.Visibility = ChartElementVisibility.Hidden;
            }
        }
        #endregion
        #region Set Axis Value
        /// <summary>
        /// 设置X轴值
        /// </summary>
        public void SetAxisXValue(double? x = null)
        {
            if (!_line_visible)
            {
                _const_line_x.Visible = false;
                _const_line_x.Title.Visible = false;
                _const_line_y.Visible = false;
                _const_line_y.Title.Visible = false;
                return;
            }
            else
            {
                _const_line_x.Visible = true;
                _const_line_x.Title.Visible = true;
                _const_line_y.Visible = true;
                _const_line_y.Title.Visible = true;
            }
            if (this.IsInvalidData())
                return;
            var vm_sel = _vm_list.Find(x => x.IsSelect);
            if (vm_sel == null)
                return;
            var min_x = vm_sel.FitPointList.Min(x => x.X);
            var max_x = vm_sel.FitPointList.Max(x => x.X);
            if (x == null)
            {
                x = (min_x + max_x) / 2;
            }
            else
            {
                if (x < min_x || x > max_x)
                    return;
            }
            var x_value = x.Value;
            var y_value = vm_sel.FitPointList.GetInterPointsY(x_value)?.FirstOrDefault();
            _const_line_x.AxisValue = x_value;
            _const_line_x.Title.Text = $"{x_value:N1}";
            _const_line_y.AxisValue = y_value;
            _const_line_y.Title.Text = $"{y_value:N1}";
        }
        /// <summary>
        /// 设置Y轴值
        /// </summary>
        public void SetAxisYValue(double y)
        {
            if (!_line_visible)
                return;
            if (IsInvalidData())
                return;
            var vm_sel = _vm_list.Find(x => x.IsSelect);
            if (vm_sel == null)
                return;
            var min_y = vm_sel.FitPointList.Min(x => x.Y);
            var max_y = vm_sel.FitPointList.Max(x => x.Y);
            if (y < min_y || y > max_y)
                return;
            var x_value = vm_sel.FitPointList.GetInterPointsX(y)?.LastOrDefault();
            SetAxisXValue(x_value);
        }
        #endregion
    }
}
///// <summary>
///// 设置图表轴
///// </summary>
//private void SetChartAxis()
//{
//    _axis_x_flow.Visibility = DefaultBoolean.False;
//    _axis_x_flow.GridLines.Visible = false;
//    _axis_y_head.Visibility = DefaultBoolean.False;
//    _axis_y_head.GridLines.Visible = false;
//    _axis_y_eff.Visibility = DefaultBoolean.False;
//    _axis_y_eff.GridLines.Visible = false;
//    _axis_y_power.Visibility = DefaultBoolean.False;
//    _axis_y_power.GridLines.Visible = false;
//    if (_coordinate == null)
//    {
//        _const_line_x.Visible = false;
//        _const_line_y.Visible = false;
//        _bottom_pane.Visibility = ChartElementVisibility.Hidden;
//        return;
//    }
//    //计算刻度 Q
//    var axisQLabels = new List<CustomAxisLabel>();
//    var disQ = _coordinate.CoordMinQ;
//    for (int i = 0; i < _coordinate.GridNumberX + 1; i++)
//    {
//        axisQLabels.Add(new CustomAxisLabel(disQ.ToString("N0"), disQ));
//        disQ = disQ + _coordinate.CoordSpaceQ;
//    }
//    _axis_x_flow.CustomLabels.Clear();
//    _axis_x_flow.CustomLabels.AddRange(axisQLabels.ToArray());
//    _axis_x_flow.Visibility = DefaultBoolean.True;
//    _axis_x_flow.GridLines.Visible = true;
//    //计算刻度
//    var axis_head_labels = new List<CustomAxisLabel>();
//    var display_head = _coordinate.CoordMinH + _coordinate.CoordSpaceH * _coordinate.StartLineNoH;
//    for (int i = _coordinate.StartLineNoH; i < _coordinate.EndLineNoH + 1; i++)
//    {
//        axis_head_labels.Add(new CustomAxisLabel(display_head.ToString(), display_head));
//        display_head = display_head + _coordinate.CoordSpaceH;
//    }
//    _axis_y_head.CustomLabels.Clear();
//    _axis_y_head.CustomLabels.AddRange(axis_head_labels.ToArray());
//    _axis_y_head.Visibility = DefaultBoolean.True;
//    _axis_y_head.GridLines.Visible = true;
//    //效率
//    if (_maxE > _minE && _eff_visible)
//    {
//        //计算刻度
//        var label_list = new List<CustomAxisLabel>();
//        var display_eff = _coordinate.CoordMinE + _coordinate.CoordSpaceE * _coordinate.StartLineNoE;
//        for (int i = _coordinate.StartLineNoE; i < _coordinate.EndLineNoE + 1; i++)
//        {
//            label_list.Add(new CustomAxisLabel(display_eff.ToString(), display_eff));
//            display_eff = display_eff + _coordinate.CoordSpaceE;
//        }
//        _axis_y_eff.CustomLabels.Clear();
//        _axis_y_eff.CustomLabels.AddRange(label_list.ToArray());
//        _axis_y_eff.Visibility = DefaultBoolean.True;
//        _axis_y_eff.GridLines.Visible = true;
//    }
//    //功率
//    if (_maxP > _minP && _power_visible)
//    {
//        //计算刻度
//        var label_list = new List<CustomAxisLabel>();
//        double display_power = _coordinate.CoordMinP + _coordinate.CoordSpaceP * _coordinate.StartLineNoP;
//        for (int i = _coordinate.StartLineNoP; i < _coordinate.EndLineNoP + 1; i++)
//        {
//            label_list.Add(new CustomAxisLabel(display_power.ToString(), display_power));
//            display_power = display_power + _coordinate.CoordSpaceP;
//        }
//        _axis_y_power.CustomLabels.Clear();
//        _axis_y_power.CustomLabels.AddRange(label_list.ToArray());
//        _axis_y_power.Visibility = DefaultBoolean.True;
//        _axis_y_power.GridLines.Visible = true;
//    }
//    _axis_x_flow.SetAxisRange(_coordinate.CoordMinQ, _coordinate.CoordMinQ + _coordinate.GridNumberX * _coordinate.CoordSpaceQ);
//    if (_split_panel)
//    {
//        if (_power_visible)
//        {
//            var grid_count_head = _coordinate.EndLineNoH - _coordinate.StartLineNoH;
//            var grid_count_eff = _coordinate.EndLineNoE - _coordinate.StartLineNoE;
//            int grid_count_add = Math.Max(grid_count_head, grid_count_eff);
//            if (_eff_visible)
//                grid_count_add += +5;//多两条
//            var max_axis_head = _coordinate.CoordMinH + _coordinate.EndLineNoH * _coordinate.CoordSpaceH;
//            var min_axis_head = max_axis_head - grid_count_add * _coordinate.CoordSpaceH;
//            _axis_y_head.SetAxisRange(min_axis_head, max_axis_head);
//            var min_axis_eff = _coordinate.CoordMinE + _coordinate.StartLineNoE * _coordinate.CoordSpaceE;
//            var max_axis_eff = min_axis_eff + grid_count_add * _coordinate.CoordSpaceE;
//            _axis_y_eff.SetAxisRange(min_axis_eff, max_axis_eff);
//            _bottom_pane.Visibility = ChartElementVisibility.Visible;
//        }
//        else
//        {
//            var grid_count_power = _coordinate.EndLineNoP - _coordinate.StartLineNoP;
//            var grid_delete_head = grid_count_power * _coordinate.CoordSpaceH;
//            grid_delete_head = _coordinate.CoordMinH < 0 ? -grid_delete_head : grid_delete_head;
//            var grid_delete_eff = grid_count_power * _coordinate.CoordSpaceE;
//            grid_delete_eff = _coordinate.CoordMinE < 0 ? -grid_delete_eff : grid_delete_eff;
//            _axis_y_head.SetAxisRange(_coordinate.CoordMinH - grid_delete_head, _coordinate.CoordMinH + _coordinate.GridNumberY * _coordinate.CoordSpaceH);
//            _axis_y_eff.SetAxisRange(_coordinate.CoordMinE - grid_delete_eff, _coordinate.CoordMinE + _coordinate.GridNumberY * _coordinate.CoordSpaceE);
//            _bottom_pane.Visibility = ChartElementVisibility.Hidden;
//        }
//        if ((!_eff_visible) && (!_power_visible))
//        {
//            _axis_y_head.SetAxisRange(_coordinate.DispMinH(), _coordinate.DispMaxH());
//        }
//        _axis_y_power.SetAxisRange(_coordinate.DispMinP(), _coordinate.DispMaxP());
//    }
//    else
//    {
//        if ((!_eff_visible) && (!_power_visible))
//        {
//            _axis_y_head.SetAxisRange(_coordinate.DispMinH(), _coordinate.DispMaxH());
//        }
//        else if ((!_eff_visible) && _power_visible)
//        {
//            var grid_count_eff = _coordinate.EndLineNoE - _coordinate.StartLineNoE;
//            if (_coordinate.EndLineNoH - _coordinate.StartLineNoH < 6)
//                grid_count_eff++;
//            var grid_delete_head = grid_count_eff * _coordinate.CoordSpaceH;
//            grid_delete_head = _coordinate.CoordMinH < 0 ? -grid_delete_head : grid_delete_head;
//            var grid_delete_power = grid_count_eff * _coordinate.CoordSpaceP;
//            _axis_y_head.SetAxisRange(_coordinate.CoordMinH - grid_delete_head, _coordinate.CoordMinH + _coordinate.GridNumberY * _coordinate.CoordSpaceH);
//            _axis_y_power.SetAxisRange(_coordinate.CoordMinP, _coordinate.CoordMinP + _coordinate.GridNumberY * _coordinate.CoordSpaceP - grid_delete_power);
//        }
//        else if (_eff_visible && (!_power_visible))
//        {
//            var grid_count_power = _coordinate.EndLineNoP - _coordinate.StartLineNoP;
//            var grid_delete_head = grid_count_power * _coordinate.CoordSpaceH;
//            grid_delete_head = _coordinate.CoordMinH < 0 ? -grid_delete_head : grid_delete_head;
//            var grid_delete_eff = grid_count_power * _coordinate.CoordSpaceE;
//            grid_delete_eff = _coordinate.CoordMinE < 0 ? -grid_delete_eff : grid_delete_eff;
//            _axis_y_head.SetAxisRange(_coordinate.CoordMinH - grid_delete_head, _coordinate.CoordMinH + _coordinate.GridNumberY * _coordinate.CoordSpaceH);
//            _axis_y_eff.SetAxisRange(_coordinate.CoordMinE - grid_delete_eff, _coordinate.CoordMinE + _coordinate.GridNumberY * _coordinate.CoordSpaceE);
//        }
//        else
//        {
//            _axis_y_head.SetAxisRange(_coordinate.CoordMinH, _coordinate.CoordMinH + _coordinate.GridNumberY * _coordinate.CoordSpaceH);
//            _axis_y_eff.SetAxisRange(_coordinate.CoordMinE, _coordinate.CoordMinE + _coordinate.GridNumberY * _coordinate.CoordSpaceE);
//            _axis_y_power.SetAxisRange(_coordinate.CoordMinP, _coordinate.CoordMinP + _coordinate.GridNumberY * _coordinate.CoordSpaceP);
//        }
//        _bottom_pane.Visibility = ChartElementVisibility.Hidden;
//    }
//}