2012-12-18 101 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

黑色实光盘是端点。空心圆是控制点。黑色实线是曲线。虚线表示每个端点与两侧的控制点共线(在一条直线上)。