using GalaSoft.MvvmLight.Command; using LiveCharts; using LiveCharts.Configurations; using LiveCharts.Wpf; using System; using System.Collections.Generic; using System.ComponentModel; using System.Linq; using System.Text; using System.Threading.Tasks; namespace FLY.Thick.Blowing.UI.Fix.Client { public class PgBlowingExtVmUt : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; #region 曲线 /// /// 画在图上的 限位信号 /// public List LimitValues { get; } = new List(); /// /// 画在图上的 速度曲线,限制最多100个数据 /// public ChartValues VelocityValues { get; } = new ChartValues(); /// /// 画在图上的 厚度曲线,限制最多100个数据 /// public ChartValues ThicknessValues { get; } = new ChartValues(); /// /// 画在图上的 膜距离增量曲线,限制最多100个数据 /// public ChartValues FilmLength3DValues { get; } = new ChartValues(); /// /// 画在图上的 当前应用的膜距离增量曲线,不用限制,本来就只有100个 /// public ChartValues CurrFilmLength3D { get; } = new ChartValues(); /// /// 画在图上的 计算出来的膜距离增量曲线,不用限制,本来就只有100个 /// public ChartValues NewFilmLength3D { get; } = new ChartValues(); /// /// 转换为分区号单位的 每幅图 /// public SeriesCollection FrameSeries { get; } = new SeriesCollection(); #endregion #region 参数 /// /// 需要 膜距离增量曲线 /// public bool Is3D { get; set; } /// /// 膜距离 /// public double FilmLength { get; set; } /// /// 获取数据分钟数 min /// public int GetDataMinute { get; set; } /// /// 膜距离查找范围 m /// public int FLRange { get; set; } /// /// 速度滤波 s /// public int VelocityFilter { get; set; } /// /// 牵引1速度 /// public double Velocity1 { get; set; } #endregion #region 状态 public double VAvg { get; private set; } public double VMax { get; private set; } public double VMin { get; private set; } public double FAvg { get; private set; } public double FMax { get; private set; } public double FMin { get; private set; } #endregion #region 界面 /// /// y轴格式 /// public Func YFormatter { get; set; } = value => value.ToString("F1"); /// /// X轴格式 /// public Func DateTimeFormatter { get; set; } = value => new DateTime((long)value).ToString("HH:mm:ss"); public Func BoltNoFormatter { get; set; } = value => (value + 1).ToString(); public CartesianMapper MapperTv { get; set; } = Mappers.Xy() .X(value => value.Time.Ticks) .Y(value => value.Value); #endregion #region Command public RelayCommand GetDataCmd { get; private set; } public RelayCommand UpdateVCmd { get; private set; } public RelayCommand UpdateFilmLength3DCmd { get; private set; } public RelayCommand ApplyFilmLength3DCmd { get; private set; } public RelayCommand UpdateFramesCmd { get; private set; } public RelayCommand CalCmd { get; private set; } public RelayCommand ApplyFilmLengthCmd { get; private set; } public RelayCommand SaveCmd { get; private set; } public RelayCommand LoadCmd { get; private set; } #endregion public CalFilmLenUt Cfl { get; set; } public PgBlowingExtVmUt() { Init1(); init_virtualdata(); } void Init1() { #region 界面配置 //MapperTv = Mappers.Xy() // .X(value => value.Time.Ticks) // .Y(value => value.Value); //DateTimeFormatter = value => new DateTime((long)value).ToString("HH:mm:ss"); //BoltNoFormatter = value => (value + 1).ToString(); //YFormatter = value => value.ToString("F1"); #endregion } /// /// 产生虚拟数据 /// void init_virtualdata() { #region 虚拟数据 int[] thicks = new int[]{ 3518 , 3484 , 3634 , 3620 , 3579 , 3625 , 3635 , 3638 , 3635 , 3606 , 3611 , 3603 , 3590 , 3631 , 3646 , 3647 , 3710 , 3705 , 3607 , 3720 , 3680 , 3637 , 3659 , 3703 , 3860 , 3720 , 3615 , 3810 , 3772 , 3666 , 3614 , 3627 , 3618 , 3502 , 3575 , 3583 , 3615 , 3680 , 3730 , 3840 , 3927 , 3946 , 3923 , 3841 , 3797 , 3865 , 3810 , 3711 , 3754 , 3705 , 3723 , 3699 , 3723 , 3801 , 3786 , 3798 , 3907 , 3945 , 3828 , 3860 , 3846 , 3903 , 3871 , 3844 , 3759 , 3816 , 3886 , 3815 , 3789 , 3876 , 3942 , 3854 , 3842 , 3921 , 3846 , 3835 , 3886 , 3881 , 3820 , 3787 , 3730 , 3617 , 3650 , 3610 , 3536 , 3545 , 3564 , 3584 , 3580 , 3572 , 3571 , 3579 , 3620 , 3634 , 3484 , 3518 , }; //辊周长 m double RollPerimeter = 0.314; //线速度 m/min double FilmVelocity = 20; //旋转周期 TimeSpan RInterval = TimeSpan.FromMinutes(6.1); //速度震荡周期 m double FV_Range = 2; TimeSpan DataLen = TimeSpan.FromMinutes(30); DateTime dt_begin = DateTime.Now; DateTime dt_end = dt_begin + DataLen; List vList = new List(); List tList = new List(); List lList = new List(); for (TimeSpan ts = TimeSpan.Zero; ts < DataLen; ts += TimeSpan.FromSeconds(1)) { DateTime dt = dt_begin + ts; double min = ts.TotalMinutes; //速度以1/2旋转周期变化 double v = FilmVelocity + Math.Sin(Math.PI * 2 * min / (RInterval.TotalMinutes / 2)) * FV_Range; vList.Add(new TimeValue() { Time = dt, Value = v }); int n = ((int)(min / RInterval.TotalMinutes)) % 2; double m = min % RInterval.TotalMinutes; int idx = (int)(thicks.Count() * m / RInterval.TotalMinutes); if (idx < 0) idx = 0; else if (idx > thicks.Count()) idx = thicks.Count() - 1; double thick; if (n == 0) thick = thicks[idx]; else thick = thicks[thicks.Count() - 1 - idx]; tList.Add(new TimeValue() { Time = dt, Value = thick / 100.0 }); if (lList.Count() == 0) { lList.Add(new TimeValue() { Time = dt_begin + RInterval, Value = n }); } else if (dt >= lList.Last().Time) { lList.Add(new TimeValue() { Time = lList.Last().Time + RInterval, Value = n }); } } List fList = new List(); double sum = 0; double avg = vList.Average(tv => tv.Value); foreach (var tv in vList) { sum += (tv.Value - avg) * TimeSpan.FromSeconds(1).TotalMinutes; fList.Add(new TimeValue() { Time = tv.Time, Value = sum }); } { double min = fList.Min(tv => tv.Value); foreach (var tv in vList) { tv.Value -= min; } } List setFilmLength = new List(); foreach (var tv in fList) { if (tv.Time >= lList[0].Time && tv.Time <= lList[1].Time) { setFilmLength.Add(tv.Value); } else if (tv.Time > lList[1].Time) { break; } } Random r = new Random(); List currFilmLength = new List(); foreach (var f in setFilmLength) { currFilmLength.Add(f + r.NextDouble() - 0.5); } List> frames = new List>(); for (int i = 0; i < lList.Count() - 1; i++) { List frame = new List(); frame.AddRange(thicks.Select(t => (t + (r.NextDouble() - 0.5) * t * 2 / 100) / 100.0)); frames.Add(frame); } #endregion foreach (var tv in lList) { LimitValues.Add(tv); } PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("LimitValues")); for (int i = 0; i < 100; i++) { int idx = vList.Count() * i / 100; if (idx >= vList.Count()) idx = vList.Count() - 1; VelocityValues.Add(vList[idx]); } for (int i = 0; i < 100; i++) { int idx = tList.Count() * i / 100; if (idx >= tList.Count()) idx = tList.Count() - 1; ThicknessValues.Add(tList[idx]); } for (int i = 0; i < 100; i++) { int idx = fList.Count() * i / 100; if (idx >= fList.Count()) idx = fList.Count() - 1; FilmLength3DValues.Add(fList[idx]); } for (int i = 0; i < 100; i++) { int idx = currFilmLength.Count() * i / 100; if (idx >= currFilmLength.Count()) idx = currFilmLength.Count() - 1; CurrFilmLength3D.Add(currFilmLength[idx]); } for (int i = 0; i < 100; i++) { int idx = setFilmLength.Count() * i / 100; if (idx >= setFilmLength.Count()) idx = setFilmLength.Count() - 1; NewFilmLength3D.Add(setFilmLength[idx]); } for (int i = 0; i < frames.Count(); i++) { var frame = frames[i]; FrameSeries.Add( new LineSeries() { Title = i.ToString(), Values = new ChartValues(frame), LineSmoothness = 1, StrokeThickness = 3, PointGeometrySize = 0 }); } } } public class CalFilmLenUt : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; #region 参数 #endregion #region 状态 /// /// 信息 /// public string Msg { get; set; } /// /// 下载中 /// public bool IsDownloading { get; set; } /// /// 数据准备好了 /// public bool IsDataReady { get; set; } /// /// 计算中 /// public bool IsCaling { get; set; } /// /// 有足够的数据,可以下载 /// public bool IsCanDownload { get; set; } /// /// 当前数据总分钟数 min /// public int DataMaxMinute { get; set; } /// /// 必须获取的最少数据量 min /// public int DataMinMinute { get; set; } /// /// 最佳获取数据量 min /// public int DataBestMinute { get; set; } #endregion } }