C# 如何通过几个点绘制贝塞尔曲线?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13940983/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-10 10:09:55  来源:igfitidea点击:

How to draw bezier curve by several points?

c#.netcanvasbezier

提问by Roman Bats

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

My Bezier segments look like this

我的贝塞尔曲线段看起来像这样

  • 1,2,3 points - first segment
  • 3,4,5 points - second
  • 5,6,7.. ..
  • 1,2,3 点 - 第一段
  • 3,4,5 点 - 秒
  • 5、6、7……

But I got this strange curve (here is 3 big (Nodes) and 7 small ellipse (is my points)):

但是我得到了这条奇怪的曲线(这里有 3 个大(节点)和 7 个小椭圆(是我的点)):

enter image description here

在此处输入图片说明

采纳答案by Rawling

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.

如果您想要一条平滑的曲线,则需要将 9 个(或更多)点作为单个点集合(单个“贝塞尔线段”?)传递,而不是作为三个点的组传递。

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

编辑:显然BezierSegment支持三点,所以难怪这不起作用。甚至“PolyBezierSegment”也只是给出了一系列贝塞尔曲线段,而不是一个平滑的贝塞尔曲线……

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:

因此,由于 WPF 没有为您提供任何有用的信息,因此我在这里使用数学计算出一些东西。这是一个数字解决方案,但即使有足够的点看起来漂亮和平滑,它似乎也非常高效:

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

在此处输入图片说明

回答by rob mayoff

Since each of your curves has one control point (a point that influences the curve but isn't necessarily on the curve), you're using quadratic Bézier curves.

由于每条曲线都有一个控制点(影响曲线但不一定在曲线上的点),因此您使用的是二次贝塞尔曲线。

If you want to draw two quadratic curves that share an endpoint, and you want the joint to appear smooth, the control points on each side of the shared endpoint must be collinear with the endpoint. That is, the two control points and the endpoint between them must all lie on a straight line. Example:

如果要绘制两条共享端点的二次曲线,并且希望关节看起来平滑,则共享端点每一侧的控制点必须与端点共线。也就是说,两个控制点和它们之间的端点必须都在一条直线上。例子:

quadratics with smooth joints

具有光滑关节的二次方程

The solid black discs are the endpoints. The hollow circles are the control points. The solid black line is the curve. The dotted lines show that each endpoint is collinear (on a straight line with) the control point on either side.

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