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.

463 lines
17 KiB
C#

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.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
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.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-31T07:43:15.464036";
ShowWave(null,obj:fileName);
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";
_wavesModel.Json2MmEvent(dataFilePath+dataFileName+jsonStr);
}
#region 字段
Dispatcher _dispatcher;
public int CurPoints;
int _channelCount = 0;
double _samplingFrequency = 500; // 采样频率 (Hz).
double _previousX = 0;
WavesModel _wavesModel;
private int _lChartCount = 1;
public List<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 void UpdateWavesFromTxt(string fn)
{
string allStr;
smList = 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 = 1; 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);
if (chnStr1 == "SHZ")
{
smList.Add(station);
station = new StationModel();
station.Name = rowStr[0].Substring(14, 3);
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;
}
}
}
smList.Add(station);
smList.Reverse();
}
}
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.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.Number;
LChartALL.ViewXY.XAxes[0].AutoFormatLabels = false;
// LChartALL.ViewXY.XAxes[0].LabelsNumberFormat = "N0";
// LChartALL.ViewXY.XAxes[0].MajorGrid.Pattern = LinePattern.Solid;
//图表背景颜色
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 filePath, string obj = "2023-03-29T06:41:21.348")
{
string EventTimeStr = obj;
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 mseedStr = ".mseed";
string asciiSavePath = RegionNames.TxtFilePath + "\\" + datePath + "\\" + dataFileName + ".txt";
if (filePath != null) asciiSavePath = filePath;
if (!Directory.Exists(dataFilePath))
{
Directory.CreateDirectory(dataFilePath);
}
if (!Directory.Exists(Path.GetDirectoryName(asciiSavePath)))
{
Directory.CreateDirectory(Path.GetDirectoryName(asciiSavePath));
}
if (!File.Exists(asciiSavePath))
{
MSeed2Asc(dataFilePath + dataFileName + mseedStr, asciiSavePath);
}
UpdateWavesFromTxt(asciiSavePath);
_channelCount = smList.Count * 3;
UpdateChart();
UpdateChartData();
}
private void UpdateChart()
{
DisposeAllAndClear(LChartALL.ViewXY.YAxes);
DisposeAllAndClear(LChartALL.ViewXY.SampleDataSeries);
LChartALL.ViewXY.YAxes.AddRange(_wavesModel.CreateYAxisChart(smList, 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, 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[channelIndex].dz.ToArray();
multiChannelData[channelIndex * 3 + 1] = smList[channelIndex].dn.ToArray();
multiChannelData[channelIndex * 3 + 2] = smList[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();
}
}
}