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.

678 lines
26 KiB
C#

using Arction.Wpf.Charting;
using Arction.Wpf.Charting.Axes;
using Arction.Wpf.Charting.SeriesXY;
using Arction.Wpf.Charting.Views.ViewXY;
using Microsoft.Win32;
using mseedChart.Core;
using mseedChart.MainModule.Models;
using Prism.Commands;
using Prism.Events;
using Prism.Mvvm;
using SharpDX.DirectWrite;
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.ComponentModel.Design.Serialization;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net.Http.Headers;
using System.Reflection;
using System.Security.Cryptography;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Markup;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Threading;
namespace mseedChart.MainModule.ViewModels
{
public class ChartPlotViewModel : BindableBase
{
public ChartPlotViewModel()
{
_dispatcher = Application.Current.Dispatcher;
_wavesModel = new WavesModel();
CreateChart();
(Application.Current.MainWindow as System.Windows.Window).Closing += ApplicationClosingDispose;
string fileName = "2023-03-28T05:14:59.108464";
// fileName = "2023-03-24T04:53:46.199584";
bool multFlies = false;
string eventTimeStr = fileName;
string datePath = eventTimeStr.Substring(0, 4) + eventTimeStr.Substring(5, 2) + eventTimeStr.Substring(8, 2);
string dataFilePath = RegionNames.MseedFilePath + "\\" + datePath + "\\";
string dataFileName = "HA." + eventTimeStr.Substring(0, 4) + eventTimeStr.Substring(5, 2)
+ eventTimeStr.Substring(8, 2) + eventTimeStr.Substring(10, 3)
+ eventTimeStr.Substring(14, 2) + eventTimeStr.Substring(17, 2) + ".01" + RegionNames.DataTypeString;
string jsonStr = ".json";
string mseedStr = ".mseed";
string asciiSavePath = RegionNames.TxtFilePath + "\\" + datePath + "\\";
if (!multFlies)
{
CurrentEventTime = _wavesModel.mseedJsonResolve(dataFilePath + dataFileName + jsonStr);
}
ShowWave(dataFilePath + dataFileName + mseedStr, asciiSavePath + dataFileName + ".txt" , multFlies);
YaxisItems.Add("SHZ");
YaxisItems.Add("SHN");
YaxisItems.Add("SHE");
}
#region 字段
Dispatcher _dispatcher;
public int CurPoints;
int _channelCount = 0;
double _samplingFrequency = 500; // 采样频率 (Hz).
WavesModel _wavesModel;
private int _lChartCount = 1;
public ConcurrentQueue<StationModel> smList;
#endregion
#region 属性
private List<string> _yaxisItems=new List<string>();
public List<string> YaxisItems
{
get { return _yaxisItems; }
set { _yaxisItems = value; }
}
private int _selectIndex=1;
public int SelectIndex
{
get { return _selectIndex; }
set
{
SetProperty(ref _selectIndex, 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 { childContent = value; }
}
private Grid gridChart;
public Grid GridChart
{
get { return gridChart; }
set { gridChart = value; }
}
private StationEventJson _currentEventTime;
public StationEventJson CurrentEventTime
{
get { return _currentEventTime; }
set { _currentEventTime = value; }
}
#endregion
#region 事件
public DelegateCommand<object> AxesYVisibleCommand => new DelegateCommand<object>(AxesYVisible);
public DelegateCommand FileSelectorCommand => new DelegateCommand(FileSelector);
public DelegateCommand<object> OtimeSortCommand => new DelegateCommand<object>(OtimeSort);
public DelegateCommand<object> YasixZENVisibleCommand => new DelegateCommand<object>(YasixZENVisible);
public DelegateCommand IntervalSureCommand => new DelegateCommand(IntervalSure);
private void AxesYVisible(object isCheck)
{
if (_lChartAll != null)
{
bool yAxesVisible = ((bool)isCheck == true);
_lChartAll.BeginUpdate();
AxisY lastYAxis = _lChartAll.ViewXY.YAxes.Last();
_lChartAll.ViewXY.AxisLayout.AutoAdjustMargins = false;
foreach (AxisY yAxis in _lChartAll.ViewXY.YAxes)
{
if (yAxis != lastYAxis)
{
yAxis.Visible = yAxesVisible;
}
else
{
yAxis.Visible = true;
yAxis.LabelsVisible = yAxesVisible;
//yAxis.MajorDivTickStyle.Visible = yAxesVisible;
//yAxis.MinorDivTickStyle.Visible = yAxesVisible;
yAxis.Title.Visible = yAxesVisible;
if (yAxesVisible)
{
yAxis.AxisThickness = 3;
}
else
{
yAxis.AxisThickness = 0;
}
// lastYAxis.MiniScale.Visible = !yAxesVisible;
}
}
_lChartAll.EndUpdate();
}
}
private void FileSelector()
{
OpenFileDialog openFileDialog = new OpenFileDialog
{
RestoreDirectory = true,
Filter = ".mseed|*.mseed|.json|*.json|.txt|*.txt",
};
if (openFileDialog.ShowDialog() == true)
{
string asciiSavePath = openFileDialog.FileName;
asciiSavePath = asciiSavePath.Replace("Mseed","Txt");
asciiSavePath= Path.ChangeExtension(asciiSavePath, ".txt");
ShowWave(openFileDialog.FileName, asciiSavePath, IsMultFiles);
}
}
private void OtimeSort(object isCheck)
{
if (_lChartAll != null)
{
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); ;
}
foreach (var item in lines)
{
var a= item.Tag.ToString().Contains("SHZ");
}
foreach (var item in lines.Reverse())
{
int index = item.AssignYAxisIndex;
for (int i = 0; i < 3; i++)
{
AxisY axisY = v.YAxes[index + i];
v.YAxes.RemoveAt(index + i);
v.YAxes.Insert(i, axisY);
}
}
LChartALL.EndUpdate();
}
}
private void YasixZENVisible(object isCheck)
{
if (_lChartAll != null)
{
_lChartAll.BeginUpdate();
bool yAxesVisible = ((bool)isCheck == true);
ViewXY v = _lChartAll.ViewXY;
List<bool> indexs = new List<bool>();
switch (SelectIndex)
{
case 0:
indexs = v.YAxes.Select(a => a.Title.Text.Contains(".Z")).ToList();
break;
case 1:
indexs = v.YAxes.Select(a => a.Title.Text.Contains(".N")).ToList();
break;
case 2:
indexs = v.YAxes.Select(a => a.Title.Text.Contains(".E")).ToList();
break;
default:
break;
}
for (int i = 0; i < indexs.Count; i++)
{
if (indexs[i] == true)
{
AxisY axisY = v.YAxes[i];
axisY.Visible = !yAxesVisible;
v.SampleDataSeries[i].Visible = !yAxesVisible;
int index = v.LineCollections.FindIndex(a => a.AssignYAxisIndex == i);
if (index != -1)
{
v.LineCollections[index].Visible = !yAxesVisible;
}
}
}
_lChartAll.EndUpdate();
}
}
private void IntervalSure()
{
if (_lChartAll != null)
{
_lChartAll.BeginUpdate();
if (XaisInterval >= 2)
{
_lChartAll.ViewXY.XAxes[0].MajorDivCount = XaisInterval;
}
_lChartAll.EndUpdate();
}
}
#endregion
public List<StationModel> UpdateWavesFromTxt(string fn)
{
string allStr;
List<StationModel> temSM = new List<StationModel>();
using (StreamReader streamReader = new StreamReader(fn))
{
allStr = streamReader.ReadToEnd();
}
if (allStr.Length > 0)
{
string[] strLines = allStr.Trim().Split(new char[] { '\n' });
List<string> strList = strLines.ToList();
int cnt = strList.Count;
string[] snStr = strLines[0].Trim().Split(',');
string tmpName = snStr[0].Substring(14, 3);
CurPoints = int.Parse(snStr[1].Trim().Split(' ')[0]);
StationModel station = new StationModel();
station.Name = tmpName;
int channelFlag = 0;
for (int i = 0; i < strLines.Length; i++)
{
string row = strLines[i].Trim();
if (strLines[i].Contains("HA"))
{
string[] rowStr = strLines[i].Split(',');
string chnStr1 = rowStr[0].Substring(21, 3);
string stationName = rowStr[0].Substring(14, 3);
if (!temSM.Any(name => name.Name == stationName))
{
station = new StationModel();
station.Name = stationName;
station.BeginTime =Convert.ToDateTime(rowStr[3]);
station.PointCount = int.Parse(rowStr[1].Trim().Split(' ')[0]);
station.SamplingFrequency = int.Parse(rowStr[2].Trim().Split(' ')[0]);
temSM.Add(station);
}
if (chnStr1 == "SHZ")
{
channelFlag = 0;//Z
}
else if (chnStr1 == "SHN")
{
channelFlag = 1;//N
}
else
{
channelFlag = 2;//E
}
}
else
{
switch (channelFlag)
{
case 0://Z
station.dz.Add(double.Parse(row));
break;
case 1://N
station.dn.Add(double.Parse(row));
break;
case 2://E
station.de.Add(double.Parse(row));
break;
}
}
}
// temSM.Add(station);
temSM.Reverse();
}
return temSM;
}
public void MSeed2Asc(string filePath, string savePath)
{
using (Process compiler = new Process())
{
compiler.StartInfo.FileName = "mseed2ascii.exe";
compiler.StartInfo.Arguments = filePath + " -o " + savePath;
compiler.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
compiler.StartInfo.CreateNoWindow = true;
compiler.Start();
compiler.WaitForExit();
}
}
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 = "事件波形";
LChartALL.Title.Font = new WpfFont("等线", 20);
//轴属性和布局
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.AllLeft;
LChartALL.ViewXY.AxisLayout.YAxisTitleAutoPlacement = true;
LChartALL.ViewXY.AxisLayout.AutoAdjustMargins = false;
LChartALL.ViewXY.ZoomPanOptions.DevicePrimaryButtonAction = UserInteractiveDeviceButtonAction.None;
LChartALL.ViewXY.ZoomPanOptions.DeviceSecondaryButtonAction = UserInteractiveDeviceButtonAction.None;
LChartALL.ViewXY.ZoomPanOptions.WheelZooming = WheelZooming.Off;
// 反锯齿系数。值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;
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 ShowWave(string dataFilePath, string asciiSavePath, bool isMultFile = false)
{
if (!Directory.Exists(Path.GetDirectoryName(dataFilePath)))
{
Directory.CreateDirectory(Path.GetDirectoryName(dataFilePath));
}
if (!Directory.Exists(Path.GetDirectoryName(asciiSavePath)))
{
Directory.CreateDirectory(Path.GetDirectoryName(asciiSavePath));
}
smList = new ConcurrentQueue<StationModel>();
if (isMultFile)
{
var filePath = new DirectoryInfo(Path.GetDirectoryName(dataFilePath));
FileInfo[] files = filePath.GetFiles();
var mseedFiles = files.Where(i => i.Extension == ".mseed");
var asciiFiles = new DirectoryInfo(Path.GetDirectoryName(asciiSavePath));
var asciifile = asciiFiles.GetFiles();
if (asciifile.Count()==0)
{
// 并行运算
Stopwatch sw = Stopwatch.StartNew();
Parallel.ForEach(mseedFiles, (item) =>
{
MSeed2Asc(item.FullName, Path.Combine(Path.GetDirectoryName(asciiSavePath), Path.GetFileNameWithoutExtension(item.Name)));
});
sw.Stop();
Debug.WriteLine("MSeed2Asc解压时间" +sw.Elapsed.TotalSeconds);
}
// 并行运算
Parallel.ForEach(asciiFiles.GetFiles(), (item) =>
{
var list = UpdateWavesFromTxt(item.FullName);
list.ForEach(i => smList.Enqueue(i));
});
}
else
{
if (!File.Exists(asciiSavePath))
{
MSeed2Asc(dataFilePath, asciiSavePath);
}
var list = UpdateWavesFromTxt(asciiSavePath);
list.ForEach(i => smList.Enqueue(i));
}
_channelCount = smList.Count * 3;
UpdateChart();
UpdateChartData();
}
private void UpdateChart()
{
ViewXY v= LChartALL.ViewXY;
DisposeAllAndClear(v.YAxes);
DisposeAllAndClear(v.SampleDataSeries);
DisposeAllAndClear(v.LineCollections);
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.AutoSpaceLegendBoxes = true;
v.AxisLayout.SegmentsGap = 3;
v.LegendBoxes[0].Shadow.Visible =false;
StationModel stationModel = smList.ElementAt(0);
if (AxisValueType.DateTime == v.XAxes[0].ValueType)
{
//设置X轴的开始时间
v.XAxes[0].AutoFormatLabels = false;
v.XAxes[0].LabelsTimeFormat = "HH:mm:ss.ff";
v.XAxes[0].DateOriginYear = CurrentEventTime.otime.Year;
v.XAxes[0].DateOriginDay = CurrentEventTime.otime.Day;
v.XAxes[0].DateOriginMonth = CurrentEventTime.otime.Month;
DateTime MaxDateTime = CurrentEventTime.otime.AddSeconds(_samplingFrequency == 500 ? 30 : 60);
v.XAxes[0].SetRange(v.XAxes[0].DateTimeToAxisValue(CurrentEventTime.otime), v.XAxes[0].DateTimeToAxisValue(MaxDateTime));
}
double firstSampleTimeStamp = v.XAxes[0].DateTimeToAxisValue(CurrentEventTime.otime);
for (int i = 0; i < smList.Count; i++)
{
for (int k = 0; k < smList.ElementAt(i).Dzne.Count; k++)
{
int seriesIndex = i * 3 + k;
AxisY axisY= v.YAxes[seriesIndex];
axisY.LabelsColor = Colors.Black;
axisY.Title.Shadow.DropColor = Colors.Transparent;
axisY.Title.Shadow.ContrastColor = Colors.Transparent;
axisY.AllowAutoYFit = false;
axisY.Units.Visible = false;
axisY.LabelsAngle = 0;
axisY.LabelsFont.Size = 8;
axisY.Title.Angle = 0;
axisY.MajorGrid.Visible = true;
axisY.MinorGrid.Visible = false;
axisY.MajorGrid.Pattern = LinePattern.Solid;
axisY.AutoDivSpacing = false;
// axisY.AutoDivSeparationPercent = 100;
axisY.Visible = true;
axisY.MajorDivCount = 2;
axisY.MajorDivTickStyle.Visible = true;
axisY.MinorDivTickStyle.Visible = false;
axisY.MajorDivTickStyle.Alignment = 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("Segoe UI", 10, false, false);
axisY.PanningEnabled = false;
axisY.AllowScrolling = false;
axisY.AllowScaling = false;
SampleDataSeries series = new SampleDataSeries(v, v.XAxes[0], axisY);
series.ShowInLegendBox = true;
series.FirstSampleTimeStamp = firstSampleTimeStamp;
series.SamplingFrequency = _samplingFrequency;
series.Title.Text = axisY.Title.Text;
series.SampleFormat = SampleFormat.DoubleFloat;
if (k % 3 == 0)
{
series.LineStyle.Color = System.Windows.Media.Colors.Blue;
}
else if (k % 3 == 1)
{
series.LineStyle.Color = System.Windows.Media.Colors.Red;
}
else if (k % 3 == 2)
{
series.LineStyle.Color = System.Windows.Media.Colors.Green;
}
series.LineStyle.Width =0.5;
series.LineStyle.AntiAliasing = LineAntialias.None;
series.ScrollModePointsKeepLevel = 1;
series.ScrollingStabilizing = true;
series.AllowUserInteraction = false;
v.SampleDataSeries.Add(series);
}
}
}
private void UpdateChartData()
{
double[][] multiChannelData = new double[smList.Count * 3][];
try
{
for (int channelIndex = 0; channelIndex < smList.Count; channelIndex++)
{
multiChannelData[channelIndex * 3] = smList.ElementAt(channelIndex).dz.ToArray();
multiChannelData[channelIndex * 3 + 1] = smList.ElementAt(channelIndex).dn.ToArray();
multiChannelData[channelIndex * 3 + 2] = smList.ElementAt(channelIndex).de.ToArray();
}
// Invoke FeedNewDataToChart.
_dispatcher.Invoke(() =>
{
FeedNewDataToChar(multiChannelData);
});
}
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;
}
}
private void FeedNewDataToChar(double[][] data)
{
LChartALL.BeginUpdate();
_wavesModel.CreateAxisYEventTime(CurrentEventTime, LChartALL.ViewXY, smList.ToList());
for (int channelIndex = 0; channelIndex < _channelCount; channelIndex++)
{
LChartALL.ViewXY.SampleDataSeries[channelIndex].AddSamples(data[channelIndex], true);
}
LChartALL.EndUpdate();
}
}
}