375 votes

Équation pour tester si un point est à l'intérieur d'un cercle

Si vous avez un cercle avec un centre (center_x, center_y) et le rayon radius comment tester si un point donné avec des coordonnées (x, y) est à l'intérieur du cercle ?

20 votes

Cette question n'est pas liée au langage, j'utilise la même formule en Java, donc je ré-étiquette.

0 votes

Il semble que vous ne supposiez que des coordonnées positives. Les solutions ci-dessous ne fonctionnent pas avec des coordonnées signées.

2 votes

La plupart des solutions ci-dessous faire travailler avec des coordonnées positives et négatives. Je corrige simplement ce détail pour les futurs utilisateurs de cette question.

580voto

Jason Points 125291

En général, x et y doit satisfaire (x - center_x)^2 + (y - center_y)^2 < radius^2 .

Veuillez noter que les points qui satisfont l'équation ci-dessus avec < remplacé par == sont considérés comme les points sur le cercle, et les points qui satisfont l'équation ci-dessus avec < remplacé par > sont considérés comme les à l'extérieur de le cercle.

6 votes

Il peut être utile pour les moins matheux de voir l'opération de la racine carrée utilisée pour mesurer la distance par rapport au rayon. Je me rends compte que ce n'est pas optimal, mais comme votre réponse est formatée plus comme une équation que comme un code, peut-être cela a-t-il plus de sens ? C'est juste une suggestion.

45 votes

Il s'agit de l'explication la plus compréhensible fournie en une simple phrase et une équation immédiatement utilisable. Bien joué.

0 votes

C'est génial, j'aurais aimé trouver cette ressource plus rapidement. D'où vient la valeur x ?

157voto

philcolbourn Points 1182

Sur le plan mathématique, Pythagore est probablement une méthode simple, comme beaucoup l'ont déjà mentionné.

(x-center_x)^2 + (y - center_y)^2 < radius^2

Sur le plan informatique, il existe des moyens plus rapides. Définissez :

dx = abs(x-center_x)
dy = abs(y-center_y)
R = radius

Si un point est plus susceptible d'être à l'extérieur de ce cercle puis imaginez un carré dessiné autour de lui de telle sorte que ses côtés soient tangents à ce cercle :

if dx>R then 
    return false.
if dy>R then 
    return false.

Imaginez maintenant un losange carré dessiné à l'intérieur de ce cercle de telle sorte que ses sommets touchent ce cercle :

if dx + dy <= R then 
    return true.

Nous avons maintenant couvert la majeure partie de notre espace et il ne reste plus qu'une petite zone de ce cercle entre notre carré et notre diamant à tester. Ici, nous revenons à Pythagore comme ci-dessus.

if dx^2 + dy^2 <= R^2 then 
    return true
else 
    return false.

Si un point est plus susceptible d'être à l'intérieur de ce cercle puis inverser l'ordre des 3 premières étapes :

if dx + dy <= R then 
    return true.
if dx > R then 
    return false.
if dy > R 
    then return false.
if dx^2 + dy^2 <= R^2 then 
    return true
else
    return false.

D'autres méthodes consistent à imaginer un carré à l'intérieur de ce cercle au lieu d'un diamant, mais cela nécessite un peu plus de tests et de calculs, sans aucun avantage sur le plan informatique (le carré intérieur et le diamant ont des surfaces identiques) :

k = R/sqrt(2)
if dx <= k and dy <= k then 
    return true.

6 votes

Cette réponse est excellente. Je n'avais jamais réalisé certaines des optimisations que vous suggérez. Bien joué.

2 votes

Je suis curieux de savoir si vous avez profilé ces optimisations ? Mon intuition me dit que des conditionnels multiples seraient plus lents que des mathématiques et un conditionnel, mais je peux me tromper.

3 votes

@yoyo, je n'ai effectué aucun profilage - cette question concerne une méthode pour n'importe quel langage de programmation. Si quelqu'un pense que cette méthode peut améliorer les performances de son application, il doit, comme vous le suggérez, démontrer qu'elle est plus rapide dans des scénarios normaux.

85voto

Konrad Rudolph Points 231505

Tu peux utiliser Pythagore pour mesurer la distance entre ton point et le centre et voir si elle est inférieure au rayon :

def in_circle(center_x, center_y, radius, x, y):
    dist = math.sqrt((center_x - x) ** 2 + (center_y - y) ** 2)
    return dist <= radius

EDIT (coup de chapeau à Paul)

En pratique, la mise au carré est souvent beaucoup moins chère que la racine carrée et, puisque nous ne sommes intéressés que par un ordre, nous pouvons bien sûr renoncer à la racine carrée :

def in_circle(center_x, center_y, radius, x, y):
    square_dist = (center_x - x) ** 2 + (center_y - y) ** 2
    return square_dist <= radius ** 2

De plus, Jason a noté que <= doit être remplacé par < et selon l'utilisation, cela peut avoir du sens même si je crois que ce n'est pas vrai au sens mathématique strict. . Je me suis trompé.

1 votes

Remplacer dist <= rayon par dist < rayon pour tester si le point est à l'intérieur du cercle.

17 votes

Sqrt est coûteux. Évitez-le si possible - comparez le x^2+y^y à r^2.

0 votes

Jason : nos définitions peuvent diverger mais pour moi, un point qui est sur la circonférence du cercle est aussi très clairement sur le cercle et je suis presque sûr que la mienne est en accord avec la définition formelle, mathématique.

40voto

William Morrison Points 6578
boolean isInRectangle(double centerX, double centerY, double radius, 
    double x, double y)
{
        return x >= centerX - radius && x <= centerX + radius && 
            y >= centerY - radius && y <= centerY + radius;
}    

//test if coordinate (x, y) is within a radius from coordinate (center_x, center_y)
public boolean isPointInCircle(double centerX, double centerY, 
    double radius, double x, double y)
{
    if(isInRectangle(centerX, centerY, radius, x, y))
    {
        double dx = center_x - x;
        double dy = center_y - y;
        dx *= dx;
        dy *= dy;
        double distanceSquared = dx + dy;
        double radiusSquared = radius * radius;
        return distanceSquared <= radiusSquared;
    }
    return false;
}

C'est plus efficace et plus lisible. Elle évite l'opération coûteuse de la racine carrée. J'ai également ajouté une vérification pour déterminer si le point est dans le rectangle de délimitation du cercle.

Le contrôle du rectangle n'est pas nécessaire, sauf avec de nombreux points ou de nombreux cercles. Si la plupart des points sont à l'intérieur de cercles, la vérification du rectangle engendre un ralentissement de l'opération !

Comme toujours, veillez à tenir compte de votre cas d'utilisation.

19voto

dF. Points 29787

Vous devez vérifier si la distance du centre du cercle au point est inférieure au rayon, soit

if (x-center_x)**2 + (y-center_y)**2 <= radius**2:
    # inside circle

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X