You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1170 lines
46 KiB
C#

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

using Arction.Wpf.Charting;
using Arction.Wpf.Charting.Axes;
using Arction.Wpf.Charting.SeriesXY;
using Arction.Wpf.Charting.Views.ViewXY;
using Microsoft.Win32;
using Prism.Commands;
using Prism.Mvvm;
using Prism.Regions;
using ServiceStack;
using StartServerWPF.Assets;
using StartServerWPF.Models;
using StartServerWPF.Modules.MseedChart.Models;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Threading;
using ZhaoXi.Advanced.MyRedis.Service;
namespace StartServerWPF.Modules.MseedChart.ViewModels
{
public class ChartPlotRealDataViewModel : BindableBase, INavigationAware
{
Mseed2asciiApi.LoopCallbackHandler loopCallback;
WorkareaModel workarea;
public ChartPlotRealDataViewModel(SystemConfigModel configModel,WorkareaModel workareaModel)
{
(Application.Current.MainWindow as System.Windows.Window).Closing += ApplicationClosingDispose;
_dispatcher = Application.Current.Dispatcher;
IntervalTime =1000;
loopCallback = new Mseed2asciiApi.LoopCallbackHandler(Mseed2AsciiEvent);
Mseed2asciiApi.MseedDatasCallFun(loopCallback);
GC.KeepAlive(loopCallback);
workarea= workareaModel;
_wavesModel = new WavesModel();
if (workarea.Stations != null)
{
List<string> devicesNums = new List<string>();
foreach (var item in workarea.Stations)
{
if (item.Enable)
{
devicesNums.Add(item.Num);
}
}
devicesNums.Sort();
smList = _wavesModel.ReadWavesFromJson(devicesNums.ToArray());
subNameList = new Dictionary<string, ASCiiData>();
CreateChart();
StartChart();
Sure();
}
}
#region 字段
System.Timers.Timer time=new System.Timers.Timer(1000);
Dispatcher _dispatcher;
public int CurPoints;
int _channelCount = 0;
int _samplingFrequency = 1000; // 采样频率 (Hz).
WavesModel _wavesModel;
private int _lChartCount = 1;
public ConcurrentQueue<StationModel> smList=new ConcurrentQueue<StationModel>();
public List<AxisY> _chartAxisY=new List<AxisY>();
// Dictionary<string, ASCiiData> cacheChartDic=new Dictionary<string, ASCiiData>();
Dictionary<string, ASCiiData> subNameList;
#endregion
#region 属性
private string _title = "数据中心";
public string Title
{
get { return _title; }
set
{
SetProperty(ref _title, value);
}
}
private bool _IsEnableStartRealtime = true;
public bool IsEnableStartRealtime
{
get { return _IsEnableStartRealtime; }
set
{
SetProperty(ref _IsEnableStartRealtime, value);
}
}
private bool _IsEnableStopRealtime = false;
public bool IsEnableStopRealtime
{
get { return _IsEnableStopRealtime; }
set
{
SetProperty(ref _IsEnableStopRealtime, value);
}
}
private bool _isMultFiles;
public bool IsMultFiles
{
get { return _isMultFiles; }
set
{
SetProperty(ref _isMultFiles, value);
}
}
private int _xaisInterval;
public int XaisInterval
{
get { return _xaisInterval; }
set
{
SetProperty(ref _xaisInterval, value);
}
}
/// <summary>
/// 波形控件数量
/// </summary>
public int LChartCount
{
get { return _lChartCount; }
set { _lChartCount = value; }
}
private LightningChart _lChartAll;
/// <summary>
/// 所有波形
/// </summary>
public LightningChart LChartALL
{
get { return _lChartAll; }
set { _lChartAll = value; }
}
private FrameworkElement childContent;
public FrameworkElement ChildContent
{
get { return childContent; }
set { SetProperty(ref childContent, value); }
}
private StationEventJson _currentEventTime;
public StationEventJson CurrentEventTime
{
get { return _currentEventTime; }
set { _currentEventTime = value; }
}
private List<StationAxis> _stationsName;
public List<StationAxis> StationsName
{
get { return _stationsName; }
set {
SetProperty(ref _stationsName, value);
}
}
private string _currentTime;
public string CurrentTime
{
get { return _currentTime; }
set {
SetProperty(ref _currentTime, value);
}
}
private YAxisAutoPlacement _yaxisPlacement;
public YAxisAutoPlacement YaxisPlacement
{
get { return _yaxisPlacement; }
set
{
LChartALL.ViewXY.AxisLayout.YAxisAutoPlacement = value;
int distancetoX =_wavesModel.SetYasixPlacement(LChartALL);
foreach (var item in LChartALL.ViewXY.YAxes)
{
item.Title.DistanceToAxis = distancetoX;
}
SetProperty(ref _yaxisPlacement, value);
}
}
private int _IntervalTime=1000;
public int IntervalTime
{
get { return _IntervalTime; }
set
{
if (value >=10)
{
// time.Interval = value;
}
SetProperty(ref _IntervalTime, value);
}
}
private int _StationsNumberIndex=3;
public int StationsNumberIndex
{
get { return _StationsNumberIndex; }
set
{
SetProperty(ref _StationsNumberIndex, value);
}
}
private bool _SHZChannel=true;
public bool SHZChannel
{
get { return _SHZChannel; }
set
{
SetProperty(ref _SHZChannel, value);
}
}
private bool _SHEChannel = true;
public bool SHEChannel
{
get { return _SHEChannel; }
set
{
SetProperty(ref _SHEChannel, value);
}
}
private bool _SHNChannel = true;
public bool SHNChannel
{
get { return _SHNChannel; }
set
{
SetProperty(ref _SHNChannel, value);
}
}
private double _ChartHeight;
public double ChartHeight
{
get { return _ChartHeight; }
set
{
SetProperty(ref _ChartHeight, value);
}
}
#endregion
#region 事件
public DelegateCommand LoadedCommand => new DelegateCommand(Loaded);
public DelegateCommand UnloadedCommand => new DelegateCommand(UnLoaded);
public DelegateCommand SureCommand => new DelegateCommand(Sure);
public DelegateCommand<object> FileSelectorCommand => new DelegateCommand<object>(FileSelector);
public DelegateCommand<object> OtimeSortCommand => new DelegateCommand<object>(OtimeSort);
public DelegateCommand IntervalSureCommand => new DelegateCommand(IntervalSure);
public DelegateCommand<object> RealTimeDataCommand => new DelegateCommand<object>(RealTimeData);
private void Loaded()
{
}
private void UnLoaded()
{
}
private void Sure()
{
if (_lChartAll != null)
{
_lChartAll.BeginUpdate();
int index = (StationsNumberIndex == 3) ? _chartAxisY.Count : ((StationsNumberIndex + 1) * 3) * 3;
_lChartAll.ViewXY.YAxes.Clear();
for (int i = 0; i < index; i++)
{
_lChartAll.ViewXY.YAxes.Add(_chartAxisY[i]);
_lChartAll.ViewXY.SampleDataSeries[i].AssignYAxisIndex = i;
}
YasixZENVisible(".Z", SHZChannel);
YasixZENVisible(".E", SHEChannel);
YasixZENVisible(".N", SHNChannel);
_lChartAll.EndUpdate();
//if (index * 30 < 800)
//{
// ChartHeight = 800;
//}
//else
//{
// ChartHeight = index * 50;
//}
}
}
private void FileSelector(object obj)
{
IsMultFiles = Convert.ToBoolean(obj);
OpenFileDialog openFileDialog = new OpenFileDialog
{
RestoreDirectory = true,
Filter = ".mseed|*.mseed|.json|*.json|.txt|*.txt",
};
if (openFileDialog.ShowDialog() == true)
{
string asciiSavePath = openFileDialog.FileName.Replace("Mseed", "Txt");
asciiSavePath = Path.ChangeExtension(asciiSavePath, ".txt");
string JsonPath = Path.ChangeExtension(openFileDialog.FileName, "Json");
Stopwatch st = new Stopwatch();
st.Start();
//读取.json文件
CurrentEventTime = _wavesModel.ReadChartJsonFile(JsonPath);
//读取.mseed文件
smList = _wavesModel.ReadMseedFile(openFileDialog.FileName, asciiSavePath, IsMultFiles);
_channelCount = smList.Count * 3;
CurrentTime = smList.First().BeginTime.ToShortDateString();
StationsName = smList.Select(a => new StationAxis{Name= a.Name,IsChecked=true,SelectCommand =new DelegateCommand<object>(StationsNameVisible)}).ToList();
StartChart();
st.Stop();
Debug.WriteLine("统计时间StartChart************{0}", st.Elapsed);
FeedDatasToChart();
if (CurrentEventTime != null)
{
_wavesModel.CreateAxisYEventTime(CurrentEventTime, LChartALL.ViewXY, smList.ToList());
}
}
}
private void OtimeSort(object isCheck)
{
if (_lChartAll != null&& (_chartAxisY.Count!=0))
{
LChartALL.BeginUpdate();
bool yAxesVisible = ((bool)isCheck == true);
ViewXY v = _lChartAll.ViewXY;
IOrderedEnumerable<LineCollection> lines;
if (yAxesVisible)
{
lines = v.LineCollections.Where(a => a.Tag != null && a.Tag.ToString().Contains("SHZ")).OrderBy(a => a.Lines[0].AX);
}
else
{
lines = v.LineCollections.Where(a => a.Tag != null && a.Tag.ToString().Contains("SHZ")).OrderByDescending(b => b.Lines[0].AX); ;
}
int number = v.YAxes.Count / (_chartAxisY.Count / 3);
foreach (var item in lines.Reverse())
{
int index = item.AssignYAxisIndex;
for (int i = 0; i < number; i++)
{
if (index == -1) continue; //隐藏轴不需要处理
AxisY axisY = v.YAxes[index + i];
v.YAxes.RemoveAt(index + i);
v.YAxes.Insert(i, axisY);
}
}
LChartALL.EndUpdate();
}
}
/// <summary>
/// Y轴的显示和隐藏
/// </summary>
/// <param name="content">SHZ,SHN,SHE</param>
/// <param name="isVisible">true 隐藏轴false显示轴</param>
private void YasixZENVisible(string content, bool isVisible)
{
ViewXY v = _lChartAll.ViewXY;
List<AxisY> currentY= new List<AxisY>();
currentY.AddRange( v.YAxes.Where(y => y.Title.Text.Contains(content)));
foreach (var item in currentY)
{
if (!isVisible)
{
v.YAxes.Remove(item);
}
else
{
var yAxis = v.YAxes.Where(vy => vy.Title.Text == item.Title.Text).FirstOrDefault();
if (yAxis == null)
{
//没有查到重新添加
string str = item.Title.Text.Replace(content, "");
int yIndex = 0;
if (content == ".Z")
{
yIndex = v.YAxes.FindIndex(y => y.Title.Text.Contains(str));
}
else if (content == ".E")
{
yIndex = v.YAxes.FindLastIndex(y => y.Title.Text.Contains(str));
if (yIndex != -1) yIndex += 1;
}
else if (content == ".N")
{
yIndex = v.YAxes.FindIndex(y => y.Title.Text.Contains(str));
if (yIndex != -1)
{
if (v.YAxes[yIndex].Title.Text.Contains(".Z"))
{
yIndex = yIndex + 1;
}
}
}
//如果没有查到,直接添加到前面,如果为容器最大索引,只能添加到后面
if (yIndex == -1 || (yIndex == v.YAxes.Count))
{
yIndex = v.YAxes.Count;
v.YAxes.Add(item);
}
else
{
v.YAxes.Insert(yIndex, item);
}
int sampleIndex = v.SampleDataSeries.FindIndex(y => y.Title.Text == item.Title.Text);
v.SampleDataSeries[sampleIndex].AssignYAxisIndex = yIndex;
}
}
}
}
private void IntervalSure()
{
if (_lChartAll != null)
{
_lChartAll.BeginUpdate();
if (XaisInterval >= 2)
{
_lChartAll.ViewXY.XAxes[0].MajorDivCount = XaisInterval;
}
_lChartAll.EndUpdate();
}
}
private void StationsNameVisible(object obj)
{
var station = obj as StationAxis;
if (_lChartAll != null)
{
_lChartAll.BeginUpdate();
bool yAxesVisible = (station.IsChecked == false);
ViewXY v = _lChartAll.ViewXY;
var yAxisList= _chartAxisY.Where(y => y.Title.Text.Contains(station.Name));
foreach (var item in yAxisList)
{
if (yAxesVisible)
{
v.YAxes.Remove(item);
}
else
{
v.YAxes.Add(item);
//SampleDataSeries查找数据对应的Y轴索引, 重新分配到对应的轴
int sampleIndex = v.SampleDataSeries.FindIndex(s => s.Title.Text == item.Title.Text);
v.SampleDataSeries[sampleIndex].AssignYAxisIndex = v.YAxes.Count()-1;
//LineCollections查找数据对应的Y轴索引, 重新分配到对应的轴
int lineIndex = v.LineCollections.FindIndex(s => s.Title.Text.Contains(item.Title.Text));
if (lineIndex != -1)
{
v.LineCollections[lineIndex].AssignYAxisIndex = v.YAxes.Count() - 1;
}
}
}
_lChartAll.EndUpdate();
}
}
private void RealTimeData(object isCheck)
{
_channelCount = smList.Count * 3;
CurrentTime = smList.First().BeginTime.ToShortDateString();
StationsName = smList.Select(a => new StationAxis { Name = a.Name, IsChecked = true, SelectCommand = new DelegateCommand<object>(StationsNameVisible) }).ToList();
if (_lChartAll != null)
{
bool isStartRealData = (Convert.ToBoolean(isCheck) == true);
if (smList.Count == 0)
{
return;
}
_lChartAll.BeginUpdate();
if (isStartRealData)
{
IsEnableStartRealtime = false;
IsEnableStopRealtime = true;
_data = new double[smList.Count * 3][];
beginTime = DateTime.Now.AddSeconds(-0.5);
currentTime = beginTime;
if (AxisValueType.DateTime == LChartALL.ViewXY.XAxes[0].ValueType)
{
DateTime MaxDateTime = currentTime.AddSeconds(_samplingFrequency == 1000 ? 30 : 60);
LChartALL.ViewXY.XAxes[0].SetRange(LChartALL.ViewXY.XAxes[0].DateTimeToAxisValue(currentTime), LChartALL.ViewXY.XAxes[0].DateTimeToAxisValue(MaxDateTime));
}
LChartALL.ViewXY.DropOldSeriesData = true;
//Set real-time monitoring automatic old data destruction
_pointsAppended = LChartALL.ViewXY.XAxes[0].Minimum;
_lChartAll.ViewXY.XAxes[0].ScrollPosition = _pointsAppended;
time.Elapsed -= CompositionTarget_Rendering;
time.Elapsed += CompositionTarget_Rendering;
LChartALL.ViewXY.XAxes[0].ScrollMode = XAxisScrollMode.Scrolling;
time.Start();
foreach (var subName in subNameList)
{
//清空缓存数据;
while (subName.Value.DataOrders.TryDequeue(out ChartSamples result))
{
}
}
Task.Run(() =>
{
using (RedisListService service = new RedisListService())
{
// Debug.WriteLine($"注册,:{subName.Key},时间:{DateTime.Now}");
service.Subscribe((c, message, iRedisSubscription) =>
{
// Debug.WriteLine($"Name:{subName.Key}, length:{message.Length}");
string mes = System.Text.Encoding.Default.GetString(message);
byte[] data = message.Skip(15).ToArray();
string mes1 = System.Text.Encoding.Default.GetString(data);
// if (message.Length == 7 && System.Text.Encoding.Default.GetString(message) == "shutoff")
if(!IsEnableStopRealtime)
{
iRedisSubscription.UnSubscribeFromChannels(subNameList.Keys.ToArray());
}
Mseed2asciiApi.bufferMseedData(message.Length, message);
}, subNameList.Keys.ToArray());
}
});
}
else
{
IsEnableStartRealtime = true;
IsEnableStopRealtime = false;
time.Stop();
time.Elapsed -= CompositionTarget_Rendering;
LChartALL.ViewXY.XAxes[0].ScrollMode = XAxisScrollMode.None;
}
_lChartAll.EndUpdate();
}
}
private void Mseed2AsciiEvent(AsciiDataStruct asciiData)
{
DateTime startTime = Convert.ToDateTime(asciiData.starttime).AddHours(8);
DateTime endTime = Convert.ToDateTime(asciiData.endtime).AddHours(8);
byte[] bytes = new byte[asciiData.numsamples * asciiData.samplesize];
// IntPtr bufferHandler = Marshal.AllocHGlobal((int)asciiData.datasize);
Marshal.Copy(asciiData.datasamples, bytes, 0, bytes.Length);
List<double> lines = new List<double>();
string[] sid = asciiData.sid.Substring(5).Split('_');
string name = $"{sid[0]}.{sid[1]}.{sid[2]}.{sid[3]}{sid[4]}{sid[5]}";
var ts = DateTime.Now.Subtract(startTime);
//System.Diagnostics.Debug.WriteLine($"台站号:{name},总数:{asciiData.samprate},{asciiData.datasize},{asciiData.samplecnt}, {asciiData.numsamples},当前时间:{DateTime.Now.ToString("o")},接时间:{startTime.ToString("o")}********时间差:{ts.TotalSeconds}秒");
if ( ts.TotalSeconds > 10)
{
return;
}
if (asciiData.sampletype == 'i')
{
for (int index = 0; index < bytes.Length; index += 4)
{
var a = BitConverter.ToInt32(bytes, index);
lines.Add(a);
}
}
else if (asciiData.sampletype == 'f')
{
for (int index = 0; index < bytes.Length; index += 4)
{
var b = BitConverter.ToSingle(bytes, index);
lines.Add(b);
}
}
else if (asciiData.sampletype == 'd')
{
for (int index = 0; index < bytes.Length; index += 8)
{
var b = BitConverter.ToDouble(bytes, index);
lines.Add(b);
}
}
subNameList[name].AddChartSam(asciiData.numsamples, new ChartSamples
{
StartTime = startTime,
DataArray = lines.ToArray()
});
while (true)
{
var flag = subNameList[name].DataOrders.TryPeek(out ChartSamples dataOrder);
if (flag && DateTime.Now.Subtract(dataOrder.StartTime).TotalSeconds > 35)
{
//删除过期数据
subNameList[name].DataOrders.TryDequeue(out ChartSamples chart);
}
else
{
break;
}
}
}
#endregion
Grid GridChart;
private void CreateChart()
{
if (LChartALL != null)
{
LChartALL = null;
}
LChartALL = new LightningChart();
LChartALL.Title.Align = ChartTitleAlignment.TopCenter;
LChartALL.ChartRenderOptions.DeviceType = RendererDeviceType.AutoPreferD11;
LChartALL.ChartRenderOptions.LineAAType2D = LineAntiAliasingType.QLAA;
LChartALL.Title.Text = "Realtime Waves";
LChartALL.Title.Color = Colors.Black;
LChartALL.Title.Font = new WpfFont("Arial", 20);
LChartALL.Title.Shadow.Style = 0;
//轴属性和布局
LChartALL.ViewXY.AxisLayout.YAxesLayout = YAxesLayout.Stacked;
LChartALL.ViewXY.AxisLayout.SegmentsGap = 0;
LChartALL.ViewXY.ZoomPanOptions.PanDirection = PanDirection.Horizontal;
LChartALL.ViewXY.ZoomPanOptions.WheelZooming = WheelZooming.Horizontal;
LChartALL.ViewXY.AxisLayout.YAxisAutoPlacement = YAxisAutoPlacement.AllRight;
LChartALL.ViewXY.AxisLayout.YAxisTitleAutoPlacement = false;
LChartALL.ViewXY.AxisLayout.AutoAdjustMargins = false;
LChartALL.ViewXY.ZoomPanOptions.DevicePrimaryButtonAction = UserInteractiveDeviceButtonAction.None;
LChartALL.ViewXY.ZoomPanOptions.DeviceSecondaryButtonAction = UserInteractiveDeviceButtonAction.None;
LChartALL.ViewXY.ZoomPanOptions.WheelZooming = WheelZooming.Off;
LChartALL.Options.AllowInternalCursorChange = false;//来禁用掉全部图表的鼠标交互
// LChartALL.Options.ShowHints = HintsVisible.Never;
//鼠标选中高亮
LChartALL.Options.AllowUserInteraction = false;
// 反锯齿系数。值0和1都不会应用反锯齿
LChartALL.ChartRenderOptions.AntiAliasLevel = 0;
//X轴设置
LChartALL.ViewXY.XAxes[0].AllowScrolling = false;
LChartALL.ViewXY.XAxes[0].PanningEnabled = false;
LChartALL.ViewXY.XAxes[0].MajorGrid.Pattern = LinePattern.Solid;
LChartALL.ViewXY.XAxes[0].ValueType = AxisValueType.DateTime;
LChartALL.ViewXY.XAxes[0].KeepDivCountOnRangeChange = true;
//LChartALL.ViewXY.XAxes[0].MajorDiv =6;
LChartALL.ViewXY.XAxes[0].LabelsColor = Colors.Black;
LChartALL.ViewXY.XAxes[0].AutoDivSpacing = false;
LChartALL.ViewXY.XAxes[0].MajorDivCount = 5;
LChartALL.ViewXY.XAxes[0].Title.Text = "times";
LChartALL.ViewXY.XAxes[0].Title.Font = new WpfFont("Arial", 14);
LChartALL.ViewXY.XAxes[0].Title.Shadow.Style = 0;
LChartALL.ViewXY.XAxes[0].Title.Color = Colors.Black;
XaisInterval = 5;
//图表背景颜色
LChartALL.ViewXY.GraphBackground.Color = Colors.White;
LChartALL.ViewXY.GraphBackground.GradientColor = Colors.White;
LChartALL.ChartBackground.GradientFill = GradientFill.Solid;
LChartALL.ChartBackground.Color = Color.FromArgb(0, 0, 0, 0);
GridChart = new Grid();
GridChart.ColumnDefinitions.Add(new ColumnDefinition());
GridChart.Name = "chartGrid";
GridChart.Children.Add(LChartALL);
this.ChildContent = GridChart;
}
private void StartChart()
{
DisposeAllAndClear(_chartAxisY);
ViewXY v = LChartALL.ViewXY;
LChartALL.SizeChanged -= LChartALL_SizeChanged;
LChartALL.SizeChanged += LChartALL_SizeChanged;
LChartALL.ViewXY.Zoomed -= ViewXY_Zoomed;
LChartALL.ViewXY.Zoomed += ViewXY_Zoomed;
LChartALL.ViewXY.Panned -= ViewXY_Panned;
LChartALL.ViewXY.Panned += ViewXY_Panned;
DisposeAllAndClear(v.YAxes);
DisposeAllAndClear(v.SampleDataSeries);
DisposeAllAndClear(v.LineCollections);
v.Margins=new Thickness(60, 30, 60, 60);
v.YAxes.AddRange(_wavesModel.CreateYAxisChart(smList.ToList(), LChartALL));
v.LegendBoxes[0].Position = LegendBoxPositionXY.RightCenter;
v.LegendBoxes[0].Offset.SetValues(-10, 180);
v.LegendBoxes[0].Layout = LegendBoxLayout.Vertical;
v.LegendBoxes[0].Visible = false;
v.LegendBoxes[0].Shadow.Color = Colors.Transparent;
v.LegendBoxes[0].BorderColor = Colors.Transparent;
v.AutoSpaceLegendBoxes = true;
v.AxisLayout.SegmentsGap = 3;
v.LegendBoxes[0].Shadow.Visible = false;
StationModel stationModel = smList.First();
var beginTime = DateTime.Now;
if (AxisValueType.DateTime == v.XAxes[0].ValueType)
{
//设置X轴的开始时间
v.XAxes[0].AutoFormatLabels = false;
v.XAxes[0].LabelsTimeFormat = "HH:mm:ss.f";
// v.XAxes[0].DateOriginYear = beginTime.Year;
// v.XAxes[0].DateOriginDay = beginTime.Day;
// v.XAxes[0].DateOriginMonth = beginTime.Month;
DateTime MaxDateTime = beginTime.AddSeconds(_samplingFrequency == 1000? 30 : 60);
v.XAxes[0].SetRange(v.XAxes[0].DateTimeToAxisValue(beginTime), v.XAxes[0].DateTimeToAxisValue(MaxDateTime));
}
double firstSampleTimeStamp = v.XAxes[0].DateTimeToAxisValue(beginTime);
int count = stationModel.Dzne.Count;
int number= smList.Count*3;
bool isAdd = false;
if (subNameList.Count == 0)
{
isAdd = true;
}
for (int i = 0; i < number; i++)
{
int seriesIndex = i;
AxisY axisY = v.YAxes[seriesIndex];
axisY.LabelsColor = Colors.Black;
axisY.Title.Shadow.Style = 0;
axisY.Title.Font = new WpfFont("Courier New", 16);
// axisY.Title.Shadow.ContrastColor = Colors.Transparent;
axisY.Title.AllowDragging = false;
axisY.AllowAutoYFit = false;
axisY.Units.Visible = false;
axisY.LabelsFont = new WpfFont("Courier New", 7);
axisY.Title.Angle = 0;
axisY.MinorGrid.Visible = false;
axisY.AutoDivSpacing = false;
axisY.MajorDivCount = 2;
// axisY.MajorDiv = 1;
axisY.MinorDivTickStyle.Visible = false;
axisY.MajorGrid.Visible = true;
axisY.MajorGrid.Pattern = LinePattern.Solid;
axisY.MajorDivTickStyle.Alignment = Alignment.Far; //seriesIndex % 2 == 0 ? Alignment.Near : Alignment.Far;
// axisY.MajorDivTickStyle.LineLength = 6;
axisY.MajorDivTickStyle.Color = Colors.Black;
axisY.Title.Color = Colors.Black;
axisY.Title.Font = new WpfFont("Courier New", 12);
axisY.PanningEnabled = false;
axisY.AllowScrolling = false;
axisY.AllowScaling = false;
SampleDataSeries series = new SampleDataSeries(v, v.XAxes[0], axisY);
series.ShowInLegendBox = false;
series.FirstSampleTimeStamp = firstSampleTimeStamp;
series.SamplingFrequency = _samplingFrequency;
series.Title.Text = axisY.Title.Text;
series.SampleFormat = SampleFormat.DoubleFloat;
string subName = string.Empty;
string name = axisY.Title.Text.Substring(0,4);
if (seriesIndex % 3 == 0)
{
subName = $"{workarea.StationConfig.Network}.{name}.{workarea.StationConfig.Location}." +
$"{workarea.StationConfig.Channels[0]}";
series.LineStyle.Color = System.Windows.Media.Colors.DeepSkyBlue;
}
else if (seriesIndex % 3 == 1)
{
subName = $"{workarea.StationConfig.Network}.{name}.{workarea.StationConfig.Location}." +
$"{workarea.StationConfig.Channels[1]}";
series.LineStyle.Color = System.Windows.Media.Colors.OrangeRed;
}
else if (seriesIndex % 3 == 2)
{
subName = $"{workarea.StationConfig.Network}.{name}.{workarea.StationConfig.Location}." +
$"{workarea.StationConfig.Channels[2]}";
series.LineStyle.Color = System.Windows.Media.Colors.ForestGreen;
}
if (isAdd)
{
subNameList.Add(subName, new ASCiiData { Index = i, sid = subName });
}
series.LineStyle.Width = 1;
series.ScrollModePointsKeepLevel = 1;
//series.ScrollingStabilizing = true;
v.SampleDataSeries.Add(series);
_chartAxisY.Add(axisY);
}
}
private void ViewXY_Panned(object sender, PannedXYEventArgs e)
{
foreach (var item in LChartALL.ViewXY.LineCollections)
{
double b = LChartALL.ViewXY.XAxes[0].ValueToCoordD(item.Lines[0].AX) - 80;
item.Title.Offset.SetValues((int)b, 3);
}
}
private void ViewXY_Zoomed(object sender, ZoomedXYEventArgs e)
{
foreach (var item in LChartALL.ViewXY.LineCollections)
{
double b = LChartALL.ViewXY.XAxes[0].ValueToCoordD(item.Lines[0].AX) - 80;
item.Title.Offset.SetValues((int)b, 3);
}
}
private void LChartALL_SizeChanged(object sender, SizeChangedEventArgs e)
{
int distancetoX = _wavesModel.SetYasixPlacement(LChartALL);
foreach (var item in LChartALL.ViewXY.YAxes)
{
item.Title.DistanceToAxis = distancetoX;
}
foreach (var item in LChartALL.ViewXY.LineCollections)
{
double b = LChartALL.ViewXY.XAxes[0].ValueToCoordD(item.Lines[0].AX)-80;
item.Title.Offset.SetValues((int)b, 3);
}
}
private void FeedDatasToChart()
{
_data = new double[smList.Count * 3][];
try
{
for (int channelIndex = 0; channelIndex < smList.Count; channelIndex++)
{
_data[channelIndex * 3] = smList.ElementAt(channelIndex).dz.ToArray();
_data[channelIndex * 3 + 1] = smList.ElementAt(channelIndex).dn.ToArray();
_data[channelIndex * 3 + 2] = smList.ElementAt(channelIndex).de.ToArray();
}
// Invoke FeedNewDataToChart.
_dispatcher.Invoke(() =>
{
LChartALL.BeginUpdate();
for (int channelIndex = 0; channelIndex < _channelCount; channelIndex++)
{
LChartALL.ViewXY.SampleDataSeries[channelIndex].AddSamples(_data[channelIndex], true);
}
LChartALL.EndUpdate();
});
}
catch (Exception ex)
{
throw ex;
}
}
private void ApplicationClosingDispose(object sender, CancelEventArgs e)
{
if (LChartALL != null)
{
LChartALL.Dispose();
LChartALL = null;
}
}
private void DisposeAllAndClear<T>(List<T> list) where T : IDisposable
{
if (list == null)
{
return;
}
while (list.Count > 0)
{
int lastInd = list.Count - 1;
T item = list[lastInd]; // take item ref from list.
list.RemoveAt(lastInd); // remove item first
if (item != null)
{
(item as IDisposable).Dispose(); // then dispose it.
}
}
}
public void Dispose()
{
GridChart.Children.Clear();
if (LChartALL != null)
{
LChartALL.Dispose();
LChartALL = null;
}
}
#region 实时数据
private void CompositionTarget_Rendering(object sender, System.Timers.ElapsedEventArgs e)
{
try
{
RenderNextFrame();
}
catch (Exception ex)
{
throw ex;
}
//_dispatcher.Invoke(() =>
//{
//测试数据
// FeedDataTest();
//});
}
DateTime currentTime = DateTime.Now;
DateTime beginTime = DateTime.Now;
private void RenderNextFrame()
{
string minName = string.Empty;
if (_lChartAll == null )
{
return;
}
Stopwatch stopwatch = Stopwatch.StartNew();
; foreach (var item in subNameList)
{
List<double> temDou = new List<double>();
var tem = item.Value.DataOrders.Where(d => d.StartTime > currentTime.AddSeconds(-30));
if (tem.Any())
{
item.Value.FirstSampleTime = tem.ElementAt(0).StartTime; //设置数据的开始时间
tem.ToList().ForEach(d => temDou.AddRange(d.DataArray));
var time = (currentTime - tem.Last().StartTime).Duration();
if (time.TotalSeconds > 2 && time.TotalSeconds < 30)
{
//中途未收数据填充均值
temDou.AddRange(Enumerable.Repeat(temDou.Average(), (int)time.TotalMilliseconds));
}
_data[item.Value.Index] = temDou.ToArray();
}
else
{
//没有收到数据的通道填充0
var duration = (DateTime.Now - beginTime).Duration();
item.Value.FirstSampleTime = duration.TotalSeconds > 30 ? currentTime.AddSeconds(-29) : beginTime;
int feed = duration.TotalSeconds > 30 ? 30 * 1000 : (int)duration.TotalMilliseconds;
_data[item.Value.Index] = new double[feed];
}
}
stopwatch.Stop();
double time1 = stopwatch.ElapsedMilliseconds;
stopwatch.Restart();
stopwatch.Stop();
double time2 = stopwatch.ElapsedMilliseconds;
stopwatch.Restart();
_dispatcher.Invoke(() =>
{
FeedData();
});
stopwatch.Stop();
currentTime = currentTime.AddSeconds(1);
double time3 = stopwatch.ElapsedMilliseconds;
Debug.WriteLine("timeFrame:{0},time1:{1}ms,time2:{2}mstime3:{3}ms", currentTime, time1, time2,time3);
}
double _pointsAppended = 0;
double[][] _data;
private void FeedData()
{
if (_lChartAll == null) return;
_lChartAll.BeginUpdate();
foreach (var item in subNameList)
{
int index = item.Value.Index;
_lChartAll.ViewXY.SampleDataSeries[index].Clear();
var d = _lChartAll.ViewXY.XAxes[0].DateTimeToAxisValue(item.Value.FirstSampleTime);
_lChartAll.ViewXY.SampleDataSeries[index].FirstSampleTimeStamp = d;// _lChartAll.ViewXY.XAxes[0].Minimum;// item.Value.FirstSampleTimeStamp;
}
//Append data to series
System.Threading.Tasks.Parallel.For(0, _channelCount, (seriesIndex) =>
{
double[] thisSeriesData = _data[seriesIndex];
int yindex = _lChartAll.ViewXY.SampleDataSeries[seriesIndex].AssignYAxisIndex;
if (yindex >= 0)
{
_lChartAll.ViewXY.YAxes[yindex].SetRange(thisSeriesData.Min()-1, thisSeriesData.Max() + 1);
}
_lChartAll.ViewXY.SampleDataSeries[seriesIndex].AddSamples(thisSeriesData, false);
Debug.WriteLine($"{DateTime.Now}*********** index:{seriesIndex}," +
$" pointCount:{_lChartAll.ViewXY.SampleDataSeries[seriesIndex].PointCount}");
});
_pointsAppended += 1;
//Set X axis real-time scrolling position
double lastX = _pointsAppended * XInterval;
_lChartAll.ViewXY.XAxes[0].ScrollPosition = lastX;
_lChartAll.EndUpdate();
}
//Append data point per round count
private int _appendCountPerRound=30000;
//X axis length
private double _xLen;
//Generate this many rounds of data
private const int PreGenerateDataForRoundCount = 10;
//X data point step
private const double XInterval = 1;
//Data feeding round
private int _iRound = 0;
//Y axis minimum
private const double YMin = 0;
//Y axis maximum
private const double YMax = 100;
private double[][] CreateInputData(int seriesCount, int appendCountPerRound)
{
//Create input data for all series.
double[][] data = new double[seriesCount][];
// System.Threading.Tasks.Parallel.For(0, seriesCount, (seriesIndex) =>
for (int seriesIndex = 0; seriesIndex < seriesCount; seriesIndex++)
{
int dataPointCount = PreGenerateDataForRoundCount * appendCountPerRound;
double[] seriesData = new double[dataPointCount];
float seriesIndexPlus1 = seriesIndex + 1;
Random rand = new Random((int)DateTime.Now.Ticks / (seriesIndex + 1));
double y = 50;
for (int i = 0; i < dataPointCount; i++)
{
y = y - 0.05 + rand.NextDouble() / 10.0;
if (y > YMax)
{
y = YMax;
}
if (y < YMin)
{
y = YMin;
}
seriesData[i] = (float)y;
}
data[seriesIndex] = seriesData;
}//);
return data;
}
private void PrefillChartWithData()
{
/* test
_lChartAll.BeginUpdate();
_data = CreateInputData(smList.Count * 3, _appendCountPerRound);
LChartALL.ViewXY.DropOldSeriesData = true;
_pointsAppended = LChartALL.ViewXY.XAxes[0].Minimum;
time.Elapsed -= CompositionTarget_Rendering;
time.Elapsed += CompositionTarget_Rendering;
LChartALL.ViewXY.XAxes[0].ScrollMode = XAxisScrollMode.Scrolling;
LChartALL.ViewXY.AxisLayout.AutoShrinkSegmentsGap = true;
_lChartAll.EndUpdate();
time.Start();*/
//Set data almost till the end,
//so it will reach end and start scrolling quite soon.
//How many rounds to prefill in the series
int roundsToPrefill = 50;// (int)(0.9 * _xLen) / _appendCountPerRound;
//How many points to prefill in the series
int pointCount = roundsToPrefill * _appendCountPerRound;
System.Threading.Tasks.Parallel.For(0, _channelCount, (seriesIndex) =>
{
double[] thisSeriesData = _data[seriesIndex];
for (int round = 0; round < roundsToPrefill; round++)
{
float[] dataArray = new float[_appendCountPerRound];
Array.Copy(thisSeriesData, (round % PreGenerateDataForRoundCount) * _appendCountPerRound, dataArray, 0, _appendCountPerRound);
_lChartAll.ViewXY.SampleDataBlockSeries[seriesIndex].AddSamples(dataArray, false);
}
});
_pointsAppended += pointCount;
_iRound += roundsToPrefill;
//Set X axis real-time scrolling position
double lastX = _pointsAppended * XInterval;
_lChartAll.ViewXY.XAxes[0].ScrollPosition = lastX;
}
private void FeedDataTest(/*string chartTitleText*/)
{
if (_lChartAll != null)
{
_lChartAll.BeginUpdate();
foreach (var item in _lChartAll.ViewXY.SampleDataSeries)
{
item.Clear();
item.FirstSampleTimeStamp = _lChartAll.ViewXY.XAxes[0].Minimum;
}
//Append data to series
System.Threading.Tasks.Parallel.For(0, _channelCount, (seriesIndex) =>
{
double[] thisSeriesData = _data[seriesIndex];
double[] dataToAppendNow = new double[_appendCountPerRound];
Array.Copy(thisSeriesData, (_iRound % PreGenerateDataForRoundCount) * _appendCountPerRound, dataToAppendNow, 0, _appendCountPerRound);
_lChartAll.ViewXY.YAxes[seriesIndex].SetRange(dataToAppendNow.Min(), dataToAppendNow.Max());
_lChartAll.ViewXY.SampleDataSeries[seriesIndex].AddSamples(dataToAppendNow, false);
System.Diagnostics.Debug.WriteLine("***********index:{0}, pointCount:{1}", seriesIndex,
_lChartAll.ViewXY.SampleDataSeries[seriesIndex].PointCount);
});
_pointsAppended += 1;//;_appendCountPerRound;
//Set X axis real-time scrolling position
double lastX = _pointsAppended * XInterval;
_lChartAll.ViewXY.XAxes[0].ScrollPosition = lastX;
_lChartAll.EndUpdate();
_iRound++;
}
}
private DateTime GetTime()
{
DateTime time ;
var client = new System.Net.Sockets.TcpClient("time.nist.gov", 13);
using (var streamReader = new System.IO.StreamReader(client.GetStream()))
{
var response = streamReader.ReadToEnd();
var utcDateTimeString = response.Substring(7, 17);
time= DateTime.ParseExact(utcDateTimeString, "yy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal);
}
return time;
}
public void OnNavigatedTo(NavigationContext navigationContext)
{
var str= navigationContext.Parameters.GetValue<string>("model");
}
public bool IsNavigationTarget(NavigationContext navigationContext)
{
return true;
}
public void OnNavigatedFrom(NavigationContext navigationContext)
{
}
#endregion
}
}