Click here to Skip to main content
15,867,594 members
Articles / Multimedia / Image Processing

Bezier curve angle calculation in Silverlight

Rate me:
Please Sign up or sign in to vote.
4.33/5 (8 votes)
21 May 2011CPOL4 min read 40.8K   1.2K   17   6
The article demonstrates how to calculate various points in a Bezier curve and determine the angle at any point.

1.png

Introduction

A Bezier curve is a curve which is one of the most frequently used for computer graphics. Higher dimensions of Bezier curves are used for 3D works, which also includes Bezier triangle. Pierre Bezier, a fresh engineer who worked for Renault, derived the concept behind the calculative mechanism of the curve, which he used to design automobile body parts. In general, Bezier equations are simple but parametric equations in a variable of t (where t ranges from 0 - 1).

Where are we going to use this?

As a software engineer / programmer, this is a question which we have when we see some irregular mathematical calculations. But the answer is that we use Beziers in almost all graphic related works to draw simple but smooth curves. We use Bezier curves in almost all animations for smooth movement from one point to another in the background. This is widely used in Adobe Flash and Silverlight in their transformation as well.

At times, when you are using 3D animation, Bezier curves are used to define the 3D path and the 2D curves for key frame interpolation.

We also use Bezier if we want to create stretched text, or funny looking faces, as there is a lot of calculation; to be specific, a lot of mathematical calculation in the background which performs these functions.

In this article, I am trying to define a simple Bezier curve (and its points) and find the angle at any given point of the Bezier. This article will help a lot for someone who already has a Bezier curve(s) and want to move an object through it maintaining the rotation of the object.

How did I end up doing this?

I had a requirement where an object path needed to be plotted in a given canvas, and the points needed to be converted into smooth curves. On completing this, I had to move an object (like an arrow) from the starting position to the ending position, maintaining the arrow's rotation angle.

I initially thought it was a screwed up requirement, but as you know, the Wiki has almost all the definitions to calculations. Being an enthusiast in mathematics, I took the challenge to drive through the Bezier curves for a while and ended up with a standard function.

B(t) = (1-t)<sup>2</sup> P0 + 2(1-t) t P1 + t<sup>2</sup>P2 , t ranges from 0,1

This is the function for a Quadratic Bezier curve where P0 is the starting point, P2 is the ending point, and the curve passes through P1. There are various other Bezier curves which can be solved using the given function.

We convert this function into X, Y coordinates as given below:

  • B(t)x = (1-t)2 P0x + 2(1-t) t P1x + t2P2x , t ranges from 0,1 (determines the x coordinate of the curve)
  • B(t)y = (1-t)2 P0y + 2(1-t) t P1y + t2P2y , t ranges from 0,1 (determines the y coordinate of the curve)

We will be able to get a range of values on substituting values for t(0-1); giving a more precise value for t will give you minute values for x, y coordinates, making it smooth.

Code description

The code is divided into the following blocks:

  • Draw a Bezier curve (Silverlight already has this one).
  • Find the Bezier coordinates for each part of the curve.
  • Determine the angle between the points.
  • Draw your arrow.

The System.Windows.Media namespace already comes with various classes for drawing Bezier segments. They are BezierSegment (to draw a cubic Bezier curve between two points), PolyBezierSegment (to draw multiple cubic Bezier curves), QuadraticBezierSegment (to draw a quadratic Bezier curve), and PolyQuadraticBezierSegment (to draw a series of Quadratic Bezier curves).

We use the QuadraticBezierSegment class as given below which will create a Bezier curve for the three points given.

C#
Path p = new Path();
p.Stroke= new SolidColorBrush(Color.FromArgb(100,255,100,255));
p.StrokeThickness= 2;
//Setting the path. 
QuadraticBezierSegment qg = new QuadraticBezierSegment();
       
qg.Point1 = new Point(Convert.ToDouble(p1x.Text), Convert.ToDouble(p1y.Text));
//P1

qg.Point2 = new Point(Convert.ToDouble(p2x.Text), Convert.ToDouble(p2y.Text));
//P2

PathFigure pf = new PathFigure();
pf.StartPoint = new Point(Convert.ToDouble(p0x.Text), 
                          Convert.ToDouble(p0y.Text));
//P0

pf.Segments.Add(qg);
PathGeometry pg = new PathGeometry();
pg.Figures.Add(pf); 
p.Data=pg;
LayoutRoot.Children.Add(p); 

We already have a Bezier curve drawn with the above given code; once the curve is drawn, we are going to determine the various points involved in the curve. For my purpose, I only wanted to determine the end point arrow, so I am limiting the value of t from 0.99 to 1 with which I will only get two points (which is required to determine the angle of the arrow).

Note: If you want to find all the points involved in the curve, you should replace the start value from 0.99 to 0, and if you want to go into minute curve points, change the value of increment from 0.01 to any value lesser.

C#
double x = 0, y = 0;
double xold = 0, yold = 0;
double angle = 0;
for (double t = 0.99; t < 1.001; t += 0.01)
{
    x = ((1 - t) * (1 - t) * p0.X) + (2 * t * (1 - t) * p1.X) + (t * t * p2.X);
    //this statement is used to determine the x coordinate of the curve. 

    y = ((1 - t) * (1 - t) * p0.Y) + (2 * t * (1 - t) * p1.Y) + (t * t * p2.Y);
    //this statement is used to determine the y coordinate of the curve. 

    x = Math.Round(x, 3);
    y = Math.Round(y, 3);
    angle = Math.Round(Angle(xold, yold, x, y), 3);
    textBox1.Text += "Angle = " + angle.ToString() + "Degrees :" + 
                     x.ToString() + "," + y.ToString() + "\n";

    xold = x; yold = y;
}

e can determine the angle between two different points using geometric functions. This is explained beautifully in the link provided by Carlos Femmer (thank you man): http://www.carlosfemmer.com/post/2006/02/Calculate-Angle-between-2-points-using-C.aspx.

I have used the same function mentioned in the above URL.

The last part of this article is to draw an arrow based on the angle we have determined from the last point of the Bezier curve. I have used a rotateImage function which does the functionality of rotating an arrow based on the angle. The code below explains the details involved.

C#
//code to be placed in the Bezier Function
Image image = new Image();
Uri uri = new Uri("arrow.jpg", UriKind.Relative);
ImageSource img = new System.Windows.Media.Imaging.BitmapImage(uri);
image.Margin = new Thickness(x, y, 0, 0);

image.SetValue(Image.SourceProperty, img);
image.Width = 36;
image.Height = 32;
image.Stretch = Stretch.Fill;
image.VerticalAlignment = System.Windows.VerticalAlignment.Top;
image.HorizontalAlignment = System.Windows.HorizontalAlignment.Left;

LayoutRoot.Children.Add(image);

private void rotateImage(double angle, Image image1)
{
    WriteableBitmap bm;
    RotateTransform objTran;

    try
    {
        objTran = new RotateTransform();
        objTran.CenterX = 0.5 * image1.Width;
        objTran.CenterY = 0.5 * image1.Height;

        objTran.Angle = angle;

        bm = new WriteableBitmap(image1, objTran);
        image1.Source = (System.Windows.Media.ImageSource)bm;
        bm = null;
        GC.Collect();
    }
    catch (Exception ex)
    {
        //do waht ever you want here :) 
       
    } 

Other variances

We can create variances of Bezier using the formula below:

bn.png

History

The code does not have much of a history, I just wrote it a couple of days back, but I do have one. Not writing it here as you guys might screw me with your comments.

License

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


Written By
Architect Exalt Integral Solutions
India India
I have been a programmer since 1999, having worked on multiple platforms and technologies since then

Comments and Discussions

 
QuestionVote of 4 Pin
Kenneth Haugland22-Mar-15 2:32
mvaKenneth Haugland22-Mar-15 2:32 
GeneralMy vote of 5 Pin
Filip D'haene23-May-11 1:54
Filip D'haene23-May-11 1:54 
Very nice!

Thanks for sharing
GeneralRe: My vote of 5 Pin
JohnExalt23-May-11 4:47
JohnExalt23-May-11 4:47 
GeneralAnalytic method Pin
Tefik Becirovic22-May-11 1:05
Tefik Becirovic22-May-11 1:05 
GeneralRe: Analytic method Pin
JohnExalt22-May-11 19:00
JohnExalt22-May-11 19:00 
GeneralRe: Analytic method [modified] Pin
Tefik Becirovic23-May-11 8:03
Tefik Becirovic23-May-11 8:03 

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.