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.

512 lines
20 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.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.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.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-28T04:53:46.199584";
// fileName = "2023-03-24T04:53:46.199584";
bool multFlies = true;
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)
{
_wavesModel.mseedJsonResolve(dataFilePath + dataFileName + jsonStr);
}
ShowWave(dataFilePath + dataFileName + mseedStr, asciiSavePath + dataFileName + ".txt" , multFlies);
}
#region 字段
Dispatcher _dispatcher;
public int CurPoints;
int _channelCount = 0;
double _samplingFrequency = 500; // 采样频率 (Hz).
double _previousX = 0;
WavesModel _wavesModel;
private int _lChartCount = 1;
public ConcurrentQueue<StationModel> smList;
#endregion
#region 属性
/// <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 MmEvent _eventTime;
public MmEvent EventTime
{
get { return _eventTime; }
set { _eventTime = value; }
}
#endregion
#region 事件
public DelegateCommand<object> AxesYVisibleCommand => new DelegateCommand<object>(AxesYVisible);
public DelegateCommand FileSelectorCommand => new DelegateCommand(FileSelector);
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 = ".json|*.json|.mseed|*.mseed|.txt|*.txt",
};
if (openFileDialog.ShowDialog() == true)
{
//ShowWave(openFileDialog.FileName);
}
}
#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;
station.dz = new List<double>();
station.dn = new List<double>();
station.de = new List<double>();
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;
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.Color = Colors.Red;
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;
//X轴设置
LChartALL.ViewXY.XAxes[0].AllowScrolling = false;
LChartALL.ViewXY.XAxes[0].PanningEnabled = false;
LChartALL.ViewXY.XAxes[0].SweepingGap = 0;
LChartALL.ViewXY.XAxes[0].ValueType = AxisValueType.DateTime;
LChartALL.ViewXY.XAxes[0].AutoFormatLabels = false;
// LChartALL.ViewXY.XAxes[0].LabelsNumberFormat = "N0";
// LChartALL.ViewXY.XAxes[0].MajorGrid.Pattern = LinePattern.Solid;
LChartALL.ViewXY.XAxes[0].MinorGrid.Visible = false;
LChartALL.ViewXY.XAxes[0].MajorGrid.Pattern = LinePattern.Solid;
//LChartALL.ViewXY.XAxes[0].MinimumDateTime=DateTime.Now;
LChartALL.ViewXY.XAxes[0].AutoDivSpacing = false;
LChartALL.ViewXY.XAxes[0].MinorDivTickStyle.Visible = true;
LChartALL.ViewXY.XAxes[0].KeepDivCountOnRangeChange = true;
LChartALL.ViewXY.XAxes[0].MajorDivCount = 5;
LChartALL.ViewXY.XAxes[0].LabelsTimeFormat = "HH:mm.ss.ffff";
//图表背景颜色
LChartALL.ViewXY.GraphBackground.Color = Colors.White;
//LChartALL.ViewXY.GraphBackground.GradientFill = GradientFill.Solid;
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 dic = file.GetDirectories();
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, 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()
{
DisposeAllAndClear(LChartALL.ViewXY.YAxes);
DisposeAllAndClear(LChartALL.ViewXY.SampleDataSeries);
LChartALL.ViewXY.YAxes.AddRange(_wavesModel.CreateYAxisChart(smList.ToList(), LChartALL));
int seriesIndex = 0;
foreach (var axisY in LChartALL.ViewXY.YAxes)
{
axisY.LabelsColor = Colors.Black;
// axisY.AxisColor = 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.MajorDiv = 1;
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.Title.HorizontalAlign = seriesIndex % 2 == 0 ? YAxisTitleAlignmentHorizontal.Left : YAxisTitleAlignmentHorizontal.Right;
axisY.PanningEnabled = false;
axisY.AllowScrolling = false;
axisY.AllowScaling = false;
seriesIndex++;
}
LChartALL.ViewXY.LegendBoxes[0].Position = LegendBoxPositionXY.RightCenter;
LChartALL.ViewXY.LegendBoxes[0].Offset.SetValues(-10, 180);
LChartALL.ViewXY.LegendBoxes[0].Layout = LegendBoxLayout.Vertical;
LChartALL.ViewXY.LegendBoxes[0].ShowIcons = false;
LChartALL.ViewXY.AutoSpaceLegendBoxes = true;
LChartALL.ViewXY.AxisLayout.SegmentsGap = 3;
LChartALL.ViewXY.LegendBoxes[0].Shadow.Visible =false;
LChartALL.ViewXY.XAxes[0].Maximum = CurPoints / _samplingFrequency;
LChartALL.ViewXY.XAxes[0].LabelsColor = Colors.Black;
LChartALL.ViewXY.SampleDataSeries.AddRange(
_wavesModel.GetSampleDataSeriesPingPu(smList.ToList(), LChartALL, LChartALL.ViewXY.XAxes[0],
LChartALL.ViewXY.YAxes, _samplingFrequency));
}
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(EventTime, LChartALL.ViewXY);
for (int channelIndex = 0; channelIndex < _channelCount; channelIndex++)
{
LChartALL.ViewXY.SampleDataSeries[channelIndex].AddSamples(data[channelIndex], true);
}
// _previousX = (double)_samplesOutput / _samplingFrequency;
// LChartALL.ViewXY.XAxes[0].ScrollPosition = _previousX;
LChartALL.EndUpdate();
}
}
}