Draw a Bezier curve by hand in C#

[Bezier curve]

The example Draw a Bezier curve in C# shows how to use the Graphics class’s DrawBezier method to draw a Bezier curve. This post explains the equations that draw a Bezier curve and shows how you can use them to draw the curve yourself “by hand.”

A Bezier curve is a spline, a smooth curve whose shape is determined by control points. For this kind of cubic Bezier curve, the control points determine the curve’s start and end points, and the directions of the tangents at those points. (See the picture on the right.)

The points on the cubic Bezier curve are generated by the following equation where t varies from 0 to 1.

Here P0, P1, P2, and P3 are the control points. (Plug in the corresponding X and Y values to get the resulting points’ coordinates.)

This example includes a BezierStuff class that provides a static DrawBezier method to draw a Bezier curve. The following code shows that method and its helper X and Y functions.

// Parametric functions for drawing a degree 3 Bezier curve.
private static float X(float t,
    float x0, float x1, float x2, float x3)
{
    return (float)(
        x0 * Math.Pow((1 - t), 3) +
        x1 * 3 * t * Math.Pow((1 - t), 2) +
        x2 * 3 * Math.Pow(t, 2) * (1 - t) +
        x3 * Math.Pow(t, 3)
    );
}
private static float Y(float t,
    float y0, float y1, float y2, float y3)
{
    return (float)(
        y0 * Math.Pow((1 - t), 3) +
        y1 * 3 * t * Math.Pow((1 - t), 2) +
        y2 * 3 * Math.Pow(t, 2) * (1 - t) +
        y3 * Math.Pow(t, 3)
    );
}

// Draw the Bezier curve.
public static void DrawBezier(Graphics gr, Pen the_pen,
    float dt, PointF pt0, PointF pt1, PointF pt2, PointF pt3)
{
    // Draw the curve.
    List points = new List();
    for (float t = 0.0f; t < 1.0; t += dt)
    {
        points.Add(new PointF(
            X(t, pt0.X, pt1.X, pt2.X, pt3.X),
            Y(t, pt0.Y, pt1.Y, pt2.Y, pt3.Y)));
    }

    // Connect to the final point.
    points.Add(new PointF(
        X(1.0f, pt0.X, pt1.X, pt2.X, pt3.X),
        Y(1.0f, pt0.Y, pt1.Y, pt2.Y, pt3.Y)));

    // Draw the curve.
    gr.DrawLines(the_pen, points.ToArray());

    // Draw lines connecting the control points.
    gr.DrawLine(Pens.Red, pt0, pt1);
    gr.DrawLine(Pens.Green, pt1, pt2);
    gr.DrawLine(Pens.Blue, pt2, pt3);
}

The functions X and Y simply return the coordinates for a point on the curve with particular control points and a particular value of t.

The DrawBezier method creates a List<PointF>. It then loops the variable t through the values between 0 and 1. For each value of t, the code uses the X and Y functions to get the coordinates of a point on the curve. It saves that point in the list.

After the loop finishes, the program adds a final point with t = 0. It then draws lines connecting the points.

The method also draws lines between the control points so you can see how they affect the curve's shape.

The main program uses the following code to draw a curve defined by control points selected by the user. It first draws the curve using the Graphics class's DrawBezier method with a thick pen. It then draws the same curve using the new DrawBezier method and a thin pen so you can see it on top of the other curve.

// Draw the currently selected points. 
// If we have four points, draw the Bezier curve.
private void picCanvas_Paint(object sender, PaintEventArgs e)
{
    e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
    e.Graphics.Clear(picCanvas.BackColor);
    if (NextPoint >= 4)
    {
        // Draw a spline the easy way.
        using (Pen thick_pen = new Pen(Color.Yellow, 7))
        {
            e.Graphics.DrawBezier(thick_pen,
                Points[0], Points[1], Points[2], Points[3]);
        }

        // Draw a spline the hard way.
        BezierStuff.DrawBezier(e.Graphics, Pens.Black, 0.01f,
            Points[0], Points[1], Points[2], Points[3]);
    }

    // Draw the control points.
    for (int i = 0; i < NextPoint; i++)
    {
        e.Graphics.FillRectangle(Brushes.White,
            Points[i].X - 3, Points[i].Y - 3, 6, 6);
        e.Graphics.DrawRectangle(Pens.Black,
            Points[i].X - 3, Points[i].Y - 3, 6, 6);
    }
}

A Bezier curve needs two end points and two control points, so the program first checks that you have selected 4 points. If you have, it calls the Graphics object's DrawBezier method to draw the curve with a thick yellow pen. It then uses the new DrawBezier method to draw the curve again with a thin black pen. In the picture you can see that the thin black curve lies on top of the thick yellow curve.

The method finishes by drawing the control points.


Download Example   Follow me on Twitter   RSS feed   Donate




This entry was posted in algorithms, drawing, geometry, graphics, mathematics and tagged , , , , , , , , , , , . Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *