貝塞爾曲線 WPF MVVM N階實現 公式詳解+原始碼下載
阿新 • • 發佈:2018-12-12
效果圖:
本程式主要實現:
- N階貝塞爾曲線(通用公式)
本程式主要使用技術
- MVVM
- InterAction 事件繫結
- 動態新增Canvas的Item
第一部分公式:
- n=有效座標點數量
- i=座標點的下標
- P是座標
- t是時間0~1之間
有效座標點是座標點的數量減1
計算座標時分開計算,x,y時分別計算兩邊
至於括號內上n下i是組合數
計算方法是:
換成貝塞爾的公式中的組合數是:
剩下部分應該是很簡單了。
因為是求和,所以先是代入公式最後相加即可
例子(摘自百度)
3階
2階
現在給出程式碼的部分
階乘程式碼:
private int Factorial(int n) { if (n == 0) { return 1; } else { return n * Factorial(n - 1); } }
組合數公式程式碼:
private int GetCA(int r, int n) => Factorial(r) / (Factorial(n) * Factorial((r - n)));
貝塞爾
/// <summary> /// 求單座標貝塞爾公式 /// </summary> /// <param name="Max">最大有效座標點的數量</param> /// <param name="Index">需要計算的座標點的下標</param> /// <param name="Time">時間0~1</param> /// <param name="P">單個座標值(x或者y)</param> /// <returns></returns> private double GetPoints(int Max, int Index, double Time, double P) { var C = GetCA(Max, Index); var T1 = Math.Pow(Time, Index); var T2 = Math.Pow((1 - Time), Max - Index); return (C * T1 * T2 * P); }
使用方式
private void SetPoints(Polyline polyline) { polyline.Points.Clear(); double ax = 0; double ay = 0; for (double t = 0.00; t < 1.01; t += 0.01) { for (int i = 0; i < Points.Count; i++) { ax += GetPoints(Points.Count - 1, i, t, Points[i].X); ay += GetPoints(Points.Count - 1, i, t, Points[i].Y); } //此處的ax ay為t時,i下標的有效Points[i].X 座標點 和Points[i].Y座標點的Points.Count - 1階貝塞爾曲線 polyline.Points.Add(new Point(ax, ay)); ax = 0; ay = 0; } SetText(polyline.Points); }
第二部分 MVVM的事件繫結
MVVM事件繫結需要使用
System.Windwos.Interactiivity.dll
一般來說使用NuGet搜尋Expression.Blend.Sdk.WPF就可以了
使用方式為
先建立實現 TriggerAction<DependencyObject>介面類
public class EventCommand : TriggerAction<DependencyObject> { public static readonly DependencyProperty CommandProperty = DependencyProperty.Register("Command", typeof(ICommand), typeof(EventCommand), null); public static readonly DependencyProperty CommandParameterProperty = DependencyProperty.Register("CommandParameter", typeof(object), typeof(EventCommand), null); public ICommand Command { get { return (ICommand)GetValue(CommandProperty); } set { SetValue(CommandProperty, value); } } public object CommandParameter { get { return GetValue(CommandParameterProperty); } set { SetValue(CommandParameterProperty, value); } } protected override void Invoke(object parameter) { if (this.AssociatedObject != null) { ICommand command = this.Command; if (command != null) { if (this.CommandParameter != null) { if (command.CanExecute(this.CommandParameter)) { command.Execute(this.CommandParameter); } } else { if (command.CanExecute(parameter)) { command.Execute(new Tuple<object, object>(this.AssociatedObject, parameter)); } } } } } }
其次是在XAML頁面新增引用
分別為
<!--此處時引用interactivity的dll--> xmlns:event="http://schemas.microsoft.com/expression/2010/interactivity" <!--此處時引用剛才實現的介面類--> xmlns:Action="clr-namespace:MVVM_貝塞爾曲線任意點實現.Command"
使用方式:
<ItemsControl Grid.ColumnSpan="2" ItemsSource="{Binding UI}"> <event:Interaction.Triggers> <!--此處EventName為事件標準名稱--> <event:EventTrigger EventName="MouseLeftButtonUp"> <Action:EventCommand Command="{Binding MouseLeftButtonUpCommand}"/> </event:EventTrigger> </event:Interaction.Triggers> <ItemsControl.ItemsPanel> <ItemsPanelTemplate> <Canvas Background="Transparent"/> </ItemsPanelTemplate> </ItemsControl.ItemsPanel> <ItemsControl.ItemContainerStyle> <Style> <Setter Property="Canvas.Left" Value="{Binding X}"/> <Setter Property="Canvas.Top" Value="{Binding Y}"/> </Style> </ItemsControl.ItemContainerStyle> <ItemsControl.ItemTemplate> <DataTemplate> <ContentControl Content="{Binding UI}"/> </DataTemplate> </ItemsControl.ItemTemplate> </ItemsControl>
VIewMolde部分則是正常使用即可
剩餘部分
可以看看原始碼