Алгоритм обнаружения, если Круги пересекаются с любым другим кругом в одной плоскости
Я ищу алгоритм для определения того, пересекаются ли Круги с любым другим кругом в одной плоскости, учитывая, что в плоскости может быть больше одной окружности.
Стандартный метод, который я нашел, - это выполнить тест разделительной оси (это сделал поиск в 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.
но я не знаю, как применить его с кругом.
может кто-нибудь помочь мне здесь?
Ответы
Ответ 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;
}
}