Wednesday, July 20, 2005

Intersecting a QuadCurve2D (Part II)

(continued from part one)
So far we have the parametric equation of quadratic bezier curve:

Q(t) = P1 (1 - t)^2 + P2 (2t(1-t)) + P3 (t^2)

All we have to do now is devise an efficient way to check the intersection with a rectangle. We have three cases of intersection:

If one of the endpoints of the curve is contained in the rectangle, the curve intersects the rectangle

If the curve intersects one of the line segments that delimit the rectangle, the curve intersects the rectangle

If neither of these is true, there is no intersection.

The first case is the easiest to check, we just have to check if the rectangle contains either one of the endpoints (P1 and P3).
The second one is a bit trickier. First, let me make one observation: the sides of a rectangle are always parallel to one of the coordinate axis (I know this sounds obvious in this context, but bear with me).
What this means is that the top and bottom edges of the rectangle are contained by a line of the form:

y = c

with c = rect.getY() for the top edge and c = rect.getY() + rect.getHeight() for the bottom edge.
Analogously, the left and right edges:

x = c

with c = rect.getX() for the left edge and c = rect.getX()+rect.getWidth() for the right edge.
Let's use the top edge as an example, to check if the curve cuts that edge, we must do two checks:

That exists a value of t, such as 0 <= t <= 1 and c = Qy(t)

And that rect.getX() <= Qx(t) <= rect.getX() + rect.getWidth() is true for that value of t

Where Qx(t) and Qy(t) are the parametric ecuations of the curve for each coordinate:

Qx(t) = Px1 (1 - t)^2 + Px2 (2t(1-t)) + Px3 (t^2)

Qy(t) = Py1 (1 - t)^2 + Py2 (2t(1-t)) + Py3 (t^2)

To perform the aforementioned checks, we must solve t for:

c = Q(t)

(since Qx(t) and Qy(t) are analogous, I won't specify which one I'm referring , since the result is the same).

That yields (after some more mathemagic passes):

(P1 - 2 P2 + P3)t^2 + (2 P2-2 P1) t + (P1 - c) = 0

Which is a simple quadratic equation. As you know, quadratic equations have (potentially) two roots. So we must check both values (if present) to see if any of those yields the expected result.

To solve it in code, we can use the handy QuadCurve2D.solveQuadratic() method.