using LiveCharts; using System; using System.Collections.Generic; using System.ComponentModel; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; using MathNet.Numerics.LinearAlgebra; using MathNet.Numerics.LinearAlgebra.Double; using LiveCharts.Wpf; using System.Globalization; using Unity; using GalaSoft.MvvmLight.Command; namespace FLY.HeatingHelper.UI.UiModule { /// <summary> /// UC_AirRingShift.xaml 的交互逻辑 /// </summary> public partial class UC_AirRingShift : UserControl { public UC_AirRingShiftViewModel mainVM; public UC_AirRingShift() { InitializeComponent(); } private IUnityContainer container; [InjectionMethod] public void Initialize(IUnityContainer container,IThickHeatData dat) { this.container = container; mainVM = container.Resolve<UC_AirRingShiftViewModel>(); mainVM.Init(dat); FP_select1.DataContext = mainVM.vm1; FP_select2.DataContext = mainVM.vm2; DataContext = mainVM; } private void AutoCal_Shift(object sender, RoutedEventArgs e) { // 根据选定的两幅数据 mainVM.AutoCal_Shift(); } private void AirRingShift_Add(object sender, RoutedEventArgs e) { // 手动右移一个位置 mainVM.Change_Shift(1); } private void AirRingShift_Sub(object sender, RoutedEventArgs e) { // 手动左移一个位置 mainVM.Change_Shift(-1); } private void AirRingShift_Reset(object sender, RoutedEventArgs e) { mainVM.Change_Shift(int.MaxValue); } private void UserControl_Unloaded(object sender, RoutedEventArgs e) { mainVM.UnLoaded(sender); } private void UserControl_Loaded(object sender, RoutedEventArgs e) { mainVM.Loaded(sender); } private void AutoSearch_Shift(object sender, RoutedEventArgs e) { mainVM.AutoSearchAndCal_Shift(); } private void Angle_Sub(object sender, RoutedEventArgs e) { mainVM.Change_Angle(-0.5); } private void Angle_Add(object sender, RoutedEventArgs e) { mainVM.Change_Angle(0.5); } private void Button_Click(object sender, RoutedEventArgs e) { } private void Angle_Reset(object sender, RoutedEventArgs e) { mainVM.RotAngle = mainVM.CurrentAngle; } } public class UC_AirRingShiftViewModel:INotifyPropertyChanged { [InjectionMethod] public void Initilize(FLY.Thick.Blowing.IService.IBlowingService blowingService, FLY.FeedbackRenZiJia.IService.IHeatCellService heatCellService, FLY.Thick.Blowing.IService.IBlowingDetectService blowingDetectService) { blowing = blowingService; bDetect = blowingDetectService; this.heatCellService = heatCellService; Misc.BindingOperations.SetBinding(blowing, "OrgBoltNo", this, "CurrentResetBolt"); Misc.BindingOperations.SetBinding(bDetect, "RAngle", this, "CurrentAngle"); Misc.BindingOperations.SetBinding(this.heatCellService, "Kp", this, "CurrentKp"); Apply = new RelayCommand(Command_Apply); } FLY.Thick.Blowing.IService.IBlowingService blowing; FLY.Thick.Blowing.IService.IBlowingDetectService bDetect; FLY.FeedbackRenZiJia.IService.IHeatCellService heatCellService; public UC_FramePickerViewModel vm1 = new UC_FramePickerViewModel(); public UC_FramePickerViewModel vm2 = new UC_FramePickerViewModel(); public int CurrentResetBolt { get; set; } public double CurrentAngle { get; set; } public double CurrentKp { get; set; } public double Kp { get; set; } public int LockFrames { get; set; } = 1; public bool LockAngle { get; set; } = true; public int SearchProgressValue { get; set; } = 0; public bool SearchEnabled { get; set; } = true; public SeriesCollection VarSeries { get; set; } = new SeriesCollection(); public double[] DS_vthick { get; protected set; } = null; public double[] DS_vheat { get; protected set; } = null; public RelayCommand Apply { get; set; } private void Command_Apply() { if (!FLY.Thick.Base.UI.WdPassword.Authorize("Blowing")) return; var dlg = new Dlg_GetSaveSwitches.DLG_GetSaveSwitches(); var vm = new Dlg_GetSaveSwitches.VM_GetSaveSwitches(); dlg.Init(vm); dlg.ShowDialog(); if (vm.IsCancel) return; if (vm.ResetBoltSave) { blowing.OrgBoltNo = NewResetBolt; blowing.Apply(); } if (vm.RAngleSave) { bDetect.RAngle = RotAngle; bDetect.Apply(); } if (vm.KpSave) { heatCellService.Kp = Kp; heatCellService.Apply(); } FLY.ControlLibrary.Window_Tip.Show("应用成功", null, TimeSpan.FromSeconds(2)); } private IThickHeatData _data; private int _NewResetBolt = 0; public int NewResetBolt { get { return _NewResetBolt; } internal set { if (_NewResetBolt != value) { if(vth1 is null) { _NewResetBolt = value; return; } int cnt = vth1.Count(); if (cnt > 0) { while (value < 1) value += cnt; while (value > cnt) value -= cnt; _NewResetBolt = value; //while (_airRingShift < 0) _airRingShift += cnt; //while (_airRingShift >= cnt) _airRingShift -= cnt; //int rb = _airRingShift + resetBolt1; //while (rb < 0) rb += cnt; //while (rb >= cnt) rb -= cnt; //ResetBolt = rb; if (correls is null) return; TandH_Corel = correls[_NewResetBolt - 1]; } } } } public double TandH_Corel { get; internal set; } = 0; private double _rotAngle = 330; public double RotAngle { get { return _rotAngle; } set { if (Math.Abs(_rotAngle - value) > 0.00099) { _rotAngle = value; UpdateThickData(); UpdateVarChart(); } } } //private int _resetBolt; //public int ResetBolt //{ // get { return _resetBolt; } // set // { // if (_resetBolt != value) // { // _resetBolt = value; // UpdateVarChart(); // } // } //} public UC_AirRingShiftViewModel() { vm1.PropertyChanged += PickerVM_PropertyChanged; vm2.PropertyChanged += PickerVM_PropertyChanged; } public void Init(object dat) { _data = dat as IThickHeatData; //var tmpVM = ViewModel_HeatDetector.Instance; //vm1.InitData(dat, tmpVM.Selected_Idx_From, tmpVM.Selected_Idx_To); //vm2.InitData(dat, tmpVM.Selected_Idx_From, tmpVM.Selected_Idx_To); vm1.InitData(_data); vm2.InitData(_data); } public void Loaded(object s) { //var tmpVM = ViewModel_HeatDetector.Instance; //tmpVM.PropertyChanged += DataSelecter_PropertyChanged; //CurrentAngle = bDetect.Angle; RotAngle = CurrentAngle = bDetect.RAngle; NewResetBolt = CurrentResetBolt = blowing.OrgBoltNo; Kp = CurrentKp = heatCellService.Kp; vm1.OnLoaded(true); vm2.OnLoaded(); UpdateData(1); UpdateData(2); UpdateVarChart(); } public void UnLoaded(object s) { //var tmpVM = ViewModel_HeatDetector.Instance; //tmpVM.PropertyChanged -= DataSelecter_PropertyChanged; } private double[] vth1; private double[] vth2; private double[] vheat1; private double[] vheat2; private double rotAngle1; private int resetBolt1; private double rotAngle2; private int resetBolt2; private double[] correls; private void PickerVM_PropertyChanged(object s, PropertyChangedEventArgs e) { if (e.PropertyName == "SelectedFrame") { if (s.Equals(vm1)) { UpdateData(1); UpdateVarChart(); return; } if (s.Equals(vm2)) { UpdateData(2); UpdateVarChart(); return; } } } /// <summary> /// FramePicker改变时更新数据 /// </summary> /// <param name="whichframe"></param> private void UpdateData(int whichframe) { switch (whichframe) { case 1: vth1 = _data.GetThicksByIndex(vm1.SelectedFrame, 1, RotAngle); vheat1 = _data.GetHeatsByIndex(vm1.SelectedFrame, -1, -1); resetBolt1 = _data.GetResetBoltByIndex(vm1.SelectedFrame); rotAngle1 = _data.GetRotAngleByIndex(vm1.SelectedFrame); break; case 2: vth2 = _data.GetThicksByIndex(vm2.SelectedFrame, 1, RotAngle); vheat2 = _data.GetHeatsByIndex(vm2.SelectedFrame, -1, -1); resetBolt2 = _data.GetResetBoltByIndex(vm2.SelectedFrame); rotAngle2 = _data.GetRotAngleByIndex(vm2.SelectedFrame); break; default: return; } if ((vth1 == null) || (vth2 == null) || (vheat1 == null) || (vheat2 == null)) { return; } correls = _data.CalculateCorrelVector(DataHelper.VectorSub(vth1, vth2), DataHelper.VectorSub(vheat2, vheat1)); return; } /// <summary> /// 旋转角度变化时更新厚度数据 /// </summary> /// <returns></returns> private bool UpdateThickData() { vth1 = _data.GetThicksByIndex(vm1.SelectedFrame, 1, RotAngle); vth2 = _data.GetThicksByIndex(vm2.SelectedFrame, 1, RotAngle); if ((vth1 == null) || (vth2 == null) || (vheat1 == null) || (vheat2 == null)) { return false; } correls = _data.CalculateCorrelVector(DataHelper.VectorSub(vth1, vth2), DataHelper.VectorSub(vheat2, vheat1)); return true; } private ChartValues<double> tv = new ChartValues<double>(); private ChartValues<double> hv = new ChartValues<double>(); /// <summary> /// 更新图形,触发点: vm1,vm2的SelectFrame变化, /// ResetBolt的变化 /// RotAngle的变化 /// </summary> public void UpdateVarChart() { if ((vth1 == null) || (vth2 == null) || (vheat1 == null) || (vheat2 == null)) { return; } //var vth = vth1 - vth2; //var vheat = vheat2 - vheat1; //int cnt = vth.Count(); //int s = AirRingShift % cnt; //var tmp = vth.Concat(vth).Skip(s).Take(cnt); int cnt = vth1.Count(); int s = NewResetBolt - 1; //if (ResetBolt == int.MaxValue) //{ // s = 0; //} //else //{ // s = ResetBolt - resetBolt1; // //s = resetBolt1 + ResetBolt; //} //while (s >= cnt) s -= cnt; //while (s < 0) s += cnt; var vth = DataHelper.VectorSub(vth1, vth2); var tmp = vth.Concat(vth).Skip(cnt-s).Take(cnt).ToArray(); var vheat = DataHelper.VectorSub(vheat2, vheat1); DS_vthick = tmp; DS_vheat = vheat; tv.Clear();tv.AddRange(tmp); hv.Clear();hv.AddRange(vheat); if (VarSeries.Count == 0) { LineSeries ts = new LineSeries { Title = "厚度变化量", Values = tv, DataLabels = false, Fill = new SolidColorBrush(Colors.Transparent), ScalesYAt = 0, }; LineSeries hs = new LineSeries { Title = "加热变化量", Values = hv, DataLabels = false, Fill = new SolidColorBrush(Colors.Transparent), ScalesYAt = 1, }; VarSeries.Add(ts); VarSeries.Add(hs); } } public void AutoCal_Shift() {// 根据选定两幅计算偏转量 double[] corels = _data.CalculateCorrelVector(DataHelper.VectorSub(vth1, vth2), DataHelper.VectorSub(vheat2, vheat1)); var r = _data.CalculateAirRingShiftFromCorelVector(corels); NewResetBolt = r.Item1; TandH_Corel = r.Item2; } public void Change_Shift(int s) { if(s == int.MaxValue) { NewResetBolt = 1; //ResetBolt = _data.GetResetBoltByID(vm1.SelectedFrame); } else { NewResetBolt += s; } UpdateVarChart(); } public void Change_Angle(double angle) { if (double.IsNaN(angle)) { RotAngle = _data.GetRotAngleByIndex(vm1.SelectedFrame); return; } else { double tmp = RotAngle + angle; if ((tmp > 1) && (tmp < 360.0001)) { RotAngle = tmp; } return; } } public void SearchAngle() { var tmp = _data.SearchMaxSimilarity(vm1.SelectedFrame, vm2.SelectedFrame, 15, true); RotAngle = tmp.Item3; TandH_Corel = tmp.Item2; NewResetBolt = tmp.Item1; //int rb = AirRingShift + vm1.ResetBolt; //while (rb >= _data.BoltCnt) rb -= _data.BoltCnt; //while (rb < 0) rb += _data.BoltCnt; //ResetBolt = rb; } public void AutoSearchAndCal_Shift() { SearchEnabled = false; MaxSimilarityResult result = new MaxSimilarityResult(); int searchCnt = int.MaxValue; int start = vm1.MinFrame; int end = vm1.MaxFrame; if (LockFrames == 2) { int idx1 = vm1.SelectedFrame; int idx2 = vm2.SelectedFrame; if (!LockAngle) SearchAngle(); else { UpdateThickData(); var tmp = _data.CalculateAirRingShiftFromCorelVector(correls); NewResetBolt = tmp.Item1; TandH_Corel = tmp.Item2; } var heat = DataHelper.VectorSub(_data.GetHeatsByIndex(idx1, -1, -1), _data.GetHeatsByIndex(idx2, -1, -1)); var t1 = _data.GetThicksByIndex(idx1, NewResetBolt, double.MaxValue); var th = DataHelper.VectorSub(_data.GetThicksByIndex(idx2, NewResetBolt, double.MaxValue), t1); Kp = _data.CalculateHeatToThickFactor(heat, th, Misc.MyMath.Avg(t1)); //double b; //double a; //Misc.MyMath.Linest(heat, th, out a, out b); //Kp = a; SearchEnabled = true; UpdateVarChart(); return; } if (LockFrames == 1) { searchCnt = 1; end = vm2.SelectedFrame; } _data.StartSearchMaxSimilarity(start, end, searchCnt, 5, result, (o, e) => { SearchProgressValue = e.ProgressPercentage; }, (o, e) => { if (result.frameIdx1 < 0 || result.frameIdx2 < 0) return; int rb = _data.GetResetBoltByIndex(result.frameIdx2); double ra = _data.GetRotAngleByIndex(result.frameIdx2); SearchProgressValue = 0; SearchEnabled = true; vm2.SelectedFrame = result.frameIdx1; vm1.SelectedFrame = result.frameIdx2; NewResetBolt = result.frameShift; TandH_Corel = result.similarity; Kp = result.ThickToHeatFactor; //rb += AirRingShift; //while (rb >= _data.BoltCnt) rb -= _data.BoltCnt; //while (rb < 0) rb += _data.BoltCnt; //ResetBolt = rb; if (result.deltaAngle > 100) RotAngle = result.deltaAngle; UpdateVarChart(); }, int.MaxValue, 15, !LockAngle, true); } public double[] ExpandOrShrinkData(double[] ori, int orideg, int dstdeg) { double[] ori_dat = new double[360]; double[] dst_dat = new double[360]; int bolts = ori.Count(); double org_deg_per_bolt = 360 / bolts; double curr_deg_bolt = org_deg_per_bolt; int bolt_idx = 0; int i; for (i = 0; i < orideg; i++) { if (i < curr_deg_bolt) { ori_dat[i] = ori[bolt_idx]; } else { bolt_idx++; curr_deg_bolt += org_deg_per_bolt; } } for (; i < 360; i++) { ori_dat[i] = double.NaN; } int i1 = dstdeg, j1 = 0, j = 0; i = 0; double acc = 0; int remain = orideg; while (j < dstdeg) { while (remain > 0) { if (i1 >= j1 + remain) { acc += remain * ori_dat[i]; dst_dat[j++] = acc / orideg; acc = 0; j1 += remain; remain = orideg; break; } else if (i1 > j1) { acc += (i1 - j1) * ori_dat[i]; j1 = i1; remain -= (i1 - j1); i++; i1 += dstdeg; continue; } else { i++; i1 += dstdeg; continue; } } } for (; j < 360; j++) { dst_dat[j] = double.NaN; } return dst_dat; } public event PropertyChangedEventHandler PropertyChanged; } }