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 smList; #endregion #region 属性 /// /// 波形控件数量 /// public int LChartCount { get { return _lChartCount; } set { _lChartCount = value; } } private LightningChart _lChartAll; /// /// 所有波形 /// 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 AxesYVisibleCommand => new DelegateCommand(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(); using (StreamReader streamReader = new StreamReader(fn)) { allStr = streamReader.ReadToEnd(); } if (allStr.Length > 0) { string[] strLines = allStr.Trim().Split(new char[] { '\n' }); List 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(); station.dn = new List(); station.de = new List(); 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(List 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(); } } }