Je cherche un algorithme pour détecter si un cercle coupe un autre cercle dans le même plan (étant donné qu'il peut y avoir plus d'un cercle dans un plan).
Une méthode que j'ai trouvée consiste à faire le test de l'axe de séparation. Ça dit:
Deux objets ne se croisent pas si vous pouvez trouver une ligne séparant les deux objets, c’est-à-dire une ligne telle que tous les objets ou points d’un objet se trouvent sur des côtés différents de la ligne.
Cependant, je ne sais pas comment appliquer cette méthode à mon cas.
Quelqu'un peut-il m'aider?
Deux cercles se croisent si et seulement si la distance entre leurs centres est comprise entre la somme et la différence de leurs rayons. Étant donné deux cercles (x0, y0, R0)
et (x1, y1, R1)
, la formule est la suivante:
ABS(R0 - R1) <= SQRT((x0 - x1)^2 + (y0 - y1)^2) <= (R0 + R1)
La quadrature des deux côtés vous permet d’éviter la lente SQRT
et de conserver les ints si vos entrées sont des entiers:
(R0 - R1)^2 <= (x0 - x1)^2 + (y0 - y1)^2 <= (R0 + R1)^2
Comme vous n'avez besoin que d'un test oui/non, cette vérification est plus rapide que le calcul des points d'intersection exacts.
La solution ci-dessus devrait fonctionner même pour le cas "un cercle dans l'autre".
En supposant une intersection de cercle rempli (c.-à-d. Qu'un cercle à l'intérieur d'un autre est une intersection).
Où:
Code:
boolean intersects = Math.hypot(x0-x1, y0-y1) <= (r0 + r1);
Solution XNA/C #
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;
}
}
Notez que la méthode Circle.Intersects () renvoie true, même si un cercle se trouve dans un autre (les traite comme des cercles "remplis").
Si la distance entre les centres de deux cercles est au plus la somme de leurs rayons, mais au moins la valeur absolue de la différence entre les rayons, les cercles eux-mêmes se coupent en un point.
La partie "au moins la différence" s'applique si vous vous souciez uniquement des cercles eux-mêmes, et non de leurs zones intérieures. Si vous vous souciez de savoir si les cercles ou les zones qu’ils délimitent partagent des points - c’est-à-dire si un cercle totalement à l’autre compte comme "se croisant" pour vous - vous pouvez alors laisser tomber le "au moins la différence" vérifier.
J'ai essayé la formule donnée ici qui est une réponse supposée et tout le monde a voté de haut en bas bien que ce soit sérieusement imparfait. J'ai écrit un programme en JavaFX pour permettre à l'utilisateur de vérifier si deux cercles se croisent en modifiant les valeurs de chaque centre centerX, centerY et Radius. Cette formule ne fonctionne absolument déplacer le cercle 2 près du cercle 1 ça marche mais quand je déplace le cercle 1 de l’autre côté du cercle 2 ça ne marche pas ..... ????? c'est un peu bizarre ... pensais que la formule devait être testée dans le sens opposé, donc essayée et ça ne marche pas
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;
}
Cela marche:
// 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;
}
Allez ici pour la formule Intersection de deux cercles
La formule utilisée n’est pas la mienne, tout le mérite revient à Paul Bourke (avril 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