65.9K
CodeProject 正在变化。 阅读更多。
Home

绘制简单贝塞尔曲线的中点算法(分治法)

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.79/5 (19投票s)

2011年7月9日

CPOL

3分钟阅读

viewsIcon

59612

downloadIcon

3169

一个简单的程序,帮助理解用于构建贝塞尔曲线的中点算法。

引言

贝塞尔曲线是一种参数曲线,常用于计算机图形学及相关领域。在矢量图形中,贝塞尔曲线用于建模可无限缩放的平滑曲线。构建贝塞尔曲线的方法有很多种。这个简单的程序使用中点算法来构建贝塞尔曲线。为了展示算法中分治法的特性,使用递归函数来实现贝塞尔曲线片段的构造。

mainWindow.JPG

构建贝塞尔曲线

该程序基于三个可以手动调整的点来构建贝塞尔曲线。下面的动画展示了在代码中,我们用两次中点法迭代构建贝塞尔曲线时究竟发生了什么。

midpoint.gif

以红色显示的这些点是初始点。在给出初始点之后,它会计算位于三个初始点之间的每条线的中间点。这些新计算的中间点以绿色显示。将颜色变为蓝色的点将在最终的贝塞尔曲线上。颜色变化的顺序与代码中计算贝塞尔曲线点的顺序相同。使用给定的点和两次迭代近似的贝塞尔曲线由一组红色的直线表示。

Using the Code

  • BezierCurve:负责构建贝塞尔曲线的类。
  • CustomCanvas:负责曲线的图形视图和点操作的类。

函数

private void CreateBezier(PointF ctrl1, PointF ctrl2, PointF ctrl3)
{
    bezierPoints = new List<PointF>();
    bezierPoints.Clear();
    bezierPoints.Add(ctrl1); // add the first control point
    PopulateBezierPoints(ctrl1, ctrl2, ctrl3, 0);
    bezierPoints.Add(ctrl3);// add the last control point
}

此函数将三个点作为参数,然后填充曲线的点列表。点 ctrl1 (曲线的起始端点) 显然在曲线上,因此将其添加到列表中,无需任何计算。然后它调用函数 PopulateBezierPoints 来计算曲线上其余的点。最后,点 ctrl3 被添加到列表中,因为它显然是曲线的另一端点。

private void PopulateBezierPoints(PointF ctrl1, PointF ctrl2, 
             PointF ctrl3, int currentIteration)
{
    if (currentIteration < iterations)
    {
        //calculate next mid points
        PointF midPoint1 = MidPoint(ctrl1, ctrl2);
        PointF midPoint2 = MidPoint(ctrl2, ctrl3);
        PointF midPoint3 = MidPoint(midPoint1, midPoint2); 
                //the next control point
        currentIteration++;
        PopulateBezierPoints(ctrl1, midPoint1, 
                             midPoint3, currentIteration);//left branch
        bezierPoints.Add(midPoint3); 
                //add the next control point
        PopulateBezierPoints(midPoint3, midPoint2, ctrl3, currentIteration);
                //right branch
    }
}

此函数将三个初始点与参数 currentIteration 一起作为参数。该函数是递归调用的,在开始时,当前迭代次数为零。在调用此函数之前,应设置算法中的迭代次数。

此函数简单地获取前两个点的中点、后两个点的中点 (来自给定的三个点),以及上面两个新中点的中点 (如果 currentIteration 小于算法中要迭代的 iterations 次数(变量 iterations 的值是用户从用户界面中选择的值)。在计算了三个新的中点后,我们得到了一对三个点。这对点中的一组点用于构造曲线的左半部分,另一组点用于构造曲线的右半部分。根据调用此递归函数的顺序,它将点按从曲线的左半部分到右半部分的顺序添加到列表中。您可以参考上面的动画来更好地了解此函数的执行顺序。

private PointF MidPoint(PointF controlPoint1, PointF controlPoint2)
{
    return new PointF(
    (controlPoint1.X + controlPoint2.X) / 2,
    (controlPoint1.Y + controlPoint2.Y) / 2
    );
}

此函数将两个点作为参数,并返回它们的中点。

如何使用

该程序允许您指定三个初始点和迭代次数。然后您可以观察贝塞尔曲线的平滑度和点数。除此之外,您可以通过拖动初始点来移动它们。

备注

当曲线变得更复杂、更平滑时,使用递归函数来构建贝塞尔曲线是不切实际的。在这种情况下,我们必须使用一些有效的方法来构建贝塞尔曲线。

© . All rights reserved.