duheng
2025-03-28 9be9ba4e159969fb5e32648c2c34e912ccc3ae6d
WinFrmUI/Yw.WinFrmUI.Phart.Core/02-universal/02-edit/UniversalEditChart.cs
@@ -23,11 +23,11 @@
        private Series _series_edit_pt;
        private List<Yw.Geometry.Point2d> _def_pt_list;
        private List<Yw.Geometry.Point2d> _def_pt_list;
        private List<Yw.Geometry.Point2d> _fit_pt_list;
        private UniversalCoordinate _coordinate;
        private bool _initial_data = false;
        private bool _initial_data = false;
        private bool _mouse_mode = false;//鼠标模式
        #endregion
@@ -63,7 +63,7 @@
                _axis_y.Title.Text = value;
            }
        }
        /// <summary>
        /// 鼠标模式
        /// </summary>
@@ -75,7 +75,7 @@
            }
            set
            {
                _mouse_mode = value;
                _mouse_mode = value;
            }
        }
@@ -93,9 +93,13 @@
        /// </summary>
        public event Action<List<Yw.Geometry.Point2d>> DefinePointChangedEvent;
        /// <summary>
        /// 选中点
        /// </summary>
        public event Action<int> SelectedPointIndexChangedEvent;
        #endregion 
        #region Initial
        #region Private Initial
        /// <summary>
        /// 初始化图表
@@ -114,16 +118,17 @@
            _diagram = (XYDiagram)chartControl1.Diagram;
            _default_pane=_diagram.DefaultPane;
            _axis_x = _diagram.AxisX;
            _default_pane = _diagram.DefaultPane;
            _axis_x = _diagram.AxisX;
            _axis_x.SetAxisXQDisplay();
            _axis_y = _diagram.AxisY;
            _axis_y.SetAxisYQHDisplay();
            _axis_x.Visibility = DefaultBoolean.False;
            _axis_x.GridLines.Visible = false;
            _axis_y.Visibility = DefaultBoolean.False;
            _axis_y.GridLines.Visible = false;
            this.chartControl1.SetChartMonoColorDisplay();
        }
@@ -144,249 +149,8 @@
        #endregion Initial
        #region SetBindingData
        #region Private Chart Event
        /// <summary>
        /// 绑定数据
        /// </summary>
        public void Clear()
        {
            _initial_data = false;
            _def_pt_list = null;
            _fit_pt_list = null;
            _coordinate = null;
            _series_edit_pt = null;
            this.chartControl1.BeginInit();
            this.chartControl1.Series.Clear();
            this.chartControl1.AnnotationRepository.Clear();
            this.chartControl1.Legend.CustomItems.Clear();
            this.chartControl1.EndInit();
        }
        /// <summary>
        /// 绑定数据
        /// </summary>
        public void SetBindingData(List<Yw.Geometry.Point2d> def_pt_list, List<Yw.Geometry.Point2d> fit_pt_list, string coordinate = null, Color? color = null)
        {
            _initial_data = false;
            _def_pt_list = def_pt_list?.Select(x => new Geometry.Point2d(x.X, x.Y)).ToList();
            _fit_pt_list = fit_pt_list?.Select(x => new Geometry.Point2d(x.X, x.Y)).ToList();
            _coordinate = UniversalCoordinate.ToModel(coordinate);
            _series_edit_pt = null;
            if (color == null)
                color = Color.DodgerBlue;
            this.chartControl1.BeginInit();
            this.chartControl1.Series.Clear();
            this.chartControl1.AnnotationRepository.Clear();
            this.chartControl1.Legend.CustomItems.Clear();
            if (IsInvalidData())
            {
                _initial_data = false;
                this.chartControl1.EndInit();
                return;
            }
            _series_edit_pt = AddPointSeries(color.Value, _axis_x, _axis_y, _default_pane, _def_pt_list);
            AddLineSeries(color.Value, _axis_x, _axis_y, _default_pane, _fit_pt_list);
            if (_coordinate == null)
                SetCoordinate();
            SetChartAxis();
            this.chartControl1.EndInit();
            _initial_data = true;
        }
        //是否是无效数据
        private bool IsInvalidData()
        {
            if (_def_pt_list == null || !_def_pt_list.Any())
            {
                return true;
            }
            if (_fit_pt_list == null || !_fit_pt_list.Any())
            {
                return true;
            }
            return false;
        }
        #region Add Chart Data
        private Series AddPointSeries(Color color, AxisXBase axis_x, AxisYBase axis_y, XYDiagramPaneBase pane, List<Yw.Geometry.Point2d> pt_list)
        {
            if (pt_list == null || !pt_list.Any())
                return null;
            var view = new DevExpress.XtraCharts.PointSeriesView();
            view.PointMarkerOptions.Size = 8;
            view.PointMarkerOptions.Kind = MarkerKind.Circle;
            view.PointMarkerOptions.BorderColor = color;
            view.Color = color;
            view.AxisX = axis_x;
            view.AxisY = axis_y;
            view.EmptyPointOptions.Color = Color.Transparent;
            view.Pane = pane;
            var series_pt_list = new List<SeriesPoint>();
            for (int i = 0; i < pt_list.Count; i++)
            {
                var pt = pt_list[i];
                var series_pt = new DevExpress.XtraCharts.SeriesPoint(pt.X, new double[] { pt.Y });
                series_pt.Tag = i;
                series_pt_list.Add(series_pt);
            }
            var series = new DevExpress.XtraCharts.Series();
            series.ShowInLegend = false;
            series.ArgumentScaleType = DevExpress.XtraCharts.ScaleType.Numerical;
            series.LabelsVisibility = DevExpress.Utils.DefaultBoolean.False;
            series.CrosshairEnabled = DefaultBoolean.False;
            series.CrosshairLabelVisibility = DefaultBoolean.False;
            series.ToolTipEnabled = DefaultBoolean.False;
            series.SeriesPointsSorting = SortingMode.None;
            series.Visible = true;
            series.View = view;
            series.CrosshairLabelPattern = "{A}";
            series.Points.AddRange(series_pt_list.ToArray());
            this.chartControl1.Series.Add(series);
            return series;
        }
        private void AddLineSeries(Color color, AxisXBase axis_x, AxisYBase axis_y, XYDiagramPaneBase pane, List<Yw.Geometry.Point2d> pt_list, DashStyle dash = DashStyle.Solid)
        {
            if (pt_list == null || !pt_list.Any())
                return;
            var view = new DevExpress.XtraCharts.LineSeriesView();
            view.LineStyle.DashStyle = dash;
            view.LineStyle.LineJoin = System.Drawing.Drawing2D.LineJoin.Round;
            view.LineStyle.Thickness = 2;
            view.Color = color;
            view.EnableAntialiasing = DefaultBoolean.True;
            view.MarkerVisibility = DefaultBoolean.False;
            view.AxisX = axis_x;
            view.AxisY = axis_y;
            view.EmptyPointOptions.Color = Color.Transparent;
            view.Pane = pane;
            var series_pt_list = pt_list.Select(x => x.ToSeriesPoint()).ToArray();
            var series = new DevExpress.XtraCharts.Series();
            series.ShowInLegend = false;
            series.ArgumentScaleType = DevExpress.XtraCharts.ScaleType.Numerical;
            series.LabelsVisibility = DevExpress.Utils.DefaultBoolean.False;
            series.CrosshairEnabled = DefaultBoolean.False;
            series.ToolTipEnabled = DefaultBoolean.False;
            series.SeriesPointsSorting = SortingMode.None;
            series.Visible = true;
            series.View = view;
            series.Points.AddRange(series_pt_list);
            this.chartControl1.Series.Add(series);
        }
        #endregion
        #endregion
        #region Set Axis
        private double _minX, _maxX;
        private double _maxY = 0, _minY = 10000;
        /// <summary>
        /// 设置坐标
        /// </summary>
        private void SetCoordinate()
        {
            if (IsInvalidData())
            {
                InitialCoordinate();
                return;
            }
            _minX = _def_pt_list.Min(x => x.X);
            _maxX = _def_pt_list.Max(x => x.X);
            _minY = _def_pt_list.Min(x => x.Y);
            _maxY = _def_pt_list.Max(x => x.Y);
            _minX = Math.Min(_fit_pt_list.Min(x => x.X), _minX);
            _maxX = Math.Min(_fit_pt_list.Max(x => x.X), _maxX);
            _minY = Math.Min(_fit_pt_list.Min(x => x.Y), _minY);
            _maxY = Math.Min(_fit_pt_list.Max(x => x.Y), _maxY);
            _coordinate = UniversalCoordinate.CalcCoordinate(_minX, _maxX, _minY, _maxY);
            if (_coordinate == null)
                return;
            if (_coordinate.CoordMinX + _coordinate.CoordSpaceX * this._coordinate.GridNumberX < _maxX * 1.05)
            {
                _coordinate.GridNumberX++;
            }
        }
        /// <summary>
        /// 设置图表轴
        /// </summary>
        public void SetChartAxis()
        {
            if (_coordinate == null || IsInvalidData())
            {
                _axis_x.Visibility = DefaultBoolean.False;
                _axis_x.GridLines.Visible = false;
                _axis_y.Visibility = DefaultBoolean.False;
                _axis_y.GridLines.Visible = false;
                return;
            }
            //计算刻度 X
            var axis_x_labels = new List<CustomAxisLabel>();
            var display_x = _coordinate.CoordMinX;
            for (int i = 0; i < _coordinate.GridNumberX + 1; i++)
            {
                axis_x_labels.Add(new CustomAxisLabel(display_x.ToString("N0"), display_x));
                display_x = display_x + _coordinate.CoordSpaceX;
            }
            _axis_x.CustomLabels.Clear();
            _axis_x.CustomLabels.AddRange(axis_x_labels.ToArray());
            _axis_x.Visibility = DefaultBoolean.True;
            _axis_x.GridLines.Visible = true;
            //计算刻度 Y
            var axis_y_labels = new List<CustomAxisLabel>();
            var display_y = _coordinate.CoordMinY + _coordinate.CoordSpaceY * _coordinate.StartLineNoY;
            for (int i = _coordinate.StartLineNoY; i < _coordinate.EndLineNoY + 1; i++)
            {
                axis_y_labels.Add(new CustomAxisLabel(display_y.ToString(), display_y));
                display_y = display_y + _coordinate.CoordSpaceY;
            }
            _axis_y.CustomLabels.Clear();
            _axis_y.CustomLabels.AddRange(axis_y_labels.ToArray());
            _axis_y.Visibility = DefaultBoolean.True;
            _axis_y.GridLines.Visible = true;
            _axis_x.SetAxisRange(_coordinate.CoordMinX, _coordinate.DispMaxX());
            _axis_y.SetAxisRange(_coordinate.DispMinY(), _coordinate.DispMaxY());
        }
        #endregion Calc
        #region Chart Event
        private int _pick_point_index = -1;
        private void chartControl1_MouseDown(object sender, MouseEventArgs e)
        {
@@ -399,6 +163,7 @@
                if (hitInfo.InSeriesPoint && hitInfo.SeriesPoint.Tag is int index)
                {
                    _pick_point_index = index;
                    this.SelectedPointIndexChangedEvent?.Invoke(_pick_point_index);
                }
            }
        }
@@ -427,7 +192,7 @@
            if (_pick_point_index < 0)
                return;
            if (IsInvalidData())
                return;
                return;
            var x = _series_edit_pt.Points[_pick_point_index].NumericalArgument;
            var y = _series_edit_pt.Points[_pick_point_index].Values[0];
            x = Math.Round(x, 2);
@@ -484,8 +249,250 @@
            this.DefinePointChangedEvent?.Invoke(_def_pt_list);
        }
        #endregion
        #endregion
        #region Set
        /// <summary>
        /// 绑定数据
        /// </summary>
        public void Clear()
        {
            _initial_data = false;
            _def_pt_list = null;
            _fit_pt_list = null;
            _coordinate = null;
            _series_edit_pt = null;
            this.chartControl1.BeginInit();
            this.chartControl1.Series.Clear();
            this.chartControl1.AnnotationRepository.Clear();
            this.chartControl1.Legend.CustomItems.Clear();
            this.chartControl1.EndInit();
        }
        /// <summary>
        /// 绑定数据
        /// </summary>
        public void SetBindingData(List<Yw.Geometry.Point2d> def_pt_list, List<Yw.Geometry.Point2d> fit_pt_list, string coordinate = null, Color? color = null)
        {
            _initial_data = false;
            _def_pt_list = def_pt_list?.Select(x => new Geometry.Point2d(x.X, x.Y)).ToList();
            _fit_pt_list = fit_pt_list?.Select(x => new Geometry.Point2d(x.X, x.Y)).ToList();
            _coordinate = UniversalCoordinate.ToModel(coordinate);
            _series_edit_pt = null;
            if (color == null)
                color = Color.DodgerBlue;
            this.chartControl1.BeginInit();
            this.chartControl1.Series.Clear();
            this.chartControl1.AnnotationRepository.Clear();
            this.chartControl1.Legend.CustomItems.Clear();
            if (IsInvalidData())
            {
                _initial_data = false;
                this.chartControl1.EndInit();
                return;
            }
            _series_edit_pt = AddPointSeries(color.Value, _axis_x, _axis_y, _default_pane, _def_pt_list);
            AddLineSeries(color.Value, _axis_x, _axis_y, _default_pane, _fit_pt_list);
            if (_coordinate == null)
                SetCoordinate();
            SetChartAxis();
            this.chartControl1.EndInit();
            _initial_data = true;
        }
        //是否是无效数据
        private bool IsInvalidData()
        {
            if (_def_pt_list == null || !_def_pt_list.Any())
            {
                return true;
            }
            if (_fit_pt_list == null || !_fit_pt_list.Any())
            {
                return true;
            }
            return false;
        }
        #region Add Chart Data
        private Series AddPointSeries(Color color, AxisXBase axis_x, AxisYBase axis_y, XYDiagramPaneBase pane, List<Yw.Geometry.Point2d> pt_list)
        {
            if (pt_list == null || !pt_list.Any())
                return null;
            var view = new DevExpress.XtraCharts.PointSeriesView();
            view.PointMarkerOptions.Size = 8;
            view.PointMarkerOptions.Kind = MarkerKind.Circle;
            view.PointMarkerOptions.BorderColor = color;
            view.Color = color;
            view.AxisX = axis_x;
            view.AxisY = axis_y;
            view.EmptyPointOptions.Color = Color.Transparent;
            view.Pane = pane;
            var series_pt_list = new List<SeriesPoint>();
            for (int i = 0; i < pt_list.Count; i++)
            {
                var pt = pt_list[i];
                var series_pt = new DevExpress.XtraCharts.SeriesPoint(pt.X, new double[] { pt.Y });
                series_pt.Tag = i;
                series_pt_list.Add(series_pt);
            }
            var series = new DevExpress.XtraCharts.Series();
            series.ShowInLegend = false;
            series.ArgumentScaleType = DevExpress.XtraCharts.ScaleType.Numerical;
            series.LabelsVisibility = DevExpress.Utils.DefaultBoolean.False;
            series.CrosshairEnabled = DefaultBoolean.False;
            series.CrosshairLabelVisibility = DefaultBoolean.False;
            series.ToolTipEnabled = DefaultBoolean.False;
            series.SeriesPointsSorting = SortingMode.None;
            series.Visible = true;
            series.View = view;
            series.CrosshairLabelPattern = "{A}";
            series.Points.AddRange(series_pt_list.ToArray());
            this.chartControl1.Series.Add(series);
            return series;
        }
        private void AddLineSeries(Color color, AxisXBase axis_x, AxisYBase axis_y, XYDiagramPaneBase pane, List<Yw.Geometry.Point2d> pt_list, DashStyle dash = DashStyle.Solid)
        {
            if (pt_list == null || !pt_list.Any())
                return;
            var view = new DevExpress.XtraCharts.LineSeriesView();
            view.LineStyle.DashStyle = dash;
            view.LineStyle.LineJoin = System.Drawing.Drawing2D.LineJoin.Round;
            view.LineStyle.Thickness = 2;
            view.Color = color;
            view.EnableAntialiasing = DefaultBoolean.True;
            view.MarkerVisibility = DefaultBoolean.False;
            view.AxisX = axis_x;
            view.AxisY = axis_y;
            view.EmptyPointOptions.Color = Color.Transparent;
            view.Pane = pane;
            var series_pt_list = pt_list.Select(x => x.ToSeriesPoint()).ToArray();
            var series = new DevExpress.XtraCharts.Series();
            series.ShowInLegend = false;
            series.ArgumentScaleType = DevExpress.XtraCharts.ScaleType.Numerical;
            series.LabelsVisibility = DevExpress.Utils.DefaultBoolean.False;
            series.CrosshairEnabled = DefaultBoolean.False;
            series.ToolTipEnabled = DefaultBoolean.False;
            series.SeriesPointsSorting = SortingMode.None;
            series.Visible = true;
            series.View = view;
            series.Points.AddRange(series_pt_list);
            this.chartControl1.Series.Add(series);
        }
        #endregion
        #endregion
        #region Set Axis
        private double _minX, _maxX;
        private double _maxY = 0, _minY = 10000;
        /// <summary>
        /// 设置坐标
        /// </summary>
        private void SetCoordinate()
        {
            if (IsInvalidData())
            {
                InitialCoordinate();
                return;
            }
            _minX = _def_pt_list.Min(x => x.X);
            _maxX = _def_pt_list.Max(x => x.X);
            _minY = _def_pt_list.Min(x => x.Y);
            _maxY = _def_pt_list.Max(x => x.Y);
            _minX = Math.Min(_fit_pt_list.Min(x => x.X), _minX);
            _maxX = Math.Min(_fit_pt_list.Max(x => x.X), _maxX);
            _minY = Math.Min(_fit_pt_list.Min(x => x.Y), _minY);
            _maxY = Math.Min(_fit_pt_list.Max(x => x.Y), _maxY);
            _coordinate = UniversalCoordinate.CalcCoordinate(_minX, _maxX, _minY, _maxY);
            if (_coordinate == null)
                return;
            if (_coordinate.CoordMinX + _coordinate.CoordSpaceX * this._coordinate.GridNumberX < _maxX * 1.05)
            {
                _coordinate.GridNumberX++;
            }
        }
        /// <summary>
        /// 设置图表轴
        /// </summary>
        public void SetChartAxis()
        {
            if (_coordinate == null || IsInvalidData())
            {
                _axis_x.Visibility = DefaultBoolean.False;
                _axis_x.GridLines.Visible = false;
                _axis_y.Visibility = DefaultBoolean.False;
                _axis_y.GridLines.Visible = false;
                return;
            }
            //计算刻度 X
            var axis_x_labels = new List<CustomAxisLabel>();
            var display_x = _coordinate.CoordMinX;
            for (int i = 0; i < _coordinate.GridNumberX + 1; i++)
            {
                axis_x_labels.Add(new CustomAxisLabel(display_x.ToString("N0"), display_x));
                display_x = display_x + _coordinate.CoordSpaceX;
            }
            _axis_x.CustomLabels.Clear();
            _axis_x.CustomLabels.AddRange(axis_x_labels.ToArray());
            _axis_x.Visibility = DefaultBoolean.True;
            _axis_x.GridLines.Visible = true;
            //计算刻度 Y
            var axis_y_labels = new List<CustomAxisLabel>();
            var display_y = _coordinate.CoordMinY + _coordinate.CoordSpaceY * _coordinate.StartLineNoY;
            for (int i = _coordinate.StartLineNoY; i < _coordinate.EndLineNoY + 1; i++)
            {
                axis_y_labels.Add(new CustomAxisLabel(display_y.ToString(), display_y));
                display_y = display_y + _coordinate.CoordSpaceY;
            }
            _axis_y.CustomLabels.Clear();
            _axis_y.CustomLabels.AddRange(axis_y_labels.ToArray());
            _axis_y.Visibility = DefaultBoolean.True;
            _axis_y.GridLines.Visible = true;
            _axis_x.SetAxisRange(_coordinate.CoordMinX, _coordinate.DispMaxX());
            _axis_y.SetAxisRange(_coordinate.DispMinY(), _coordinate.DispMaxY());
        }
        #endregion Calc
    }
}