1. 程式人生 > >貝塞爾曲線 WPF MVVM N階實現 公式詳解+原始碼下載

貝塞爾曲線 WPF MVVM N階實現 公式詳解+原始碼下載

原始碼下載

效果圖:

 

 

本程式主要實現:

  • 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部分則是正常使用即可

 

剩餘部分

可以看看原始碼