using Avalonia.Collections; using Avalonia.Controls; using Avalonia.Utilities; using CommunityToolkit.Mvvm.Input; using OxyPlot; using OxyPlot.Series; using Shaker.Models; using Shaker.Models.Tools; using System; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using System.Text; using System.Threading.Tasks; using System.Windows.Input; namespace ShakerApp.ViewModels { internal class SweepConfigViewModel:ViewModelBase { private float interval = 0.1f; 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(SweepData.TargetAcceleration), nameof(SweepData.UpStopAcceleration), nameof(SweepData.DownStopAcceleration), nameof(SweepData.UpWarnAcceleration), nameof(SweepData.DownWarnAcceleration) }; List datas = new List(); private SweepConfigViewModel() { OnceSweepTime = Model.OCTToTime(Model.SweepSpeed); Content = typeof(Views.SweepConfigView); for(int i=0;i(i+1,i)); } #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 { 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().Subscrip((sender, args) => { UpDateModel(args.Data.SweepConfig); CommunicationViewModel.Instance.LocalCommunication?.GetEvent()?.Subscrip((sender, args) => { UpDateModel(args.Data); Refresh(); SineMainPageViewModel.Instance.SetRefSpectrum(datas); CommunicationViewModel.Instance.ServiceCommunication?.GetEvent()?.Publish(this, Model); }); }); } static SweepConfigViewModel() { } public AvaloniaList> Channels { get; } = new AvaloniaList>(); [PropertyAssociation(nameof(SweepConfigModel.SelectChannel))] public int SelectChannel { get => Model.SelectChannel; set { SetProperty(ref Model.SelectChannel, value); for(int i=0;i Model.MaxSweepItemCount; [PropertyAssociation(nameof(SweepConfigModel.SweepCount))] public uint SweepCount { get => Model.SweepCount; set => SetProperty(ref Model.SweepCount, value); } [PropertyAssociation(nameof(SweepConfigModel.SweepType))] public SweepType SweepType { get => Model.SweepType; set { if (Model.SweepType == value) return; SetProperty(ref Model.SweepType, value); Model.OnceSweepTime = Model.OCTToTime(Model.SweepSpeed); OnPropertyChanged(nameof(OnceSweepTime)); } } [PropertyAssociation(nameof(SweepConfigModel.SweepDirection))] public SweepDirection SweepDirection { get => Model.SweepDirection; set => SetProperty(ref Model.SweepDirection, value); } [PropertyAssociation(nameof(SweepConfigModel.SignalType))] public SignalType SignalType { get => Model.SignalType; set { SetProperty(ref Model.SignalType, value); if(value == SignalType.Sweep) { OnceSweepTime = Model.OCTToTime(Model.SweepSpeed); } } } [PropertyAssociation(nameof(SweepConfigModel.StartFrequency))] public double StartFrequency { get => Model.StartFrequency; set { if (value == Model.StartFrequency) return; SetProperty(ref Model.StartFrequency, value); if (SignalType == SignalType.Fixed) return; OnceSweepTime = Model.OCTToTime(Model.SweepSpeed); } } public ICommand MaxLoadCommand => new RelayCommand(MaxLoad); private void MaxLoad() { SweepItems.Clear(); SweepItems.Add(new IndexValueItemViewModel(1,new SweepItemViewModel(new SweepItemModel() { Frequency = ShakerConfigViewModel.Instance.MinFrequency, Value = ShakerConfigViewModel.Instance.MaxDisplacement, SweepValueType = SweepValueType.FixedDisplacement, }))); SweepItems.Add(new IndexValueItemViewModel(2,new SweepItemViewModel( new SweepItemModel() { Frequency = ShakerConfigViewModel.Instance.MinFrequency + interval, Value = ShakerConfigViewModel.Instance.MaxVelocity, SweepValueType = SweepValueType.FixedVelocity, }))); SweepItems.Add(new IndexValueItemViewModel(3,new SweepItemViewModel( new SweepItemModel() { Frequency = ShakerConfigViewModel.Instance.MinFrequency + interval * 2, Value = ShakerConfigViewModel.Instance.MaxAcceleration, SweepValueType = SweepValueType.FixedAcceleration, }))); SweepItems.Add(new IndexValueItemViewModel(4,new SweepItemViewModel( new SweepItemModel() { Frequency = ShakerConfigViewModel.Instance.MaxFrequency, Value = ShakerConfigViewModel.Instance.MaxAcceleration, SweepValueType = SweepValueType.FixedAcceleration, }))); Refresh(); } public double MaxAcceleration => datas.Count ==0 ?0: datas.Max(x => x.TargetAcceleration); public double MaxDisplacement => displacementdata.Count == 0 ? 0 : displacementdata.Max(x => x.Y); public double MaxVelocity => velocitydata.Count == 0 ? 0 : velocitydata.Max(x => x.Y); 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); [PropertyAssociation(nameof(SweepConfigModel.EndFrequency))] public double EndFrequency { get => Model.EndFrequency; set { if (value == Model.EndFrequency) return; SetProperty(ref Model.EndFrequency, value); if (SignalType == SignalType.Fixed) return; OnceSweepTime = Model.OCTToTime(Model.SweepSpeed); } } [PropertyAssociation(nameof(SweepConfigModel.OnceSweepTime))] public double OnceSweepTime { get => Model.OnceSweepTime; set { if (Math.Abs(value - Model.OnceSweepTime) <= Increment || double.IsNaN(value)) return; SetProperty(ref Model.OnceSweepTime, value); OnPropertyChanged(nameof(TotalSweepTime)); if (SignalType == SignalType.Fixed) return; SweepSpeed = Model.TimeToOCT(value); } } private bool VerifySweepItem() { if (SweepItems.Count < 2) { ShowError(string.Format(App.Current?.FindResource("SweepItemsCountError")+"",2)); return false; } Model.SweepItems = SweepItems.Select(x => x.Value.Model).Where(x=>x.Value >0).OrderBy(x => x.Frequency).DistinctBy(x => x.Frequency).ToList(); SweepItems.Clear(); if (Model.SweepItems.Count < 2) { for (int i = 0; i < Model.SweepItems.Count; i++) { SweepItems.Add(new IndexValueItemViewModel(i + 1, new SweepItemViewModel(Model.SweepItems[i]))); } ShowError(string.Format(App.Current?.FindResource("SweepItemsCountError") + "", 2)); return false; } else { for (int i = 0; i < Model.SweepItems.Count; i++) { if (i == 0) { SweepItems.Add(new IndexValueItemViewModel(i + 1, new SweepItemViewModel(Model.SweepItems[i]))); continue; } switch (Model.SweepItems[i].SweepValueType) { case SweepValueType.DynamicAcceleration: case SweepValueType.FixedAcceleration: { switch(Model.SweepItems[i-1].SweepValueType) { case SweepValueType.DynamicAcceleration: break; case SweepValueType.FixedAcceleration: break; case SweepValueType.FixedDisplacement: Model.SweepItems[i].Frequency =Math.Round(Math.Sqrt(Model.SweepItems[i].Value*9800 / Model.SweepItems[i - 1].Value) / (2 * Math.PI),2); break; case SweepValueType.FixedVelocity: Model.SweepItems[i].Frequency = Math.Round(Model.SweepItems[i].Value * 9.8f / (2 * MathF.PI * Model.SweepItems[i - 1].Value), 2); break; } } break; case SweepValueType.FixedDisplacement: { switch(Model.SweepItems[i-1].SweepValueType) { case SweepValueType.DynamicAcceleration: case SweepValueType.FixedAcceleration: Model.SweepItems[i].Frequency = Math.Round(Math.Sqrt(Model.SweepItems[i-1].Value * 9800 / Model.SweepItems[i].Value) / (2 * Math.PI), 2); break; case SweepValueType.FixedVelocity: Model.SweepItems[i].Frequency = Math.Round(Model.SweepItems[i - 1].Value * 1000 / (2 * Math.PI * Model.SweepItems[i].Value), 2); break; case SweepValueType.FixedDisplacement: break; } } break; case SweepValueType.FixedVelocity: { switch (Model.SweepItems[i - 1].SweepValueType) { case SweepValueType.DynamicAcceleration: case SweepValueType.FixedAcceleration: Model.SweepItems[i].Frequency = Math.Round(Model.SweepItems[i-1].Value * 9.8f / (2 * Math.PI * Model.SweepItems[i].Value), 2); break; case SweepValueType.FixedVelocity: break; case SweepValueType.FixedDisplacement: Model.SweepItems[i].Frequency = Math.Round(Model.SweepItems[i].Value * 1000 / (2 * Math.PI * Model.SweepItems[i-1].Value), 2); break; } } break; } SweepItems.Add(new IndexValueItemViewModel(i + 1, new SweepItemViewModel(Model.SweepItems[i]))); } } return true; } public ICommand RefreshCommand => new RelayCommand(Refresh); private void Refresh() { var result = VerifySweepItem(); if (MaxFrequency <= MinFrequency) return; if (EndFrequency > MaxFrequency) EndFrequency = MaxFrequency; if (StartFrequency < MinFrequency) StartFrequency = MinFrequency; if (!result) return; datas.Clear(); velocitydata.Clear(); displacementdata.Clear(); int count = (int)Math.Ceiling((MaxFrequency - MinFrequency) / interval)+1; for(int i=0;i Model.SweepSpeed; set { if (Math.Abs(value - Model.SweepSpeed)<=Increment || double.IsNaN(value)) return; SetProperty(ref Model.SweepSpeed, value); OnceSweepTime = Model.OCTToTime(value); } } [PropertyAssociation(nameof(SweepConfigModel.Increment))] public double Increment => Model.Increment; [PropertyAssociation(nameof(SweepConfigModel.OnceSweepTime),nameof(SweepConfigModel.SweepCount))] public double TotalSweepTime => OnceSweepTime * SweepCount; [PropertyAssociation(nameof(SweepConfigModel.SweepItems))] public bool AddEnabled => SweepItems.Count < MaxSweepItemCount; [PropertyAssociation(nameof(SweepConfigModel.SweepItems))] public bool DeleteEnabled => SweepItems.Count > 0; [PropertyAssociation(nameof(SweepConfigModel.SweepItems))] public bool RefreshEnabled => SweepItems.Count >= 2; [PropertyAssociation(nameof(SweepConfigModel.SweepStartLevel))] public double SweepStartLevel { get => Model.SweepStartLevel; set => SetProperty(ref Model.SweepStartLevel, value); } [PropertyAssociation(nameof(SweepConfigModel.CrossoverPoint))] public double CrossoverPoint { get => Model.CrossoverPoint; set => SetProperty(ref Model.CrossoverPoint, value); } [PropertyAssociation(nameof(SweepConfigModel.SweepLevelGain))] public double SweepLevelGain { get => Model.SweepLevelGain; set => SetProperty(ref Model.SweepLevelGain, value); } [PropertyAssociation(nameof(SweepConfigModel.LowFrequencyMinCorrect))] public double LowFrequencyMinCorrect { get => Model.LowFrequencyMinCorrect; set => SetProperty(ref Model.LowFrequencyMinCorrect, value); } [PropertyAssociation(nameof(SweepConfigModel.LowFrequencyMaxCorrect))] public double LowFrequencyMaxCorrect { get => Model.LowFrequencyMaxCorrect; set => SetProperty(ref Model.LowFrequencyMaxCorrect, value); } [PropertyAssociation(nameof(SweepConfigModel.HigthFrequencyMinCorrect))] public double HigthFrequencyMinCorrect { get => Model.HigthFrequencyMinCorrect; set => SetProperty(ref Model.HigthFrequencyMinCorrect, value); } [PropertyAssociation(nameof(SweepConfigModel.HigthFrequencyMaxCorrect))] public double HigthFrequencyMaxCorrect { get => Model.HigthFrequencyMaxCorrect; set => SetProperty(ref Model.HigthFrequencyMaxCorrect, value); } [PropertyAssociation(nameof(SweepConfigModel.SweepItems))] public AvaloniaList> SweepItems { get; } = new AvaloniaList>(); public ICommand AddCommand => new RelayCommand(Add); [PropertyAssociation(nameof(SweepConfigModel.SweepItems))] public double MaxFrequency => SweepItems.Count ==0 ? ShakerConfigViewModel.Instance.MaxFrequency: SweepItems.Max(x=>x.Value.Frequency); [PropertyAssociation(nameof(SweepConfigModel.SweepItems))] public double MinFrequency => SweepItems.Count ==0 ? ShakerConfigViewModel.Instance.MinFrequency: SweepItems.Min(x => x.Value.Frequency); private void Add() { if (SweepItems.Count >= MaxSweepItemCount) return; Model.SweepItems.Add(new SweepItemModel()); SweepItems.Add(new IndexValueItemViewModel(SweepItems.Count + 1,new SweepItemViewModel(Model.SweepItems[^1]))); OnPropertyChanged(nameof(AddEnabled)); OnPropertyChanged(nameof(DeleteEnabled)); OnPropertyChanged(nameof(RefreshEnabled)); OnPropertyChanged(nameof(MaxFrequency)); OnPropertyChanged(nameof(MinFrequency)); if (MaxFrequency <= MinFrequency) return; if (EndFrequency > MaxFrequency) EndFrequency = MaxFrequency; if (StartFrequency < MinFrequency) StartFrequency = MinFrequency; } public ICommand DeleteCommand => new RelayCommand(Delete); private void Delete() { if (SweepItems.Count == 0) return; Model.SweepItems.RemoveAt(Model.SweepItems.Count - 1); SweepItems.RemoveAt(SweepItems.Count - 1); OnPropertyChanged(nameof(AddEnabled)); OnPropertyChanged(nameof(DeleteEnabled)); OnPropertyChanged(nameof(RefreshEnabled)); OnPropertyChanged(nameof(MaxFrequency)); OnPropertyChanged(nameof(MinFrequency)); if (MaxFrequency <= MinFrequency) return; if (EndFrequency > MaxFrequency) EndFrequency = MaxFrequency; if (StartFrequency < MinFrequency) StartFrequency = MinFrequency; } public override void UpDateModel(SweepConfigModel model) { base.UpDateModel(model); int count = model.SweepItems.Count - SweepItems.Count; if(count>0) { for(int i=0;i(SweepItems.Count + 1, new SweepItemViewModel())); } } else if(count<0) { SweepItems.RemoveRange(SweepItems.Count + count, Math.Abs(count)); } else { } for(int i=0;i()?.Publish(this, Model); CommunicationViewModel.Instance.ServiceCommunication?.GetEvent()?.Publish(this, Model); } public List RefSpectrum => datas; public OxyPlot.PlotModel AccelerationModel { get; } = new OxyPlot.PlotModel(); public PlotModel DisplacementModel { get; } = new PlotModel(); public PlotModel VelocityModel { get; } = new PlotModel(); public static SweepConfigViewModel Instance { get; } = new SweepConfigViewModel(); } }