RandomConfigViewModel.cs 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536
  1. using Avalonia.Collections;
  2. using Avalonia.Controls;
  3. using Avalonia.Utilities;
  4. using CommunityToolkit.Mvvm.Input;
  5. using OxyPlot;
  6. using OxyPlot.Series;
  7. using Shaker.Models;
  8. using System;
  9. using System.Collections.Generic;
  10. using System.Linq;
  11. using System.Numerics;
  12. using System.Runtime.CompilerServices;
  13. using System.Runtime.InteropServices;
  14. using System.Text;
  15. using System.Threading.Tasks;
  16. using System.Windows.Input;
  17. namespace ShakerApp.ViewModels
  18. {
  19. internal class RandomConfigViewModel : ViewModelBase<Shaker.Models.RandomConfigModel>
  20. {
  21. private RandomConfigViewModel()
  22. {
  23. Content = typeof(Views.RandomConfigView);
  24. #region 加速度谱曲线
  25. AccelerationModel.Axes.Add(new OxyPlot.Axes.LogarithmicAxis()
  26. {
  27. MaximumPadding = 0,
  28. MinimumPadding = 0,
  29. Title = App.Current?.FindResource(Shaker.Models.ShakerConstant.FrequencyKey) + "",
  30. Unit = "Hz",
  31. MajorGridlineStyle = LineStyle.Solid,
  32. Position = OxyPlot.Axes.AxisPosition.Bottom,
  33. Key = "Freq"
  34. });
  35. AccelerationModel.Axes.Add(new OxyPlot.Axes.LogarithmicAxis()
  36. {
  37. Key = "Ampt",
  38. Title = App.Current?.FindResource(ShakerConstant.AmptAxisTitleKey) + "",
  39. Unit = "g",
  40. MajorGridlineStyle = LineStyle.Solid,
  41. Position = OxyPlot.Axes.AxisPosition.Left,
  42. });
  43. AccelerationModel.Title = App.Current?.FindResource(ShakerConstant.AccelerationSpectrumKey) + "";
  44. for (int i = 0; i < oxyColors.Count; i++)
  45. {
  46. LineSeries line = new LineSeries();
  47. line.Title = App.Current?.FindResource(ShakerConstant.SweepAccelerationSpectrumNames[i]) + "";
  48. line.Color = oxyColors[i];
  49. line.StrokeThickness = 1;
  50. line.DataFieldX = nameof(SweepData.Frequency);
  51. line.DataFieldY = properties[i];
  52. line.LineStyle = lineStyles[i];
  53. line.XAxisKey = "Freq";
  54. line.YAxisKey = "Ampt";
  55. lineSeries.Add(line);
  56. AccelerationModel.Series.Add(line);
  57. }
  58. AccelerationModel.Legends.Add(new OxyPlot.Legends.Legend()
  59. {
  60. ShowInvisibleSeries = true,
  61. });
  62. #endregion
  63. #region 速度
  64. VelocityModel.Axes.Add(new OxyPlot.Axes.LogarithmicAxis()
  65. {
  66. MaximumPadding = 0,
  67. MinimumPadding = 0,
  68. Title = App.Current?.FindResource(Shaker.Models.ShakerConstant.FrequencyKey) + "",
  69. Unit = "Hz",
  70. MajorGridlineStyle = LineStyle.Solid,
  71. Position = OxyPlot.Axes.AxisPosition.Bottom,
  72. Key = "Freq"
  73. });
  74. VelocityModel.Title = App.Current?.FindResource(ShakerConstant.VelocityKey) + "";
  75. VelocityModel.Axes.Add(new OxyPlot.Axes.LogarithmicAxis()
  76. {
  77. Key = "Ampt",
  78. Title = App.Current?.FindResource(ShakerConstant.AmptAxisTitleKey) + "",
  79. Unit = "m/s",
  80. MajorGridlineStyle = LineStyle.Solid,
  81. Position = OxyPlot.Axes.AxisPosition.Left,
  82. });
  83. velocity = new LineSeries();
  84. velocity.Title = App.Current?.FindResource(ShakerConstant.VelocityKey) + "";
  85. velocity.Color = oxyColors[0];
  86. velocity.StrokeThickness = 1;
  87. velocity.DataFieldX = nameof(DataPoint.X);
  88. velocity.DataFieldY = nameof(DataPoint.Y);
  89. velocity.LineStyle = lineStyles[0];
  90. velocity.XAxisKey = "Freq";
  91. velocity.YAxisKey = "Ampt";
  92. VelocityModel.Series.Add(velocity);
  93. #endregion
  94. #region 位移
  95. DisplacementModel.Axes.Add(new OxyPlot.Axes.LogarithmicAxis()
  96. {
  97. MaximumPadding = 0,
  98. MinimumPadding = 0,
  99. Title = App.Current?.FindResource(Shaker.Models.ShakerConstant.FrequencyKey) + "",
  100. Unit = "Hz",
  101. MajorGridlineStyle = LineStyle.Solid,
  102. Position = OxyPlot.Axes.AxisPosition.Bottom,
  103. Key = "Freq"
  104. });
  105. DisplacementModel.Title = App.Current?.FindResource(ShakerConstant.DisplacementKey) + "";
  106. DisplacementModel.Axes.Add(new OxyPlot.Axes.LogarithmicAxis()
  107. {
  108. Key = "Ampt",
  109. Title = App.Current?.FindResource(ShakerConstant.AmptAxisTitleKey) + "",
  110. Unit = "mm",
  111. MajorGridlineStyle = LineStyle.Solid,
  112. Position = OxyPlot.Axes.AxisPosition.Left,
  113. });
  114. displacement = new LineSeries();
  115. displacement.Title = App.Current?.FindResource(ShakerConstant.DisplacementKey) + "";
  116. displacement.Color = oxyColors[0];
  117. displacement.StrokeThickness = 1;
  118. displacement.DataFieldX = nameof(DataPoint.X);
  119. displacement.DataFieldY = nameof(DataPoint.Y);
  120. displacement.LineStyle = lineStyles[0];
  121. displacement.XAxisKey = "Freq";
  122. displacement.YAxisKey = "Ampt";
  123. DisplacementModel.Series.Add(displacement);
  124. #endregion
  125. GetEvent(ShakerSettingViewModel.LANGUAGECHANGEDEVENT).Subscrip((_, _) =>
  126. {
  127. AccelerationModel.InvalidatePlot(false);
  128. AccelerationModel.Axes[0].Title = App.Current?.FindResource(ShakerConstant.FrequencyKey) + "";
  129. AccelerationModel.Axes[1].Title = App.Current?.FindResource(ShakerConstant.AmptAxisTitleKey) + "";
  130. AccelerationModel.Title = App.Current?.FindResource(ShakerConstant.AccelerationSpectrumKey) + "";
  131. for (int i = 0; i < lineSeries.Count; i++)
  132. {
  133. lineSeries[i].Title = App.Current?.FindResource(ShakerConstant.SweepAccelerationSpectrumNames[i]) + "";
  134. }
  135. AccelerationModel.InvalidatePlot(true);
  136. VelocityModel.InvalidatePlot(false);
  137. VelocityModel.Axes[0].Title = App.Current?.FindResource(ShakerConstant.FrequencyKey) + "";
  138. VelocityModel.Axes[1].Title = App.Current?.FindResource(ShakerConstant.AmptAxisTitleKey) + "";
  139. VelocityModel.Title = App.Current?.FindResource(ShakerConstant.VelocityKey) + "";
  140. velocity.Title = App.Current?.FindResource(ShakerConstant.VelocityKey) + "";
  141. VelocityModel.InvalidatePlot(true);
  142. DisplacementModel.InvalidatePlot(false);
  143. DisplacementModel.Axes[0].Title = App.Current?.FindResource(ShakerConstant.FrequencyKey) + "";
  144. DisplacementModel.Axes[1].Title = App.Current?.FindResource(ShakerConstant.AmptAxisTitleKey) + "";
  145. DisplacementModel.Title = App.Current?.FindResource(ShakerConstant.DisplacementKey) + "";
  146. displacement.Title = App.Current?.FindResource(ShakerConstant.DisplacementKey) + "";
  147. DisplacementModel.InvalidatePlot(true);
  148. });
  149. CommunicationViewModel.Intance.LocalCommunication?.GetEvent<RandomConfigModel>()?.Subscrip((sender, args) =>
  150. {
  151. UpDateModel(args.Data);
  152. Refresh();
  153. CommunicationViewModel.Intance.ServiceCommunication?.GetEvent<RandomConfigModel>()?.Publish(this, args.Data);
  154. });
  155. }
  156. static RandomConfigViewModel()
  157. {
  158. }
  159. [PropertyAssociation(nameof(RandomConfigModel.SpectrumItemsCount))]
  160. public uint SpectrumItemsCount => Model.SpectrumItemsCount;
  161. [PropertyAssociation(nameof(RandomConfigModel.HanningWindowCompensationCoefficient))]
  162. public double HanningWindowCompensationCoefficient { get => Model.HanningWindowCompensationCoefficient; set => SetProperty(ref Model.HanningWindowCompensationCoefficient, value); }
  163. [PropertyAssociation(nameof(RandomConfigModel.LinearAverage))]
  164. public uint LinearAverage { get => Model.LinearAverage; set => SetProperty(ref Model.LinearAverage, value); }
  165. [PropertyAssociation(nameof(RandomConfigModel.ExponentialAverage))]
  166. public uint ExponentialAverage { get => Model.ExponentialAverage; set => SetProperty(ref Model.ExponentialAverage, value); }
  167. [PropertyAssociation(nameof(RandomConfigModel.LinearAverage),nameof(RandomConfigModel.ExponentialAverage))]
  168. public uint DOF => (LinearAverage << 1) * ((ExponentialAverage << 1) - 1);
  169. [PropertyAssociation(nameof(RandomConfigModel.MaxFrequency),nameof(SpectrumLines))]
  170. public double FrequencyResolution => (double)MaxFrequency / (double)SpectrumLines;
  171. [PropertyAssociation(nameof(RandomConfigModel.RandomSampleRate))]
  172. public uint RandomSampleRate => Model.RandomSampleRate;
  173. List<OxyPlot.Series.LineSeries> lineSeries = new List<OxyPlot.Series.LineSeries>();
  174. List<DataPoint> velocitydata = new List<DataPoint>();
  175. LineSeries velocity = new LineSeries();
  176. LineSeries displacement = new LineSeries();
  177. List<DataPoint> displacementdata = new List<DataPoint>();
  178. List<OxyColor> oxyColors = new List<OxyColor>() { OxyColors.Green, OxyColors.Red, OxyColors.Red, OxyColors.Yellow, OxyColors.Yellow };
  179. List<LineStyle> lineStyles = new List<LineStyle>() { LineStyle.Solid, LineStyle.Solid, LineStyle.Solid, LineStyle.LongDashDotDot, LineStyle.LongDashDotDot };
  180. List<string> properties = new List<string>() { nameof(SweepData.TargetAcceleration), nameof(SweepData.UpStopAcceleration), nameof(SweepData.DownStopAcceleration), nameof(SweepData.UpWarnAcceleration), nameof(SweepData.DownWarnAcceleration) };
  181. List<SweepData> datas = new List<SweepData>();
  182. private double rmsAcceleration = 0;
  183. private double maxDisplacement;
  184. private double maxVelocity;
  185. private bool canResetRMS = false;
  186. private double resetRMS;
  187. [PropertyAssociation(nameof(RandomConfigModel.MaxFrequency))]
  188. public RandomMaxFrequency MaxFrequency
  189. {
  190. get => Model.MaxFrequency;
  191. set
  192. {
  193. SetProperty(ref Model.MaxFrequency, value);
  194. OnPropertyChanged(nameof(FFTLength));
  195. }
  196. }
  197. public bool CanResetRMS { get => canResetRMS; set =>SetProperty(ref canResetRMS, value); }
  198. public double ResetRMS { get => resetRMS; set =>SetProperty(ref resetRMS , value); }
  199. [PropertyAssociation(nameof(RandomConfigModel.SynthesisType))]
  200. public AccelerationSynthesisType SynthesisType { get => Model.SynthesisType; set => SetProperty(ref Model.SynthesisType, value); }
  201. [PropertyAssociation(nameof(RandomConfigModel.MinFrequency))]
  202. public double MinFrequency { get => Model.MinFrequency; set => SetProperty(ref Model.MinFrequency, value); }
  203. [PropertyAssociation(nameof(RandomConfigModel.SpectrumLines))]
  204. public SpectrumLines SpectrumLines
  205. {
  206. get => Model.SpectrumLines;
  207. set
  208. {
  209. SetProperty(ref Model.SpectrumLines, value);
  210. OnPropertyChanged(nameof(FFTLength));
  211. }
  212. }
  213. [PropertyAssociation(nameof(RandomConfigModel.Sigma))]
  214. public double Sigma { get => Model.Sigma; set => SetProperty(ref Model.Sigma, value); }
  215. [PropertyAssociation(nameof(RandomConfigModel.RandomSampleRate),nameof(RandomConfigModel.MaxFrequency),nameof(RandomConfigModel.SpectrumLines))]
  216. public uint FFTLength => (uint)(Model.RandomSampleRate / (float)MaxFrequency * (uint)SpectrumLines);
  217. [PropertyAssociation(nameof(RandomConfigModel.RandomSampleRate), nameof(RandomConfigModel.MaxFrequency), nameof(RandomConfigModel.SpectrumLines))]
  218. public uint FFTHalfLength => FFTLength >> 1;
  219. public RandomIdentifyViewModel Identify { get; } = new RandomIdentifyViewModel();
  220. public AvaloniaList<IndexValueItemViewModel<RandomSpectrumItemViewModel>> SpectrumItems { get; }= new AvaloniaList<IndexValueItemViewModel<RandomSpectrumItemViewModel>>();
  221. public AvaloniaList<IndexValueItemViewModel<RandomPlanItemViewModel>> PlanItems { get; } = new AvaloniaList<IndexValueItemViewModel<RandomPlanItemViewModel>>();
  222. [PropertyAssociation(nameof(RandomConfigModel.StopLins))]
  223. public uint StopLins { get => Model.StopLins; set => SetProperty(ref Model.StopLins, value); }
  224. [PropertyAssociation(nameof(RandomConfigModel.WarnLines))]
  225. public uint WarnLines { get => Model.WarnLines; set => SetProperty(ref Model.WarnLines, value); }
  226. [PropertyAssociation(nameof(RandomConfigModel.StopRMS))]
  227. public double StopRMS { get => Model.StopRMS; set => SetProperty(ref Model.StopRMS, value); }
  228. public OxyPlot.PlotModel AccelerationModel { get; } = new OxyPlot.PlotModel();
  229. public PlotModel DisplacementModel { get; } = new PlotModel();
  230. public PlotModel VelocityModel { get; } = new PlotModel();
  231. public static RandomConfigViewModel Instance { get; } = new RandomConfigViewModel();
  232. [PropertyAssociation(nameof(RandomConfigModel.Sigma))]
  233. public double MaxAcceleration => RMSAcceleration * Sigma;
  234. public double MaxDisplacement { get => maxDisplacement; set =>SetProperty(ref maxDisplacement , value); }
  235. public double MaxVelocity { get => maxVelocity; set =>SetProperty(ref maxVelocity , value); }
  236. public bool AccelerationOverLimit => MaxAcceleration >= ShakerConfigViewModel.Instance.MaxAcceleration;
  237. public bool DisplacementOverLimit => MaxDisplacement > ShakerConfigViewModel.Instance.MaxDisplacement;
  238. public bool VelocityOverLimit => MaxVelocity > ShakerConfigViewModel.Instance.MaxVelocity;
  239. public double AccelerationLoad => Math.Round(MaxAcceleration / ShakerConfigViewModel.Instance.MaxAcceleration * 100f, 2);
  240. public double DisplacementLoad => Math.Round((double)MaxDisplacement / ShakerConfigViewModel.Instance.MaxDisplacement * 100f, 2);
  241. public double VelocityLoad => Math.Round((double)MaxVelocity / ShakerConfigViewModel.Instance.MaxVelocity * 100f, 2);
  242. public double RMSAcceleration { get => rmsAcceleration; set =>SetProperty(ref rmsAcceleration , value); }
  243. public ICommand AddCommand => new RelayCommand(Add);
  244. private void Add()
  245. {
  246. if (SpectrumItems.Count >= SpectrumItemsCount) return;
  247. SpectrumItems.Add(new IndexValueItemViewModel<RandomSpectrumItemViewModel>(SpectrumItems.Count + 1, new RandomSpectrumItemViewModel()));
  248. }
  249. public ICommand DeleteCommand => new RelayCommand(Delete);
  250. private void Delete()
  251. {
  252. if (SpectrumItems.Count == 0) return;
  253. SpectrumItems.RemoveAt(SpectrumItems.Count - 1);
  254. }
  255. public ICommand ResetRMSCommand=>new RelayCommand(ResetRMSExecute);
  256. private void ResetRMSExecute()
  257. {
  258. if (!CanResetRMS) return;
  259. if (ResetRMS <= 0) return;
  260. for(int i=0;i<SpectrumItems.Count;i++)
  261. {
  262. SpectrumItems[i].Value.Value *= (ResetRMS*ResetRMS)/(RMSAcceleration * RMSAcceleration);
  263. }
  264. CanResetRMS = false;
  265. }
  266. public ICommand AddPlanCommand => new RelayCommand(AddPlan);
  267. private void AddPlan()
  268. {
  269. if (PlanItems.Count >= 10) return;
  270. PlanItems.Add(new IndexValueItemViewModel<RandomPlanItemViewModel>(PlanItems.Count + 1, new RandomPlanItemViewModel()));
  271. }
  272. public ICommand DeletePlanCommand => new RelayCommand(DeletePlan);
  273. private void DeletePlan()
  274. {
  275. if (PlanItems.Count == 0) return;
  276. PlanItems.RemoveAt(PlanItems.Count - 1);
  277. }
  278. public ICommand RefreshPlanCommand => new RelayCommand(RefreshPlan);
  279. private void RefreshPlan()
  280. {
  281. if (PlanItems.Count < 1) return;
  282. }
  283. public ICommand RefreshCommand => new RelayCommand(Refresh);
  284. private unsafe void Refresh()
  285. {
  286. if (SpectrumItems.Count < 3) return;
  287. var items = SpectrumItems.Select(x => x.Value.Model.CloneBase()).DistinctBy(x => x.Frequency).OrderBy(x => x.Frequency).ToList();
  288. SpectrumItems.Clear();
  289. for(int i=0;i<items.Count;i++)
  290. {
  291. SpectrumItems.Add(new IndexValueItemViewModel<RandomSpectrumItemViewModel>(i + 1, new RandomSpectrumItemViewModel(items[i])));
  292. }
  293. if (items.Count < 3) return;
  294. CalcRefSpectrum(items.Select(x => x.Frequency).ToArray(), items.Select(x => x.Value).ToArray(), items.Select(x => x.ValueType).ToArray(), FrequencyResolution,out var fy_array,out var f,out var turningfreq);
  295. if (fy_array.Length == 0) return;
  296. RMSAcceleration = Math.Sqrt(ViewModels.MainViewModel.Default.Calc.Sum.Sum(ref fy_array[0], (uint)fy_array.Length) * FrequencyResolution);
  297. ResetRMS = RMSAcceleration;
  298. double[] f2 = new double[f.Length];
  299. double[] fv = new double[f.Length];
  300. MainViewModel.Default.Calc.Multiply.Multiply(ref f[0], ref f[0], (uint)f.Length,ref f2[0]);
  301. MainViewModel.Default.Calc.Division.Division(ref fy_array[0],ref f2[0], (uint)f.Length,ref fv[0]);
  302. double sum = MainViewModel.Default.Calc.Sum.Sum(ref fv[0], (uint)fv.Length);
  303. MaxVelocity = Math.Sqrt((sum - (fv[0] + fv[^1] / 2) / 2) * FrequencyResolution) / (2 * Math.PI) * Sigma * 9.8f;
  304. MainViewModel.Default.Calc.Division.Division(ref fv[0], ref f2[0], (uint)f.Length, ref fv[0]);
  305. sum = MainViewModel.Default.Calc.Sum.Sum(ref fv[0], (uint)fv.Length);
  306. MaxDisplacement = Math.Sqrt((sum - (fv[0] + fv[^1] / 2) / 2) * FrequencyResolution) / (2 * Math.PI*2*Math.PI) * Sigma * 9800f;
  307. OnPropertyChanged(nameof(MaxAcceleration));
  308. double[,] spectrumdata = new double[5, f.Length];
  309. Unsafe.CopyBlock(ref Unsafe.As<double, byte>(ref spectrumdata[0, 0]), ref Unsafe.As<double, byte>(ref fy_array[0]), (uint)(Unsafe.SizeOf<double>() * fy_array.Length));
  310. CalcSpectrum(items, f, fy_array, FrequencyResolution, turningfreq, ref spectrumdata);
  311. datas.Clear();
  312. velocitydata.Clear();
  313. displacementdata.Clear();
  314. for (int i=0;i<f.Length;i++)
  315. {
  316. datas.Add(new SweepData()
  317. {
  318. Frequency = f[i],
  319. TargetAcceleration = spectrumdata[0, i],
  320. UpStopAcceleration = spectrumdata[1, i],
  321. UpWarnAcceleration = spectrumdata[2, i],
  322. DownStopAcceleration = spectrumdata[3, i],
  323. DownWarnAcceleration = spectrumdata[4, i]
  324. });
  325. velocitydata.Add(new DataPoint(f[i], Shaker.Models.Tools.Tools.AccelerationToVelocity(spectrumdata[0, i], f[i])));
  326. displacementdata.Add(new DataPoint(f[i], Shaker.Models.Tools.Tools.AccelerationToDisplacement(spectrumdata[0, i], f[i])));
  327. }
  328. AccelerationModel.InvalidatePlot(false);
  329. VelocityModel.InvalidatePlot(false);
  330. DisplacementModel.InvalidatePlot(false);
  331. for (int i = 0; i < lineSeries.Count; i++)
  332. {
  333. lineSeries[i].ItemsSource = datas;
  334. }
  335. velocity.ItemsSource = velocitydata;
  336. displacement.ItemsSource = displacementdata;
  337. AccelerationModel.InvalidatePlot(true);
  338. VelocityModel.InvalidatePlot(true);
  339. DisplacementModel.InvalidatePlot(true);
  340. CanResetRMS = true;
  341. }
  342. private void CalcSpectrum(List<RandomSpectrumItemModel> models, [In] double[] f, [In] double[] fy_array, [In] double deltaf, [In] double[] turn_freq,ref double[,] spectrumdata)
  343. {
  344. CalcItemSpectrum(models.Select(x => x.UpStop).ToArray(), f, fy_array, deltaf, turn_freq, ref spectrumdata[1, 0]);
  345. CalcItemSpectrum(models.Select(x => x.UpWarn).ToArray(), f, fy_array, deltaf, turn_freq, ref spectrumdata[2, 0]);
  346. CalcItemSpectrum(models.Select(x => x.DownStop).ToArray(), f, fy_array, deltaf, turn_freq, ref spectrumdata[3, 0]);
  347. CalcItemSpectrum(models.Select(x => x.DownWarn).ToArray(), f, fy_array, deltaf, turn_freq, ref spectrumdata[4, 0]);
  348. }
  349. private void CalcItemSpectrum(double[] offset, [In] double[] f, [In] double[] fy_array, [In] double deltaf, [In] double[] turn_freq, ref double spectrumdata)
  350. {
  351. for (int i = 0; i < offset.Length - 1; i++)
  352. {
  353. int index = (int)((turn_freq[i] - turn_freq[0]) / deltaf);
  354. uint len = (uint)((turn_freq[i + 1] - turn_freq[i]) / deltaf);
  355. if (offset[i+1] == offset[i])
  356. {
  357. var x = Math.Pow(10, offset[i] / 10);
  358. MainViewModel.Default.Calc.Multiply.Multiply(ref fy_array[index], x, len, ref Unsafe.Add(ref spectrumdata,index));
  359. }
  360. else
  361. {
  362. double db1_psd = Math.Pow(10, offset[i] / 10) * fy_array[index];
  363. double db2_psd = Math.Pow(10, offset[i + 1] / 10) * fy_array[index+len];
  364. var x= Math.Log10(db2_psd / db1_psd) / (Math.Log2(turn_freq[i + 1] / turn_freq[i])) * 10;
  365. for(int j=0;j<len;j++)
  366. {
  367. ref double result = ref Unsafe.Add(ref spectrumdata, index + j);
  368. result = Math.Pow(10, Math.Log2(f[index + j] / turn_freq[i]) * x / 10) * db1_psd;
  369. }
  370. }
  371. }
  372. ref double temp = ref Unsafe.Add(ref spectrumdata, fy_array.Length - 1);
  373. temp = Math.Pow(10, offset[^1] / 10) * fy_array[^1];
  374. }
  375. private void CalcRefSpectrum(double[] f_array, double[] y_array, RandomValueType[] k_array, double deltaf ,out double[] fy_array,out double[] f,out double[] turningfreq)
  376. {
  377. int n=f_array.Length;
  378. // 计算圆整频率值及其对应的谱值
  379. double[] round_f = new double[n];
  380. double[] round_y = new double[n];
  381. turningfreq = new double[n];
  382. for (int i = 0; i < n; i++)
  383. {
  384. round_f[i] = Math.Ceiling(f_array[i] / deltaf) * deltaf;
  385. turningfreq[i] = round_f[i];
  386. }
  387. // 若第一个点值未知时,需先计算第一个点的值
  388. if (k_array[0] == RandomValueType.Slope && k_array[1] == RandomValueType.Slope)
  389. {
  390. y_array[0] = y_array[1];
  391. }
  392. if (k_array[0] == RandomValueType.Slope && k_array[1] == RandomValueType.Value)
  393. {
  394. k_array[0] = 0;
  395. y_array[0] = y_array[1];
  396. }
  397. if (k_array[0] == RandomValueType.Slope)
  398. {
  399. double kk = y_array[1];
  400. y_array[0] = y_array[2] / (Math.Pow(10, kk / 10 * Math.Log(f_array[1] / f_array[0], 2)));
  401. y_array[1] = y_array[2];
  402. k_array[0] = 0;
  403. k_array[1] = 0;
  404. }
  405. // 计算第二点及其后点的值
  406. for (int i = 1; i < n; i++)
  407. {
  408. if (f_array[i] == 0)
  409. {
  410. double kk = y_array[i];
  411. y_array[i] = y_array[i + 1];
  412. f_array[i] = Math.Pow(2, (10 * Math.Log(y_array[i + 1] / y_array[i - 1], 10) / kk)) * f_array[i - 1];
  413. }
  414. else
  415. {
  416. if (k_array[i] == RandomValueType.Slope)
  417. {
  418. y_array[i] = Math.Pow(10, y_array[i] / 10 * Math.Log(f_array[i] / f_array[i - 1], 2)) * y_array[i - 1];
  419. k_array[i] = 0;
  420. }
  421. }
  422. }
  423. // 验证结果值
  424. double[] k_exam = new double[n - 1];
  425. for (int i = 0; i < n; i++)
  426. {
  427. if (i < n - 1)
  428. {
  429. k_exam[i] = 10 * Math.Log(y_array[i + 1] / y_array[i], 10) / Math.Log(f_array[i + 1] / f_array[i], 2);
  430. }
  431. }
  432. // 计算圆整后频率对应的谱值
  433. for (int i = 0; i < n; i++)
  434. {
  435. if (round_f[i] == f_array[i])
  436. {
  437. round_y[i] = y_array[i];
  438. }
  439. if (i < n - 1)
  440. {
  441. if (round_f[i] > f_array[i])
  442. {
  443. round_y[i] = Math.Pow(10, k_exam[i] / 10 * Math.Log(round_f[i] / f_array[i], 2)) * y_array[i];
  444. }
  445. }
  446. if (i == n - 1)
  447. {
  448. round_y[i] = Math.Pow(10, k_exam[i - 1] / 10 * Math.Log(round_f[i] / f_array[i], 2)) * y_array[i];
  449. }
  450. if (round_f[i] < f_array[i])
  451. {
  452. round_y[i] = Math.Pow(10, k_exam[i - 1] / 10 * Math.Log(f_array[i] / round_f[i], 2)) * y_array[i];
  453. }
  454. }
  455. int parts = k_exam.Length; // 将谱按斜率分成几段,parts为总的段数\
  456. f = Enumerable.Range(0, (int)((round_f[n - 1] - round_f[0]) / deltaf) + 1).Select(x => x * deltaf + round_f[0]).ToArray();
  457. fy_array =new double[f.Length];
  458. fy_array[0] = round_y[0];
  459. fy_array[^1] = round_y[^1];
  460. int part_begin = 0;
  461. for (int i = 0; i < parts; i++)
  462. {
  463. fy_array[part_begin] = round_y[i];
  464. int n_part = (int)Math.Round((round_f[i + 1] - round_f[i]) / deltaf);
  465. if (k_exam[i] == 0)
  466. {
  467. for (int k = part_begin + 1; k <= part_begin + n_part; k++)
  468. {
  469. fy_array[k] = fy_array[k - 1];
  470. }
  471. }
  472. else
  473. {
  474. if (n_part > 0)
  475. {
  476. for (int k = part_begin + 1; k <= part_begin + n_part; k++)
  477. {
  478. fy_array[k] = Math.Pow(10, k_exam[i] / 10 * Math.Log(f[k] / f[k - 1], 2)) * fy_array[k - 1];
  479. }
  480. }
  481. }
  482. part_begin += n_part;
  483. }
  484. }
  485. protected override void Save()
  486. {
  487. base.Save();
  488. CommunicationViewModel.Intance.LocalCommunication?.GetEvent<RandomConfigModel>()?.Publish(this, Model);
  489. CommunicationViewModel.Intance.ServiceCommunication?.GetEvent<RandomConfigModel>()?.Publish(this, Model);
  490. }
  491. }
  492. }