1817 lines
74 KiB
C#
1817 lines
74 KiB
C#
using Arction.Wpf.Charting;
|
||
using Arction.Wpf.Charting.Annotations;
|
||
using Arction.Wpf.Charting.Axes;
|
||
using Arction.Wpf.Charting.SeriesXY;
|
||
using Arction.Wpf.Charting.Views.View3D;
|
||
using Arction.Wpf.Charting.Views.ViewXY;
|
||
using CapMachine.Model;
|
||
using CapMachine.Wpf.ChannelModel;
|
||
using CapMachine.Wpf.Models.Tag;
|
||
using CapMachine.Wpf.PrismEvent;
|
||
using CapMachine.Wpf.Services;
|
||
using ImTools;
|
||
using Microsoft.Win32;
|
||
using NPOI.HSSF.Record.CF;
|
||
using NPOI.SS.Formula.Functions;
|
||
using NPOI.SS.UserModel;
|
||
using NPOI.SS.UserModel.Charts;
|
||
using Prism.Events;
|
||
using Prism.Mvvm;
|
||
using Prism.Services.Dialogs;
|
||
using System.Collections;
|
||
using System.Collections.ObjectModel;
|
||
using System.Diagnostics;
|
||
using System.Reflection.Metadata.Ecma335;
|
||
using System.Runtime.ExceptionServices;
|
||
using System.Text;
|
||
using System.Windows.Input;
|
||
using System.Windows.Interop;
|
||
|
||
namespace CapMachine.Wpf.Models.LightChart
|
||
{
|
||
/// <summary>
|
||
/// 曲线管理
|
||
/// 实现对一个Chart实例进行管理
|
||
/// </summary>
|
||
public class ChartManager : BindableBase
|
||
{
|
||
/// <summary>
|
||
/// 实例化函数
|
||
/// </summary>
|
||
public ChartManager(IEventAggregator eventAggregator, TagManager tagManager, DataRecordService datRecordService, IFreeSql freeSql,
|
||
LightningChart lightningChart,
|
||
string Name,
|
||
int TabIndex,
|
||
string Machine,
|
||
bool isRealTimeChart, ILogService logService, ConfigService configService)
|
||
{
|
||
ListChartRtSeries = new ObservableCollection<ChartRtSeries>();
|
||
ListConfigChart = new List<ConfigChart>();
|
||
CurSelectedGroupTabIndex = TabIndex;
|
||
CurSelectedMachine = Machine;
|
||
|
||
//实例化函数
|
||
LgChart = lightningChart;
|
||
ChartName = Name;
|
||
|
||
LgChart.ChartRenderOptions.GPUPreference = GPUPreference.SystemSetting;
|
||
//LgChart.ChartMessage += LgChart_ChartMessage;
|
||
//事件服务
|
||
_EventAggregator = eventAggregator;
|
||
TagManager = tagManager;
|
||
DatRecordService = datRecordService;
|
||
FreeSql = freeSql;
|
||
|
||
IsRealTimeChart = isRealTimeChart;
|
||
LogService = logService;
|
||
ConfigService = configService;
|
||
|
||
if (IsRealTimeChart)
|
||
{
|
||
//实时曲线就订阅实时数据
|
||
_EventAggregator.GetEvent<RecordDataEvent>().Subscribe(UpdateRecordData, ThreadOption.UIThread);
|
||
|
||
_EventAggregator.GetEvent<ChartSetEvent>().Subscribe(ChartSetEventCall);
|
||
_EventAggregator.GetEvent<ChartSetEnableEvent>().Subscribe(ChartSetEnableEventCall);
|
||
|
||
_EventAggregator.GetEvent<ChartRtSeriesActionEvent>().Subscribe(ChartRtSeriesActionEventCall);
|
||
|
||
_EventAggregator.GetEvent<ChartTabGroupSwitchEvent>().Subscribe(ChartTabGroupSwitchCall);
|
||
}
|
||
else
|
||
{
|
||
_EventAggregator.GetEvent<HistoryChartSetEvent>().Subscribe(ChartSetEventCall);
|
||
_EventAggregator.GetEvent<HistoryChartSetEnableEvent>().Subscribe(ChartSetEnableEventCall);
|
||
|
||
_EventAggregator.GetEvent<HistoryChartRtSeriesActionEvent>().Subscribe(ChartRtSeriesActionEventCall);
|
||
|
||
_EventAggregator.GetEvent<HistoryChartTabGroupSwitchEvent>().Subscribe(ChartTabGroupSwitchCall);
|
||
|
||
_EventAggregator.GetEvent<HistoryDataToChartEvent>().Subscribe(HistoryDataToChartCall, ThreadOption.UIThread);
|
||
|
||
}
|
||
|
||
//Y轴对任何的曲线都适用
|
||
_EventAggregator.GetEvent<ChartYAxisConfigEvent>().Subscribe(ChartYAxisConfigEventCall);
|
||
|
||
//初始化曲线
|
||
InitChart();
|
||
}
|
||
|
||
/// <summary>
|
||
/// LightningChart 通知、错误和异常处理
|
||
/// </summary>
|
||
/// <param name="info"></param>
|
||
/// <exception cref="NotImplementedException"></exception>
|
||
private void LgChart_ChartMessage(ChartMessageInfo info)
|
||
{
|
||
//
|
||
//var InternalErrorMsg = "";
|
||
//if (info.InternalError != null)
|
||
//{
|
||
// InternalErrorMsg = info.InternalError.Message;
|
||
//}
|
||
|
||
//LogService.Info($"{ChartName}" +
|
||
// $"-是否实时IsRealTimeChart:{IsRealTimeChart.ToString()}" +
|
||
// $"-消息严重程度:{info.MessageSeverity.ToString()}" +
|
||
// $"-MessageType:{info.MessageType.ToString()}" +
|
||
// $"-Description:{info.Description}" +
|
||
// $"-Source:{info.Source.ToString()}" +
|
||
// $"-StackTrace:{info.StackTrace}" +
|
||
// $"-InternalError:{InternalErrorMsg}" +
|
||
// $"-Details:{info.Details}");
|
||
|
||
}
|
||
|
||
/// <summary>
|
||
/// 更新Y轴的信息
|
||
/// </summary>
|
||
/// <param name="msg"></param>
|
||
private void ChartYAxisConfigEventCall(ChartYAxisConfigMsg msg)
|
||
{
|
||
UpdateChartAxisY(msg.ConfigChartYAxes);
|
||
}
|
||
|
||
#region 历史曲线数据
|
||
|
||
/// <summary>
|
||
/// 历史数据
|
||
/// </summary>
|
||
private List<CsvRecordModel> CurHistoryData { get; set; }
|
||
|
||
/// <summary>
|
||
/// 历史数据加载到Chart的信息
|
||
/// </summary>
|
||
/// <param name="msg"></param>
|
||
private void HistoryDataToChartCall(HistoryDataToChartMsg msg)
|
||
{
|
||
if (msg.Machine != CurSelectedMachine)
|
||
{
|
||
//选择了其他的机械的话,则也是没有被激活
|
||
IsActivated = false;
|
||
return;
|
||
}
|
||
CurHistoryData = msg.Data;
|
||
|
||
LoadHistoryDataChart();
|
||
}
|
||
|
||
Stopwatch stopwatch = new Stopwatch();
|
||
|
||
/// <summary>
|
||
/// 加载历史数据到曲线中
|
||
/// </summary>
|
||
private void LoadHistoryDataChart()
|
||
{
|
||
if (CurHistoryData == null || CurHistoryData.Count == 0) return;
|
||
|
||
////第一次计时
|
||
stopwatch.Start(); //启动Stopwatch
|
||
|
||
//var Tags = TagManager.DicTags.Values.ToList();
|
||
|
||
foreach (var ChartRtSerie in ListChartRtSeries)
|
||
{
|
||
//var SeriesData = CurHistoryData.Select(a => new ChartPoint() { Value = a.Speed, Time = a.CreateTime }).OrderBy(a => a.Time).ToList();
|
||
var SeriesData = GetChartPointByName(ChartRtSerie.Name, CurHistoryData);
|
||
ChartRtSerie.ChartPointLineSeries!.Clear();
|
||
//批量增加数据
|
||
ChartRtSerie.AddRangePoint(SeriesData);
|
||
//foreach (var item in SeriesData)
|
||
//{
|
||
// ChartRtSerie.AddPoint(item.Time, (double)item.Value, false, false);
|
||
//}
|
||
}
|
||
|
||
//到当前的界面
|
||
ChartAxisX.ScrollPosition = ChartAxisX.DateTimeToAxisValue(CurHistoryData.LastOrDefault()!.CreateTime);
|
||
|
||
stopwatch.Stop(); //停止Stopwatch
|
||
Console.WriteLine("加载到曲线耗时::{0}--{1}", stopwatch.Elapsed.TotalSeconds.ToString(), CurSelectedGroupTabIndex.ToString());
|
||
stopwatch.Reset();
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// 根据名称获取Point数据
|
||
/// </summary>
|
||
/// <returns></returns>
|
||
private List<ChartPoint> GetChartPointByName(string Name, List<CsvRecordModel> CurHistoryData)
|
||
{
|
||
switch (Name)
|
||
{
|
||
case "转速[rpm]":
|
||
return CurHistoryData.Select(a => new ChartPoint() { Value = a.Speed, Time = a.CreateTime }).OrderBy(a => a.Time).ToList();
|
||
case "排气压力[BarA]":
|
||
return CurHistoryData.Select(a => new ChartPoint() { Value = a.ExPress, Time = a.CreateTime }).OrderBy(a => a.Time).ToList();
|
||
case "吸气压力[BarA]":
|
||
return CurHistoryData.Select(a => new ChartPoint() { Value = a.InhPress, Time = a.CreateTime }).OrderBy(a => a.Time).ToList();
|
||
case "吸气温度[℃]":
|
||
return CurHistoryData.Select(a => new ChartPoint() { Value = a.InhTemp, Time = a.CreateTime }).OrderBy(a => a.Time).ToList();
|
||
case "COND1温度[℃]":
|
||
return CurHistoryData.Select(a => new ChartPoint() { Value = a.Cond1Temp, Time = a.CreateTime }).OrderBy(a => a.Time).ToList();
|
||
case "润滑油压力[BarA]":
|
||
return CurHistoryData.Select(a => new ChartPoint() { Value = a.LubePress, Time = a.CreateTime }).OrderBy(a => a.Time).ToList();
|
||
case "COND2压力[BarA]":
|
||
return CurHistoryData.Select(a => new ChartPoint() { Value = a.Cond2Press, Time = a.CreateTime }).OrderBy(a => a.Time).ToList();
|
||
case "OCR[%]":
|
||
return CurHistoryData.Select(a => new ChartPoint() { Value = a.OCR, Time = a.CreateTime }).OrderBy(a => a.Time).ToList();
|
||
case "HV[V]":
|
||
return CurHistoryData.Select(a => new ChartPoint() { Value = a.HV, Time = a.CreateTime }).OrderBy(a => a.Time).ToList();
|
||
case "HV[A]":
|
||
return CurHistoryData.Select(a => new ChartPoint() { Value = a.HVCur, Time = a.CreateTime }).OrderBy(a => a.Time).ToList();
|
||
case "HV[W]":
|
||
return CurHistoryData.Select(a => new ChartPoint() { Value = a.HVPw, Time = a.CreateTime }).OrderBy(a => a.Time).ToList();
|
||
case "LV[V]":
|
||
return CurHistoryData.Select(a => new ChartPoint() { Value = a.LV, Time = a.CreateTime }).OrderBy(a => a.Time).ToList();
|
||
case "LV[A]":
|
||
return CurHistoryData.Select(a => new ChartPoint() { Value = a.LVCur, Time = a.CreateTime }).OrderBy(a => a.Time).ToList();
|
||
case "环境温度[℃]":
|
||
return CurHistoryData.Select(a => new ChartPoint() { Value = a.EnvTemp, Time = a.CreateTime }).OrderBy(a => a.Time).ToList();
|
||
case "环境湿度[%]":
|
||
return CurHistoryData.Select(a => new ChartPoint() { Value = a.EnvRH, Time = a.CreateTime }).OrderBy(a => a.Time).ToList();
|
||
case "OS1温度[℃]":
|
||
return CurHistoryData.Select(a => new ChartPoint() { Value = a.OS1Temp, Time = a.CreateTime }).OrderBy(a => a.Time).ToList();
|
||
case "OS2温度[℃]":
|
||
return CurHistoryData.Select(a => new ChartPoint() { Value = a.OS2Temp, Time = a.CreateTime }).OrderBy(a => a.Time).ToList();
|
||
case "COND2温度[℃]":
|
||
return CurHistoryData.Select(a => new ChartPoint() { Value = a.Cond2Temp, Time = a.CreateTime }).OrderBy(a => a.Time).ToList();
|
||
case "EVAP出口温度[℃]":
|
||
return CurHistoryData.Select(a => new ChartPoint() { Value = a.EVAPExpTemp, Time = a.CreateTime }).OrderBy(a => a.Time).ToList();
|
||
case "冷媒流量[L/min]":
|
||
return CurHistoryData.Select(a => new ChartPoint() { Value = a.VRV, Time = a.CreateTime }).OrderBy(a => a.Time).ToList();
|
||
case "润滑油流量[L/min]":
|
||
return CurHistoryData.Select(a => new ChartPoint() { Value = a.LubeFlow, Time = a.CreateTime }).OrderBy(a => a.Time).ToList();
|
||
case "排气温度[℃]":
|
||
return CurHistoryData.Select(a => new ChartPoint() { Value = a.ExTemp, Time = a.CreateTime }).OrderBy(a => a.Time).ToList();
|
||
case "膨胀阀前压力[BarA]":
|
||
return CurHistoryData.Select(a => new ChartPoint() { Value = a.TxvFrPress, Time = a.CreateTime }).OrderBy(a => a.Time).ToList();
|
||
case "膨胀阀前温度[℃]":
|
||
return CurHistoryData.Select(a => new ChartPoint() { Value = a.TxvFrTemp, Time = a.CreateTime }).OrderBy(a => a.Time).ToList();
|
||
case "EVAP出口压力[BarA]":
|
||
return CurHistoryData.Select(a => new ChartPoint() { Value = a.EVAPExpPress, Time = a.CreateTime }).OrderBy(a => a.Time).ToList();
|
||
case "腔内压力[BarA]":
|
||
return CurHistoryData.Select(a => new ChartPoint() { Value = a.IntrplPress, Time = a.CreateTime }).OrderBy(a => a.Time).ToList();
|
||
case "压缩机表面温度[℃]":
|
||
return CurHistoryData.Select(a => new ChartPoint() { Value = a.CapSurfTemp, Time = a.CreateTime }).OrderBy(a => a.Time).ToList();
|
||
case "PTC流量[L/min]":
|
||
return CurHistoryData.Select(a => new ChartPoint() { Value = a.PTCFlow, Time = a.CreateTime }).OrderBy(a => a.Time).ToList();
|
||
case "PTC入水温度[℃]":
|
||
return CurHistoryData.Select(a => new ChartPoint() { Value = a.PTCEntTemp, Time = a.CreateTime }).OrderBy(a => a.Time).ToList();
|
||
case "PTC出水温度[℃]":
|
||
return CurHistoryData.Select(a => new ChartPoint() { Value = a.PTCExpTemp, Time = a.CreateTime }).OrderBy(a => a.Time).ToList();
|
||
case "AT04_01[℃]":
|
||
return CurHistoryData.Select(a => new ChartPoint() { Value = a.AT04_01Temp, Time = a.CreateTime }).OrderBy(a => a.Time).ToList();
|
||
case "AT04_02[℃]":
|
||
return CurHistoryData.Select(a => new ChartPoint() { Value = a.AT04_02Temp, Time = a.CreateTime }).OrderBy(a => a.Time).ToList();
|
||
case "通讯Cmp母线电流[A]":
|
||
return CurHistoryData.Select(a => new ChartPoint() { Value = a.ComCapBusCur, Time = a.CreateTime }).OrderBy(a => a.Time).ToList();
|
||
case "通讯Cmp母线电压[V]":
|
||
return CurHistoryData.Select(a => new ChartPoint() { Value = a.ComCapBusVol, Time = a.CreateTime }).OrderBy(a => a.Time).ToList();
|
||
case "通讯Cmp逆变器温度[℃]":
|
||
return CurHistoryData.Select(a => new ChartPoint() { Value = a.ComCapInvTemp, Time = a.CreateTime }).OrderBy(a => a.Time).ToList();
|
||
case "通讯Cmp相电流[A]":
|
||
return CurHistoryData.Select(a => new ChartPoint() { Value = a.ComCapPhCur, Time = a.CreateTime }).OrderBy(a => a.Time).ToList();
|
||
case "通讯Cmp功率[W]":
|
||
return CurHistoryData.Select(a => new ChartPoint() { Value = a.ComCapPw, Time = a.CreateTime }).OrderBy(a => a.Time).ToList();
|
||
case "通讯Cmp芯片温度[℃]":
|
||
return CurHistoryData.Select(a => new ChartPoint() { Value = a.ComCapChipTemp, Time = a.CreateTime }).OrderBy(a => a.Time).ToList();
|
||
case "通讯PTC入水温度[℃]":
|
||
return CurHistoryData.Select(a => new ChartPoint() { Value = a.ComPTCEntTemp, Time = a.CreateTime }).OrderBy(a => a.Time).ToList();
|
||
case "通讯PTC出水温度[℃]":
|
||
return CurHistoryData.Select(a => new ChartPoint() { Value = a.ComPTCExpTemp, Time = a.CreateTime }).OrderBy(a => a.Time).ToList();
|
||
case "通讯PTC峰值电流[A]":
|
||
return CurHistoryData.Select(a => new ChartPoint() { Value = a.ComPTCPeakCur, Time = a.CreateTime }).OrderBy(a => a.Time).ToList();
|
||
case "通讯PTC母线电流[A]":
|
||
return CurHistoryData.Select(a => new ChartPoint() { Value = a.ComPTCBusCur, Time = a.CreateTime }).OrderBy(a => a.Time).ToList();
|
||
case "通讯PTC膜温[℃]":
|
||
return CurHistoryData.Select(a => new ChartPoint() { Value = a.ComPTCFlmTemp, Time = a.CreateTime }).OrderBy(a => a.Time).ToList();
|
||
case "通讯PTC模块温度[℃]":
|
||
return CurHistoryData.Select(a => new ChartPoint() { Value = a.ComPTCMdTemp, Time = a.CreateTime }).OrderBy(a => a.Time).ToList();
|
||
default:
|
||
return CurHistoryData.Select(a => new ChartPoint() { Value = a.Speed, Time = a.CreateTime }).OrderBy(a => a.Time).ToList();
|
||
break;
|
||
}
|
||
|
||
}
|
||
|
||
#endregion
|
||
|
||
|
||
/// <summary>
|
||
/// 更新Y轴的信息,最大值和最小值
|
||
/// </summary>
|
||
private void UpdateChartAxisY(List<ConfigChartYAxis> configChartYAxes)
|
||
{
|
||
LgChart.BeginUpdate();
|
||
|
||
//只更改最大值和最小值 如果改动名称需要从Id入手
|
||
foreach (var item in LgChart.ViewXY.YAxes)
|
||
{
|
||
var FindData = configChartYAxes.Find(a => a.Name == item.Title.Text);
|
||
if (FindData != null)
|
||
{
|
||
item.Minimum = FindData.Min;
|
||
item.Maximum = FindData.Max;
|
||
}
|
||
}
|
||
|
||
LgChart.EndUpdate();
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// 切换Tab,是不是当前的Tab信息
|
||
/// </summary>
|
||
/// <param name="msg"></param>
|
||
private void ChartTabGroupSwitchCall(ChartTabGroupSwitchMsg msg)
|
||
{
|
||
if (msg.Machine != CurSelectedMachine)
|
||
{
|
||
//选择了其他的机械的话,则也是没有被激活
|
||
IsActivated = false;
|
||
return;
|
||
}
|
||
|
||
//当前的系列
|
||
if (msg.GroupTabIndex == CurSelectedGroupTabIndex)
|
||
{
|
||
IsActivated = true;
|
||
}
|
||
else
|
||
{
|
||
IsActivated = false;
|
||
}
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// 事件聚合器
|
||
/// </summary>
|
||
private IEventAggregator _EventAggregator { get; set; }
|
||
public TagManager TagManager { get; }
|
||
private DataRecordService DatRecordService { get; set; }
|
||
public IFreeSql FreeSql { get; }
|
||
|
||
/// <summary>
|
||
/// 当前的Chart所属的TabIndex
|
||
/// </summary>
|
||
private int CurSelectedGroupTabIndex { get; set; }
|
||
|
||
/// <summary>
|
||
/// 当前选中的Machine
|
||
/// </summary>
|
||
private string CurSelectedMachine { get; set; }
|
||
|
||
/// <summary>
|
||
/// 当前曲线是否被激活
|
||
/// 当前被查看的Chart控件
|
||
/// </summary>
|
||
private bool IsActivated { get; set; } = false;
|
||
|
||
/// <summary>
|
||
/// 初始化Ok了吗
|
||
/// </summary>
|
||
private bool IsInitOk { get; set; } = false;
|
||
|
||
/// <summary>
|
||
/// 是否为实时曲线
|
||
/// 默认为实时曲线
|
||
/// 否则为历史数据曲线
|
||
/// </summary>
|
||
private bool IsRealTimeChart { get; set; } = true;
|
||
public ILogService LogService { get; }
|
||
public ConfigService ConfigService { get; }
|
||
|
||
/// <summary>
|
||
/// Chart曲线的实例
|
||
/// </summary>
|
||
public LightningChart LgChart { get; set; }
|
||
|
||
/// <summary>
|
||
/// 是否为双游标
|
||
/// </summary>
|
||
private bool IsDoubleCurson { get; set; } = false;
|
||
|
||
|
||
/// <summary>
|
||
/// 曲线名称
|
||
/// </summary>
|
||
public string ChartName { get; set; }
|
||
|
||
private ObservableCollection<ChartRtSeries> _ListChartRtSeries;
|
||
/// <summary>
|
||
/// 曲线数据系列集合
|
||
/// </summary>
|
||
public ObservableCollection<ChartRtSeries> ListChartRtSeries
|
||
{
|
||
get { return _ListChartRtSeries; }
|
||
set { _ListChartRtSeries = value; RaisePropertyChanged(); }
|
||
}
|
||
|
||
|
||
///// <summary>
|
||
///// 曲线数据系列集合
|
||
///// </summary>
|
||
//public List<ChartRtSeries> ListChartRtSeries { get; set; }
|
||
|
||
/// <summary>
|
||
/// Chart显示哪些参数配置 业务相关
|
||
/// </summary>
|
||
public List<ConfigChart> ListConfigChart { get; set; }
|
||
|
||
/// <summary>
|
||
/// 曲线配置
|
||
/// </summary>
|
||
public ChartColor ChartColorInfo { get; set; } = new ChartColor();
|
||
|
||
///// <summary>
|
||
///// Chart图表X轴的跨度-秒
|
||
///// </summary>
|
||
//public int ChartXDateTimeRange { get; set; } = 3600_8;
|
||
|
||
/// <summary>
|
||
/// X轴滚动
|
||
/// </summary>
|
||
public bool IsScrollEnable { get; set; } = true;
|
||
|
||
/// <summary>
|
||
/// 隐藏图例
|
||
/// </summary>
|
||
public bool IsLegendHide { get; set; } = false;
|
||
|
||
/// <summary>
|
||
/// 是否删除之前的数据
|
||
/// </summary>
|
||
public bool IsDeleteBefore { get; set; } = true;
|
||
|
||
/// <summary>
|
||
/// X轴
|
||
/// </summary>
|
||
public AxisX? ChartAxisX { get; set; }
|
||
|
||
/// <summary>
|
||
/// 第一个光标
|
||
/// 单双光标时使用
|
||
/// </summary>
|
||
public LineSeriesCursor FirstLineSeriesCursor { get; set; }
|
||
|
||
/// <summary>
|
||
/// 第一个光标的X轴时间
|
||
/// </summary>
|
||
public DateTime FirstCursorDatetime { get; set; }
|
||
|
||
/// <summary>
|
||
/// 第二个光标
|
||
/// 双光标时使用
|
||
/// </summary>
|
||
public LineSeriesCursor SecondLineSeriesCursor { get; set; }
|
||
|
||
/// <summary>
|
||
/// 第二个光标的X轴时间
|
||
/// </summary>
|
||
public DateTime SecondCursorDatetime { get; set; }
|
||
|
||
/// <summary>
|
||
/// Annotations 注释
|
||
/// </summary>
|
||
public AnnotationXY CursorValueDisplay { get; set; }
|
||
|
||
/// <summary>
|
||
/// 当前的图例
|
||
/// </summary>
|
||
public LegendBoxXY LegendBox { get; set; }
|
||
|
||
/// <summary>
|
||
/// 卡尺 注释 没有使用
|
||
/// </summary>
|
||
public AnnotationXY Caliper { get; set; }
|
||
|
||
|
||
/// <summary>
|
||
/// Chart初始化
|
||
/// </summary>
|
||
public void InitChart()
|
||
{
|
||
//Disable rendering, strongly recommended before updating chart properties
|
||
LgChart.BeginUpdate();
|
||
|
||
//性能设置
|
||
//Sync (default): 图表同步更新。图表在最后一次 EndUpdate()调用后更新,或者
|
||
// 当设置属性(或调用一个 method)会改变图表时更新。属性的改变(没有
|
||
// BeginUpdate…EndUpdate)会引发即时渲染新帧。
|
||
//Async: 图表以异步方式更新。图表在属性改变后将尽快更新,但是图表将在随后的某
|
||
//个的点渲染一个新帧。这也许让图表在某些情况下更方便使用。
|
||
//LimitedFrameRate: 帧率受限于在 FrameRateLimit 属性中规定的值。0 = 无限制。例
|
||
//如,如果想要最大每秒刷新10次,则设置值为10。这与Async选项类似,但会防止在
|
||
//第一个帧之后立即渲染新的帧,如此以来,减少帧率,但节省了系统资源。
|
||
//注意! 确保在LimitedFrameRate和 Async模式下正确的线程处理。如果异步更新图表,
|
||
//并且图表属性也同时更新,可能会引发冲突,导致图表或应用程序奔溃。
|
||
LgChart.ChartRenderOptions.UpdateType = ChartUpdateTypes.Async;
|
||
LgChart.ChartRenderOptions.FrameRateLimit = 0;
|
||
|
||
//Reduce memory usage and increase performance. Destroys out-scrolled data.
|
||
LgChart.ViewXY.DropOldSeriesData = false;
|
||
|
||
//多个Y曲线摆放形式
|
||
LgChart.ViewXY.AxisLayout.YAxesLayout = YAxesLayout.Layered;
|
||
//网格带
|
||
LgChart.ViewXY.AxisLayout.AxisGridStrips = XYAxisGridStrips.X;
|
||
//y轴的在左边还是右边
|
||
LgChart.ViewXY.AxisLayout.YAxisAutoPlacement = YAxisAutoPlacement.AllLeft;
|
||
|
||
//LgChart.Parent = this.panel1;
|
||
//LgChart.Name = "Temperature measurement _chart";
|
||
LgChart.Title.Text = "";
|
||
|
||
//LgChart.ViewXY.
|
||
//LgChart.Dock = DockStyle.Fill;
|
||
|
||
//清除Y轴系列
|
||
LgChart.ViewXY.YAxes.Clear();
|
||
var InitAxisY = new AxisY(LgChart.ViewXY);
|
||
InitAxisY.Visible = false;
|
||
InitAxisY.ZoomingEnabled = false;
|
||
LgChart.ViewXY.YAxes.Add(InitAxisY);
|
||
|
||
//Configure x-axis
|
||
AxisX xAxis = LgChart.ViewXY.XAxes[0];
|
||
xAxis.ValueType = AxisValueType.DateTime;
|
||
xAxis.Title.Text = "时间";
|
||
xAxis.AutoFormatLabels = true;
|
||
xAxis.LabelsTimeFormat = "MM/dd \n HH:mm.ss";
|
||
//xAxis.LabelsTimeFormat = "dd/MM/yyyy\nHH:mm.ss";
|
||
xAxis.LabelsAngle = 45;
|
||
//xAxis.SteppingInterval = 0.1;
|
||
//xAxis.ScrollingGap = 15;
|
||
ChartAxisX = xAxis;
|
||
|
||
|
||
//xAxis.AllowScaling = true;
|
||
|
||
xAxis.ScrollMode = XAxisScrollMode.Scrolling;
|
||
xAxis.ZoomingEnabled = true;
|
||
|
||
//Convert DateTime values to axis values
|
||
DateTime now = DateTime.Now;
|
||
double minX = xAxis.DateTimeToAxisValue(now);
|
||
double maxX = xAxis.DateTimeToAxisValue(now.AddMinutes(60));
|
||
xAxis.SetRange(minX, maxX);
|
||
|
||
|
||
//DateTime now = DateTime.Now;
|
||
|
||
//xAxis.SetDateTimeRange(now,now.AddMinutes(60));
|
||
|
||
|
||
//Add an annotation to show the cursor values
|
||
//AnnotationXY cursorValueDisplay = new AnnotationXY();
|
||
|
||
//光标注释数据
|
||
CursorValueDisplay = new AnnotationXY(LgChart.ViewXY, LgChart.ViewXY.XAxes[0], LgChart.ViewXY.YAxes[0]);
|
||
//显示光标数据的内容的载体
|
||
CursorValueDisplay.Text = "";
|
||
CursorValueDisplay.Style = AnnotationStyle.Rectangle;//注释是矩形框显示
|
||
CursorValueDisplay.LocationCoordinateSystem = CoordinateSystem.ScreenCoordinates;//屏幕的位置
|
||
//CursorValueDisplay.LocationRelativeOffset.X = 130;
|
||
//CursorValueDisplay.LocationRelativeOffset.Y = -100;
|
||
//光标注释相对的位置 右上侧
|
||
//CursorValueDisplay.LocationScreenCoords.Y = 45;
|
||
//CursorValueDisplay.LocationScreenCoords.X = 1480;
|
||
|
||
//光标注释相对的位置 左上侧
|
||
CursorValueDisplay.LocationScreenCoords.Y = 35;
|
||
CursorValueDisplay.LocationScreenCoords.X = 1380;
|
||
|
||
//CursorValueDisplay.TargetAxisValues.X = 0;
|
||
//CursorValueDisplay.TargetAxisValues.Y = 0;
|
||
|
||
CursorValueDisplay.Sizing = AnnotationXYSizing.Automatic;
|
||
//cursorValueDisplay.TextStyle.Font = new WpfFont("Lucida console", 10f, FontStyle.Regular);
|
||
CursorValueDisplay.TextStyle.Color = System.Windows.Media.Color.FromRgb(102, 255, 51);
|
||
CursorValueDisplay.Fill.Style = RectFillStyle.ColorOnly;
|
||
CursorValueDisplay.Fill.Color = System.Windows.Media.Color.FromArgb(150, 48, 48, 48);//带透明度
|
||
CursorValueDisplay.Fill.GradientColor = System.Windows.Media.Color.FromRgb(48, 48, 48);//渐变色
|
||
CursorValueDisplay.BorderVisible = false;
|
||
CursorValueDisplay.AllowTargetMove = false;
|
||
CursorValueDisplay.AllowDragging = false;//是否允许拖动
|
||
CursorValueDisplay.AllowResize = false;//是否允许用户改变大小
|
||
CursorValueDisplay.Visible = false;
|
||
LgChart.ViewXY.Annotations.Add(CursorValueDisplay);
|
||
|
||
|
||
//第一个光标 cursor
|
||
FirstLineSeriesCursor = new LineSeriesCursor(LgChart.ViewXY, LgChart.ViewXY.XAxes[0]);
|
||
LgChart.ViewXY.LineSeriesCursors.Add(FirstLineSeriesCursor);
|
||
FirstLineSeriesCursor.PositionChanged += FirstCursor_PositionChanged;
|
||
FirstLineSeriesCursor.ValueAtXAxis = LgChart.ViewXY.XAxes[0].DateTimeToAxisValue(DateTime.Now.AddMinutes(30));
|
||
FirstLineSeriesCursor.LineStyle.Color = System.Windows.Media.Color.FromRgb(100, 200, 200);
|
||
FirstLineSeriesCursor.SnapToPoints = false;
|
||
FirstLineSeriesCursor.TrackPoint.Color1 = System.Windows.Media.Color.FromRgb(255, 255, 255);
|
||
FirstLineSeriesCursor.Style = CursorStyle.PointTracking;
|
||
|
||
//第二个光标 cursor
|
||
SecondLineSeriesCursor = new LineSeriesCursor(LgChart.ViewXY, LgChart.ViewXY.XAxes[0]);
|
||
LgChart.ViewXY.LineSeriesCursors.Add(SecondLineSeriesCursor);
|
||
SecondLineSeriesCursor.PositionChanged += SecondCursor_PositionChanged;
|
||
SecondLineSeriesCursor.ValueAtXAxis = LgChart.ViewXY.XAxes[0].DateTimeToAxisValue(DateTime.Now.AddMinutes(30));
|
||
SecondLineSeriesCursor.LineStyle.Color = System.Windows.Media.Color.FromRgb(0, 191, 255);
|
||
SecondLineSeriesCursor.SnapToPoints = false;
|
||
SecondLineSeriesCursor.TrackPoint.Color1 = System.Windows.Media.Color.FromRgb(255, 255, 255);
|
||
SecondLineSeriesCursor.Style = CursorStyle.PointTracking;
|
||
|
||
SecondLineSeriesCursor.Visible = false;
|
||
|
||
//两个光标的卡纸信息
|
||
//Caliper = new AnnotationXY(LgChart.ViewXY, LgChart.ViewXY.XAxes[0], LgChart.ViewXY.YAxes[0]);
|
||
//Caliper.Style = AnnotationStyle.Arrow;
|
||
//Caliper.ArrowStyleBegin = ArrowStyle.Caliper;
|
||
//Caliper.ArrowStyleEnd = ArrowStyle.Caliper;
|
||
//Caliper.ArrowLineStyle.Width = 5;
|
||
//Caliper.ArrowLineStyle.Pattern = LinePattern.Dash;
|
||
//Caliper.LocationCoordinateSystem = CoordinateSystem.AxisValues;
|
||
//Caliper.TargetCoordinateSystem = AnnotationTargetCoordinates.AxisValues;
|
||
////double dCaliperY = yAxisTemperature.Maximum - (yAxisTemperature.Maximum - yAxisTemperature.Minimum) * 0.10;
|
||
//double dCaliperY = 0.1;
|
||
//Caliper.LocationAxisValues.SetValues(FirstLineSeriesCursor.ValueAtXAxis, dCaliperY);
|
||
//Caliper.TargetAxisValues.SetValues(SecondLineSeriesCursor.ValueAtXAxis, dCaliperY);
|
||
//Caliper.TextStyle.Visible = false;
|
||
//LgChart.ViewXY.Annotations.Add(Caliper);
|
||
|
||
LgChart.Loaded += LgChart_Loaded;
|
||
LgChart.SizeChanged += LgChart_SizeChanged;
|
||
//LgChart.Resize += new EventHandler(_chart_Resize);
|
||
|
||
////清除Y轴系列
|
||
//LgChart.ViewXY.YAxes.Clear();
|
||
|
||
//图例框
|
||
LgChart.ViewXY.LegendBoxes[0].Visible = true;
|
||
LgChart.ViewXY.LegendBoxes[0].Position = LegendBoxPositionXY.TopRight;
|
||
//LgChart.ViewXY.AutoSpaceLegendBoxes = true;
|
||
LgChart.ViewXY.LegendBoxes[0].Layout = LegendBoxLayout.Vertical;//排列方式
|
||
LgChart.ViewXY.LegendBoxes[0].AllowDragging = false;
|
||
LgChart.ViewXY.LegendBoxes[0].Offset = new PointIntXY(0, 16);
|
||
LgChart.ViewXY.LegendBoxes[0].CheckBoxSize = 14;
|
||
LgChart.ViewXY.LegendBoxes[0].ValueLabelFont = new WpfFont(16);
|
||
LgChart.ViewXY.LegendBoxes[0].Fill.Color = System.Windows.Media.Color.FromArgb(0, 180, 180, 180); ;//带透明度
|
||
LegendBox = LgChart.ViewXY.LegendBoxes[0];
|
||
|
||
//Allow chart rendering
|
||
LgChart.EndUpdate();
|
||
|
||
IsInitOk = true;
|
||
}
|
||
|
||
|
||
|
||
/// <summary>
|
||
/// 获取订阅的的数据
|
||
/// 确保和数据记录的数据是一致的,并且是同一个时刻
|
||
/// </summary>
|
||
/// <param name="data"></param>
|
||
/// <exception cref="NotImplementedException"></exception>
|
||
private void UpdateRecordData(RecordChannelData data)
|
||
{
|
||
|
||
|
||
if (data.Data != null)
|
||
{
|
||
foreach (var item in data.Data)
|
||
{
|
||
//var FindData= ListChartRtSeries.Where(a=>a.Name==item.Key);
|
||
//判断是否存在
|
||
//if (ListChartRtSeries.Exists(a => a.Name == item.Key))
|
||
if (ListChartRtSeries.Where(a => a.Name == item.Key).Any())
|
||
{
|
||
var Data = ListChartRtSeries.FindFirst(a => a.Name == item.Key);
|
||
Data.Value = Convert.ToDouble(item.Value);
|
||
Data.AddPointByCache(data.CreateTime, Data.Value, IsDeleteBefore, IsScrollEnable);
|
||
}
|
||
//ListConfigChart
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// 曲线个数
|
||
/// </summary>
|
||
private int ChartSeriesCount { get; set; } = 0;
|
||
|
||
/// <summary>
|
||
/// 更新图表信息
|
||
/// </summary>
|
||
public void UpdateChartData()
|
||
{
|
||
//timeStamp = timeStamp.AddSeconds(-60);
|
||
foreach (var item in LgChart.ViewXY.PointLineSeries)
|
||
{
|
||
//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.Now);
|
||
points[0].X = _previousX;
|
||
points[0].Y = GetChartRtValue(item.Title.Text);
|
||
//Add the new point into end of first PointLineSeries
|
||
item.AddPoints(points, false);
|
||
|
||
item.DeletePointsBeforeX(_previousX - ConfigService.ChartRtDataCacheTimeSec);
|
||
//item.DeletePointsBeforeX(_previousX - 100);
|
||
|
||
if (IsScrollEnable)
|
||
{
|
||
LgChart.ViewXY.XAxes[0].ScrollPosition = _previousX;
|
||
}
|
||
|
||
//Allow updates again, and update
|
||
LgChart.EndUpdate();
|
||
|
||
}
|
||
}
|
||
|
||
|
||
|
||
/// <summary>
|
||
/// 根据名称获取曲线所需的数据
|
||
/// </summary>
|
||
private double GetChartRtValue(string Name)
|
||
{
|
||
try
|
||
{
|
||
//var Data = ListChartRtValue.Find(a => a.Name == Name);
|
||
//if (Data != null)
|
||
//{
|
||
// return Data.Value;
|
||
//}
|
||
return 0;
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
//logger.Error(String.Format("ErrSource : {0} ErrMsg : {1}", ex.StackTrace.ToString(), ex.Message.ToString()));
|
||
return 0;
|
||
}
|
||
finally
|
||
{
|
||
|
||
}
|
||
|
||
}
|
||
|
||
|
||
|
||
private void LgChart_SizeChanged(object sender, System.Windows.SizeChangedEventArgs e)
|
||
{
|
||
//UpdateCursorResult();
|
||
}
|
||
|
||
private void LgChart_Loaded(object sender, System.Windows.RoutedEventArgs e)
|
||
{
|
||
//UpdateCursorResult();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 第一个光标位置变化
|
||
/// </summary>
|
||
/// <param name="sender"></param>
|
||
/// <param name="e"></param>
|
||
private void FirstCursor_PositionChanged(object sender, PositionChangedEventArgs e)
|
||
{
|
||
e.CancelRendering = true;
|
||
|
||
if (!IsInitOk) return;
|
||
|
||
FirstUpdateCursorResult(sender);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 光标位置变化
|
||
/// </summary>
|
||
/// <param name="sender"></param>
|
||
/// <param name="e"></param>
|
||
private void SecondCursor_PositionChanged(object sender, PositionChangedEventArgs e)
|
||
{
|
||
e.CancelRendering = true;
|
||
|
||
if (!IsInitOk) return;
|
||
|
||
SecondUpdateCursorResult(sender);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Update cursor texts.
|
||
/// 更新光标的注释信息
|
||
/// 使用AnnotationXY进行展示,已经舍弃
|
||
/// </summary>
|
||
private void UpdateCursorResult()
|
||
{
|
||
bool showNextToCursor = true;
|
||
|
||
//Disable rendering, strongly recommended before updating chart properties
|
||
LgChart.BeginUpdate();
|
||
|
||
//Get cursor 光标
|
||
LineSeriesCursor cursor = LgChart.ViewXY.LineSeriesCursors[0];
|
||
|
||
//Get annotation 注释
|
||
AnnotationXY cursorValueDisplay = LgChart.ViewXY.Annotations[0];
|
||
|
||
//Set annotation target. The location is relative to target.
|
||
//Use graph bottom as target Y value.
|
||
float targetYCoord = (float)LgChart.ViewXY.GetMarginsRect().Bottom;
|
||
double y;
|
||
LgChart.ViewXY.YAxes[0].CoordToValue(targetYCoord, out y);
|
||
|
||
//设置注释的位置
|
||
//cursorValueDisplay.TargetAxisValues.X = cursor.ValueAtXAxis;
|
||
//cursorValueDisplay.TargetAxisValues.Y = y;
|
||
cursorValueDisplay.TargetAxisValues.X = 0;
|
||
cursorValueDisplay.TargetAxisValues.Y = 0;
|
||
|
||
double seriesYValue = 0;
|
||
|
||
StringBuilder sb = new StringBuilder();
|
||
int seriesIndex = 1;
|
||
|
||
//string channelStringFormat = "Mill {0}: {1,12:#####.###} {2}";
|
||
string channelStringFormat = "{0}: {1}";
|
||
bool labelVisible = false;
|
||
bool accurateValue = false;
|
||
string value = "";
|
||
|
||
foreach (PointLineSeries pointLineSeries in LgChart.ViewXY.PointLineSeries)
|
||
{
|
||
//show series titles and cursor values in them, on the right side of the chart,
|
||
//if cursor values are not shown next to the cursor in an annotation
|
||
pointLineSeries.Title.Visible = !showNextToCursor;
|
||
//pointLineSeries.Title.Visible = true;
|
||
bool resolved = false;
|
||
value = "";
|
||
|
||
if (accurateValue)
|
||
resolved = SolveValueAccurate(pointLineSeries, cursor.ValueAtXAxis, out seriesYValue);
|
||
else
|
||
resolved = SolveValueCoarse(pointLineSeries, cursor.ValueAtXAxis, out seriesYValue);
|
||
|
||
AxisY axisY = LgChart.ViewXY.YAxes[pointLineSeries.AssignYAxisIndex];
|
||
|
||
if (resolved)
|
||
{
|
||
labelVisible = true;
|
||
//value = string.Format(channelStringFormat, seriesIndex, seriesYValue.ToString("0.000"), axisY.Units.Text);
|
||
value = string.Format(channelStringFormat, pointLineSeries.Title.Text, seriesYValue.ToString("0.000"));
|
||
}
|
||
else
|
||
{
|
||
//value = string.Format(channelStringFormat, seriesIndex, "---", axisY.Units.Text);
|
||
value = string.Format(channelStringFormat, pointLineSeries.Title.Text, "---");
|
||
}
|
||
sb.AppendLine(value);
|
||
//这个会改变曲线标题的名称,影响曲线的定位、删除等操作
|
||
//pointLineSeries.Title.Text = value;
|
||
seriesIndex++;
|
||
}
|
||
|
||
//sb.AppendLine("");
|
||
//sb.AppendLine("时间: " + LgChart.ViewXY.XAxes[0].TimeString(cursor.ValueAtXAxis, "HH:mm:ss.ffff"));
|
||
|
||
////Set text
|
||
cursorValueDisplay.Text = sb.ToString();
|
||
|
||
////Show the label only if it selected to be shown 是否显示
|
||
cursorValueDisplay.Visible = labelVisible && showNextToCursor;
|
||
//cursorValueDisplay.Visible = true;
|
||
|
||
//Allow chart rendering
|
||
LgChart.EndUpdate();
|
||
}
|
||
|
||
/// <summary>
|
||
/// Update cursor texts.
|
||
/// 更新到ListView中
|
||
/// </summary>
|
||
private void UpdateCursorResultToLv(object sender)
|
||
{
|
||
bool showNextToCursor = true;
|
||
|
||
//拖动的Cursor
|
||
LineSeriesCursor DraggedCursor = (LineSeriesCursor)sender;
|
||
|
||
//Disable rendering, strongly recommended before updating chart properties
|
||
LgChart.BeginUpdate();
|
||
|
||
// 判断这个拖动的Cursor是左侧的还是右侧的,防止左侧的越过右侧
|
||
if (DraggedCursor == FirstLineSeriesCursor)
|
||
{
|
||
if (DraggedCursor.ValueAtXAxis > SecondLineSeriesCursor.ValueAtXAxis - 1)
|
||
{
|
||
DraggedCursor.ValueAtXAxis = SecondLineSeriesCursor.ValueAtXAxis - 1;
|
||
}
|
||
}
|
||
else if (DraggedCursor == SecondLineSeriesCursor)
|
||
{
|
||
if (DraggedCursor.ValueAtXAxis < FirstLineSeriesCursor.ValueAtXAxis + 1)
|
||
{
|
||
DraggedCursor.ValueAtXAxis = FirstLineSeriesCursor.ValueAtXAxis + 1;
|
||
}
|
||
}
|
||
|
||
//Get cursor 光标
|
||
LineSeriesCursor cursor = LgChart.ViewXY.LineSeriesCursors[0];
|
||
|
||
//Get annotation 注释
|
||
AnnotationXY cursorValueDisplay = LgChart.ViewXY.Annotations[0];
|
||
|
||
//Set annotation target. The location is relative to target.
|
||
//Use graph bottom as target Y value.
|
||
float targetYCoord = (float)LgChart.ViewXY.GetMarginsRect().Bottom;
|
||
double y;
|
||
LgChart.ViewXY.YAxes[0].CoordToValue(targetYCoord, out y);
|
||
|
||
//设置注释的位置
|
||
//cursorValueDisplay.TargetAxisValues.X = cursor.ValueAtXAxis;
|
||
//cursorValueDisplay.TargetAxisValues.Y = y;
|
||
cursorValueDisplay.TargetAxisValues.X = 0;
|
||
cursorValueDisplay.TargetAxisValues.Y = 0;
|
||
|
||
//Y轴的值
|
||
double seriesYValue = 0;
|
||
|
||
StringBuilder sb = new StringBuilder();
|
||
int seriesIndex = 1;
|
||
|
||
//string channelStringFormat = "Mill {0}: {1,12:#####.###} {2}";
|
||
string channelStringFormat = "{0}: {1}";
|
||
bool labelVisible = false;
|
||
bool accurateValue = false;
|
||
string value = "";
|
||
|
||
foreach (ChartRtSeries chartRtSeries in ListChartRtSeries)
|
||
{
|
||
//show series titles and cursor values in them, on the right side of the chart,
|
||
//if cursor values are not shown next to the cursor in an annotation
|
||
chartRtSeries.ChartPointLineSeries!.Title.Visible = !showNextToCursor;
|
||
//pointLineSeries.Title.Visible = true;
|
||
bool resolved = false;
|
||
value = "";
|
||
|
||
if (accurateValue)
|
||
resolved = SolveValueAccurate(chartRtSeries.ChartPointLineSeries!, cursor.ValueAtXAxis, out seriesYValue);
|
||
else
|
||
resolved = SolveValueCoarse(chartRtSeries.ChartPointLineSeries!, cursor.ValueAtXAxis, out seriesYValue);
|
||
|
||
AxisY axisY = LgChart.ViewXY.YAxes[chartRtSeries.ChartPointLineSeries!.AssignYAxisIndex];
|
||
|
||
//已经计算出值了
|
||
chartRtSeries.LeftCursorValue = seriesYValue;
|
||
|
||
if (resolved)
|
||
{
|
||
labelVisible = true;
|
||
//value = string.Format(channelStringFormat, seriesIndex, seriesYValue.ToString("0.000"), axisY.Units.Text);
|
||
value = string.Format(channelStringFormat, chartRtSeries.ChartPointLineSeries!.Title.Text, seriesYValue.ToString("0.000"));
|
||
}
|
||
else
|
||
{
|
||
//value = string.Format(channelStringFormat, seriesIndex, "---", axisY.Units.Text);
|
||
value = string.Format(channelStringFormat, chartRtSeries.ChartPointLineSeries!.Title.Text, "---");
|
||
}
|
||
sb.AppendLine(value);
|
||
//这个会改变曲线标题的名称,影响曲线的定位、删除等操作
|
||
//pointLineSeries.Title.Text = value;
|
||
seriesIndex++;
|
||
}
|
||
|
||
//sb.AppendLine("");
|
||
//sb.AppendLine("时间: " + LgChart.ViewXY.XAxes[0].TimeString(cursor.ValueAtXAxis, "HH:mm:ss.ffff"));
|
||
|
||
////Set text
|
||
cursorValueDisplay.Text = sb.ToString();
|
||
|
||
////Show the label only if it selected to be shown 是否显示
|
||
cursorValueDisplay.Visible = labelVisible && showNextToCursor;
|
||
//cursorValueDisplay.Visible = true;
|
||
|
||
//Allow chart rendering
|
||
LgChart.EndUpdate();
|
||
}
|
||
|
||
/// <summary>
|
||
/// Update cursor texts.
|
||
/// 第一个游标更新位置,更新结果
|
||
/// </summary>
|
||
private void FirstUpdateCursorResult(object sender)
|
||
{
|
||
bool showNextToCursor = true;
|
||
|
||
//拖动的Cursor
|
||
LineSeriesCursor DraggedCursor = (LineSeriesCursor)sender;
|
||
|
||
//Disable rendering, strongly recommended before updating chart properties
|
||
LgChart.BeginUpdate();
|
||
|
||
//左侧的游标,在双游标时才会被限制,单游标时不做处理
|
||
if (IsDoubleCurson)
|
||
{
|
||
// 判断这个拖动的Cursor是左侧的还是右侧的,防止左侧的越过右侧
|
||
if (DraggedCursor == FirstLineSeriesCursor)
|
||
{
|
||
if (DraggedCursor.ValueAtXAxis > SecondLineSeriesCursor.ValueAtXAxis - 1)
|
||
{
|
||
DraggedCursor.ValueAtXAxis = SecondLineSeriesCursor.ValueAtXAxis - 1;
|
||
}
|
||
}
|
||
else if (DraggedCursor == SecondLineSeriesCursor)
|
||
{
|
||
if (DraggedCursor.ValueAtXAxis < FirstLineSeriesCursor.ValueAtXAxis + 1)
|
||
{
|
||
DraggedCursor.ValueAtXAxis = FirstLineSeriesCursor.ValueAtXAxis + 1;
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
//设置注释的位置
|
||
//cursorValueDisplay.TargetAxisValues.X = cursor.ValueAtXAxis;
|
||
//cursorValueDisplay.TargetAxisValues.Y = y;
|
||
CursorValueDisplay.TargetAxisValues.X = 0;
|
||
CursorValueDisplay.TargetAxisValues.Y = 0;
|
||
|
||
//Y轴的值
|
||
double seriesYValue = 0;
|
||
|
||
StringBuilder Strb = new StringBuilder();
|
||
|
||
string channelStringFormat = "{0}: {1}";
|
||
//算法的选择
|
||
bool accurateValue = false;
|
||
string value = "";
|
||
|
||
FirstCursorDatetime = ChartAxisX!.AxisValueToDateTime(FirstLineSeriesCursor.ValueAtXAxis);
|
||
|
||
foreach (ChartRtSeries chartRtSeries in ListChartRtSeries)
|
||
{
|
||
//show series titles and cursor values in them, on the right side of the chart,
|
||
//if cursor values are not shown next to the cursor in an annotation
|
||
//chartRtSeries.ChartPointLineSeries!.Title.Visible = !showNextToCursor;
|
||
//pointLineSeries.Title.Visible = true;
|
||
bool resolved = false;
|
||
value = "";
|
||
|
||
if (accurateValue)
|
||
resolved = SolveValueAccurate(chartRtSeries.ChartPointLineSeries!, FirstLineSeriesCursor.ValueAtXAxis, out seriesYValue);
|
||
else
|
||
resolved = SolveValueCoarse(chartRtSeries.ChartPointLineSeries!, FirstLineSeriesCursor.ValueAtXAxis, out seriesYValue);
|
||
|
||
//已经计算出值了
|
||
chartRtSeries.LeftCursorValue = seriesYValue;
|
||
|
||
|
||
//双游标需要统计数据
|
||
if (IsDoubleCurson)
|
||
{
|
||
if (IsRealTimeChart)
|
||
{
|
||
var StatisValue = CalcStatis(chartRtSeries.Name);
|
||
chartRtSeries.MaxValue = StatisValue.Max;
|
||
chartRtSeries.MinValue = StatisValue.Min;
|
||
chartRtSeries.AveValue = StatisValue.Ave;
|
||
}
|
||
else
|
||
{
|
||
var StatisValue = CalcHistoryStatis(chartRtSeries.Name);
|
||
chartRtSeries.MaxValue = StatisValue.Max;
|
||
chartRtSeries.MinValue = StatisValue.Min;
|
||
chartRtSeries.AveValue = StatisValue.Ave;
|
||
}
|
||
|
||
}
|
||
|
||
//不需要光标位置处的数据
|
||
//if (resolved)
|
||
//{
|
||
// value = string.Format(channelStringFormat, chartRtSeries.ChartPointLineSeries!.Title.Text, seriesYValue.ToString("0.000"));
|
||
//}
|
||
//else
|
||
//{
|
||
// value = string.Format(channelStringFormat, chartRtSeries.ChartPointLineSeries!.Title.Text, "---");
|
||
//}
|
||
|
||
//Strb.AppendLine(value);
|
||
|
||
}
|
||
|
||
//sb.AppendLine("");
|
||
//sb.AppendLine("时间: " + LgChart.ViewXY.XAxes[0].TimeString(cursor.ValueAtXAxis, "HH:mm:ss.ffff"));
|
||
|
||
////Set text
|
||
//CursorValueDisplay.Text = Strb.ToString();
|
||
CursorValueDisplay.Text = $"左光标:{FirstCursorDatetime.ToString("MM-dd HH:mm:ss")}";
|
||
|
||
////Show the label only if it selected to be shown 是否显示
|
||
CursorValueDisplay.Visible = true;
|
||
|
||
//Allow chart rendering
|
||
LgChart.EndUpdate();
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// Update cursor texts.
|
||
/// 第二个游标更新位置,更新结果
|
||
/// </summary>
|
||
private void SecondUpdateCursorResult(object sender)
|
||
{
|
||
bool showNextToCursor = true;
|
||
|
||
//拖动的Cursor
|
||
LineSeriesCursor DraggedCursor = (LineSeriesCursor)sender;
|
||
|
||
//Disable rendering, strongly recommended before updating chart properties
|
||
LgChart.BeginUpdate();
|
||
|
||
// 判断这个拖动的Cursor是左侧的还是右侧的,防止左侧的越过右侧
|
||
if (DraggedCursor == FirstLineSeriesCursor)
|
||
{
|
||
if (DraggedCursor.ValueAtXAxis > SecondLineSeriesCursor.ValueAtXAxis - 1)
|
||
{
|
||
DraggedCursor.ValueAtXAxis = SecondLineSeriesCursor.ValueAtXAxis - 1;
|
||
}
|
||
}
|
||
else if (DraggedCursor == SecondLineSeriesCursor)
|
||
{
|
||
if (DraggedCursor.ValueAtXAxis < FirstLineSeriesCursor.ValueAtXAxis + 1)
|
||
{
|
||
DraggedCursor.ValueAtXAxis = FirstLineSeriesCursor.ValueAtXAxis + 1;
|
||
}
|
||
}
|
||
|
||
|
||
//设置注释的位置
|
||
//cursorValueDisplay.TargetAxisValues.X = cursor.ValueAtXAxis;
|
||
//cursorValueDisplay.TargetAxisValues.Y = y;
|
||
CursorValueDisplay.TargetAxisValues.X = 0;
|
||
CursorValueDisplay.TargetAxisValues.Y = 0;
|
||
|
||
//Y轴的值
|
||
double seriesYValue = 0;
|
||
|
||
StringBuilder Strb = new StringBuilder();
|
||
|
||
string channelStringFormat = "{0}: {1}";
|
||
//算法的选择
|
||
bool accurateValue = false;
|
||
string value = "";
|
||
|
||
SecondCursorDatetime = ChartAxisX!.AxisValueToDateTime(SecondLineSeriesCursor.ValueAtXAxis);
|
||
|
||
foreach (ChartRtSeries chartRtSeries in ListChartRtSeries)
|
||
{
|
||
//show series titles and cursor values in them, on the right side of the chart,
|
||
//if cursor values are not shown next to the cursor in an annotation
|
||
//chartRtSeries.ChartPointLineSeries!.Title.Visible = !showNextToCursor;
|
||
//pointLineSeries.Title.Visible = true;
|
||
bool resolved = false;
|
||
value = "";
|
||
|
||
if (accurateValue)
|
||
resolved = SolveValueAccurate(chartRtSeries.ChartPointLineSeries!, SecondLineSeriesCursor.ValueAtXAxis, out seriesYValue);
|
||
else
|
||
resolved = SolveValueCoarse(chartRtSeries.ChartPointLineSeries!, SecondLineSeriesCursor.ValueAtXAxis, out seriesYValue);
|
||
|
||
//已经计算出值
|
||
chartRtSeries.RightCursorValue = seriesYValue;
|
||
|
||
//双游标需要统计数据
|
||
if (IsDoubleCurson)
|
||
{
|
||
if (IsRealTimeChart)
|
||
{
|
||
var StatisValue = CalcStatis(chartRtSeries.Name);
|
||
chartRtSeries.MaxValue = StatisValue.Max;
|
||
chartRtSeries.MinValue = StatisValue.Min;
|
||
chartRtSeries.AveValue = StatisValue.Ave;
|
||
}
|
||
else
|
||
{
|
||
var StatisValue = CalcHistoryStatis(chartRtSeries.Name);
|
||
chartRtSeries.MaxValue = StatisValue.Max;
|
||
chartRtSeries.MinValue = StatisValue.Min;
|
||
chartRtSeries.AveValue = StatisValue.Ave;
|
||
}
|
||
}
|
||
|
||
//不需要光标位置处的数据
|
||
//if (resolved)
|
||
//{
|
||
//value = string.Format(channelStringFormat, chartRtSeries.ChartPointLineSeries!.Title.Text, seriesYValue.ToString("0.000"));
|
||
//}
|
||
//else
|
||
//{
|
||
// value = string.Format(channelStringFormat, chartRtSeries.ChartPointLineSeries!.Title.Text, "---");
|
||
//}
|
||
|
||
//Strb.AppendLine(value);
|
||
|
||
}
|
||
|
||
//sb.AppendLine("");
|
||
//sb.AppendLine("时间: " + LgChart.ViewXY.XAxes[0].TimeString(cursor.ValueAtXAxis, "HH:mm:ss.ffff"));
|
||
|
||
////Set text
|
||
//CursorValueDisplay.Text = Strb.ToString();
|
||
CursorValueDisplay.Text = $"右光标:{SecondCursorDatetime.ToString("MM-dd HH:mm:ss")}";
|
||
////Show the label only if it selected to be shown 是否显示
|
||
CursorValueDisplay.Visible = true;
|
||
|
||
//Allow chart rendering
|
||
LgChart.EndUpdate();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 计算数据
|
||
/// </summary>
|
||
/// <returns></returns>
|
||
private (double Max, double Min, double Ave) CalcStatis(string Name)
|
||
{
|
||
if (FirstCursorDatetime < SecondCursorDatetime)
|
||
{
|
||
var datas = DatRecordService.CacheRecordData
|
||
.Where(a => a.CreateTime >= FirstCursorDatetime && a.CreateTime <= SecondCursorDatetime)
|
||
.Where(a => a.Data != null && a.Data.ContainsKey(Name))
|
||
.Select(a => Convert.ToDouble(a.Data[Name]))
|
||
.ToList();
|
||
|
||
if (!datas.Any())
|
||
{
|
||
return (0, 0, 0); // 返回默认值
|
||
}
|
||
return (datas.Max(), datas.Min(), datas.Average());
|
||
}
|
||
return (0, 0, 0); // 返回默认值
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// 计算历史数据
|
||
/// 历史曲线
|
||
/// </summary>
|
||
/// <returns></returns>
|
||
private (double Max, double Min, double Ave) CalcHistoryStatis(string Name)
|
||
{
|
||
if (FirstCursorDatetime < SecondCursorDatetime)
|
||
{
|
||
////第一次计时
|
||
stopwatch.Start(); //启动Stopwatch
|
||
|
||
if (CurHistoryData == null || CurHistoryData.Count == 0)
|
||
{
|
||
return (0, 0, 0); // 返回默认值
|
||
}
|
||
|
||
var TimeRangeData = CurHistoryData
|
||
.Where(a => a.CreateTime >= FirstCursorDatetime && a.CreateTime <= SecondCursorDatetime)
|
||
.ToList();
|
||
|
||
if (!TimeRangeData.Any())
|
||
{
|
||
return (0, 0, 0); // 返回默认值
|
||
}
|
||
|
||
var Data = GetChartPointByName(Name, TimeRangeData);
|
||
|
||
stopwatch.Stop(); //停止Stopwatch
|
||
Console.WriteLine("历史数据统计耗时::{0}--{1}", stopwatch.Elapsed.TotalSeconds.ToString(), CurSelectedGroupTabIndex.ToString());
|
||
stopwatch.Reset();
|
||
|
||
return (Data.Max(a => a.Value), Data.Min(a => a.Value), Data.Average(a => a.Value));
|
||
}
|
||
return (0, 0, 0); // 返回默认值
|
||
}
|
||
|
||
|
||
|
||
/// <summary>
|
||
/// Solve value from series data points array. Accurate method, but slower than SolveValueCoarse
|
||
/// </summary>
|
||
/// <param name="series">Series</param>
|
||
/// <param name="xValue">X value</param>
|
||
/// <param name="yValue">Output Y value</param>
|
||
/// <returns>Success status</returns>
|
||
private bool SolveValueAccurate(PointLineSeries series, double xValue, out double yValue)
|
||
{
|
||
AxisY axisY = LgChart.ViewXY.YAxes[series.AssignYAxisIndex];
|
||
yValue = 0;
|
||
|
||
LineSeriesValueSolveResult result = series.SolveYValueAtXValue(xValue);
|
||
if (result.SolveStatus == LineSeriesSolveStatus.OK)
|
||
{
|
||
//PointLineSeries may have two or more points at same X value. If so, center it between min and max
|
||
yValue = (result.YMax + result.YMin) / 2.0;
|
||
return true;
|
||
}
|
||
else
|
||
{
|
||
return false;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Solve value from screen coordinates. Faster method, but not less accurateValue than SolveValueAccurate
|
||
/// </summary>
|
||
/// <param name="series">Series</param>
|
||
/// <param name="xValue">X value</param>
|
||
/// <param name="yValue">Output Y value</param>
|
||
/// <returns>Success status</returns>
|
||
private bool SolveValueCoarse(PointLineSeries series, double xValue, out double yValue)
|
||
{
|
||
AxisY axisY = LgChart.ViewXY.YAxes[series.AssignYAxisIndex];
|
||
float coordX = LgChart.ViewXY.XAxes[0].ValueToCoord(xValue);
|
||
float coordY;
|
||
yValue = 0;
|
||
|
||
LineSeriesCoordinateSolveResult result = series.SolveYCoordAtXCoord(coordX);
|
||
if (result.SolveStatus == LineSeriesSolveStatus.OK)
|
||
{
|
||
coordY = (result.CoordBottom + result.CoordTop) / 2f;
|
||
if (axisY.CoordToValue((int)Math.Round(coordY), out yValue) == false)
|
||
{
|
||
return false;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
return false;
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// 增加Y轴
|
||
/// </summary>
|
||
/// <param name="Name"></param>
|
||
/// <param name="MaxVal"></param>
|
||
/// <param name="MinVal"></param>
|
||
private void AddYAxis(string Name, double MinVal, double MaxVal)
|
||
{
|
||
LgChart.BeginUpdate();
|
||
|
||
var CreateAxisY = new AxisY();
|
||
CreateAxisY.Title.Text = Name;
|
||
CreateAxisY.Title.AllowDragging = false;
|
||
CreateAxisY.SetRange(MinVal, MaxVal);
|
||
CreateAxisY.MajorGrid.Visible = false;
|
||
//取消滚轮缩放
|
||
CreateAxisY.ZoomingEnabled = false;
|
||
LgChart.ViewXY.YAxes.Add(CreateAxisY);
|
||
|
||
//Configure and add series to the chart
|
||
PointLineSeries CreateSeries = new PointLineSeries(LgChart.ViewXY, LgChart.ViewXY.XAxes[0], CreateAxisY);
|
||
CreateSeries.Title.Text = Name;
|
||
CreateSeries.LineStyle.Color = ChartColorInfo.ListColor[LgChart.ViewXY.YAxes.Count + 1];
|
||
CreateSeries.AllowUserInteraction = false;
|
||
LgChart.ViewXY.PointLineSeries.Add(CreateSeries);
|
||
|
||
LgChart.EndUpdate();
|
||
ChartSeriesCount++;
|
||
}
|
||
|
||
private void DeleteYAxis(string TitleName)
|
||
{
|
||
LgChart.BeginUpdate();
|
||
|
||
for (int i = 0; i < LgChart.ViewXY.YAxes.Count; i++)
|
||
{
|
||
if (LgChart.ViewXY.YAxes[i].Title.Text == TitleName)
|
||
{
|
||
LgChart.ViewXY.YAxes.RemoveAt(i);
|
||
break;
|
||
}
|
||
}
|
||
|
||
LgChart.EndUpdate();
|
||
if (ChartSeriesCount <= 0)
|
||
{
|
||
ChartSeriesCount = 0;
|
||
}
|
||
else
|
||
{
|
||
ChartSeriesCount--;
|
||
}
|
||
|
||
}
|
||
|
||
/// <summary>
|
||
/// 删除系列
|
||
/// </summary>
|
||
public void DeleteSeries(string SeriesName)
|
||
{
|
||
LgChart.BeginUpdate();
|
||
|
||
//LgChart.ViewXY.PointLineSeries.Remove(ChartPointLineSeries);
|
||
|
||
for (int i = 0; i < LgChart.ViewXY.PointLineSeries.Count; i++)
|
||
{
|
||
if (LgChart.ViewXY.PointLineSeries[i].Title.Text == SeriesName)
|
||
{
|
||
LgChart.ViewXY.PointLineSeries.RemoveAt(i);
|
||
break;
|
||
}
|
||
}
|
||
|
||
LgChart.EndUpdate();
|
||
|
||
ListChartRtSeries.Remove(ListChartRtSeries.FindFirst(a => a.Name == SeriesName));
|
||
}
|
||
|
||
/// <summary>
|
||
/// Chart设置事件
|
||
/// </summary>
|
||
/// <param name="obj"></param>
|
||
/// <exception cref="NotImplementedException"></exception>
|
||
private void ChartSetEventCall(ChartSetMsg par)
|
||
{
|
||
if (par.Machine != CurSelectedMachine)
|
||
{
|
||
return;
|
||
}
|
||
|
||
|
||
////当前是否是给自己的指令的信息
|
||
//if (par.GroupTabIndex == CurSelectedGroupTabIndex)
|
||
//{
|
||
//chart 的配置操作
|
||
switch (par.ChartSetInfo)
|
||
{
|
||
case "单游标":
|
||
SecondLineSeriesCursor.Visible = false;
|
||
IsDoubleCurson = false;
|
||
if (IsDoubleCurson)//双光标
|
||
{
|
||
FirstLineSeriesCursor.ValueAtXAxis = ChartAxisX!.DateTimeToAxisValue(returnMidTime(ChartAxisX.MinimumDateTime, ChartAxisX.MaximumDateTime));
|
||
SecondLineSeriesCursor.ValueAtXAxis = ChartAxisX!.DateTimeToAxisValue(returnSecondMidTime(ChartAxisX.MinimumDateTime, ChartAxisX.MaximumDateTime));
|
||
|
||
}
|
||
else//单光标
|
||
{
|
||
FirstLineSeriesCursor.ValueAtXAxis = ChartAxisX!.DateTimeToAxisValue(returnMidTime(ChartAxisX.MinimumDateTime, ChartAxisX.MaximumDateTime));
|
||
//把右侧的游标放的远一点,不然会挡住左侧游标
|
||
//SecondLineSeriesCursor.ValueAtXAxis = ChartAxisX!.DateTimeToAxisValue(returnMidTime(ChartAxisX.MinimumDateTime, ChartAxisX.MaximumDateTime))*1.1;
|
||
}
|
||
break;
|
||
case "双游标":
|
||
SecondLineSeriesCursor.Visible = true;
|
||
IsDoubleCurson = true;
|
||
if (IsDoubleCurson)//双光标
|
||
{
|
||
FirstLineSeriesCursor.ValueAtXAxis = ChartAxisX!.DateTimeToAxisValue(returnMidTime(ChartAxisX.MinimumDateTime, ChartAxisX.MaximumDateTime));
|
||
SecondLineSeriesCursor.ValueAtXAxis = ChartAxisX!.DateTimeToAxisValue(returnSecondMidTime(ChartAxisX.MinimumDateTime, ChartAxisX.MaximumDateTime));
|
||
|
||
}
|
||
else//单光标
|
||
{
|
||
FirstLineSeriesCursor.ValueAtXAxis = ChartAxisX!.DateTimeToAxisValue(returnMidTime(ChartAxisX.MinimumDateTime, ChartAxisX.MaximumDateTime));
|
||
//把右侧的游标放的远一点,不然会挡住左侧游标
|
||
//SecondLineSeriesCursor.ValueAtXAxis = ChartAxisX!.DateTimeToAxisValue(returnMidTime(ChartAxisX.MinimumDateTime, ChartAxisX.MaximumDateTime))*1.1;
|
||
}
|
||
break;
|
||
case "游标置中":
|
||
if (IsDoubleCurson)//双光标
|
||
{
|
||
FirstLineSeriesCursor.ValueAtXAxis = ChartAxisX!.DateTimeToAxisValue(returnMidTime(ChartAxisX.MinimumDateTime, ChartAxisX.MaximumDateTime));
|
||
SecondLineSeriesCursor.ValueAtXAxis = ChartAxisX!.DateTimeToAxisValue(returnSecondMidTime(ChartAxisX.MinimumDateTime, ChartAxisX.MaximumDateTime));
|
||
|
||
}
|
||
else//单光标
|
||
{
|
||
FirstLineSeriesCursor.ValueAtXAxis = ChartAxisX!.DateTimeToAxisValue(returnMidTime(ChartAxisX.MinimumDateTime, ChartAxisX.MaximumDateTime));
|
||
//把右侧的游标放的远一点,不然会挡住左侧游标
|
||
//SecondLineSeriesCursor.ValueAtXAxis = ChartAxisX!.DateTimeToAxisValue(returnMidTime(ChartAxisX.MinimumDateTime, ChartAxisX.MaximumDateTime))*1.1;
|
||
}
|
||
break;
|
||
case "游标放大":
|
||
|
||
break;
|
||
case "保存照片":
|
||
|
||
//只保存当前TabIndex的图片截图
|
||
if (par.GroupTabIndex == CurSelectedGroupTabIndex)
|
||
{
|
||
//临时屏蔽状态,保存会执行两次
|
||
if (ConfigService.ChartSavePageTempState)
|
||
{
|
||
ConfigService.ChartSavePageTempState = false;
|
||
}
|
||
else
|
||
{
|
||
return;
|
||
}
|
||
|
||
var PicPath = GetFilePath();
|
||
if (PicPath != null)
|
||
{
|
||
LgChart.SaveToFile(PicPath);
|
||
}
|
||
}
|
||
|
||
//
|
||
break;
|
||
default: break;
|
||
}
|
||
//}
|
||
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// 设置控件的
|
||
/// 启用的信息
|
||
/// </summary>
|
||
/// <param name="msg"></param>
|
||
/// <exception cref="NotImplementedException"></exception>
|
||
private void ChartSetEnableEventCall(ChartSetEnableMsg par)
|
||
{
|
||
if (par.Machine != CurSelectedMachine)
|
||
{
|
||
return;
|
||
}
|
||
|
||
////当前是否是给自己的指令的信息
|
||
//if (par.GroupTabIndex == CurSelectedGroupTabIndex)
|
||
//{
|
||
//chart 的配置操作
|
||
switch (par.ChartSetInfo)
|
||
{
|
||
case "实时滚动":
|
||
IsScrollEnable = par.Enable;
|
||
break;
|
||
case "隐藏图例":
|
||
IsLegendHide = par.Enable;
|
||
LegendBox.Visible = !par.Enable;
|
||
break;
|
||
default: break;
|
||
}
|
||
//}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 实时曲线更改的动作调用
|
||
/// </summary>
|
||
/// <param name="msg"></param>
|
||
private void ChartRtSeriesActionEventCall(ChartRtSeriesActionMsg msg)
|
||
{
|
||
if (msg.Machine != CurSelectedMachine)
|
||
{
|
||
return;
|
||
}
|
||
|
||
if (IsRealTimeChart)//实时曲线数据
|
||
{
|
||
//当前的系列
|
||
if (msg.GroupTabIndex == CurSelectedGroupTabIndex)
|
||
{
|
||
var ChartSelectedData = FreeSql.Select<ConfigChart>().Where(a => a.Machine == CurSelectedMachine
|
||
&& a.GroupTabIndex == CurSelectedGroupTabIndex).Include(a => a.ConfigChartYAxis).ToList();
|
||
if (ChartSelectedData.Count > 0)
|
||
{
|
||
LoadChartConfig(ChartSelectedData);
|
||
}
|
||
}
|
||
}
|
||
else//历史曲线数据
|
||
{
|
||
var ChartSelectedData = FreeSql.Select<HistoryConfigChart>().Where(a => a.Machine == CurSelectedMachine
|
||
&& a.GroupTabIndex == CurSelectedGroupTabIndex).Include(a => a.ConfigChartYAxis).ToList();
|
||
if (ChartSelectedData.Count > 0)
|
||
{
|
||
LoadHistoryChartConfig(ChartSelectedData);
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 加载曲线配置信息到当前曲线的实例中
|
||
/// </summary>
|
||
public void LoadChartConfig(List<ConfigChart> configChartSelects)
|
||
{
|
||
//从配置入手对比目前的状态,针对配置新增
|
||
foreach (var itemConfig in configChartSelects)
|
||
{
|
||
//判断当前是否已经存在,不存在的话,则新增
|
||
var data = ListChartRtSeries.FindFirst(a => a.Name == itemConfig.Name);
|
||
if (data == null)
|
||
{
|
||
var TagDecimalPoint = TagManager.DicTags.FindFirst(a => a.Key == itemConfig.Name).Value.DecimalPoint;
|
||
|
||
//新增系列曲线数据
|
||
var NewChartRtSeries = new ChartRtSeries(LgChart, ChartColorInfo, ListChartRtSeries, itemConfig, ConfigService, TagDecimalPoint);
|
||
//新增的曲线加载初始的数据 DatRecordService.CacheRecordData.
|
||
NewChartRtSeries.AddPointByDicData(DatRecordService.CacheRecordData, itemConfig.Name);
|
||
ListChartRtSeries.Add(NewChartRtSeries);
|
||
}
|
||
else
|
||
{
|
||
//修改 已经存在当前的曲线信息
|
||
|
||
}
|
||
}
|
||
|
||
////从目前的状态对比配置,针对删除项目
|
||
//foreach (var itemSeries in ListChartRtSeries)
|
||
//{
|
||
// var data = configChartSelects.FindFirst(a => a.Name == itemSeries.Name);
|
||
// if (data == null)
|
||
// {
|
||
// //查找删除的系列的Y轴是否还有其他的配置使用
|
||
// var configChartYAxis = configChartSelects.Find(a => a.ConfigChartYAxis.Name == itemSeries.ChartAxisY.Name);
|
||
// if (configChartYAxis == null)
|
||
// {
|
||
// //Y轴没有使用,则删除
|
||
// itemSeries.DeleteAxisY();
|
||
// }
|
||
|
||
// //未找到,则删除
|
||
// ListChartRtSeries.Remove(itemSeries);
|
||
|
||
// }
|
||
// else
|
||
// {
|
||
// //存在就不需要操作
|
||
// }
|
||
//}
|
||
|
||
|
||
//从目前的状态对比配置,针对删除项目
|
||
for (var index = ListChartRtSeries.Count - 1; index >= 0; index--)
|
||
{
|
||
var data = configChartSelects.FindFirst(a => a.Name == ListChartRtSeries[index].Name);
|
||
if (data == null)
|
||
{
|
||
//查找删除的系列的Y轴是否还有其他的配置使用-先删除Y轴
|
||
var configChartYAxis = configChartSelects.Find(a => a.ConfigChartYAxis.Name == ListChartRtSeries[index].ChartAxisY.Name);
|
||
if (configChartYAxis == null)
|
||
{
|
||
//Y轴没有使用,则删除
|
||
DeleteYAxis(ListChartRtSeries[index].ChartAxisY.Name);
|
||
//ListChartRtSeries[i].DeleteAxisY();
|
||
}
|
||
|
||
//未找到,则删除 曲线实例删除
|
||
DeleteSeries(ListChartRtSeries[index].Name);
|
||
}
|
||
else
|
||
{
|
||
//存在就不需要操作
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 加载曲线配置信息到当前曲线的实例中
|
||
/// </summary>
|
||
public void LoadHistoryChartConfig(List<HistoryConfigChart> configChartSelects)
|
||
{
|
||
//从配置入手对比目前的状态,针对配置新增
|
||
foreach (var itemConfig in configChartSelects)
|
||
{
|
||
//判断当前是否已经存在,不存在的话,则新增
|
||
var data = ListChartRtSeries.FindFirst(a => a.Name == itemConfig.Name);
|
||
if (data == null)
|
||
{
|
||
var TagDecimalPoint = TagManager.DicTags.FindFirst(a => a.Key == itemConfig.Name).Value.DecimalPoint;
|
||
//新增系列曲线数据
|
||
var NewChartRtSeries = new ChartRtSeries(LgChart, ChartColorInfo, ListChartRtSeries, itemConfig, ConfigService, TagDecimalPoint);
|
||
//新增的曲线加载初始的数据 CurHistoryData.
|
||
|
||
//历史数据需要增加使用历史的数据集
|
||
if (CurHistoryData != null && CurHistoryData.Count > 0)
|
||
{
|
||
//数据集更改
|
||
var SeriesData = GetChartPointByName(itemConfig.Name, CurHistoryData);
|
||
//批量增加数据
|
||
NewChartRtSeries.AddRangePoint(SeriesData);
|
||
}
|
||
|
||
ListChartRtSeries.Add(NewChartRtSeries);
|
||
}
|
||
else
|
||
{
|
||
//修改 已经存在当前的曲线信息
|
||
|
||
}
|
||
}
|
||
|
||
////从目前的状态对比配置,针对删除项目
|
||
//foreach (var itemSeries in ListChartRtSeries)
|
||
//{
|
||
// var data = configChartSelects.FindFirst(a => a.Name == itemSeries.Name);
|
||
// if (data == null)
|
||
// {
|
||
// //查找删除的系列的Y轴是否还有其他的配置使用
|
||
// var configChartYAxis = configChartSelects.Find(a => a.ConfigChartYAxis.Name == itemSeries.ChartAxisY.Name);
|
||
// if (configChartYAxis == null)
|
||
// {
|
||
// //Y轴没有使用,则删除
|
||
// itemSeries.DeleteAxisY();
|
||
// }
|
||
|
||
// //未找到,则删除
|
||
// ListChartRtSeries.Remove(itemSeries);
|
||
|
||
// }
|
||
// else
|
||
// {
|
||
// //存在就不需要操作
|
||
// }
|
||
//}
|
||
|
||
|
||
//从目前的状态对比配置,针对删除项目
|
||
for (var index = ListChartRtSeries.Count - 1; index >= 0; index--)
|
||
{
|
||
var data = configChartSelects.FindFirst(a => a.Name == ListChartRtSeries[index].Name);
|
||
if (data == null)
|
||
{
|
||
//查找删除的系列的Y轴是否还有其他的配置使用-先删除Y轴
|
||
var configChartYAxis = configChartSelects.Find(a => a.ConfigChartYAxis.Name == ListChartRtSeries[index].ChartAxisY.Name);
|
||
if (configChartYAxis == null)
|
||
{
|
||
//Y轴没有使用,则删除
|
||
DeleteYAxis(ListChartRtSeries[index].ChartAxisY.Name);
|
||
//ListChartRtSeries[i].DeleteAxisY();
|
||
}
|
||
|
||
//未找到,则删除 曲线实例删除
|
||
DeleteSeries(ListChartRtSeries[index].Name);
|
||
}
|
||
else
|
||
{
|
||
//存在就不需要操作
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// 返回两个时间差的中间时刻
|
||
/// </summary>
|
||
/// <param name="url"></param>
|
||
/// <returns></returns>
|
||
public DateTime returnMidTime(DateTime dateTimeMin, DateTime dateTimeMax)//返回随机时间
|
||
{
|
||
TimeSpan ts = dateTimeMax - dateTimeMin;
|
||
var cur = ts.TotalSeconds / 2;
|
||
return dateTimeMin.AddSeconds(cur);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取区间数据的比值 第二个光标
|
||
/// </summary>
|
||
/// <param name="url"></param>
|
||
/// <returns></returns>
|
||
public DateTime returnSecondMidTime(DateTime dateTimeMin, DateTime dateTimeMax)//返回随机时间
|
||
{
|
||
TimeSpan ts = dateTimeMax - dateTimeMin;
|
||
var cur = (ts.TotalSeconds / 2) + ts.TotalSeconds * 0.15;
|
||
return dateTimeMin.AddSeconds(cur);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取保存文件的路径
|
||
/// </summary>
|
||
/// <returns></returns>
|
||
public string GetFilePath()
|
||
{
|
||
SaveFileDialog saveFileDialog = new SaveFileDialog
|
||
{
|
||
//CheckFileExists = true,
|
||
Filter = "Image Files (*.png;*.jpg;*.bmp)|*.png;*.jpg;*.bmp", // 设置文件类型过滤
|
||
Title = "保存图片文件",
|
||
CheckPathExists = true,
|
||
ValidateNames = true
|
||
};
|
||
bool? result = saveFileDialog.ShowDialog();
|
||
|
||
if (result == true)
|
||
{
|
||
return saveFileDialog.FileName;
|
||
}
|
||
|
||
return null;
|
||
}
|
||
|
||
#region ListView数据操作
|
||
|
||
|
||
#endregion
|
||
|
||
}
|
||
}
|