Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to find out Y coordinate of specific point in bezier curve in canvas?

I need to find out Y coordinate of specific point of bezier curve in canvas. Do you know, how to find it out? Thank you

like image 846
Jan Kožušník Avatar asked Jan 05 '13 17:01

Jan Kožušník


2 Answers

Using de Casteljau's algorithm you can find the coordinates x and y of a bezier curve for any t, the percentage or interpolation step. So a t of .1 would give you the x and y at 10% of the curve from the beginning. A t of .9 would be 90% from the beginning, and so on.

In our cubic bezier we have p0 (point 0), cp0 (control point 0), cp1 (control point 1), and p1 (point 1).

In the first step of the algorithm we draw a line connecting p0 and cp0, another line connecting cp0 and cp1, and another still connecting cp1 and p1. Then for all 3 of these lines we're going to find the point on them that is t % from the start of them.

I'll call the points as follows:

  • p0 -> cp0 = A
  • cp0 -> cp1 = B
  • cp1 -> p1 = C

    Ax = ( (1 - t) * p0x ) + (t * cp0x);
    Ay = ( (1 - t) * p0y ) + (t * cp0y);
    Bx = ( (1 - t) * cp0x ) + (t * cp1x);
    By = ( (1 - t) * cp0y ) + (t * cp1y);
    Cx = ( (1 - t) * cp1x ) + (t * p1x);
    Cy = ( (1 - t) * cp1y ) + (t * p1y);
    

The second step is very much like the first. In the first we connected the four points with lines and then found 3 new points on them. In this step we'll connect those 3 points with lines find 2 new points on them. I'll call these two new points D and E.

    Dx = ( (1 - t) * Ax ) + (t * Bx);
    Dy = ( (1 - t) * Ay ) + (t * By);

    Ex = ( (1 - t) * Bx ) + (t * Cx);
    Ey = ( (1 - t) * By ) + (t * Cy);

Finally, we can connect these last two points with another line, and find the last point on it which will give us the point on the bezier curve for that t. I'll call this point P.

    Px = ( (1 - t) * Dx ) + (t * Ex);
    Py = ( (1 - t) * Dy ) + (t * Ey);

There we go, we now have the x and y coordinate of a point on the bezier that is t% from the start. I'll add some pictures soon.

enter image description here

like image 162
DerekR Avatar answered Oct 08 '22 22:10

DerekR


I've been trying to figure same thing and I think I solved it at least for square bezier curves, which are bezier curves with only a single control point.

Mathematical explanation

The mathematical formula for a square bezier curve is:

Where 'X' is the result, 'A' is the the position of the start point, 'B' the control point and 'C' the end point.

't' is a number between 0 and 1 that indicates which point on the line you want to calculate. 0 represents the start point, 1 the end point, and 0.5 would refer to the center of the curve.

This function is used for calculating both the X and the Y coordinates of a point on the line. If you want to calculate X just fill in the X coordinate of the A,B and C points.

Now in order to determine the Y that belongs to the X we need to determine the 't' for said X coordinate.

We can write the same bezier equation in the quadratic form ():

This allows us to use the quadratic formula to derive the values of 't' that solve the equation. The quadratic formula is actually 2 formulas.

and

The resulting formula is:

and

Code solution

We can describe this in code as:

GetYValues(StartPoint, ControlPoint, EndPoint, X)
{
    Ax = StartPoint.X
    Bx = ControlPoint.X
    Cx = EndPoint.X

    q1 = 2*Ax - 2*Bx;
    q2 = Sqrt(5*Ax*Ax - 10*Ax*Bx + Ax*Cx - Ax*X + 2*Bx*X + 4*Bx*Bx)
    q3 = 2*Ax - 4*Bx + 2*Cx

    t1 = (q1 + q2) / q3
    t2 = (q1 - q2) / q3

    Ay = StartPoint.Y
    By = ControlPoint.Y
    Cy = EndPoint.Y

    Y1 = Ay*(1-t1)*(1-t1) + By*2*(1-t1)*t1 + Cy*t1
    Y2 = Ay*(1-t2)*(1-t2) + By*2*(1-t2)*t2 + Cy*t2

    return [Y1,Y2]
}

Now, I haven't tested this, and the function doesn't check if there are actually any valid points, so there are definitely values for which it will throw an exception. Be sure to check for 'divide by 0' and 'square root of numbers below 0'.

Problems with this solution

A big problem with this equation is that it only works for square bezier curves, while most bezier curves are actually cubic. I've tried to find a similar way to solve the cubic version of this problem, unfortunately this is an order of magnitude more difficult. The only formula I've been able to find for solving cubic equations can be found here Cubic function. This formula contains imaginary numbers and I have no idea what to do with those.

Another problem is that for bezier curves with 4 control points or more, there is no way to solve the equation at all.

Conclusion

In the end, your best bet is to simply convert the bezier curve into straight lines, which are infinitely easier to calculate with.

like image 32
Boyd Avatar answered Oct 08 '22 23:10

Boyd