Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/71.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何通过几个点绘制贝塞尔曲线?_C#_.net_Canvas_Bezier - Fatal编程技术网

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

C# 如何通过几个点绘制贝塞尔曲线?,c#,.net,canvas,bezier,C#,.net,Canvas,Bezier,我有几个要点,我试着用下面的代码画贝塞尔曲线 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; Pa

我有几个要点,我试着用下面的代码画贝塞尔曲线

 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个小的椭圆(是我的点)):


您得到的直线是三条不同的贝塞尔曲线的并集-每组三个点一条。(每个“贝塞尔段”一个)

如果需要单个平滑曲线,则需要将9个(或更多)点作为单个点集合(单个“Bezier段”)传递,而不是作为三个点的组传递

编辑:显然只支持三个点,所以难怪这不起作用。甚至只给出一组贝塞尔线段,而不是一个平滑的贝塞尔线段

所以,既然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);
}
给予


由于每条曲线都有一个控制点(一个影响曲线但不一定在曲线上的点),因此使用的是二次Bézier曲线

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


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

我看到有这个图是很自然的,你能用所需的曲线发布一个链接吗?或者,也许,你想用7个控制点绘制一个线段?这太酷了!帮了我很多忙!非常感谢。近似值不正确,使控制路径为圆形,并且绘制的是elipsoid。您可能需要重新考虑近似数学。您可能需要重新考虑如何绘制圆?非常感谢,非常好,尽管我发现GetBezierPoint的第1行必须是“if(count==0)”
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);
}