Comment savoir si un cercle et un rectangle se croisent dans un espace euclidien 2D? (c'est-à-dire géométrie 2D classique)
192
Comment savoir si un cercle et un rectangle se croisent dans un espace euclidien 2D? (c'est-à-dire géométrie 2D classique)
Réponses:
Il n'y a que deux cas où le cercle croise le rectangle:
Notez que cela ne nécessite pas que le rectangle soit parallèle à l'axe.
(Une façon de voir ceci: si aucune des arêtes n'a de point dans le cercle (si toutes les arêtes sont complètement "à l'extérieur" du cercle), la seule façon pour le cercle de toujours croiser le polygone est de savoir s'il se trouve complètement à l'intérieur du cercle. polygone.)
Avec cette idée, quelque chose comme ce qui suit fonctionnera, où le cercle a le centre
P
et le rayonR
, et le rectangle a sommetsA
,B
,C
,D
dans cet ordre (code non complet):Si vous écrivez une géométrie, vous avez probablement déjà les fonctions ci-dessus dans votre bibliothèque. Sinon,
pointInRectangle()
peut être mis en œuvre de plusieurs manières; n'importe quel point général des méthodes polygonales fonctionnera, mais pour un rectangle, vous pouvez simplement vérifier si cela fonctionne:Et
intersectCircle()
c'est facile à mettre en œuvre aussi: une façon serait de vérifier si le pied de la perpendiculaire deP
à la ligne est suffisamment proche et entre les extrémités, et de vérifier les extrémités autrement.Ce qui est cool, c'est que la même idée fonctionne non seulement pour les rectangles, mais pour l'intersection d'un cercle avec n'importe quel polygone simple - n'a même pas besoin d'être convexe!
la source
Voici comment je le ferais:
Voici comment ça fonctionne:
La première paire de lignes calcule les valeurs absolues de la différence x et y entre le centre du cercle et le centre du rectangle. Cela réduit les quatre quadrants en un seul, de sorte que les calculs ne doivent pas être effectués quatre fois. L'image montre la zone dans laquelle le centre du cercle doit maintenant se trouver. Notez que seul le quadrant unique est affiché. Le rectangle est la zone grise et la bordure rouge délimite la zone critique qui est exactement à un rayon des bords du rectangle. Le centre du cercle doit être à l'intérieur de cette bordure rouge pour que l'intersection se produise.
La deuxième paire de lignes élimine les cas faciles où le cercle est suffisamment éloigné du rectangle (dans les deux sens) pour qu'aucune intersection ne soit possible. Cela correspond à la zone verte de l'image.
La troisième paire de lignes gère les cas faciles où le cercle est suffisamment proche du rectangle (dans les deux sens) pour qu'une intersection soit garantie. Cela correspond aux sections orange et grise de l'image. Notez que cette étape doit être effectuée après l'étape 2 pour que la logique ait un sens.
Les lignes restantes calculent le cas difficile où le cercle peut croiser le coin du rectangle. Pour résoudre, calculez la distance entre le centre du cercle et le coin, puis vérifiez que la distance n'est pas supérieure au rayon du cercle. Ce calcul renvoie faux pour tous les cercles dont le centre se trouve dans la zone ombrée rouge et renvoie vrai pour tous les cercles dont le centre se trouve dans la zone ombrée blanche.
la source
;)
circleDistance_x = abs(circle.x - (rect.x-rect.w/2)); circleDistance_y = abs(circle.y - (rect.y-rect.h/2));
Voici une autre solution assez simple à mettre en œuvre (et assez rapide aussi). Il capturera toutes les intersections, y compris lorsque la sphère est complètement entrée dans le rectangle.
Avec n'importe quelle bibliothèque mathématique décente, cela peut être raccourci à 3 ou 4 lignes.
la source
votre sphère et votre rect se croisent IIF
la distance entre le centre du cercle et un sommet de votre rect est plus petite que le rayon de votre sphère
OU
la distance entre le centre du cercle et un bord de votre rect est plus petite que le rayon de votre sphère ( [ distance point-ligne ])
OU
le centre du cercle est à l'intérieur de la
distance point-point rect :
distance point-ligne:
centre du cercle à l'intérieur du rect:
prenez une approche d'axes séparés: s'il existe une projection sur une ligne qui sépare le rectangle du point, ils ne se croisent pas
vous projetez le point sur des lignes parallèles aux côtés de votre rect et pouvez alors facilement déterminer si elles se croisent. s'ils ne se croisent pas sur les 4 projections, ils (le point et le rectangle) ne peuvent pas se croiser.
vous avez juste besoin du produit interne (x = [x1, x2], y = [y1, y2], x * y = x1 * y1 + x2 * y2)
votre test ressemblerait à ça:
cela ne suppose pas un rectangle aligné sur l'axe et est facilement extensible pour tester les intersections entre des ensembles convexes.
la source
C'est la solution la plus rapide:
Notez l'ordre d'exécution, et la moitié de la largeur / hauteur est pré-calculée. La mise au carré est également effectuée "manuellement" pour enregistrer certains cycles d'horloge.
la source
La solution la plus simple que j'ai trouvée est assez simple.
Cela fonctionne en trouvant le point dans le rectangle le plus proche du cercle, puis en comparant la distance.
Vous pouvez faire tout cela avec quelques opérations, et même éviter la fonction sqrt.
Et c'est tout! La solution ci-dessus suppose une origine dans le coin supérieur gauche du monde avec l'axe des x pointant vers le bas.
Si vous voulez une solution pour gérer les collisions entre un cercle et un rectangle en mouvement, c'est beaucoup plus compliqué et couvert dans une autre de mes réponses.
la source
En fait, c'est beaucoup plus simple. Vous n'avez besoin que de deux choses.
Tout d'abord, vous devez trouver quatre distances orthogonales entre le centre du cercle et chaque ligne du rectangle. Ensuite, votre cercle ne coupera pas le rectangle si trois d'entre eux sont plus grands que le rayon du cercle.
Deuxièmement, vous devez trouver la distance entre le centre du cercle et le centre du rectangle, puis votre cercle ne sera pas à l'intérieur du rectangle si la distance est supérieure à la moitié de la longueur diagonale du rectangle.
Bonne chance!
la source
Voici mon code C pour résoudre une collision entre une sphère et une boîte non alignée sur l'axe. Il repose sur quelques-unes de mes propres routines de bibliothèque, mais cela peut s'avérer utile pour certains. Je l'utilise dans un jeu et cela fonctionne parfaitement.
la source
Pour visualiser, prenez le pavé numérique de votre clavier. Si la touche «5» représente votre rectangle, alors toutes les touches 1 à 9 représentent les 9 quadrants de l'espace divisés par les lignes qui composent votre rectangle (5 étant l'intérieur.)
1) Si le centre du cercle est dans le quadrant 5 (c'est-à-dire à l'intérieur du rectangle), les deux formes se croisent.
Avec cela à l'écart, il y a deux cas possibles: a) Le cercle croise deux ou plusieurs arêtes voisines du rectangle. b) Le cercle coupe un bord du rectangle.
Le premier cas est simple. Si le cercle coupe deux arêtes voisines du rectangle, il doit contenir le coin reliant ces deux arêtes. (Cela, ou son centre se trouve dans le quadrant 5, que nous avons déjà couvert. Notez également que le cas où le cercle coupe avec seulement deux opposés bords du rectangle est également couvert.)
2) Si l'un des coins A, B, C, D du rectangle se trouve à l'intérieur du cercle, les deux formes se croisent.
Le deuxième cas est plus délicat. Nous devons noter que cela ne peut se produire que lorsque le centre du cercle se trouve dans l'un des quadrants 2, 4, 6 ou 8. (En fait, si le centre est sur l'un des quadrants 1, 3, 7, 8, le le coin correspondant en sera le point le plus proche.)
Nous avons maintenant le cas où le centre du cercle est dans l'un des quadrants «arête», et il ne croise que l'arête correspondante. Ensuite, le point du bord le plus proche du centre du cercle doit se trouver à l'intérieur du cercle.
3) Pour chaque ligne AB, BC, CD, DA, construisez des droites perpendiculaires p (AB, P), p (BC, P), p (CD, P), p (DA, P) passant par le centre du cercle P. Pour chaque ligne perpendiculaire, si l'intersection avec l'arête d'origine se trouve à l'intérieur du cercle, les deux formes se croisent.
Il existe un raccourci pour cette dernière étape. Si le centre du cercle est dans le quadrant 8 et que l'arête AB est l'arête supérieure, le point d'intersection aura la coordonnée y de A et B, et la coordonnée x du centre P.
Vous pouvez construire les quatre intersections de lignes et vérifier si elles se trouvent sur leurs arêtes correspondantes, ou trouver dans quel quadrant P se trouve et vérifier l'intersection correspondante. Les deux devraient se simplifier à la même équation booléenne. Méfiez-vous du fait que l'étape 2 ci-dessus n'exclut pas que P se trouve dans l'un des quadrants de «coin»; il a juste cherché une intersection.
Edit: En fin de compte, j'ai négligé le simple fait que le n ° 2 est un sous-cas du n ° 3 ci-dessus. Après tout, les coins sont aussi des points sur les bords. Voir la réponse de @ ShreevatsaR ci-dessous pour une excellente explication. Et en attendant, oubliez le n ° 2 ci-dessus, sauf si vous voulez une vérification rapide mais redondante.
la source
Cette fonction détecte les collisions (intersections) entre Circle et Rectangle. Il fonctionne comme la méthode e.James dans sa réponse, mais celle-ci détecte les collisions pour tous les angles du rectangle (pas seulement le coin droit).
REMARQUE:
aRect.origin.x et aRect.origin.y sont les coordonnées de l'angle inférieur gauche du rectangle!
aCircle.x et aCircle.y sont les coordonnées de Circle Center!
la source
J'ai une méthode qui évite le pythagore coûteux si ce n'est pas nécessaire - c'est à dire. lorsque les boîtes englobantes du rectangle et du cercle ne se croisent pas.
Et cela fonctionnera aussi pour les non-euclidiens:
dLat=(lat-circleY); dLon=(lon-circleX); normed=dLat*dLat+dLon*dLon
. Bien sûr, si vous utilisez cette méthode normDist, vous devrez créer unnormedDist = dist*dist;
pour le cercleVoir le code complet BBox et Circle de mon projet GraphHopper .
la source
J'ai créé une classe pour travailler avec des formes j'espère que vous apprécierez
la source
Voici le code modifié fonctionnant à 100%:
Bassam Alugili
la source
Voici un test rapide en une ligne pour cela:
Il s'agit du cas aligné sur l'axe où se
rect_halves
trouve un vecteur positif pointant du milieu du rectangle vers un coin. L'expression à l'intérieurlength()
est un vecteur delta allantcenter
du point le plus proche du rectangle. Cela fonctionne dans toutes les dimensions.la source
C'est efficace, car:
la source
a fonctionné pour moi (ne fonctionne que lorsque l'angle du rectangle est de 180)
la source
Améliorer un peu la réponse de e.James :
Cela soustrait
rect.w / 2
etrect.h / 2
une fois au lieu de jusqu'à trois fois.la source
Pour ceux qui doivent calculer la collision Cercle / Rectangle dans les coordonnées géographiques avec SQL, voici
mon implémentation dans l'oracle 11 de l' algorithme suggéré par e.James .
En entrée, il nécessite les coordonnées du cercle, le rayon du cercle en km et les coordonnées de deux sommets du rectangle:
la source
Works, je viens de comprendre cela il y a une semaine, et je viens de le tester.
la source
la source
En supposant que vous ayez les quatre bords du rectangle, vérifiez la distance entre les bords et le centre du cercle, si elle est inférieure au rayon, les formes se croisent.
la source
Si le rectangle croise le cercle, un ou plusieurs points d'angle du rectangle doivent être à l'intérieur du cercle. Supposons que les quatre points d'un rectangle soient A, B, C, D. au moins l'un d'entre eux doit couper le cercle. donc si la distance entre un point et le centre du cercle est inférieure au rayon du cercle, elle doit couper le cercle. Pour obtenir la distance, vous pouvez utiliser le théorème de Pythagore,
Cette technique a quelques limites. Mais cela fonctionnera mieux pour les développeurs de jeux. en particulier la détection de collision
C'est une bonne mise à jour de l'algorithme d'Arvo
la source