web-dev-qa-db-fra.com

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

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

275
directedition

En général, x et y doivent 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és par > sont considérés comme le extérieur le cercle.

447
jason

Mathématiquement, 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 du calcul, il existe des moyens plus rapides. Définir:

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

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

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

Imaginons maintenant un losange carré dessiné à l'intérieur de ce cercle, tel que ses sommets touchent ce cercle:

if dx + dy <= R then 
    return true.

Nous avons maintenant recouvert la plus grande partie de notre espace et il ne reste qu'une petite zone de ce cercle entre notre carré et le diamant à tester. Nous revenons ici à Pythagore comme ci-dessus.

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

Si un point a plus de chance d'être à l'intérieur ce cercle , inversez 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.

Les méthodes alternatives imaginent 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 en calcul (le carré intérieur et les diamants ont des zones identiques):

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

Mettre à jour:

Pour ceux qui s'intéressent à la performance, j'ai implémenté cette méthode en c, et compilé avec -O3.

J'ai obtenu les temps d'exécution par time ./a.out

J'ai mis en œuvre cette méthode, une méthode normale et une méthode fictive pour déterminer le temps système nécessaire.

Normal: 21.3s This: 19.1s Overhead: 16.5s

Il semble donc que cette méthode soit plus efficace dans cette implémentation.

// compile gcc -O3 <filename>.c
// run: time ./a.out

#include <stdio.h>
#include <stdlib.h>

#define TRUE  (0==0)
#define FALSE (0==1)

#define ABS(x) (((x)<0)?(0-(x)):(x))

int xo, yo, R;

int inline inCircle( int x, int y ){  // 19.1, 19.1, 19.1
  int dx = ABS(x-xo);
  if (    dx >  R ) return FALSE;
  int dy = ABS(y-yo);
  if (    dy >  R ) return FALSE;
  if ( dx+dy <= R ) return TRUE;
  return ( dx*dx + dy*dy <= R*R );
}

int inline inCircleN( int x, int y ){  // 21.3, 21.1, 21.5
  int dx = ABS(x-xo);
  int dy = ABS(y-yo);
  return ( dx*dx + dy*dy <= R*R );
}

int inline dummy( int x, int y ){  // 16.6, 16.5, 16.4
  int dx = ABS(x-xo);
  int dy = ABS(y-yo);
  return FALSE;
}

#define N 1000000000

int main(){
  int x, y;
  xo = Rand()%1000; yo = Rand()%1000; R = 1;
  int n = 0;
  int c;
  for (c=0; c<N; c++){
    x = Rand()%1000; y = Rand()%1000;
//    if ( inCircle(x,y)  ){
    if ( inCircleN(x,y) ){
//    if ( dummy(x,y) ){
      n++;
    }
  }
  printf( "%d of %d inside circle\n", n, N);
}
119
philcolbourn

Vous pouvez utiliser Pythagore pour mesurer la distance entre votre 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(astuce de Paul)

En pratique, la quadrature est souvent beaucoup moins chère que de prendre la racine carrée et comme nous ne sommes intéressés que par une commande, 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

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

71
Konrad Rudolph
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 = centerX - x;
        double dy = centerY - y;
        dx *= dx;
        dy *= dy;
        double distanceSquared = dx + dy;
        double radiusSquared = radius * radius;
        return distanceSquared <= radiusSquared;
    }
    return false;
}

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

La vérification du rectangle est inutile sauf avec beaucoup de points ou plusieurs cercles. Si la plupart des points sont à l'intérieur de cercles, la vérification du rectangle de contour ralentira les choses!

Comme toujours, veillez à prendre en compte votre cas d'utilisation.

35
William Morrison

Calculer la distance

D = Math.Sqrt(Math.Pow(center_x - x, 2) + Math.Pow(center_y - y, 2))
return D <= radius

c'est en C ... converti pour être utilisé en python ...

12
Jason Punyon

Vous devez vérifier si la distance entre le centre du cercle et le point est inférieure au rayon, c.-à-d.

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

Comme dit ci-dessus - utilisez la distance euclidienne.

from math import hypot

def in_radius(c_x, c_y, r, x, y):
    return math.hypot(c_x-x, c_y-y) <= r
5
i0cus

Trouvez la distance entre le centre du cercle et les points indiqués. Si la distance qui les sépare est inférieure au rayon, alors le point est à l'intérieur du cercle . Si la distance les séparant est égale au rayon du cercle, le point se trouve sur la circonférence du cercle . Si la distance est plus grand que le rayon alors le point est en dehors du cercle.

int d = r^2 - (center_x-x)^2 + (center_y-y)^2;

if(d>0)
  print("inside");
else if(d==0)
  print("on the circumference");
else
  print("outside");
3
DEEPAK KUMAR SINGH

C’est la même solution que mentionnée par Jason Punyon , mais elle contient un exemple de pseudo-code et quelques détails supplémentaires. J'ai vu sa réponse après avoir écrit ceci, mais je ne voulais pas enlever la mienne.

Je pense que le moyen le plus facile à comprendre consiste à calculer d'abord la distance entre le centre du cercle et le point. Je voudrais utiliser cette formule:

d = sqrt((circle_x - x)^2 + (circle_y - y)^2)

Ensuite, comparez simplement le résultat de cette formule, la distance (d), avec le radius. Si la distance (d) est inférieure ou égale au rayon (r), le point est à l'intérieur du cercle (sur le bord du cercle si d et r sont égaux).

Voici un exemple de pseudo-code qui peut facilement être converti en n’importe quel langage de programmation:

function is_in_circle(circle_x, circle_y, r, x, y)
{
    d = sqrt((circle_x - x)^2 + (circle_y - y)^2);
    return d <= r;
}

circle_x et circle_y sont les coordonnées du centre du cercle, r est le rayon du cercle et x et y sont les coordonnées du point.

2
Daniel Kvist

Ma réponse en C # en tant que solution complète de copier/coller (non optimisée):

public static bool PointIsWithinCircle(double circleRadius, double circleCenterPointX, double circleCenterPointY, double pointToCheckX, double pointToCheckY)
{
    return (Math.Pow(pointToCheckX - circleCenterPointX, 2) + Math.Pow(pointToCheckY - circleCenterPointY, 2)) < (Math.Pow(circleRadius, 2));
}

Usage:

if (!PointIsWithinCircle(3, 3, 3, .5, .5)) { }
2
Adam Cox

L'équation ci-dessous est une expression qui teste si un point se trouve dans un cercle donné où xP & yP sont les coordonnées du point, xC & yC sont les coordonnées du centre du cercle et R est le rayon de ce cercle.

enter image description here

Si l'expression ci-dessus est vraie, alors le point est dans le cercle.

Voici un exemple d'implémentation en C #:

    public static bool IsWithinCircle(PointF pC, Point pP, Single fRadius){
        return Distance(pC, pP) <= fRadius;
    }

    public static Single Distance(PointF p1, PointF p2){
        Single dX = p1.X - p2.X;
        Single dY = p1.Y - p2.Y;
        Single multi = dX * dX + dY * dY;
        Single dist = (Single)Math.Round((Single)Math.Sqrt(multi), 3);

        return (Single)dist;
    }
1
Cabbage Champion

En entrant dans le monde de la 3D, si vous souhaitez vérifier si un point 3D se trouve dans une unité Sphère, vous finirez par faire quelque chose de similaire. Pour travailler en 2D, il suffit d’utiliser des opérations vectorielles 2D.

    public static bool Intersects(Vector3 point, Vector3 center, float radius)
    {
        Vector3 displacementToCenter = point - center;

        float radiusSqr = radius * radius;

        bool intersects = displacementToCenter.magnitude < radiusSqr;

        return intersects;
    }
0
user5747799

Je sais que c’est à quelques années de la réponse la mieux votée, mais j’ai réussi à réduire le temps de calcul de 4.

Il vous suffit de calculer les pixels à partir de 1/4 du cercle, puis de les multiplier par 4.

C'est la solution que j'ai atteinte:

#include <stdio.h>
#include <stdlib.h>
#include <time.h> 

int x, y, r;
int mx, c, t;
int dx, dy;
int p;

int main() {
    for (r = 1; r < 128; r++){

        clock_t t; 
        t = clock();

        p = calculatePixels(r);

        t = clock() - t; 
        double time_taken = ((double)t)/CLOCKS_PER_SEC; // in seconds 

        printf( "%d of pixels inside circle with radius %d, took %f seconds to execute \n", p, r, time_taken);
    }
}

int calculatePixels(int r){
    mx = 2 * r;
    c = (mx+1)*(mx+1);
    t = r * r;
    int a = 0;
    for (x = 0; x < r; x++){
      for (y = 0; y < r; y++){
          dx = x-r;
          dy = y-r;
          if ((dx*dx + dy*dy) > t)
              a++;
          else 
              y = r;
      }
    }
    return (c - (a * 4));
}
0
graffitiMSX

Voici le code Java simple pour résoudre ce problème: 

et les calculs derrière: https://math.stackexchange.com/questions/198764/how-to-know-if-a-point-is-inside-a-circle

boolean insideCircle(int[] point, int[] center, int radius) {
    return (float)Math.sqrt((int)Math.pow(point[0]-center[0],2)+(int)Math.pow(point[1]-center[1],2)) <= radius;
}
0
Ketan Ramteke

Comme indiqué précédemment, pour montrer si le point est dans le cercle, nous pouvons utiliser le code suivant:

if ((x-center_x)^2 + (y - center_y)^2 < radius^2) {
    in.circle <- "True"
} else {
    in.circle <- "False"
}

Pour le représenter graphiquement, nous pouvons utiliser:

plot(x, y, asp = 1, xlim = c(-1, 1), ylim = c(-1, 1), col = ifelse((x-center_x)^2 + (y - center_y)^2 < radius^2,'green','red'))
draw.circle(0, 0, 1, nv = 1000, border = NULL, col = NA, lty = 1, lwd = 1)
0
Selrac

J'ai utilisé le code ci-dessous pour les débutants comme moi :).

classe publique incirkel {

public static void main(String[] args) {
    int x; 
    int y; 
    int middelx; 
    int middely; 
    int straal; {

// Adjust the coordinates of x and y 
x = -1;
y = -2;

// Adjust the coordinates of the circle
middelx = 9; 
middely = 9;
straal =  10;

{
    //When x,y is within the circle the message below will be printed
    if ((((middelx - x) * (middelx - x)) 
                    + ((middely - y) * (middely - y))) 
                    < (straal * straal)) {
                        System.out.println("coordinaten x,y vallen binnen cirkel");
    //When x,y is NOT within the circle the error message below will be printed
    } else {
        System.err.println("x,y coordinaten vallen helaas buiten de cirkel");
    } 
}



    }
}}
0
user5560892