Рассчитать перекрытие между двумя эллипсами

У меня есть 2 эллипсы, и мне нужно обнаружить любое перекрытие между ними.

Вот пример обнаружения перекрытия между двумя кругами, и я ищу что-то похожее для эллипсов:

var circle1 = {radius: 20, x: 5, y: 5};
var circle2 = {radius: 12, x: 10, y: 5};
var dx = circle1.x - circle2.x;
var dy = circle1.y - circle2.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < circle1.radius + circle2.radius) {
 // collision !
}

Для эллипсов у меня есть одна и та же переменная, потому что мой радиус по вертикальной оси в 2 раза меньше радиуса по горизонтальной оси:

var oval1 = {radius: 20, x: 5, y: 5};
var oval2 = {radius: 12, x: 10, y: 5};
// what comes here?
if ( /* condition ? */ ) {
 // collision !
}

1 ответ

Поскольку ваши эллипсы очень специфичны, в том, что они являются просто кругами, сжатыми вдоль оси Y, вы можете себе представить, что произойдет, если вы растянете плоскость вдоль оси Y с коэффициентом 2. Вы согласитесь, что эти перекрывающиеся эллипсы станут перекрывающимися кругами, а те, которые не перекрываются, также не будут перекрываться после растяжения. Вы могли представить это так, как если бы эллипсы были нарисованы на эластичном материале, и вы просто растягиваете материал в вертикальном направлении: это, конечно, не изменит никакого перекрывающегося состояния.

Итак, вы можете написать это:

var stretchedDistance = Math.sqrt(dx * dx + 2 * dy * 2 * dy);

... и продолжайте с условием, поскольку оно основано на радиусе в направлении X, которое после растяжения также является радиусом в направлении Y. Конечно, я назвал переменную по-разному, поэтому вы должны проверить эту переменную. Итак, чтобы завершить код, получим:

var stretchedDistance = Math.sqrt(dx * dx + 4 * dy * dy);
if (stretchedDistance < circle1.radius + circle2.radius) {
 // collision !
}

Обратите внимание, что растяжение учитывается путем умножения dy на 2. В формуле расстояния это эквивалентно и короче записать 4 * dy * dy.

Вот хороший интерактивный fiddle, который вы создали, с моим обновлением.

licensed under cc by-sa 3.0 with attribution.