Уравнение для проверки, если точка находится внутри круга
Если у вас есть круг с центром (center_x, center_y)
и радиус radius
Как проверить, если заданная точка с координатами (x, y)
внутри круга?
18 ответов
В общем, x
а также y
должен удовлетворить (x - center_x)^2 + (y - center_y)^2 < radius^2
,
Обратите внимание, что точки, которые удовлетворяют вышеуказанному уравнению с <
заменен на ==
считаются точками на окружности, и точками, которые удовлетворяют приведенному выше уравнению с <
заменен на >
считаются вне круга.
Математически Пифагор, вероятно, является простым методом, как многие уже упоминали.
(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);
}
Вы можете использовать Пифагор, чтобы измерить расстояние между вашей точкой и центром и посмотреть, меньше ли оно радиуса:
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
Также Джейсон отметил, что <=
должен быть заменен <
и в зависимости от использования это может действительно иметь смысл хотя я считаю, что это не так в строгом математическом смысле, Я стою исправлено.
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;
}
Это более эффективно и доступно для чтения. Это позволяет избежать дорогостоящей операции с квадратным корнем. Я также добавил проверку, чтобы определить, находится ли точка внутри ограничительного прямоугольника круга.
Проверка прямоугольника не нужна, за исключением множества точек или кругов. Если большинство точек находятся внутри окружностей, проверка ограничивающего прямоугольника на самом деле замедлит процесс!
Как всегда, обязательно рассмотрите ваш вариант использования.
Вы должны проверить, меньше ли расстояние от центра круга до точки, чем радиус, т.е.
if (x-center_x)**2 + (y-center_y)**2 <= radius**2:
# inside circle
Найти расстояние между центром круга и заданными точками. Если расстояние между ними меньше радиуса, то точка находится внутри круга. если расстояние между ними равно радиусу круга, то точка находится на окружности круга. если расстояние больше радиуса, то точка находится за пределами круга.
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");
Рассчитать расстояние
D = Math.Sqrt(Math.Pow(center_x - x, 2) + Math.Pow(center_y - y, 2))
return D <= radius
это в C#... конвертировать для использования в Python...
Как сказано выше - используйте евклидово расстояние.
from math import hypot
def in_radius(c_x, c_y, r, x, y):
return math.hypot(c_x-x, c_y-y) <= r
Приведенное ниже уравнение - это выражение, которое проверяет, находится ли точка внутри данного круга, где xP и yP - координаты точки, xC и yC - координаты центра круга, а R - радиус этого круга.
Если приведенное выше выражение верно, то точка находится внутри круга.
Ниже приведен пример реализации на 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;
}
Это то же решение, которое упоминал Джейсон Пуньон, но оно содержит пример псевдокода и некоторые другие детали. Я видел его ответ после того, как написал это, но я не хотел удалять свой.
Я думаю, что наиболее легко понятный способ - это сначала вычислить расстояние между центром круга и точкой. Я бы использовал эту формулу:
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
это координаты точки.
Мой ответ в 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)) { }
Переходя в мир 3D, если вы хотите проверить, находится ли 3D-точка в Сфере Юнитов, вы в конечном итоге делаете нечто подобное. Все, что нужно для работы в 2D - это использовать 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;
}
Как указывалось ранее, чтобы показать, находится ли точка в окружности, мы можем использовать следующее
if ((x-center_x)^2 + (y - center_y)^2 < radius^2) {
in.circle <- "True"
} else {
in.circle <- "False"
}
Чтобы представить это графически, мы можем использовать:
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)
iOS 15, принятый ответ написан на Swift 5.5
func isInRectangle(center: CGPoint, radius: Double, point: CGPoint) -> Bool
{
return point.x >= center.x - radius && point.x <= center.x + radius &&
point.y >= center.y - radius && point.y <= center.y + radius
}
//test if coordinate (x, y) is within a radius from coordinate (center_x, center_y)
func isPointInCircle(center: CGPoint,
radius:Double, point: CGPoint) -> Bool
{
if(isInRectangle(center: center, radius: radius, point: point))
{
var dx:Double = center.x - point.x
var dy:Double = center.y - point.y
dx *= dx
dy *= dy
let distanceSquared:Double = dx + dy
let radiusSquared:Double = radius * radius
return distanceSquared <= radiusSquared
}
return false
}
Я использовал код ниже для начинающих, как я:).
открытый класс 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");
}
}
}
}}
PHP
if ((($x - $center_x) ** 2 + ($y - $center_y) ** 2) <= $radius **2) {
return true; // Inside
} else {
return false; // Outside
}
Вот простой Java-код для решения этой проблемы:
и математика за ним: 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;
}
Я знаю, что через несколько лет я получил ответ, получивший наибольшее количество голосов, но мне удалось сократить время расчета на 4.
Вам нужно только рассчитать пиксели от 1/4 круга, а затем умножить на 4.
Это решение, которое я достиг:
#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));
}