Detect if two arbitrary rotated/scaled/translated ellipses are colliding. Interactive simulation available using SFML.
The colliding ellipses are marked with red boundary.
Clone project:
git clone https://github.com/stripe2933/EllipseCollision.git
cd EllipseCollision
Build using CMake (SFML 3, Eigen 3, and fmt required.)
mkdir build
cd build
cmake ..
cd ../
cmake --build build #! [--config release] for release build.
Run executable
./build/EllipseCollision
You can read the answer of Nick Alger, or the original paper to get the details.
Let two ellipses
where
Now define the following convex scalar function
If the global minimum of this function is nonnegative, then two ellipses are colliding. Note that it also holds if one ellipse contains the whole another ellipse so that each boundaries are not met.
Since the definition of a
, b
are two Eigen::Vector2f
correspond to ellipses' centers and A
, B
are two Eigen::Matrix2f
correspond to each quadratic form matrices. Then the
Eigen::GeneralizedSelfAdjointEigenSolver<Eigen::Matrix2f> es { A.inverse(), B.inverse() };
auto lambdas = es.eigenvalues();
auto phi = es.eigenvectors();
auto v_squared = (phi.transpose() * (a - b)).array().square();
auto k_function = [&](float s){
return 1.f - (v_squared * (s * (1.f - s) / (1.f + s * (lambdas.array() - 1.f)))).sum();
};
auto [_, min_k] = optimize(0.5f, k_function);
bool is_collide = min_k >= 0.f;
The function optimize
find the global minimum of convex-downwarded function using gradient descent method. The full code is in here.