How to draw bezier curve by several points?

后端 未结 2 1500
[愿得一人]
[愿得一人] 2020-12-28 22:44

I have several points, and I try to draw Bezier curve using code below

 PathFigure pf = new PathFigure(points.From, ps, false); //ps - list of Bezier segment         


        
2条回答
  •  梦谈多话
    2020-12-28 22:59

    The line you're getting is the union of three distinct Bezier curves - one for each group of three points. (One for each "Bezier segment"?)

    If you want a single smooth curve, you need to pass your 9 (or more) points as a single collection of points (single "Bezier segment"?), not as groups of three points.

    Edit: Apparently BezierSegment only supports three points, so no wonder this doesn't work. Even 'PolyBezierSegment' just gives a collection of Bezier segments rather than a single smooth Bezier...

    So since WPF doesn't give you anything useful, I knocked something together using the maths here. It's a numeric solution, but it seems to be pretty performant even with enough points to look nice and smooth:

    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);
    }
    

    Using this,

    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);
    }
    

    gives

    enter image description here

提交回复
热议问题