AnalogSignalPreviewViewModel.cs 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. using Avalonia.Collections;
  2. using Avalonia.Controls;
  3. using OxyPlot;
  4. using OxyPlot.Axes;
  5. using Shaker.Models;
  6. using System;
  7. using System.Collections.Generic;
  8. using System.Linq;
  9. using System.Text;
  10. using System.Threading.Tasks;
  11. using ShakerApp.Tools;
  12. using OxyPlot.Series;
  13. using System.Diagnostics;
  14. using System.Diagnostics.CodeAnalysis;
  15. namespace ShakerApp.ViewModels
  16. {
  17. public class AnalogSignalPreviewViewModel:DisplayViewModelBase<IModel>,IDataPreview
  18. {
  19. public string AttachTitle
  20. {
  21. get => attachTitle;
  22. set
  23. {
  24. if (attachTitle == value) return;
  25. attachTitle = value;
  26. UpdatePlotTitle(SelectedAnalog);
  27. }
  28. }
  29. List<OxyPlot.Series.LineSeries> lineSeries = new List<OxyPlot.Series.LineSeries>();
  30. private object locker = new object();
  31. public AvaloniaList<ViewModels.StatisticsViewModel> Statistics { get; } = new AvaloniaList<StatisticsViewModel>();
  32. private AnalogType selectedAnalog;
  33. private bool canChangedAnalog = true;
  34. public bool StatisticsVisibily { get => statisticsVisibily; set =>SetProperty(ref statisticsVisibily , value); }
  35. public AnalogSignalPreviewViewModel(bool createcontrol = false):base()
  36. {
  37. Content = typeof(Views.AnalogSignalPreviewView);
  38. if(createcontrol)
  39. {
  40. Control = (Control)Activator.CreateInstance(Content)!;
  41. }
  42. PlotModel.Axes.Add(new OxyPlot.Axes.LinearAxis()
  43. {
  44. MaximumPadding = 0,
  45. MinimumPadding = 0,
  46. Title = App.Current?.FindResource("Time") + "",
  47. Unit = "s",
  48. Key = "X",
  49. MajorGridlineStyle = OxyPlot.LineStyle.Solid,
  50. Position = OxyPlot.Axes.AxisPosition.Bottom
  51. });
  52. PlotModel.Axes.Add(new OxyPlot.Axes.LinearAxis()
  53. {
  54. Title = App.Current?.FindResource("Ampt") + "",
  55. Unit = "V",
  56. Key = "Y",
  57. MajorGridlineStyle = OxyPlot.LineStyle.Solid,
  58. Position = OxyPlot.Axes.AxisPosition.Left,
  59. });
  60. UpdatePlotTitle(lasttype);
  61. PlotModel.Legends.Add(new OxyPlot.Legends.Legend()
  62. {
  63. ShowInvisibleSeries = true,
  64. });
  65. PlotController.BindMouseWheel(OxyMouseWheelCommand);
  66. GetEvent(Topic.DATA).Subscrip((_, _) =>
  67. {
  68. if (!UpSignalData) return;
  69. lock(locker)
  70. {
  71. if(SelectedAnalog == AnalogType.Driver)
  72. {
  73. }
  74. var data = ShakerDataViewModel.Instance.GetAnalogData(SelectedAnalog);
  75. PlotModel.InvalidatePlot(false);
  76. for(int i=0;i<data.Count;i++)
  77. {
  78. lineSeries[i].ItemsSource = data[i].Item1;
  79. Statistics[i].UpDateModel(data[i].Item2);
  80. if (ShakerDataViewModel.Instance.AllowTHDChannels.Contains(data[i].Item2.Name))
  81. {
  82. THD = data[i].Item2.THD;
  83. }
  84. }
  85. PlotModel.InvalidatePlot(true);
  86. }
  87. });
  88. GetEvent(Models.Topic.InitSeries).Subscrip((_, _) =>
  89. {
  90. lock(locker)
  91. {
  92. Menu.Clear();
  93. ShakerConfigViewModel.Instance.AnalogSignals
  94. .DistinctBy(x=>x.Value.AnalogType)
  95. .ToList()
  96. .ForEach(x =>
  97. {
  98. Menu.Add(new TimeDomainMenuViewModel()
  99. {
  100. IsChecked = false,
  101. IsEnabled = true,
  102. AnalogType = x.Value.AnalogType,
  103. Unit = x.Value.Unit,
  104. });
  105. });
  106. if (CanChangedAnalog)
  107. {
  108. int index = Menu.ToList().FindIndex(x => x.AnalogType == lasttype);
  109. if (index == -1)
  110. {
  111. SelectedAnalog = Menu.First().AnalogType;
  112. }
  113. else
  114. {
  115. SelectedAnalog = lasttype;
  116. }
  117. }
  118. else
  119. {
  120. SelectedAnalog = lasttype;
  121. }
  122. }
  123. });
  124. GetEvent(ViewModels.ShakerSettingViewModel.LANGUAGECHANGEDEVENT).Subscrip((_, _) =>
  125. {
  126. PlotModel.InvalidatePlot(false);
  127. PlotModel.Axes[0].Title = App.Current?.FindResource("Time") + "";
  128. PlotModel.Axes[1].Title = App.Current?.FindResource("Ampt") + "";
  129. UpdatePlotTitle(SelectedAnalog);
  130. var config = ShakerConfigViewModel.Instance.Model.AnalogSignalConfigs.First(x => x.AnalogType == SelectedAnalog);
  131. for(int i=0;i<PlotModel.Series.Count;i++)
  132. {
  133. PlotModel.Series[i].Title = App.Current?.FindResource(config.Name) + "";
  134. }
  135. });
  136. }
  137. public string THDTitle { get => tHDTitle; set =>SetProperty(ref tHDTitle , value); }
  138. public float THD { get => tHD; set =>SetProperty(ref tHD , value); }
  139. public bool THDVisibily => SelectedAnalog == AnalogType.Acceleration || SelectedAnalog == AnalogType.Displacement;
  140. [AllowNull]
  141. public Control Control { get; }
  142. private AnalogType lasttype = AnalogType.Displacement;
  143. private bool statisticsVisibily = true;
  144. private string attachTitle = string.Empty;
  145. private float tHD = 0;
  146. private string tHDTitle = string.Empty;
  147. private bool tHDEnabled = true;
  148. private void UpdatePlotTitle(AnalogType analogType)
  149. {
  150. PlotModel.Title = string.IsNullOrEmpty(AttachTitle) ? App.Current?.FindResource(analogType.Description()) + "" : $"{App.Current?.FindResource(AttachTitle)}-{App.Current?.FindResource(analogType.Description())}";
  151. }
  152. public AvaloniaList<TimeDomainMenuViewModel> Menu { get; } = new AvaloniaList<TimeDomainMenuViewModel>();
  153. public AnalogSignalPreviewViewModel(Shaker.Models.AnalogType analogType,bool createcontrol = false):this(createcontrol)
  154. {
  155. lasttype = analogType;
  156. }
  157. public AnalogType SelectedAnalog
  158. {
  159. get => selectedAnalog;
  160. set
  161. {
  162. SetProperty(ref selectedAnalog, value);
  163. ChangeAnalogType(value);
  164. OnPropertyChanged(nameof(THDVisibily));
  165. }
  166. }
  167. public bool UpSignalData { get; set; } = true;
  168. private void ChangeAnalogType(AnalogType type)
  169. {
  170. lock (locker)
  171. {
  172. lineSeries.Clear();
  173. PlotModel.Series.Clear();
  174. Statistics.Clear();
  175. for(int i=0;i<Menu.Count;i++)
  176. {
  177. Menu[i].IsChecked = Menu[i].AnalogType == type;
  178. }
  179. var config = ShakerConfigViewModel.Instance.Model.AnalogSignalConfigs.First(x => x.AnalogType == type);
  180. PlotModel.Axes[1].Unit = config.Unit;
  181. var allconfig = ShakerConfigViewModel.Instance.Model.AnalogSignalConfigs.Where(x => x.AnalogType == type).ToList();
  182. for (int i = 0; i < allconfig.Count; i++)
  183. {
  184. LineSeries series = new LineSeries();
  185. series.Title = App.Current?.FindResource(allconfig[i].Name) + "";
  186. if (ShakerDataViewModel.Instance.AllowTHDChannels.Contains(allconfig[i].Name))
  187. {
  188. THDTitle = allconfig[i].Name;
  189. }
  190. series.XAxisKey = "X";
  191. series.YAxisKey = "Y";
  192. series.DataFieldX = nameof(DataPoint.X);
  193. series.DataFieldY = nameof(DataPoint.Y);
  194. Statistics.Add(new StatisticsViewModel(new Models.StatisticsModel()
  195. {
  196. Name = allconfig[i].Name,
  197. }));
  198. lineSeries.Add(series);
  199. }
  200. PlotModel.InvalidatePlot(false);
  201. UpdatePlotTitle(type);
  202. lineSeries.ForEach(x => PlotModel.Series.Add(x));
  203. PlotModel.InvalidatePlot(true);
  204. }
  205. }
  206. public bool CanChangedAnalog
  207. {
  208. get => canChangedAnalog;
  209. set =>SetProperty(ref canChangedAnalog , value);
  210. }
  211. public bool THDEnabled { get => tHDEnabled; set =>SetProperty(ref tHDEnabled , value); }
  212. public OxyPlot.PlotModel PlotModel { get; } = new OxyPlot.PlotModel();
  213. public OxyPlot.PlotController PlotController { get; } = new OxyPlot.PlotController();
  214. public IViewCommand<OxyMouseWheelEventArgs> OxyMouseWheelCommand => new DelegatePlotCommand<OxyMouseWheelEventArgs>(OnOxyMouseWheel);
  215. private void OnOxyMouseWheel(IPlotView view, IController controller, OxyMouseWheelEventArgs args)
  216. {
  217. HandleZoomByWheel(view, args);
  218. if (view.ActualModel is PlotModel plotModel && plotModel.Axes.Count >= 1 && plotModel.Axes[0] is LinearAxis axis)
  219. {
  220. axis.MajorStep = (axis.Maximum - axis.Minimum) / 10;
  221. }
  222. }
  223. private void HandleZoomByWheel(IPlotView view, OxyMouseWheelEventArgs args, double factor = 1)
  224. {
  225. var m = new ZoomStepManipulator(view)
  226. {
  227. AxisPreference = AxisPreference.X,
  228. Step = args.Delta * 0.001 * factor,
  229. FineControl = args.IsControlDown,
  230. };
  231. m.Started(args);
  232. }
  233. }
  234. }