Click here to Skip to main content
15,881,882 members
Articles / Programming Languages / C#
Article

Bezier Curves Made Simple

Rate me:
Please Sign up or sign in to vote.
4.92/5 (43 votes)
14 Apr 2008CPOL4 min read 387.7K   15.1K   103   53
A simple implementation of the famous Bezier curves in C#. Easy to understand.

BezierInterpolation.gif

Introduction

Bezier curves are the most fundamental curves, used generally in computer graphics and image processing. These curves are mainly used in interpolation, approximation, curve fitting, and object representation. In this article, I will demonstrate, in a very simple and straightforward way, how one can construct these curves and make use of them.

Background

Bezier curves are parametric curves which are pretty much customizable and smooth. They are well suited for many applications. They were named after Pierre Bézier, a French mathematician and engineer who developed this method of computer drawing in the late 1960s while working for the car manufacturer Renault. People say that at the same time the same development took place during the research of Ford. There is still a confusion about who found it first.

Because of my imaging background, my article will mainly focus on interpolation and curve fitting. In interpolation, what one would simply like to do is to find unknown points using known values. This way, a discrete case can be represented with a more continuous structure, and we can have a well defined curve for missing points. The curve is initialized with certain data points, and it tries to generate new ones that are approximating (or interpolating) the old values.

Constructive Bezier Curve Algorithm

Consider the n+1 points P0,…,Pn and connect the points into a polyline we will denote hereafter as the control polygon.

figure2.jpg

Given points Pi, i = 0,...,n, our goal is to determine a curve g (t), for all values t Î [0,1]. The idea is demonstrated below:

figure.jpg

Basic Algorithm

The objective here is to find points in the middle of two nearby points and iterate this until we have no more iterations. The new values of points will give us the curve. The famous Bezier equation is the exact formulation of this idea. Here is the algorithm:

Step 1: Select a value t Î [0,1]. This value remains constant for the rest of the steps.

Step 2: Set Pi[0] (t) = Pi, for i = 0,...,n.

Step 3: For j= 0,...,n, set simple.jpg for i = j,...,n.

Step 4: g (t) = Pn[n] (t)

Special & General Cases

Now, I will give formulas for common, special cases that can be helpful in certain applications. The code of the article does not demonstrate any of them, but it uses the generalized formula. So, let me start with the generalized formula:

general.jpg

For the sake of simplicity and convention used in this article and code, it is better to represent this formula as:

notation.jpg

What this equation tells us is nothing but the formulation of the above algorithm (the mid-point iterations). It is very important in the sense that a whole algorithm could be summarized into a formula and a straightforward implementation would yield correct results. Here, n denotes the number of points and P denotes the points themselves. The factorial coefficients of the points are simply called the Bernstein basis functions, because of the name of the founder.

Here are the special cases:

Linear Bezier:

f1.jpg

Quadratic Bezier:

f3.jpg

Cubic Bezier:

f2.jpg

Understanding and Using the Code

This is the function, doing all the work. I think it is very short and very easy. Because we are dealing only with 2D curves, we have points in X and Y coordinates. The function simply calculates the Bezier points.

C#
public void Bezier2D(double[] b, int cpts, double[] p)
{
    int npts = (b.Length) / 2;
    int icount, jcount;
    double step, t;

    // Calculate points on curve

    icount = 0;
    t = 0;
    step = (double)1.0 / (cpts - 1);

    for (int i1 = 0; i1 != cpts; i1++)
    { 
        if ((1.0 - t) < 5e-6) 
            t = 1.0;

        jcount = 0;
        p[icount] = 0.0;
        p[icount + 1] = 0.0;
        for (int i = 0; i != npts; i++)
        {
            double basis = Bernstein(npts - 1, i, t);
            p[icount] += basis * b[jcount];
            p[icount + 1] += basis * b[jcount + 1];
            jcount = jcount +2;
        }

        icount += 2;
        t += step;
    }
}

The rest of the functions are only helper functions taking part in factorial calculations and basis function calculations, which I believe are pretty obvious. To properly use this function, give it a set of points in the format: XYXYXYXYXYXYXYXYXYXY.... coordinates and how many points you would like to calculate on the curve. The function will fill the p array with the path points.

Points of Interest

Because of the limitations of factorial calculations, the code could only calculates curves up to 32 points. More complicated structures are generally represented by a combination of these curves (as in Adobe Photoshop, Illustrator, and Flash - path tool).

Even though GDI has a built-in Bezier curve calculation function, it is never good for learning to use built-in libraries. You won't always have GDI to do things for you! At some place, some time, you may have to implement it, and I think by now, you should have a rough idea of how these curves work.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
CEO Gravi Information Technologies and Consultancy Ltd
Turkey Turkey
Currently, also an MSc. student in Technical University of Munich, I develop practical application in computer vision for more than 5 years. I design real-time solutions to industrial and practical vision problems, both 3D and 2D. Very interested in developing algorithms in C relating math and vision.

Please visit Gravi's web page (http://www.gravi.com.tr) and my page (http://www.tbirdal.me) to learn more about what we develop.

I admire performance in algorithms.

"Great minds never die, they just tend to infinity..."

Comments and Discussions

 
QuestionRegarding the 32 maximum Pin
Member 118045053-Sep-19 9:56
Member 118045053-Sep-19 9:56 
AnswerRe: Regarding the 32 maximum Pin
gr584-Jan-24 22:43
gr584-Jan-24 22:43 
QuestionCould this be a bug..? Pin
Member 1109071321-Dec-17 17:05
Member 1109071321-Dec-17 17:05 
QuestionNice Pin
veen_rp14-Apr-16 0:05
professionalveen_rp14-Apr-16 0:05 
I incorporated your neat little class in a VB.Net app. I'm now looking at the limitation of 32 points (as mentioned above in the Q&A's) and also a way to influence the tension of the Bezier towards the control points. Any idea on that?

Here's my VB.net code for those of you interested. I've made some changes, major one is moving from an array of interlaced x and y's to a list of points (PointD is similar to the pointF structure except it uses doubles instead of singles.

VB
Public Class BezierApprox
	'from: http://www.codeproject.com/Articles/25237/Bezier-Curves-Made-Simple
	
	Public Sub New()
	End Sub
	
	Public Function BezierApproximate(points As List(Of PointD), controlPoints As Integer) As List(Of PointD)
		'checks
		If points Is Nothing OrElse points.Count < 2 Then Return Nothing
		If controlPoints < 2 Then controlPoints = 2 'at least have 2 points
		
		Try
			Dim newpoints As New List(Of PointD)
			
			Dim x, y, basis As Double
			Dim t As Double = 0
			Dim stepsz As Double = 1/(controlPoints-1)
			
			For i As Integer = 0 To controlPoints-1
					
				If (1-t) < 5E-06 Then t = 1
				
				x = 0
				y = 0
				
				For p As Integer = 0 To points.Count-1
					basis = calcBernstein(points.Count-1,p,t)
					x += basis * points(p).X
					y += basis * points(p).Y
				Next
				
				newpoints.Add(New PointD(x,y))
				t += stepsz
			Next
			
			Return newpoints
		Catch exc As Exception
			Debug.Print(exc.ToString)
			Return Nothing
		End Try
	End Function
	
	Public Function GetFactorial(number As Integer) As Integer
		If number < 2 Then
			Return 1
		Else
			Try
				Dim fact As Integer = 1
				For i As Integer = 1 To number
					fact = fact * i
				Next
				Return fact
			Catch exc As Exception
				Debug.Print(exc.ToString)
				Return 0
			End Try
		End If
	End Function

	Private Function calcNi(n As Integer, i As Integer) As Double
		Dim ni As Double
		Dim a1 As Double = Veet.Geometry.GetFactorial(n)
		Dim a2 As Double = Veet.Geometry.GetFactorial(i)
		Dim a3 As Double = Veet.Geometry.GetFactorial(n-i)
		ni = a1/(a2*a3)
		Return ni
	End Function

	' Calculate Bernstein basis
	Private Function calcBernstein(n As Integer, i As Integer, t As Double) As Double
		Dim basis As Double
		Dim ti As Double
		Dim tni As Double
		
		'checks
		If t = 0.0 AndAlso i = 0 Then
			ti = 1.0
		Else
			ti = Math.Pow(t,i)
		End If
		
		If n = i AndAlso t = 1.0 Then
			tni = 1.0
		Else
			tni = Math.Pow((1-t),(n-i))
		End If
		
		'Bernstein basis
		basis = calcNi(n,i) * ti * tni
		Return basis
	End Function

End Class

AnswerRe: Nice Pin
veen_rp17-Apr-16 19:19
professionalveen_rp17-Apr-16 19:19 
QuestionCould you pls elaborate on "Because of the limitations of factorial calculations, the code could only calculates curves up to 32 points" Pin
sr.dekker11-Nov-15 10:05
sr.dekker11-Nov-15 10:05 
AnswerRe: Could you pls elaborate on "Because of the limitations of factorial calculations, the code could only calculates curves up to 32 points" Pin
enhzflep25-Nov-15 5:18
enhzflep25-Nov-15 5:18 
QuestionGet bezier point list between two control points. Pin
Cyril Clavaud12-Aug-15 1:04
Cyril Clavaud12-Aug-15 1:04 
AnswerRe: Get bezier point list between two control points. Pin
Tolga Birdal21-Sep-15 9:13
Tolga Birdal21-Sep-15 9:13 
Question3D bezier curve Pin
Laurent Chougrani8-Apr-15 5:32
Laurent Chougrani8-Apr-15 5:32 
AnswerRe: 3D bezier curve Pin
S. Becker5-Nov-19 1:24
S. Becker5-Nov-19 1:24 
GeneralRe: 3D bezier curve Pin
OveDag5-Jun-20 0:24
OveDag5-Jun-20 0:24 
SuggestionPorted to C, FWIW Pin
Member 110512801-Sep-14 14:34
Member 110512801-Sep-14 14:34 
GeneralRe: Ported to C, FWIW Pin
Tolga Birdal1-Sep-14 14:46
Tolga Birdal1-Sep-14 14:46 
GeneralRe: Ported to C, FWIW Pin
Member 110512804-Sep-14 5:48
Member 110512804-Sep-14 5:48 
GeneralExactly what I was looking for Pin
Member 795460812-Jan-13 12:12
Member 795460812-Jan-13 12:12 
GeneralRe: Exactly what I was looking for Pin
Tolga Birdal4-Aug-13 18:10
Tolga Birdal4-Aug-13 18:10 
GeneralMy vote of 5 Pin
as4527-Nov-12 6:30
as4527-Nov-12 6:30 
QuestionAnswer Pin
Member 912643914-Nov-12 9:06
Member 912643914-Nov-12 9:06 
AnswerRe: Answer Pin
Tolga Birdal14-Nov-12 10:10
Tolga Birdal14-Nov-12 10:10 
SuggestionRe: Answer Pin
Member 167073211-Sep-13 18:23
Member 167073211-Sep-13 18:23 
GeneralRe: Answer Pin
Tolga Birdal11-Sep-13 21:17
Tolga Birdal11-Sep-13 21:17 
GeneralMy vote of 5 Pin
Manoj Kumar Choubey20-Feb-12 19:11
professionalManoj Kumar Choubey20-Feb-12 19:11 
GeneralGreat work Pin
Rainer Halanek17-Mar-11 9:17
Rainer Halanek17-Mar-11 9:17 
GeneralRe: Great work Pin
Tolga Birdal17-Mar-11 10:09
Tolga Birdal17-Mar-11 10:09 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.