Подтвердить что ты не робот

Алгоритм обнаружения, если Круги пересекаются с любым другим кругом в одной плоскости

Я ищу алгоритм для определения того, пересекаются ли Круги с любым другим кругом в одной плоскости, учитывая, что в плоскости может быть больше одной окружности.

Стандартный метод, который я нашел, - это выполнить тест разделительной оси (это сделал поиск в Google).

В нем говорится:

Two objects don't intersect if you can find a line that separates 
the two objects. e.g. the objects / all points of an object are on 
different sides of the line.

но я не знаю, как применить его с кругом.

может кто-нибудь помочь мне здесь?

4b9b3361

Ответ 1

Два круга пересекаются, если и только если расстояние между их центрами находится между суммой и разностью их радиусов. Учитывая два круга (x0, y0, R0) и (x1, y1, R1), формула такова:

ABS(R0-R1) <= SQRT((x0-x1)^2+(y0-y1)^2) <= (R0+R1)

Сжатие обеих сторон позволяет избежать медленного SQRT и оставаться с ints, если ваши входы целые:

(R0-R1)^2 <= (x0-x1)^2+(y0-y1)^2 <= (R0+R1)^2

Поскольку вам нужен только тест yes/no, эта проверка выполняется быстрее, чем вычисление точных точек пересечения.

Изменить: исправлено для случая "один круг внутри другого".

Ответ 2

Предполагая пересечение заполненного круга (т.е. один круг внутри другого является пересечением).

Где:

  • x0, y0, r0 = центр и радиус окружности 0.
  • x1, y1, r1 = центр и радиус круга 1.

код:

boolean intersects = Math.hypot(x0-x1, y0-y1) <= (r0 + r1);

Ответ 3

Решение XNA/С#

    class Circle
    {
        public Vector2 Center;
        public float Radius;

        public bool Intersects(Circle circle)
        {
            float distanceX = Center.X - circle.Center.X;
            float distanceY = Center.Y - circle.Center.Y;
            float radiusSum = circle.Radius + Radius;
            return distanceX * distanceX + distanceY * distanceY <= radiusSum * radiusSum;
        }
        public bool Contains(Circle circle)
        {
            if (circle.Radius > Radius)
                return false;
            float distanceX = Center.X - circle.Center.X;
            float distanceY = Center.Y - circle.Center.Y;
            float radiusD = Radius - circle.Radius;
            return distanceX * distanceX + distanceY * distanceY <= radiusD * radiusD;
        }
    }

Ответ 4

Если расстояние между центрами двух окружностей не превышает сумму их радиусов, но по крайней мере абсолютное значение разности между радиусами, то сами круги пересекаются в некоторой точке.

Часть "по крайней мере разница" применяется, если вы заботитесь только о самих кругах, а не о своих внутренних областях. Если вам небезразличны ли круги или области, в которые они заключают друг друга, то есть, если один круг полностью внутри другого считается "пересекающимся" с вами, тогда вы можете сбросить "по крайней мере разницу".

Ответ 5

Я попробовал приведенную здесь формулу, которая является предположительным ответом, и все проголосовали, хотя это серьезно испорчено. Я написал программу в JavaFX, чтобы пользователь мог проверить, пересекаются ли два круга, изменяя значения каждого окружности centerX, centerY и Radius, и эта формула абсолютно не работает, кроме одного способа... Я не могу понять, почему, но когда я перемещайте круг 2 рядом с кругом 1, он работает, но когда я перемещаю круг 1 на другую сторону рядом с кругом 2, он не работает.....????? что немного странно... вычислил формулу, которую нужно было протестировать противоположным образом, так что попробовал это, и она не работает.

if (Math.abs(circle1Radius - circle2Radius) <=
            Math.sqrt(Math.pow((circle1X - circle2X), 2)
            + Math.pow((circle1Y - circle2Y), 2)) &&
            Math.sqrt(Math.pow((circle1X - circle2X), 2)
            + Math.pow((circle1X - circle2Y), 2)) <=
            (circle1Radius + circle2Radius)} {
    return true;
} else {
    return false;
}

Это работает:

    // dx and dy are the vertical and horizontal distances
    double dx = circle2X - circle1X;
    double dy = circle2Y - circle1Y;

    // Determine the straight-line distance between centers.
    double d = Math.sqrt((dy * dy) + (dx * dx));

    // Check Intersections
    if (d > (circle1Radius + circle2Radius)) {
        // No Solution. Circles do not intersect
        return false;
    } else if (d < Math.abs(circle1Radius - circle2Radius)) {
        // No Solution. one circle is contained in the other
        return false;
    } else {
        return true;
    }

Перейдите сюда для формулы Пересечение двух кругов

Используемая формула - это не моя формула, все кредиты принадлежат Полю Бурку (апрель 1997 г.)

 First calculate the distance d between the center of the circles. d = ||P1 - P0||.

    If d > r0 + r1 then there are no solutions, the circles are separate.

    If d < |r0 - r1| then there are no solutions because one circle is contained within the other.

    If d = 0 and r0 = r1 then the circles are coincident and there are an infinite number of solutions.

Considering the two triangles P0P2P3 and P1P2P3 we can write

a2 + h2 = r02 and b2 + h2 = r12

Using d = a + b we can solve for a,

a = (r02 - r12 + d2 ) / (2 d)

It can be readily shown that this reduces to r0 when the two circles touch at one point, ie: d = r0 + r1

Solve for h by substituting a into the first equation, h2 = r02 - a2
So

P2 = P0 + a ( P1 - P0 ) / d

And finally, P3 = (x3,y3) in terms of P0 = (x0,y0), P1 = (x1,y1) and P2 = (x2,y2), is

x3 = x2 +- h ( y1 - y0 ) / d

y3 = y2 -+ h ( x1 - x0 ) / d 

Ответ 6

Решение Swift 4:

struct Circle {
    let radius: CGFloat
    let position: CGPoint
}

func circlesIntersect(circleA: Circle, circleB: Circle) -> Bool {
    let Δr² = pow(circleA.radius - circleB.radius, 2)
    let Δx² = pow(circleA.position.x - circleB.position.x, 2)
    let Δy² = pow(circleA.position.y - circleB.position.y, 2)
    let ΣΔx²Δy² = Δx² + Δy²
    let Σr² = pow(circleA.radius + circleB.radius, 2)
    return Δr² <= ΣΔx²Δy² && ΣΔx²Δy² <= Σr²
}

Ответ 7

Это решение в Java использовало математическое выражение, которое было описано выше:

/**
     * 
     * @param values
     *            { x0, y0, r0, x1, y1, r1 }
     * @return true if circles is intersected
     * 
     *         Check if circle is intersect to another circle
     */
    public static boolean isCircleIntersect(double... values) {
        /*
         * check using mathematical relation: ABS(R0-R1) <=
         * SQRT((x0-x1)^2+(y0-y1)^2) <= (R0+R1)
         */
        if (values.length == 6) {
            /* get values from first circle */
            double x0 = values[0];
            double y0 = values[1];
            double r0 = values[2];
            /* get values from second circle */
            double x1 = values[3];
            double y1 = values[4];
            double r1 = values[5];
            /* returun result */
            return (Math.abs(r0 - r1) <= Math.sqrt(Math.pow((x0 - x1), 2)
                    + Math.pow((y0 - y1), 2)))
                    && (Math.sqrt(Math.pow((x0 - x1), 2)
                            + Math.pow((y0 - y1), 2)) <= (r0 + r1));
        } else {
            /* return default result */
            return false;
        }
    }