Уравнение для проверки, если точка находится внутри круга - PullRequest
283 голосов
/ 26 января 2009

Если у вас есть круг с центром (center_x, center_y) и радиусом radius, как проверить, находится ли заданная точка с координатами (x, y) внутри круга?

Ответы [ 15 ]

453 голосов
/ 26 января 2009

В общем, x и y должны удовлетворять (x - center_x)^2 + (y - center_y)^2 < radius^2.

Обратите внимание, что точки, которые удовлетворяют вышеприведенному уравнению с заменой < на ==, считаются точками на окружности, а точки, которые удовлетворяют приведенному выше уравнению с <, заменяются > считаются вне круга.

120 голосов
/ 29 августа 2011

Математически Пифагор, вероятно, является простым методом, о котором многие уже упоминали.

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

В вычислительном отношении есть более быстрые способы. Определить:

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

Если точка с большей вероятностью будет за пределами этого круга , представьте квадрат, нарисованный вокруг него так, что его стороны касаются этого круга:

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

Теперь представьте квадратный ромб, нарисованный внутри этого круга так, чтобы его вершины касались этого круга:

if dx + dy <= R then 
    return true.

Теперь мы покрыли большую часть нашего пространства, и только небольшая область этого круга остается между нашим квадратом и алмазом, подлежащим проверке. Здесь мы возвращаемся к Пифагору, как указано выше.

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

Если точка с большей вероятностью будет внутри этого круга , тогда обратный порядок первых 3 шагов:

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.

Альтернативные методы представляют квадрат внутри этого круга вместо ромба, но для этого требуется немного больше тестов и вычислений без вычислительных преимуществ (внутренний квадрат и ромбы имеют одинаковые площади):

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

Обновление:

Для тех, кто интересуется производительностью, я реализовал этот метод в c и скомпилировал с -O3.

Я получил время выполнения на time ./a.out

Я реализовал этот метод, обычный метод и фиктивный метод для определения временных затрат.

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

Итак, кажется, что этот метод более эффективен в этой реализации.

// 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);
}
71 голосов
/ 26 января 2009

Вы можете использовать Пифагор, чтобы измерить расстояние между вашей точкой и центром и посмотреть, меньше ли оно радиуса:

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

РЕДАКТИРОВАТЬ (кончик шляпы Полу)

На практике возведение в квадрат часто намного дешевле, чем получение квадратного корня, и, поскольку нас интересует только порядок, мы, конечно, можем отказаться от получения квадратного корня:

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

Кроме того, Джейсон отметил, что <= следует заменить на <, и в зависимости от использования это может иметь смысл , хотя я считаю, что это не так в строгом математическом смысле . Я исправлен.

35 голосов
/ 11 июня 2011
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;
}

Это более эффективно и доступно для чтения. Это позволяет избежать дорогостоящей операции с квадратным корнем. Я также добавил проверку, чтобы определить, находится ли точка внутри ограничительного прямоугольника круга.

Проверка прямоугольника не нужна, за исключением множества точек или кругов. Если большинство точек находятся внутри окружностей, проверка ограничивающего прямоугольника на самом деле замедлит процесс!

Как всегда, обязательно рассмотрите вариант использования.

12 голосов
/ 26 января 2009

Рассчитать расстояние

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

это в C # ... конвертировать для использования в python ...

10 голосов
/ 26 января 2009

Вы должны проверить, меньше ли расстояние от центра круга до точки, чем радиус, т.е.

if (x-center_x)**2 + (y-center_y)**2 <= radius**2:
    # inside circle
5 голосов
/ 28 января 2009

Как сказано выше - используйте евклидово расстояние.

from math import hypot

def in_radius(c_x, c_y, r, x, y):
    return math.hypot(c_x-x, c_y-y) <= r
4 голосов
/ 06 июля 2016

Найдите расстояние между центром круга и указанными точками. Если расстояние между ними меньше радиуса, то точка находится внутри круга. если расстояние между ними равно радиусу круга, то точка находится на окружности круга. если расстояние больше радиуса, то точка находится за пределами круга.

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");
2 голосов
/ 22 января 2017

Мой ответ на C # как полное решение «вырезать и вставить» (не оптимизировано):

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));
}

Использование:

if (!PointIsWithinCircle(3, 3, 3, .5, .5)) { }
2 голосов
/ 09 июня 2015

Это то же решение, что и , упомянутое Джейсоном Пуньоном , но оно содержит пример псевдокода и некоторые другие подробности. Я видел его ответ после того, как написал это, но я не хотел удалять свой.

Я думаю, что самый простой способ - это сначала вычислить расстояние между центром круга и точкой. Я бы использовал эту формулу:

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

Затем просто сравните результат этой формулы, расстояние (d), с radius. Если расстояние (d) меньше или равно радиусу (r), точка находится внутри круга (на краю круга, если d и r равны).

Вот пример псевдокода, который можно легко преобразовать в любой язык программирования:

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 и circle_y - это координаты центра круга, r - радиус круга, а x и y - координаты точки.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...