Commit 45bb6303 authored by 潘栩锋's avatar 潘栩锋 🚴

添加 完成机架修正的 关键点插入方式拟合

parent 94bbae44
......@@ -293,16 +293,31 @@
<StackPanel Orientation="Horizontal">
<StackPanel Orientation="Horizontal">
<Button Content="添加" Command="{Binding AddKeyPointModeCmd}" Style="{StaticResource Styles.Button.Square2}"/>
<Button Content="删除" Command="{Binding RemoveKeyPointModeCmd}" Style="{StaticResource Styles.Button.Square2}" />
<Button Content="移动" Command="{Binding MoveKeyPointModeCmd}" Style="{StaticResource Styles.Button.Square2}" />
<Button Content="生成" Command="{Binding CreateCorrByKeyPointCmd}" >
<Button Content="添加" Command="{Binding AddKeyPointModeCmd}" >
<Button.Style>
<Style TargetType="Button" BasedOn="{StaticResource Styles.Button.Square.Accent2}">
<Style TargetType="Button" BasedOn="{StaticResource Styles.Button.Square2}">
<Style.Triggers>
<DataTrigger Binding="{Binding KpSelectMode}" Value="{x:Static local:KeyPointsSelectMode.Add}" >
<Setter Property="IsEnabled" Value="False"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
<Button Content="删除" Command="{Binding RemoveKeyPointModeCmd}" >
<Button.Style>
<Style TargetType="Button" BasedOn="{StaticResource Styles.Button.Square2}">
<Style.Triggers>
<DataTrigger Binding="{Binding KpSelectMode}" Value="{x:Static local:KeyPointsSelectMode.Remove}" >
<Setter Property="IsEnabled" Value="False"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
<Button Style="{StaticResource Styles.Button.Square.Accent2}"
Content="生成" Command="{Binding CreateCorrByKeyPointCmd}" />
</StackPanel>
</StackPanel>
</StackPanel>
......
......@@ -78,7 +78,7 @@ namespace FLY.Thick.Base.UI
//pEnd = closetsPoint;
pEnd = p;
vm.Select(pBegin, pEnd);
vm.Select(PgScanCorrVm.SelectType.Move, pBegin, pEnd);
}
......@@ -105,7 +105,7 @@ namespace FLY.Thick.Base.UI
//}
//cpBegin = closetsPoint;
vm.Select(pBegin, pBegin);
vm.Select(PgScanCorrVm.SelectType.Click, pBegin, pBegin);
}
private void UIElement_MouseUp(object sender, MouseButtonEventArgs e)
......@@ -132,7 +132,7 @@ namespace FLY.Thick.Base.UI
//if (closetsPoint == null)
// return;
pEnd = p;
vm.Select(pBegin, pEnd);
vm.Select(PgScanCorrVm.SelectType.Cancel, pBegin, pEnd);
}
}
......
......@@ -3,6 +3,7 @@ using GalaSoft.MvvmLight.Command;
using LiveCharts;
using LiveCharts.Configurations;
using LiveCharts.Wpf;
using MathNet.Numerics.LinearAlgebra.Double;
using Microsoft.Win32;
using Misc;
using OfficeOpenXml;
......@@ -93,6 +94,7 @@ namespace FLY.Thick.Base.UI
}
public SeriesInfo[] SeriesInfos { get; set; }
ChartValues<XY> KeyPointDatas = new ChartValues<XY>();
CartesianMapper<XY> Mapper { get; set; }
#endregion
......@@ -165,27 +167,10 @@ namespace FLY.Thick.Base.UI
#endregion
#region 关键点方式生成修正曲线
/// <summary>
/// 关键点列表,单位grid
/// </summary>
public ObservableCollection<int> KeyPoints = new ObservableCollection<int>();
/// <summary>
/// 每个关键点的数据宽度 单位grid
/// </summary>
public int KeyPointWidth { get; set; }
/// <summary>
/// 选择中
/// </summary>
public bool IsSelecting => SelectObj != SELECT_OBJ.Null;
public SELECT_OBJ SelectObj { get; set; } = SELECT_OBJ.Null;
public enum SELECT_OBJ
{
Null,
Add,
Remove,
Move
}
public KeyPointsSelectMode KpSelectMode { get; set; } = KeyPointsSelectMode.Null;
#endregion
/// <summary>
......@@ -196,6 +181,7 @@ namespace FLY.Thick.Base.UI
public double AvgAd { get; set; }
#region CMD
public RelayCommand SelectedGroup0Cmd { get; }
public RelayCommand SelectedGroup1Cmd { get; }
......@@ -218,9 +204,12 @@ namespace FLY.Thick.Base.UI
public RelayCommand SaveXlsxCmd { get; }
public RelayCommand LoadXlsxCmd { get; }
#endregion
IScanCorrService scanCorrService;
IInitParamService initParamService;
ITDGageService gageService;
KeyPointLine keyPointLine;
public PgScanCorrVm()
{
......@@ -237,9 +226,9 @@ namespace FLY.Thick.Base.UI
{
return $"{ y:F0}";
};
//Mapper = Mappers.Xy<XY>()
// .X((value, index) => value.X)
// .Y(value => value.Y);
Mapper = Mappers.Xy<XY>()
.X((value, index) => value.X)
.Y(value => value.Y);
SeriesInfos = new SeriesInfo[] {
new SeriesInfo(){Name = "正向原始", Color = FLY.ControlLibrary.Themes.Styles.GetForeground(0)},
......@@ -260,12 +249,31 @@ namespace FLY.Thick.Base.UI
StrokeThickness = 2,
Fill = new SolidColorBrush(System.Windows.Media.Colors.Transparent),
Stroke = seriesInfo.Color,
PointGeometry = null,
Configuration = Mapper
PointGeometry = null
};
Series.Add(lineSeries);
}
keyPointLine = new KeyPointLine();
Misc.BindingOperations.SetBinding(this, nameof(SmoothFactor), keyPointLine, nameof(keyPointLine.SmoothFactor));
{
var lineSeries = new LineSeries
{
Values = KeyPointDatas,
StrokeThickness = 6,
Fill = new SolidColorBrush(System.Windows.Media.Colors.Transparent),
Stroke = FLY.ControlLibrary.Themes.Styles.GetForeground(2),
Configuration = Mapper,
//PointGeometry = Geometry.
PointGeometrySize = 15,
//PointForeground = "#222E31"
};
Series.Add(lineSeries);
}
keyPointLine.KeyPoints.CollectionChanged += (s, e) =>
{
UpdateKeyPointDatas();
};
#endregion
StopCmd = new RelayCommand(Stop);
......@@ -392,71 +400,47 @@ namespace FLY.Thick.Base.UI
private void MoveKeyPointMode()
{
SelectObj = SELECT_OBJ.Move;
KpSelectMode = KeyPointsSelectMode.Move;
}
private void RemoveKeyPointMode()
{
SelectObj = SELECT_OBJ.Remove;
KpSelectMode = KeyPointsSelectMode.Remove;
}
private void AddKeyPointMode()
{
SelectObj = SELECT_OBJ.Add;
KpSelectMode = KeyPointsSelectMode.Add;
}
private void CancelKeyPointMode() {
SelectObj = SELECT_OBJ.Null;
KpSelectMode = KeyPointsSelectMode.Null;
}
List<XY> GetKeyValues(ChartValues<double> orgDatas) {
List<XY> keyValues = new List<XY>();
for (int i = 0; i < KeyPoints.Count(); i++) {
int x = KeyPoints[i];
double sum = 0;
int cnt = 0;
for (int j = 0; j < KeyPointWidth; j++)
{
int index = x - KeyPointWidth / 2 + j;
if (index < 0)
continue;
else if (index >= orgDatas.Count())
break;
if(!double.IsNaN(orgDatas[index]))
{
sum += orgDatas[index];
cnt++;
}
}
double y;
if (cnt > 0)
y = sum / cnt;
else
y = double.NaN;
keyValues.Add(new XY() { X = x, Y = y });
}
return keyValues;
}
private void CreateCorrByKeyPoint()
{
//if (KeyPoints.Count() < 2)
//{
// //少于2个点
// FLY.ControlLibrary.Window_WarningTip.Show("异常", $"关键点必须多于2个", TimeSpan.FromSeconds(2));
// return;
//}
////TODO
////1.计算出全部关键点的值
//var keyValues = GetKeyValues(SeriesInfos[0].Datas);
////2.生成样条曲线
CancelKeyPointMode();
if (keyPointLine.KeyPoints.Count() < 3)
{
//少于3个点
FLY.ControlLibrary.Window_WarningTip.Show("异常", $"关键点必须≥3个", TimeSpan.FromSeconds(2));
return;
}
for (int i = 0; i < 2; i++) {
var filterDatas = keyPointLine.CalFilterDatas(SeriesInfos[i].Datas);
SeriesInfos[i + 2].Datas.Clear();
SeriesInfos[i + 2].Datas.AddRange(filterDatas);
}
//计算平均值
double avg0 = SeriesInfos[2].Datas.AverageNoNull();
double avg1 = SeriesInfos[3].Datas.AverageNoNull();
AvgAd = (int)((avg0 + avg1) / 2);
//FLY.ControlLibrary.Window_Tip.Show("生成成功",
// null,
// TimeSpan.FromSeconds(2));
FLY.ControlLibrary.Window_Tip.Show("生成成功",
null,
TimeSpan.FromSeconds(2));
}
......@@ -517,7 +501,7 @@ namespace FLY.Thick.Base.UI
//下载数据
scanCorrService.GetScanCorrGroup(SelectedGroupIndex, scanCorrService_GetScanCorrGroup, null);
keyPointLine.Clear();
}
void scanCorrService_GetScanCorrGroup(object asyncContext, object retData)
......@@ -585,40 +569,50 @@ namespace FLY.Thick.Base.UI
}
}
public void Select(System.Windows.Point cpBegin, System.Windows.Point cpEnd)
public enum SelectType
{
Click,
Move,
Cancel
}
public void Select(SelectType selectType, System.Windows.Point cpBegin, System.Windows.Point cpEnd)
{
if (SelectObj == SELECT_OBJ.Null)
if (KpSelectMode == KeyPointsSelectMode.Null)
return;
switch (KpSelectMode) {
case KeyPointsSelectMode.Add:
{
if (selectType != SelectType.Click)
return;
keyPointLine.Add(cpBegin.X, SeriesInfos[0].Datas);
return;
}
break;
case KeyPointsSelectMode.Remove:
{
if (selectType != SelectType.Click)
return;
keyPointLine.Remove(cpBegin.X);
return;
}
break;
case KeyPointsSelectMode.Move:
{
keyPointLine.Move(cpEnd.X, SeriesInfos[0].Datas);
if (selectType == SelectType.Cancel)
keyPointLine.ResetSelected();
}
break;
}
}
//double xMin = Math.Min(cpBegin.X, cpEnd.X);
//double xMax = Math.Max(cpBegin.X, cpEnd.X);
//int posMin = (int)(xMin * PosOfGrid);
//int posMax = (int)(xMax * PosOfGrid);
////int adMin = (int)Math.Min(cpBegin.Y, cpEnd.Y);
////int adMax = (int)Math.Max(cpBegin.Y, cpEnd.Y);
//int posEnd = (int)(cpEnd.X * PosOfGrid);
//int adEnd = (int)cpEnd.Y;
//switch (SelectObj)
//{
// case SELECT_OBJ.Valid:
// {
// SetValid(posMin, posMax);
// }
// break;
// case SELECT_OBJ.Sample:
// {
// SetSample(Samples, posEnd, adEnd);
// }
// break;
// case SELECT_OBJ.Sample2:
// {
// SetSample(Samples2, posEnd, adEnd);
// }
// break;
//}
void UpdateKeyPointDatas()
{
KeyPointDatas.Clear();
KeyPointDatas.AddRange(keyPointLine.KeyPoints);
}
......@@ -885,4 +879,252 @@ namespace FLY.Thick.Base.UI
#endregion
}
/// <summary>
/// 生成关键点曲线
/// </summary>
public class KeyPointLine:INotifyPropertyChanged
{
public ObservableCollection<XY> KeyPoints { get; } = new ObservableCollection<XY>();
public int SmoothFactor { get; set; } = 20;
public int SelectedIndex { get; private set; } = -1;
public event PropertyChangedEventHandler PropertyChanged;
public void Add(double x, IEnumerable<double> orgDatas)
{
ResetSelected();
int index = FindIndex(x);
if (index == -1)
{
double y = CalY(x, orgDatas);
//没有,可以添加
Insert(x, y);
}
}
public void Remove(double x)
{
ResetSelected();
int index = FindIndex(x);
if (index == -1)
{
return;
}
KeyPoints.RemoveAt(index);
}
public void Move(double x, IEnumerable<double> orgDatas)
{
if (SelectedIndex>=0 && SelectedIndex<KeyPoints.Count())
{
if (SelectedIndex - 1 >= 0
&& x <= KeyPoints[SelectedIndex - 1].X)
{
// 移过头了,停!!!!
//换个点
SelectedIndex--;
return;
}
if (SelectedIndex + 1 < KeyPoints.Count()
&& x >= KeyPoints[SelectedIndex + 1].X)
{
// 移过头了,停!!!!
//换个点
SelectedIndex++;
return;
}
double y = CalY(x,orgDatas);
KeyPoints[SelectedIndex] = new XY() { X = x, Y = y };
}
else {
SelectedIndex = FindIndex(x);
}
}
public void Clear() {
ResetSelected();
KeyPoints.Clear();
}
public void ResetSelected() {
SelectedIndex = -1;
}
/// <summary>
/// 计算 位置为x 在 orgDatas中的y
/// </summary>
/// <param name="x"></param>
/// <param name="orgDatas"></param>
/// <returns></returns>
double CalY(double x, IEnumerable<double> orgDatas)
{
double sum = 0;
int cnt = 0;
for (int j = 0; j < SmoothFactor; j++)
{
int index = (int)(x - SmoothFactor / 2 + j);
if (index < 0)
continue;
else if (index >= orgDatas.Count())
break;
var value = orgDatas.ElementAt(index);
if (!double.IsNaN(value))
{
sum += value;
cnt++;
}
}
if (cnt > 0)
return sum / cnt;
else
return double.NaN;
}
int FindIndex(double x)
{
for (int i = 0; i < KeyPoints.Count(); i++)
{
if (Math.Abs(KeyPoints[i].X - x) < SmoothFactor / 2)
{
return i;
}
}
return -1;
}
int Insert(double x, double y)
{
for (int i = 0; i < KeyPoints.Count(); i++)
{
if (x < KeyPoints[i].X)
{
//就在它前面插入
KeyPoints.Insert(i, new XY() { X = x, Y = y });
return i;
}
}
//在最后添加
KeyPoints.Add(new XY() { X = x, Y = y });
return KeyPoints.Count() - 1;
}
List<XY> GetKeyValues(IEnumerable<double> orgDatas)
{
List<XY> keyValues = new List<XY>();
for (int i = 0; i < KeyPoints.Count(); i++)
{
int x = (int)KeyPoints[i].X;
double sum = 0;
int cnt = 0;
for (int j = 0; j < SmoothFactor; j++)
{
int index = x - SmoothFactor / 2 + j;
if (index < 0)
continue;
else if (index >= orgDatas.Count())
break;
var value = orgDatas.ElementAt(index);
if (!double.IsNaN(value))
{
sum += value;
cnt++;
}
}
double y;
if (cnt > 0)
y = sum / cnt;
else
y = double.NaN;
keyValues.Add(new XY() { X = x, Y = y });
}
return keyValues;
}
DenseVector Solve(List<XY> keyValues, int i) {
DenseMatrix X = new DenseMatrix(3, 3);
DenseVector Y = new DenseVector(3);
var kv0 = keyValues[i - 1];
var kv1 = keyValues[i];
var kv2 = keyValues[i + 1];
X.SetRow(0, new double[] { kv0.X * kv0.X, kv0.X, 1 });
X.SetRow(1, new double[] { kv1.X * kv1.X, kv1.X, 1 });
X.SetRow(2, new double[] { kv2.X * kv2.X, kv2.X, 1 });
Y.SetValues(new double[] { kv0.Y, kv1.Y, kv2.Y });
DenseVector abc = (DenseVector)X.Solve(Y);
return abc;
}
public double[] CalFilterDatas(IEnumerable<double> orgDatas)
{
List<XY> keyValues = GetKeyValues(orgDatas);
//计算每个点的2次方程 a,b,c
List<DenseVector> abcList = new List<DenseVector>();
for (int i = 0; i < keyValues.Count(); i++)
{
if (i == 0)
{
DenseVector abc = Solve(keyValues, 1);
abcList.Add(abc);
}
else if (i == 1)
{
abcList.Add(abcList.Last());
}
else if (i == keyValues.Count() - 1)
{
abcList.Add(abcList.Last());
}
else {
DenseVector abc = Solve(keyValues, i);
abcList.Add(abc);
}
}
double[] filterDatas = new double[orgDatas.Count()];
int begin = -1;
for (int i = 0; i < keyValues.Count(); i++)
{
int j = (int)keyValues[i].X;
filterDatas[j] = keyValues[i].Y;
for (j=j-1; j > begin; j--)
{
double y = abcList[i][0] * j * j + abcList[i][1] * j + abcList[i][2];
if (i - 1 >= 0) {
double y_pre = abcList[i - 1][0] * j * j + abcList[i - 1][1] * j + abcList[i - 1][2];
//权重
double t = (j - keyValues[i - 1].X) / (keyValues[i].X - keyValues[i - 1].X);
y = t*y +(1 - t) * y_pre;
}
filterDatas[j] = y;
}
begin = (int)keyValues[i].X;
}
//计算最后的
{
int i = keyValues.Count() - 1;
for (int j = begin + 1; j < filterDatas.Count(); j++) {
double y = abcList[i][0] * j * j + abcList[i][1] * j + abcList[i][2];
filterDatas[j] = y;
}
}
return filterDatas;
}
}
public enum KeyPointsSelectMode
{
Null,
Add,
Remove,
Move
}
}
......@@ -132,27 +132,10 @@ namespace FLY.Thick.Base.UI
#endregion
#region 关键点方式生成修正曲线
/// <summary>
/// 关键点列表,单位grid
/// </summary>
public ObservableCollection<int> KeyPoints = new ObservableCollection<int>();
/// <summary>
/// 每个关键点的数据宽度 单位grid
/// </summary>
public int KeyPointWidth { get; set; }
/// <summary>
/// 选择中
/// </summary>
public bool IsSelecting => SelectObj != SELECT_OBJ.Null;
public SELECT_OBJ SelectObj { get; set; } = SELECT_OBJ.Null;
public enum SELECT_OBJ
{
Null,
Add,
Remove,
Move
}
public KeyPointsSelectMode KpSelectMode { get; set; } = KeyPointsSelectMode.Null;
#endregion
/// <summary>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment