Home

How to calculate the tangent to a Bezier curve

This is hard to find online. It must be a secret closely held by those who know. Oh you can find the math formulae, but have fun interpreting them if you are not a mathematician. So what is a poor developer to do? Go back to school.

I spent a couple days bashing my skull over this one. I googled my brains out (which was easier once my skull was sufficiently bashed). Then one bright beautiful Saturday, I was holed up in my developer's dungeon resting my weary bones. I had the TV on in front of me and Wikipedia to the right and there I was lazily switching between watching them both.

I had Wikipedia on the Bezier Curves page of course. I would glance back now and then mostly looking at the diagrams. How do I find the tangent? How do I find the tangent? How do I find the tangent? How do I find the tangent?

Then it just hit me!

Funny how not really thinking hard about things often brings you the answer. And a simple answer it was. Embarrassingly simple. So simple in fact that if you are reading this then you too should be embarrassed and I will record your IP and twitter about it (don't worry, I don't twitter)

The animation library herein uses cubic Bezier curves. That is 4 points: start, end, and 2 guide points between them. Quadratic Bezier curves use just 3 points: start, end and 1 guide point. (don't those names seem like they should be reversed?). Below are 2 curve diagrams copied over from Wikipedia. Can you see how to get the tangent?


Quadratic

Cubic

On the quadratic, the green line is the obvious tangent. Just get the two points along the guide lines. But what about the cubic? It is a little daunting to calculate the slope of that blue line. Is there an easier way? It turns out that if you form a quadratic Bezier curve from the first 3 points of your cubic Bezier curve (start, guide 1, guide 2), then find the point along that curve, then the tangent of your cubic Bezier curve is the slope between the points calculated for both the cubic and the quadratic.

Just remember how this works in general: given a ratio such as 1/4, find the x,y coordinates of the point on the curve that is 1/4 the distance along its length. So apply that to getting the tangent:

  1. Calculate the point that is the ratio (r) along your cubic Bezier curve
  2. Create a quadratic Bezier curve from the first 3 points of your cubic Bezier curve description
  3. Calculate the point that is the ratio (r) along your quadratic Bezier curve
  4. Calculate the angle between the two points from steps 1 & 3

And that is how you get your tangent and how the tangent of the curves are found in the Animation Library. Source code follows:

Getting point along the cubic curve

rtn.X = (float)
(
    Math.Pow(1 - p_ratio, 3) * p_points[0].X +
    3 * Math.Pow(1 - p_ratio, 2) * p_ratio * p_points[1].X +
    3 * Math.Pow(1 - p_ratio, 1) * Math.Pow(p_ratio, 2) * p_points[2].X +
    Math.Pow(p_ratio, 3) * p_points[3].X
);

rtn.Y = (float)
(
    Math.Pow(1 - p_ratio, 3) * p_points[0].Y +
    3 * Math.Pow(1 - p_ratio, 2) * p_ratio * p_points[1].Y +
    3 * Math.Pow(1 - p_ratio, 1) * Math.Pow(p_ratio, 2) * p_points[2].Y +
    Math.Pow(p_ratio, 3) * p_points[3].Y
);

Getting point along the quadratic curve

float cx = (float)
    (
        (1-p_ratio)*(1-p_ratio)*p_points[0].X +
        2*(1-p_ratio)*p_ratio*p_points[1].X +
        p_ratio*p_ratio*p_points[2].X
    );

float cy = (float)
    (
        (1-p_ratio)*(1-p_ratio)*p_points[0].Y +
        2*(1-p_ratio)*p_ratio*p_points[1].Y +
        p_ratio*p_ratio*p_points[2].Y
    );

Get slope between points

double rtn = 0.0d;

double dy = (p_2.Y - p_1.Y);
double dx = (p_2.X - p_1.X);

rtn = (float)Math.Atan2(dy, dx) * (float)(180 / Math.PI);

if (dx < 0 && dy < 0) rtn *= -1;
if (dx > 0 && dy < 0) rtn *= -1;
if (dx < 0 && dy > 0) rtn = 360.0d - rtn;
if (dx > 0 && dy > 0) rtn = 360.0d - rtn;

return rtn;

The article is Copyright © 2009. Reprint and distribution by permission only.