I want to improve a collision system.
Right now I detect if 2 irregular objects collide if their bounding rectangles collide.
I want to obtain the for recta
An ellipse is defined a the set of points whose sum of the distance to point A and the distance to point B is constant e. (A and B are called the foci of the ellipse).
All Points P, whose sum AP + BP is less than e, lie within the ellipse.
A circle is defined as the set of points whose distance to point C is r.
A simple test for intersection of circle and ellipse is following:
Find
P as the intersection of the circle and the line AC and
Q as the intersection of the circle and the line BC.
Circle and ellipse intersect (or the circle lies completely within the ellipse) if
AP + BP <= e or AQ + BQ <= e
EDIT:
After the comment of Martin DeMello and adapting my answer accordingly I thought more about the problem and found that the answer (with the 2nd check) still doesn't detect all intersections:
If circle and ellipse are intersecting only very scarcely (just a little more than being tangent) P and Q will not lie within the ellipse:
So the test described above detects collision only if the overlap is "big enough". Maybe it is good enough for your practical purposes, although mathematically it is not perfect.
I wanted to provide some input into the more general problem involving contact between two ellipses. Calculating the distance of closest approach of two ellipses was a long standing problem and was only solved analytically within the last ten years-it is by no means simple. The solution to the problem may be found here http://www.e-lc.org/docs/2007_01_17_00_46_52/.
The general method to determine if there is contact between two ellipses is to first calculate the distance of closest approach of the ellipses in their current configuration and then subtract this from their current magnitude of separation. If this result is less than or equal to 0, then they are in contact.
If anyone is interested I can post code that calculates the distance of closest approach--it's in C++. The code is for the general case of two arbitrary ellipses, but you can obviously do it for a circle and ellipse, since a circle is an ellipse with equal minor and major axes.
Short answer: Solving exactly for whether the two objects intersect is complicated enough to be infeasible for the purpose of collision detection. Discretize your ellipse as an n-sided polygon for some n (depending on how accurate you need to be) and do collision detection with that polygon.
Long answer: If you insist on determining if the smooth ellipse and circle intersect, there are two main approaches. Both involve solving first for the closest point to the circle's center on the ellipse, and then comparing that distance to the circle's radius.
Approach 1: Use a parametrization of the ellipse. Transform your coordinates so that the ellipse is at the origin, with its axes aligned to the x-y axes. That is:
The equation of the ellipse is then given by a cos(t), b sin(t)
. To find the closest point, we want to minimize the square distance
|| (a cos t, b sin t) - c ||^2
. As Jean points out, this is "just calculus": take a derivative, and set it equal to 0. Unless I'm missing something, though, solving the resulting (quite nasty) equation for t
is not possible analytically, and must be approximated using e.g. Newton's Method.
Plug in the t
you find into the parametric equation to get the closest point.
t
.Approach 2: Use multidimensional calculus. No change of coordinates is necessary.
Finding the point on the ellipse closest to the center of the circle can then be phrased as a constrained minimization problem:
Minimize ||(x,y) - c||^2 subject to g(x,y) = 0
(Minimizing the square distance is equivalent to minimizing the distance, and much more pleasant to deal with since it's a quadratic polynomial in x,y.)
To solve the constrained minimization problem, we introduce Lagrange multiplier lambda, and solve the system of equations
2 * [ (x,y) -c ] + lambda * Jg(x,y) = 0
g(x,y) = 0
Here Jg is the gradient of g. This is a system of three (nonlinear) equations in three unknowns: x, y, and lambda. We can solve this system using Newton's Method, and the (x,y) we get is the closest point to the circle's center.
Caveat: both of these approaches technically solve for the point which extremizes the distance to the circle's center. Thus the point found might be the furthest point from the circle, and not the closest. For both methods, seeding your solve with a good initial guess (the center of the circle works well for Method 2; you're on your own for Method 1) will reduce this danger.
Potential Third Approach?: It may be possible to directly solve for the roots of the system of two quadratic equations in two variables representing the circle and ellipse. If a real root exists, the objects intersect. The most direct way of solving this system, again using a numerical algorithm like Newton's Method, won't help because lack of convergence does not necessary imply nonexistence of a real root. For two quadratic equations in two variables, however, there may exist a specialized method that's guaranteed to find real roots, if they exist. I myself can't think of a way of doing this, but you may want to research it yourself (or see if someone on stackoverflow can elaborate.)
if a circle and an ellipse collide, then either their boundaries intersect 1, 2, 3, or 4 times(or infinitely many in the case of a circular ellipse that coincides with the circle), or the circle is within the ellipse or vice versa.
I'm assuming the circle has an equation of (x - a)^2 + (y - b)^2 <= r^2 (1) and the ellipse has an equation of [(x - c)^2]/[d^2] + [(y - e)^2]/[f^2] <= 1 (2)
To check whether one of them is inside the other, you can evaluate the equation of the circle at the coordinates of the center of the ellipse(x=c, y=e), or vice versa, and see if the inequality holds.
to check the other cases in which their boundaries intersect, you have to check whether the system of equations described by (1) and (2) has any solutions.
you can do this by adding (1) and (2), giving you
(x - a)^2 + (y - b)^2 + [(x - c)^2]/[d^2] + [(y - e)^2]/[f^2] = r^2 + 1
next you multiply out the terms, giving
x^2 - 2ax + a^2 + y^2 - 2by + b^2 + x^2/d^2 - 2cx/d^2 + c^2/d^2 + y^2/f^2 - 2ey/f^2 + e^2/f^2 = r^2 + 1
collecting like terms, we get
(1 + 1/d^2)x^2 - (2a + 2c/d^2)x + (1 + 1/f^2)y^2 - (2b + 2e/f^2)y = 1 + r^2 - a^2 - b^2 - c^2/d^2 - e^2/f^2
now let m = (1 + 1/d^2), n = -(2a + 2c/d^2), o = (1 + 1/f^2), and p = -(2b + 2e/f^2)
the equation is now mx^2 + nx + oy^2 + py = 1 + r^2 - a^2 - b^2 - c^2/d^2 - e^2/f^2
now we need to complete the squares on the left hand side
m[x^2 + (n/m)x] + o[y^2 + (p/o)y] = 1 + r^2 - a^2 - b^2 - c^2/d^2 - e^2/f^2
m[x^2 + (n/m)x + (n/2m)^2 - (n/2m)^2] + o[y^2 + (p/o)y + (p/2o)^2 - (p/2o)^2] = 1 + r^2 - a^2 - b^2 - c^2/d^2 - e^2/f^2
m[(x + n/2m)^2 - (n/2m)^2] + o[(y + p/2o)^2 - (p/2o)^2] = 1 + r^2 - a^2 - b^2 - c^2/d^2 - e^2/f^2
m(x + n/2m)^2 - m(n/2m)^2 + o(y + p/2o)^2 - o(p/2o)^2 = 1 + r^2 - a^2 - b^2 - c^2/d^2 - e^2/f^2
m(x + n/2m)^2 + o(y + p/2o)^2 = 1 + r^2 - a^2 - b^2 - c^2/d^2 - e^2/f^2 + m(n/2m)^2 + o(p/2o)^2
this system has a solution iff 11 + r^2 - a^2 - b^2 - c^2/d^2 - e^2/f^2 + m(n/2m)^2 + o(p/2o)^2 >= 0
There you have it, if I didn't make any algebraic mistakes. I don't know how much you can simplify the resulting expression, so this solution might be quite computationally expensive if you're going to check for many circles/ellipses