using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; using OxyPlot.Series; using OxyPlot; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Timers; using System.Windows; using OxyPlot.Axes; using GettingStarted.Filter; namespace GettingStarted.ViewModels { internal partial class MainViewModel3 : ObservableObject { private readonly double DT = 0.01; [ObservableProperty] private PlotModel _myModel; [ObservableProperty] private LineSeries _lineSeries; [ObservableProperty] private LineSeries _lpfSeries; [ObservableProperty] private double _cutOffSecond; private IFilter _filter; public MainViewModel3() { MyModel = new PlotModel() { Title = "Getting Started with RT Plot", PlotMargins = new OxyThickness(50, 10, 50, 50) }; LineSeries = new LineSeries() { Title = "Dynamic Data" }; LpfSeries = new LineSeries() { Title = "Filtered" }; _filter = new LowPassFilter(5d, DT); DateTimeAxis timeAxis = new DateTimeAxis() { Position = AxisPosition.Bottom, StringFormat = "HH:mm:ss", Title = "Time", IntervalType = DateTimeIntervalType.Seconds, IntervalLength = 60, IsZoomEnabled = false, IsPanEnabled = false, }; MyModel.Axes.Add(timeAxis); LinearAxis linearAxis = new LinearAxis() { Position = AxisPosition.Left, Title = "Value" }; MyModel.Axes.Add(linearAxis); MyModel.Series.Add(LineSeries); MyModel.Series.Add(LpfSeries); CutOffSecond = 10d; _timer = new System.Timers.Timer(); _timer.Interval = DT * 1000; _timer.Elapsed -= _timer_Elapsed; _timer.Elapsed += _timer_Elapsed; } private int _lastX = 0; private Random _rand = new Random(); private double _noiseLevel = 0.3; private void _timer_Elapsed(object? sender, ElapsedEventArgs e) { Application.Current.Dispatcher.Invoke(() => { DateTime now = DateTime.Now; double noise = (_rand.NextDouble() - 0.5) * _noiseLevel; double value = Math.Sin(_lastX * 0.1) + noise; LineSeries.Points.Add(new DataPoint(DateTimeAxis.ToDouble(DateTime.Now), value)); LpfSeries.Points.Add(new DataPoint(DateTimeAxis.ToDouble(DateTime.Now), _filter.Filter(value))); DateTime cutOff = now.AddSeconds(-1 * CutOffSecond); LineSeries.Points.RemoveAll(d => DateTimeAxis.ToDateTime(d.X) < cutOff); LpfSeries.Points.RemoveAll(d => DateTimeAxis.ToDateTime(d.X) < cutOff); if (MyModel.Axes[0] is DateTimeAxis timeAxis) { timeAxis.Minimum = DateTimeAxis.ToDouble(cutOff); timeAxis.Maximum = DateTimeAxis.ToDouble(now); } MyModel.InvalidatePlot(true); _lastX++; }); } private bool _isTimerStarted = false; private System.Timers.Timer _timer; [RelayCommand] private void FlipTimer() { if (!_isTimerStarted) { _timer.Start(); _isTimerStarted = true; } else { _timer.Stop(); _isTimerStarted = false; } } public void OnClosing() { _timer.Stop(); _timer.Dispose(); } } }