using Avalonia.Collections; using Avalonia.Controls; using Avalonia.Utilities; using CommunityToolkit.Mvvm.Input; using OxyPlot; using OxyPlot.Series; using Shaker.Models; using System; using System.Collections.Generic; using System.Linq; using System.Numerics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks; using System.Windows.Input; namespace ShakerApp.ViewModels { internal class RandomConfigViewModel : DisplayViewModelBase { public List RefSpectrum => datas; private RandomConfigViewModel() { Content = typeof(Views.RandomConfigView); #region 加速度谱曲线 AccelerationModel.Axes.Add(new OxyPlot.Axes.LogarithmicAxis() { MaximumPadding = 0, MinimumPadding = 0, Title = App.Current?.FindResource(Shaker.Models.ShakerConstant.FrequencyKey) + "", Unit = "Hz", MajorGridlineStyle = LineStyle.Solid, Position = OxyPlot.Axes.AxisPosition.Bottom, Key = "Freq" }); AccelerationModel.Axes.Add(new OxyPlot.Axes.LogarithmicAxis() { Key = "Ampt", Title = App.Current?.FindResource(ShakerConstant.AmptAxisTitleKey) + "", Unit = "g", MajorGridlineStyle = LineStyle.Solid, Position = OxyPlot.Axes.AxisPosition.Left, }); AccelerationModel.Title = App.Current?.FindResource(ShakerConstant.AccelerationSpectrumKey) + ""; for (int i = 0; i < oxyColors.Count; i++) { LineSeries line = new LineSeries(); line.Title = App.Current?.FindResource(ShakerConstant.SweepAccelerationSpectrumNames[i]) + ""; line.Color = oxyColors[i]; line.StrokeThickness = 1; line.DataFieldX = nameof(SweepData.Frequency); line.DataFieldY = properties[i]; line.LineStyle = lineStyles[i]; line.XAxisKey = "Freq"; line.YAxisKey = "Ampt"; lineSeries.Add(line); AccelerationModel.Series.Add(line); } AccelerationModel.Legends.Add(new OxyPlot.Legends.Legend() { ShowInvisibleSeries = true, }); #endregion #region 速度 VelocityModel.Axes.Add(new OxyPlot.Axes.LogarithmicAxis() { MaximumPadding = 0, MinimumPadding = 0, Title = App.Current?.FindResource(Shaker.Models.ShakerConstant.FrequencyKey) + "", Unit = "Hz", MajorGridlineStyle = LineStyle.Solid, Position = OxyPlot.Axes.AxisPosition.Bottom, Key = "Freq" }); VelocityModel.Title = App.Current?.FindResource(ShakerConstant.VelocityKey) + ""; VelocityModel.Axes.Add(new OxyPlot.Axes.LogarithmicAxis() { Key = "Ampt", Title = App.Current?.FindResource(ShakerConstant.AmptAxisTitleKey) + "", Unit = "m/s", MajorGridlineStyle = LineStyle.Solid, Position = OxyPlot.Axes.AxisPosition.Left, }); velocity = new LineSeries(); velocity.Title = App.Current?.FindResource(ShakerConstant.VelocityKey) + ""; velocity.Color = oxyColors[0]; velocity.StrokeThickness = 1; velocity.DataFieldX = nameof(DataPoint.X); velocity.DataFieldY = nameof(DataPoint.Y); velocity.LineStyle = lineStyles[0]; velocity.XAxisKey = "Freq"; velocity.YAxisKey = "Ampt"; VelocityModel.Series.Add(velocity); #endregion #region 位移 DisplacementModel.Axes.Add(new OxyPlot.Axes.LogarithmicAxis() { MaximumPadding = 0, MinimumPadding = 0, Title = App.Current?.FindResource(Shaker.Models.ShakerConstant.FrequencyKey) + "", Unit = "Hz", MajorGridlineStyle = LineStyle.Solid, Position = OxyPlot.Axes.AxisPosition.Bottom, Key = "Freq" }); DisplacementModel.Title = App.Current?.FindResource(ShakerConstant.DisplacementKey) + ""; DisplacementModel.Axes.Add(new OxyPlot.Axes.LogarithmicAxis() { Key = "Ampt", Title = App.Current?.FindResource(ShakerConstant.AmptAxisTitleKey) + "", Unit = "mm", MajorGridlineStyle = LineStyle.Solid, Position = OxyPlot.Axes.AxisPosition.Left, }); displacement = new LineSeries(); displacement.Title = App.Current?.FindResource(ShakerConstant.DisplacementKey) + ""; displacement.Color = oxyColors[0]; displacement.StrokeThickness = 1; displacement.DataFieldX = nameof(DataPoint.X); displacement.DataFieldY = nameof(DataPoint.Y); displacement.LineStyle = lineStyles[0]; displacement.XAxisKey = "Freq"; displacement.YAxisKey = "Ampt"; DisplacementModel.Series.Add(displacement); #endregion GetEvent(ShakerSettingViewModel.LANGUAGECHANGEDEVENT).Subscrip((_, _) => { AccelerationModel.InvalidatePlot(false); AccelerationModel.Axes[0].Title = App.Current?.FindResource(ShakerConstant.FrequencyKey) + ""; AccelerationModel.Axes[1].Title = App.Current?.FindResource(ShakerConstant.AmptAxisTitleKey) + ""; AccelerationModel.Title = App.Current?.FindResource(ShakerConstant.AccelerationSpectrumKey) + ""; for (int i = 0; i < lineSeries.Count; i++) { lineSeries[i].Title = App.Current?.FindResource(ShakerConstant.SweepAccelerationSpectrumNames[i]) + ""; } AccelerationModel.InvalidatePlot(true); VelocityModel.InvalidatePlot(false); VelocityModel.Axes[0].Title = App.Current?.FindResource(ShakerConstant.FrequencyKey) + ""; VelocityModel.Axes[1].Title = App.Current?.FindResource(ShakerConstant.AmptAxisTitleKey) + ""; VelocityModel.Title = App.Current?.FindResource(ShakerConstant.VelocityKey) + ""; velocity.Title = App.Current?.FindResource(ShakerConstant.VelocityKey) + ""; VelocityModel.InvalidatePlot(true); DisplacementModel.InvalidatePlot(false); DisplacementModel.Axes[0].Title = App.Current?.FindResource(ShakerConstant.FrequencyKey) + ""; DisplacementModel.Axes[1].Title = App.Current?.FindResource(ShakerConstant.AmptAxisTitleKey) + ""; DisplacementModel.Title = App.Current?.FindResource(ShakerConstant.DisplacementKey) + ""; displacement.Title = App.Current?.FindResource(ShakerConstant.DisplacementKey) + ""; DisplacementModel.InvalidatePlot(true); }); GetEvent().Subscrip((sender, args) => { UpDateModel(args.Data.RandomConfig); CommunicationViewModel.Instance.LocalCommunication?.GetEvent()?.Subscrip((sender, args) => { UpDateModel(args.Data); Refresh(); RandomMainPageViewModel.Instance.SetRefSpectrum(datas); CommunicationViewModel.Instance.ServiceCommunication?.GetEvent()?.Publish(this, Model); }); }); Identify.PropertyChanged += (_, _) => SaveIsEnabled = true; } static RandomConfigViewModel() { } [PropertyAssociation(nameof(RandomConfigModel.SpectrumItemsCount))] public uint SpectrumItemsCount => Model.SpectrumItemsCount; [PropertyAssociation(nameof(RandomConfigModel.HanningWindowCompensationCoefficient))] public double HanningWindowCompensationCoefficient { get => Model.HanningWindowCompensationCoefficient; set => SetProperty(ref Model.HanningWindowCompensationCoefficient, value); } [PropertyAssociation(nameof(RandomConfigModel.LinearAverage))] public uint LinearAverage { get => Model.LinearAverage; set => SetProperty(ref Model.LinearAverage, value); } [PropertyAssociation(nameof(RandomConfigModel.ExponentialAverage))] public uint ExponentialAverage { get => Model.ExponentialAverage; set => SetProperty(ref Model.ExponentialAverage, value); } [PropertyAssociation(nameof(RandomConfigModel.LinearAverage),nameof(RandomConfigModel.ExponentialAverage))] public uint DOF => (LinearAverage << 1) * ((ExponentialAverage << 1) - 1); [PropertyAssociation(nameof(RandomConfigModel.MaxFrequency),nameof(SpectrumLines))] public double FrequencyResolution => (double)MaxFrequency / (double)SpectrumLines; [PropertyAssociation(nameof(RandomConfigModel.RandomSampleRate))] public uint RandomSampleRate => Model.RandomSampleRate; List lineSeries = new List(); List velocitydata = new List(); LineSeries velocity = new LineSeries(); LineSeries displacement = new LineSeries(); List displacementdata = new List(); List oxyColors = new List() { OxyColors.Green, OxyColors.Red, OxyColors.Red, OxyColors.Yellow, OxyColors.Yellow }; List lineStyles = new List() { LineStyle.Solid, LineStyle.Solid, LineStyle.Solid, LineStyle.LongDashDotDot, LineStyle.LongDashDotDot }; List properties = new List() { nameof(RandomData.TargetAcceleration), nameof(RandomData.UpStopAcceleration), nameof(RandomData.DownStopAcceleration), nameof(RandomData.UpWarnAcceleration), nameof(RandomData.DownWarnAcceleration) }; List datas = new List(); private double maxDisplacement; private double maxVelocity; private bool canResetRMS = false; private double resetRMS; [PropertyAssociation(nameof(RandomConfigModel.MaxFrequency))] public RandomMaxFrequency MaxFrequency { get => Model.MaxFrequency; set { SetProperty(ref Model.MaxFrequency, value); OnPropertyChanged(nameof(FFTLength)); } } public bool CanResetRMS { get => canResetRMS; set =>SetProperty(ref canResetRMS, value); } public double ResetRMS { get => resetRMS; set =>SetProperty(ref resetRMS , value); } [PropertyAssociation(nameof(RandomConfigModel.SynthesisType))] public AccelerationSynthesisType SynthesisType { get => Model.SynthesisType; set => SetProperty(ref Model.SynthesisType, value); } [PropertyAssociation(nameof(RandomConfigModel.MinFrequency))] public double MinFrequency { get => Model.MinFrequency; set => SetProperty(ref Model.MinFrequency, value); } [PropertyAssociation(nameof(RandomConfigModel.SpectrumLines))] public SpectrumLines SpectrumLines { get => Model.SpectrumLines; set { SetProperty(ref Model.SpectrumLines, value); OnPropertyChanged(nameof(FFTLength)); } } [PropertyAssociation(nameof(RandomConfigModel.Sigma))] public double Sigma { get => Model.Sigma; set => SetProperty(ref Model.Sigma, value); } [PropertyAssociation(nameof(RandomConfigModel.RandomSampleRate),nameof(RandomConfigModel.MaxFrequency),nameof(RandomConfigModel.SpectrumLines))] public uint FFTLength => (uint)(Model.RandomSampleRate / (float)MaxFrequency * (uint)SpectrumLines); [PropertyAssociation(nameof(RandomConfigModel.RandomSampleRate), nameof(RandomConfigModel.MaxFrequency), nameof(RandomConfigModel.SpectrumLines))] public uint FFTHalfLength => FFTLength >> 1; public RandomIdentifyViewModel Identify { get; } = new RandomIdentifyViewModel(); public AvaloniaList> SpectrumItems { get; }= new AvaloniaList>(); public AvaloniaList> PlanItems { get; } = new AvaloniaList>(); [PropertyAssociation(nameof(RandomConfigModel.StopLins))] public uint StopLins { get => Model.StopLins; set => SetProperty(ref Model.StopLins, value); } [PropertyAssociation(nameof(RandomConfigModel.WarnLines))] public uint WarnLines { get => Model.WarnLines; set => SetProperty(ref Model.WarnLines, value); } [PropertyAssociation(nameof(RandomConfigModel.StopRMS))] public double StopRMS { get => Model.StopRMS; set => SetProperty(ref Model.StopRMS, value); } public OxyPlot.PlotModel AccelerationModel { get; } = new OxyPlot.PlotModel(); public PlotModel DisplacementModel { get; } = new PlotModel(); public PlotModel VelocityModel { get; } = new PlotModel(); public static RandomConfigViewModel Instance { get; } = new RandomConfigViewModel(); [PropertyAssociation(nameof(RandomConfigModel.Sigma))] public double MaxAcceleration => RMSAcceleration * Sigma; public double MaxDisplacement { get => maxDisplacement; set =>SetProperty(ref maxDisplacement , value); } public double MaxVelocity { get => maxVelocity; set =>SetProperty(ref maxVelocity , value); } public bool AccelerationOverLimit => MaxAcceleration >= ShakerConfigViewModel.Instance.MaxAcceleration; public bool DisplacementOverLimit => MaxDisplacement > ShakerConfigViewModel.Instance.MaxDisplacement; public bool VelocityOverLimit => MaxVelocity > ShakerConfigViewModel.Instance.MaxVelocity; public double AccelerationLoad => Math.Round(MaxAcceleration / ShakerConfigViewModel.Instance.MaxAcceleration * 100f, 2); public double DisplacementLoad => Math.Round((double)MaxDisplacement / ShakerConfigViewModel.Instance.MaxDisplacement * 100f, 2); public double VelocityLoad => Math.Round((double)MaxVelocity / ShakerConfigViewModel.Instance.MaxVelocity * 100f, 2); public double RMSAcceleration { get => Model.RMSAcceleration; set =>SetProperty(ref Model.RMSAcceleration , value); } public ICommand AddCommand => new RelayCommand(Add); public override void UpDateModel(RandomConfigModel model) { SpectrumItems.Clear(); PlanItems.Clear(); for(int i=0;i(i + 1, new RandomSpectrumItemViewModel(model.SpectrumItems[i]))); } for(int i=0;i(i + 1, new RandomPlanItemViewModel(model.PlanItems[i]))); } Identify.UpDateModel(model.Identify); base.UpDateModel(model); } private void Add() { if (SpectrumItems.Count >= SpectrumItemsCount) return; if (Model.SpectrumItems.Count == 0) Model.SpectrumItems.Add(new RandomSpectrumItemModel()); else Model.SpectrumItems.Add(Model.SpectrumItems[^1].CloneBase()); SpectrumItems.Add(new IndexValueItemViewModel(SpectrumItems.Count + 1, new RandomSpectrumItemViewModel(Model.SpectrumItems[^1]))); } public ICommand DeleteCommand => new RelayCommand(Delete); private void Delete() { if (SpectrumItems.Count == 0) return; if(Model.SpectrumItems.Count>0) { Model.SpectrumItems.RemoveAt(Model.SpectrumItems.Count - 1); } SpectrumItems.RemoveAt(SpectrumItems.Count - 1); } public ICommand ResetRMSCommand=>new RelayCommand(ResetRMSExecute); private void ResetRMSExecute() { if (!CanResetRMS) return; if (ResetRMS <= 0) return; for(int i=0;i new RelayCommand(AddPlan); private void AddPlan() { if (PlanItems.Count >= 10 || Model.PlanItems.Count>=10) return; if (Model.PlanItems.Count == 0) Model.PlanItems.Add(new RandomPlanItemModel()); else Model.PlanItems.Add(Model.PlanItems[^1].CloneBase()); PlanItems.Add(new IndexValueItemViewModel(PlanItems.Count + 1, new RandomPlanItemViewModel(Model.PlanItems[^1]))); } public ICommand DeletePlanCommand => new RelayCommand(DeletePlan); private void DeletePlan() { if (PlanItems.Count == 0) return; if(Model.PlanItems.Count==0) { Model.PlanItems.RemoveAt(Model.PlanItems.Count - 1); } PlanItems.RemoveAt(PlanItems.Count - 1); } public ICommand RefreshPlanCommand => new RelayCommand(RefreshPlan); private void RefreshPlan() { if (PlanItems.Count < 1) return; } public ICommand RefreshCommand => new RelayCommand(Refresh); private unsafe void Refresh() { if (SpectrumItems.Count < 3) return; var items = SpectrumItems.Select(x => x.Value.Model.CloneBase()).DistinctBy(x => x.Frequency).OrderBy(x => x.Frequency).ToList(); SpectrumItems.Clear(); for(int i=0;i(i + 1, new RandomSpectrumItemViewModel(items[i]))); } if (items.Count < 3) return; 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); if (fy_array.Length == 0) return; this.Model.SpectralTables.Clear(); for(int i=0;i(ref spectrumdata[0, 0]), ref Unsafe.As(ref fy_array[0]), (uint)(Unsafe.SizeOf() * fy_array.Length)); CalcSpectrum(items, f, fy_array, FrequencyResolution, turningfreq, ref spectrumdata); datas.Clear(); velocitydata.Clear(); displacementdata.Clear(); for (int i=0;i models, [In] double[] f, [In] double[] fy_array, [In] double deltaf, [In] double[] turn_freq,ref double[,] spectrumdata) { CalcItemSpectrum(models.Select(x => x.UpStop).ToArray(), f, fy_array, deltaf, turn_freq, ref spectrumdata[1, 0]); CalcItemSpectrum(models.Select(x => x.UpWarn).ToArray(), f, fy_array, deltaf, turn_freq, ref spectrumdata[2, 0]); CalcItemSpectrum(models.Select(x => x.DownStop).ToArray(), f, fy_array, deltaf, turn_freq, ref spectrumdata[3, 0]); CalcItemSpectrum(models.Select(x => x.DownWarn).ToArray(), f, fy_array, deltaf, turn_freq, ref spectrumdata[4, 0]); } private void CalcItemSpectrum(double[] offset, [In] double[] f, [In] double[] fy_array, [In] double deltaf, [In] double[] turn_freq, ref double spectrumdata) { for (int i = 0; i < offset.Length - 1; i++) { int index = (int)((turn_freq[i] - turn_freq[0]) / deltaf); uint len = (uint)((turn_freq[i + 1] - turn_freq[i]) / deltaf); if (offset[i+1] == offset[i]) { var x = Math.Pow(10, offset[i] / 10); MainViewModel.Default.Calc.Multiply.Multiply(ref fy_array[index], x, len, ref Unsafe.Add(ref spectrumdata,index)); } else { double db1_psd = Math.Pow(10, offset[i] / 10) * fy_array[index]; double db2_psd = Math.Pow(10, offset[i + 1] / 10) * fy_array[index+len]; var x= Math.Log10(db2_psd / db1_psd) / (Math.Log2(turn_freq[i + 1] / turn_freq[i])) * 10; for(int j=0;j f_array[i]) { round_y[i] = Math.Pow(10, k_exam[i] / 10 * Math.Log(round_f[i] / f_array[i], 2)) * y_array[i]; } } if (i == n - 1) { round_y[i] = Math.Pow(10, k_exam[i - 1] / 10 * Math.Log(round_f[i] / f_array[i], 2)) * y_array[i]; } if (round_f[i] < f_array[i]) { round_y[i] = Math.Pow(10, k_exam[i - 1] / 10 * Math.Log(f_array[i] / round_f[i], 2)) * y_array[i]; } } int parts = k_exam.Length; // 将谱按斜率分成几段,parts为总的段数\ f = Enumerable.Range(0, (int)((round_f[n - 1] - round_f[0]) / deltaf) + 1).Select(x => x * deltaf + round_f[0]).ToArray(); fy_array =new double[f.Length]; fy_array[0] = round_y[0]; fy_array[^1] = round_y[^1]; int part_begin = 0; for (int i = 0; i < parts; i++) { fy_array[part_begin] = round_y[i]; int n_part = (int)Math.Round((round_f[i + 1] - round_f[i]) / deltaf); if (k_exam[i] == 0) { for (int k = part_begin + 1; k <= part_begin + n_part; k++) { fy_array[k] = fy_array[k - 1]; } } else { if (n_part > 0) { for (int k = part_begin + 1; k <= part_begin + n_part; k++) { fy_array[k] = Math.Pow(10, k_exam[i] / 10 * Math.Log(f[k] / f[k - 1], 2)) * fy_array[k - 1]; } } } part_begin += n_part; } } protected override void Save() { base.Save(); CommunicationViewModel.Instance.LocalCommunication?.GetEvent()?.Publish(this, Model); CommunicationViewModel.Instance.ServiceCommunication?.GetEvent()?.Publish(this, Model); RandomMainPageViewModel.Instance.SetRefSpectrum(datas); } } }