using Arction.Wpf.Charting; using Arction.Wpf.Charting.Annotations; using Arction.Wpf.Charting.Axes; using Arction.Wpf.Charting.SeriesXY; using CapMachine.Model; using CapMachine.Wpf.ChannelModel; using CapMachine.Wpf.Models.Tag; using CapMachine.Wpf.Services; using Force.DeepCloner; using ImTools; using Prism.Mvvm; using System; using System.Collections.ObjectModel; using System.IO.Ports; using System.Windows; namespace CapMachine.Wpf.Models.LightChart { /// /// 曲线实时系列模型 /// 曲线的系列的封装 /// public class ChartRtSeries : BindableBase { /// /// 实例化函数 /// public ChartRtSeries(LightningChart Chart, ChartColor ChartColor, ObservableCollection listchartRtSeries, ConfigChart configChart, ConfigService configService,short decimalPoint) { //模型赋值 LgChart = Chart; ChartColorInfo = ChartColor; ChartAxisY = configChart.ConfigChartYAxis; ChartAxisX = LgChart.ViewXY.XAxes[0]; Name = configChart.Name; ListChartRtSeries = listchartRtSeries; ConfigService = configService; DecimalPoint = decimalPoint; AddSeries(configChart.Name!, configChart.ConfigChartYAxis!); //初始化字符串 ValueEngPvValueStr = Math.Round(0.00, DecimalPoint).ToString(); LeftCursorEngPvValueStr = Math.Round(0.00, DecimalPoint).ToString(); RightCursorEngPvValueStr = Math.Round(0.00, DecimalPoint).ToString(); MinEngPvValueStr = Math.Round(0.00, DecimalPoint).ToString(); MaxEngPvValueStr = Math.Round(0.00, DecimalPoint).ToString(); AveEngPvValueStr = Math.Round(0.00, DecimalPoint).ToString(); } public ChartRtSeries(LightningChart Chart, ChartColor ChartColor, ObservableCollection listchartRtSeries, HistoryConfigChart configChart, ConfigService configService, short decimalPoint) { //模型赋值 LgChart = Chart; ChartColorInfo = ChartColor; ChartAxisY = configChart.ConfigChartYAxis; ChartAxisX = LgChart.ViewXY.XAxes[0]; Name = configChart.Name; ListChartRtSeries = listchartRtSeries; ConfigService = configService; DecimalPoint = decimalPoint; AddSeries(configChart.Name!, configChart.ConfigChartYAxis!); //初始化字符串 ValueEngPvValueStr= Math.Round(0.00, DecimalPoint).ToString(); LeftCursorEngPvValueStr = Math.Round(0.00, DecimalPoint).ToString(); RightCursorEngPvValueStr = Math.Round(0.00, DecimalPoint).ToString(); MinEngPvValueStr = Math.Round(0.00, DecimalPoint).ToString(); MaxEngPvValueStr = Math.Round(0.00, DecimalPoint).ToString(); AveEngPvValueStr = Math.Round(0.00, DecimalPoint).ToString(); } #region 基本信息 private string? _Name; /// /// 系列的名称 /// 也是变量的名称 /// public string? Name { get { return _Name; } set { _Name = value; RaisePropertyChanged(); } } private double _Value; /// /// 值 /// public double Value { get { return _Value; } set { if (_Value != value) { _Value = value; RaisePropertyChanged(); ValueEngPvValueStr = Math.Round(value, DecimalPoint).ToString(); } } } private string _ValueEngPvValueStr; /// /// ValueEngPvValueStr 值 工程值的字符串 /// public string ValueEngPvValueStr { get { return _ValueEngPvValueStr; } set { _ValueEngPvValueStr = value; RaisePropertyChanged(); } } /// /// 小数点 /// public short DecimalPoint { get; set; } private string? _Group; /// /// 组信息 /// public string? Group { get { return _Group; } set { _Group = value; RaisePropertyChanged(); } } private string? _Unit; /// /// 单位 /// public string? Unit { get { return _Unit; } set { _Unit = value; RaisePropertyChanged(); } } private string? _FontInfo = ""; /// /// 字体信息 /// public string? FontInfo { get { return _FontInfo; } set { _FontInfo = value; RaisePropertyChanged(); } } /// /// 订阅到的缓存的数据 /// public List ListCacheRtChartData { get; set; } = new List(); #endregion #region 当前曲线的光标的信息 private double _LeftCursorValue; /// /// 左游标值 /// public double LeftCursorValue { get { return _LeftCursorValue; } set { if (_LeftCursorValue != value) { _LeftCursorValue = value; RaisePropertyChanged(); LeftCursorEngPvValueStr = Math.Round(value, DecimalPoint).ToString(); } } } private string _LeftCursorEngPvValueStr; /// /// LeftCursor 左游标值 工程值的字符串 /// public string LeftCursorEngPvValueStr { get { return _LeftCursorEngPvValueStr; } set { _LeftCursorEngPvValueStr = value; RaisePropertyChanged(); } } private double _RightCursorValue; /// /// 右游标值 /// public double RightCursorValue { get { return _RightCursorValue; } set { if (_RightCursorValue != value) { _RightCursorValue = value; RaisePropertyChanged(); RightCursorEngPvValueStr = Math.Round(value, DecimalPoint).ToString(); } } } private string _RightCursorEngPvValueStr; /// /// RightCursor 右游标值 工程值的字符串 /// public string RightCursorEngPvValueStr { get { return _RightCursorEngPvValueStr; } set { _RightCursorEngPvValueStr = value; RaisePropertyChanged(); } } private double _MinValue; /// /// 最小值 /// public double MinValue { get { return _MinValue; } set { if (_MinValue != value) { _MinValue = value; RaisePropertyChanged(); MinEngPvValueStr = Math.Round(value, DecimalPoint).ToString(); } } } private string _MinEngPvValueStr; /// /// Min 最小值 工程值的字符串 /// public string MinEngPvValueStr { get { return _MinEngPvValueStr; } set { _MinEngPvValueStr = value; RaisePropertyChanged(); } } private double _MaxValue; /// /// 最大值 /// public double MaxValue { get { return _MaxValue; } set { if (_MaxValue != value) { _MaxValue = value; RaisePropertyChanged(); MaxEngPvValueStr = Math.Round(value, DecimalPoint).ToString(); } } } private string _MaxEngPvValueStr; /// /// Max 最大值 工程值的字符串 /// public string MaxEngPvValueStr { get { return _MaxEngPvValueStr; } set { _MaxEngPvValueStr = value; RaisePropertyChanged(); } } private double _AveValue; /// /// 平均值 /// public double AveValue { get { return _AveValue; } set { if (_AveValue != value) { _AveValue = value; RaisePropertyChanged(); AveEngPvValueStr = Math.Round(value, DecimalPoint).ToString(); } } } private string _AveEngPvValueStr; /// /// Ave 平均值 工程值的字符串 /// public string AveEngPvValueStr { get { return _AveEngPvValueStr; } set { _AveEngPvValueStr = value; RaisePropertyChanged(); } } #endregion ///// ///// Chart图表X轴的跨度-秒 ///// 可以删除之前的数据 ///// //public int ChartXDateTimeRange { get; set; } = 3600_8; /// /// 删除曲线系列上的数据 /// 积累到一定量后再删除,避免每次更新都删除 /// private int MaxDeleteCacheCount { get; set; } = 0; /// /// 增加系列 /// /// private void AddSeries(string SeriesName, ConfigChartYAxis configChartYAxis) { LgChart.BeginUpdate(); //定义一个轴设置 AxisY AxisYInfo; if (configChartYAxis == null) { MessageBox.Show($"没有发现曲线:【{SeriesName}】轴设置信息,将使用默认的轴设置。请到【曲线轴设置】中进行检查", "提示", MessageBoxButton.OK, MessageBoxImage.Hand); //新增 AxisYInfo = new AxisY(); } else { //轴信息不为空的话,则进行后续的判断 //判断之前的系列是否已经存在(依据名称),存在使用之前的系列,否则新增 AxisYInfo = GetAxisY(configChartYAxis.Name); if (AxisYInfo == null) { //新增 AxisYInfo = new AxisY(); AxisYInfo.Title.Text = configChartYAxis.Name; AxisYInfo.Title.AllowDragging = false; AxisYInfo.SetRange(configChartYAxis.Min, configChartYAxis.Max); AxisYInfo.MajorGrid.Visible = false; //取消滚轮缩放 AxisYInfo.ZoomingEnabled = false; LgChart.ViewXY.YAxes.Add(AxisYInfo); } else { //使用之前 AxisYInfo.SetRange(configChartYAxis.Min, configChartYAxis.Max); } } var SeriesInfo = GetPointLineSeries(SeriesName); if (SeriesInfo == null) { //新增 SeriesInfo = new PointLineSeries(LgChart.ViewXY, LgChart.ViewXY.XAxes[0], AxisYInfo); SeriesInfo.Title.Text = SeriesName; SeriesInfo.LineStyle.Color = ChartColorInfo.ListColor[LgChart.ViewXY.PointLineSeries.Count]; SeriesInfo.AllowUserInteraction = false; LgChart.ViewXY.PointLineSeries.Add(SeriesInfo); } else { //使用之前 SeriesInfo.AssignYAxisIndex = AxisYInfo.SegmentIndex; } //赋值给当前的模型 ChartPointLineSeries = SeriesInfo; //Configure and add series to the chart LgChart.EndUpdate(); } public void AddPointByCache(DateTime dateTime, double value, bool IsDeleteBefore, bool IsScrollEnable) { //入缓存集合中 ListCacheRtChartData.Add(new CacheRtChartData() { Value = value, CreateTime = dateTime, }); //判断是否满足要求 if (ListCacheRtChartData.Count() >= 6) { //Disable updates, to prevent several extra refreshes LgChart.BeginUpdate(); var ListSeriesPoint = ListCacheRtChartData.Select(a => new SeriesPoint() { X = ChartAxisX!.DateTimeToAxisValue(a.CreateTime), Y = a.Value }); ChartPointLineSeries!.AddPoints(ListSeriesPoint.ToArray(), false); //暂时不删除数据 if (IsDeleteBefore) { MaxDeleteCacheCount++; //积累到一定量后再删除旧的数据 if (MaxDeleteCacheCount >= 200) { ChartPointLineSeries!.DeletePointsBeforeX(ListSeriesPoint.LastOrDefault().X - ConfigService.ChartRtDataCacheTimeSec); MaxDeleteCacheCount = 0; } } //ChartPointLineSeries!.DeletePointsBeforeX(_previousX - ChartXDateTimeRange); //item.DeletePointsBeforeX(_previousX - 100); if (IsScrollEnable) { LgChart.ViewXY.XAxes[0].ScrollPosition = ListSeriesPoint.FirstOrDefault().X; } //Allow updates again, and update LgChart.EndUpdate(); //删除缓存的数据 ListCacheRtChartData.Clear(); } } /// /// 增加数据的点 /// public void AddPoint(DateTime dateTime, double value, bool IsDeleteBefore, bool IsScrollEnable) { //Disable updates, to prevent several extra refreshes LgChart.BeginUpdate(); //Array for 1 point SeriesPoint[] points = new SeriesPoint[1]; //Convert 'Now' to X value var _previousX = LgChart.ViewXY.XAxes[0].DateTimeToAxisValue(dateTime); points[0].X = _previousX; points[0].Y = value; //Add the new point into end of first PointLineSeries ChartPointLineSeries!.AddPoints(points, false); //暂时不删除数据 if (IsDeleteBefore) { ChartPointLineSeries!.DeletePointsBeforeX(_previousX - ConfigService.ChartRtDataCacheTimeSec); } //ChartPointLineSeries!.DeletePointsBeforeX(_previousX - ChartXDateTimeRange); //item.DeletePointsBeforeX(_previousX - 100); if (IsScrollEnable) { LgChart.ViewXY.XAxes[0].ScrollPosition = _previousX; } //Allow updates again, and update LgChart.EndUpdate(); } /// /// 批量增加数据的点 /// public void AddRangePoint(List Data) { //Disable updates, to prevent several extra refreshes LgChart.BeginUpdate(); //Array for 1 point SeriesPoint[] points = new SeriesPoint[Data.Count]; for (int i = 0; i < Data.Count; i++) { //Convert 'Now' to X value points[i].X = LgChart.ViewXY.XAxes[0].DateTimeToAxisValue(Data[i].Time); ; points[i].Y = Data[i].Value; } //Add the new point into end of first PointLineSeries ChartPointLineSeries!.AddPoints(points, false); //Allow updates again, and update LgChart.EndUpdate(); } /// /// 增加RecordChannelData集合的数据的点 /// public void AddPointByDicData(List recordChannelDatas, string Name) { var Data = recordChannelDatas.DeepClone(); foreach (var item in Data) { if (item.Data!.TryGetValue(Name, out object result)) { AddPoint(item.CreateTime, Convert.ToDouble(result), false, false); } } } /// /// 增加历史数据的点集合 /// /// /// public void AddRecordPointByName(List chartPoints) { AddRangePoint(chartPoints); } /// /// 获取AxisY信息 /// /// /// private AxisY GetAxisY(string AxisName) { var AxisYs = LgChart.ViewXY.YAxes; if (AxisYs != null) { var findAxis = AxisYs.FindFirst(a => a.Title.Text == AxisName); if (findAxis != null) { return findAxis; } else { return null; } } else { return null; } } /// /// 获取PointLineSeries信息 /// /// /// private PointLineSeries GetPointLineSeries(string SeriesName) { var PointLineSeries = LgChart.ViewXY.PointLineSeries; if (PointLineSeries != null) { var findSeries = PointLineSeries.FindFirst(a => a.Title.Text == SeriesName); if (findSeries != null) { return findSeries; } else { return null; } } else { return null; } } /// /// 上层管理集合 /// public ObservableCollection ListChartRtSeries { get; set; } public ConfigService ConfigService { get; } /// /// 曲线数据 /// public PointLineSeries? ChartPointLineSeries { get; set; } /// /// Y轴 /// public ConfigChartYAxis? ChartAxisY { get; set; } /// /// Y轴 ConfigChartYAxis Id /// 用于标记Y轴的配置信息 /// public long ConfigChartYAxisId { get; set; } /// /// X轴 /// public AxisX? ChartAxisX { get; set; } /// /// LightningChart 实例 /// public LightningChart LgChart { get; set; } /// /// 曲线配置信息 /// public ChartColor ChartColorInfo { get; set; } } }