Draw a Bézier curve "by hand" that matches the one drawn by the Graphics object's DrawBezier method in C#

A Bézier curve is a spline, a smooth curve whose shape is determined by control points. For this kind of cubic Bézier 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 Graphics object provides a DrawBezier method that takes the four control points as parameters and draws the curve. Sometimes, however, it's useful to be able to plot points on the curve. For example, if you wanted to make text follow the curve, you would need to generate points along it and not just draw the curve in a single call to DrawBezier.

The points on the cubic Bézier 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 Bézier 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)
{
// Debugging code commented out.
// Draw the control lines.
using (Pen dashed_pen = new Pen(Color.Black))
{
dashed_pen.DashPattern = new float[] { 4, 4 };
gr.DrawLine(dashed_pen, pt0.X, pt0.Y, pt1.X, pt1.Y);
gr.DrawLine(dashed_pen, pt2.X, pt2.Y, pt3.X, pt3.Y);
}

// Draw the curve.
float t, x0, y0, x1, y1;
t = 0.0f;
x1 = X(t, pt0.X, pt1.X, pt2.X, pt3.X);
y1 = Y(t, pt0.Y, pt1.Y, pt2.Y, pt3.Y);
t += dt;
while (t < 1.0)
{
x0 = x1;
y0 = y1;
x1 = X(t, pt0.X, pt1.X, pt2.X, pt3.X);
y1 = Y(t, pt0.Y, pt1.Y, pt2.Y, pt3.Y);
gr.DrawLine(the_pen, x0, y0, x1, y1);
Console.WriteLine("(" + x1.ToString("0.00") + ", " + y1.ToString("0.00"));//@
t += dt;
}

// Connect to the final point.
t = 1.0f;
x0 = x1;
y0 = y1;
x1 = X(t, pt0.X, pt1.X, pt2.X, pt3.X);
y1 = Y(t, pt0.Y, pt1.Y, pt2.Y, pt3.Y);
gr.DrawLine(the_pen, x0, y0, x1, y1);


gr.DrawLine(Pens.Red, pt0, pt1);
gr.DrawLine(Pens.Green, pt1, pt2);
gr.DrawLine(Pens.Blue, pt2, pt3);
}

This version also draws the lines between the control points. In a real application, you would want to remove that code and do something with the curve's points other than just connecting them.

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

   

 

What did you think of this article?




Trackbacks
  • No trackbacks exist for this post.
Comments
  • No comments exist for this post.
Leave a comment

Submitted comments are subject to moderation before being displayed.

 Name

 Email (will not be published)

 Website

Your comment is 0 characters limited to 3000 characters.