Recently, after viewing this illuminating animated GIFs, I realized that finding the closest point on a quadratic Bezier curve to a given point M might be not so difficult ...and very useful for detecting collision between a disk and a quadratic curve.
Quadratic Bezier curves are familiar to flash programmers, because these are the curves they draw with functions like Movieclip.moveTo() and Movieclip.curveTo().
Such Bezier curve is defined by 3 points: P0, P1, P2.
P0 and P1 are the extreme points, and P1 is a middle point determining curvature.
The curve can be parametrized with the formula:
The above-mentioned animated GIFs greatly help to "geometrically" grasp not only the quadratic curves, but also higher order Bezier curves .
Now, the key step is to get the derivative (back to school!! ) of P(t):
where A = (P1-P0) and B = (P2-P1-A)
The derivative is a vector representing the "speed" at point defined by P(t). It also has the property to be a tangent to the curve at point P(t).
Now let M(x,y) be our point (which can be anywhere) and we want to find out a point P' (defined by t') on Bezier curve that is the closest possible to M.
P(t') will meet the condition:
(where "." is the dot product of 2 vectors)
Rewritting this condition yields:
...After a (boring ) calculus you get a third degree equation (ouch!! ):
If we can solve this equation, we get 3 possible solutions for t !!
How to solve a third degree equation is explained here (in french).
Now we have a maximum of 3 solutions t0, t1, t2 and find the one fitting in [0,1] and minimizing dist(M, P(t)) is easy !!
Here is a demo:
P0 and P2 are the blue points, P1 is green , M is red.
The yellow dot is the closest point, the orange dot indicates the normal to M.
After this, I realized that Andre Michelle had already posted a ball collision detection on his blog a long time ago. But the source wasn't available (at least I didn't work for nothing )...
The source code (AS2, FLA CS3 + Bezier.as).
Translating it into as3 should be no problem .
[UPDATE 2012/08/06] I fixed the issue pointed by makc3d. Now the end points are included as a possible solution, which is more consistent. I added a flad "onCurve" indicating if the closest point is on the curve itself (true), or one of the end points (false). The "oriented distance" is negative when the point is on the right of the path formed by [P0,P1,P2]. For backward compatibility, I kept this info in the variable "orientedDist", but it loses its meaning when the closest point is not on the curve.