2012-12-18 149 views
9

我有幾個點,我嘗試使用代碼來繪製下面如何通過幾個點來繪製貝塞爾曲線?

PathFigure pf = new PathFigure(points.From, ps, false); //ps - list of Bezier segments 
    PathFigureCollection pfc = new PathFigureCollection(); 
    pfc.Add(pf); 
    var pge = new PathGeometry(); 
    pge.Figures = pfc; 
    Path p = new Path(); 
    p.Data = pge; 
    p.Stroke = new SolidColorBrush(Color.FromRgb(244, 111, 011)); 

我貝塞爾段貝塞爾曲線看起來像這樣

  • 1,2,3點 - 第一部分
  • 3, 4,5點 - 第二
  • 5,6,7 ..

但我得到這個奇怪的曲線(這裏是3大(節點)和7個小橢圓(是我的點)):

enter image description here

+0

我看到有這個數字是很自然的,你可以發佈一個具有所需曲線的鏈接嗎? –

+0

或者,也許你想繪製一個單獨的部分與7個控制點? –

回答

18

你得到的線是三個不同的貝塞爾曲線的結合 - 每個組的三個點。 (每一個「Bezier段」?)

如果你想要一個平滑的曲線,你需要將你的9點(或更多)點作爲點的單個集合(單個「Bezier段」?),而不是三點組。

編輯︰顯然BezierSegment只有支持三點,所以難怪這不起作用。即使'PolyBezierSegment'只是給貝塞爾細分的集合,而不是一個光滑的貝塞爾...

因此,既然WPF不給你任何有用的東西,我使用數學here敲了一些東西。這是一個數字解決方案,但它似乎是即使有足夠的積分,好看,光滑漂亮的高性能:

PolyLineSegment GetBezierApproximation(Point[] controlPoints, int outputSegmentCount) 
{ 
    Point[] points = new Point[outputSegmentCount + 1]; 
    for (int i = 0; i <= outputSegmentCount; i++) 
    { 
     double t = (double)i/outputSegmentCount; 
     points[i] = GetBezierPoint(t, controlPoints, 0, controlPoints.Length); 
    } 
    return new PolyLineSegment(points, true); 
} 

Point GetBezierPoint(double t, Point[] controlPoints, int index, int count) 
{ 
    if (count == 1) 
     return controlPoints[index]; 
    var P0 = GetBezierPoint(t, controlPoints, index, count - 1); 
    var P1 = GetBezierPoint(t, controlPoints, index + 1, count - 1); 
    return new Point((1 - t) * P0.X + t * P1.X, (1 - t) * P0.Y + t * P1.Y); 
} 

利用這一點,

private void Grid_Loaded(object sender, RoutedEventArgs e) 
{ 
    Point[] points = new[] { 
      new Point(0, 200), 
      new Point(0, 0), 
      new Point(300, 0), 
      new Point(350, 200), 
      new Point(400, 0) 
     }; 
    var b = GetBezierApproximation(points, 256); 
    PathFigure pf = new PathFigure(b.Points[0], new[] { b }, false); 
    PathFigureCollection pfc = new PathFigureCollection(); 
    pfc.Add(pf); 
    var pge = new PathGeometry(); 
    pge.Figures = pfc; 
    Path p = new Path(); 
    p.Data = pge; 
    p.Stroke = new SolidColorBrush(Color.FromRgb(255, 0, 0)); 
    ((Grid)sender).Children.Add(p); 
} 

enter image description here

+0

這是超級酷!幫助了我很多!謝謝! – Gilad

+0

不正確的近似值,使控制路徑爲圓形,並繪製一個elipsoid。您可能需要重新考慮近似數學。 – SoLaR

+2

@SoLaR [使用Beziers製作圓形是不可能的](http://stackoverflow.com/questions/1734745/how-to-create-circle-with-b%C3%A9zier-curves)。你可能需要重新思考如何繪製一個圓圈? – Rawling

12

由於每條曲線都有一個控制點(一個影響曲線但不一定在曲線上的點),因此您使用的是二次Bézier曲線。

如果要繪製共享端點的兩條二次曲線,並且希望該連接看起來平滑,則共享端點每邊的控制點必須與端點共線。也就是說,兩個控制點和它們之間的端點必須全部位於一條直線上。例如:

quadratics with smooth joints

黑色實光盤是端點。空心圓是控制點。黑色實線是曲線。虛線表示每個端點與兩側的控制點共線(在一條直線上)。