359

如果你有一个 center(center_x, center_y)和 radius的圆radius,你如何测试一个给定的坐标点(x, y)是否在圆内?

4

16 回答 16

562

一般来说,xy必须满足(x - center_x)² + (y - center_y)² < radius²

请注意,满足上述等式的点<==认为是圆的点,满足上述等式的点<>认为是圆的点。

于 2009-01-26T20:09:56.793 回答
153

在数学上,毕达哥拉斯可能是许多人已经提到的简单方法。

(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);
}
于 2011-08-29T07:00:05.033 回答
82

您可以使用毕达哥拉斯来测量您的点与中心之间的距离,看看它是否低于半径:

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

此外,Jason 指出<=应该替换为<并根据使用情况,这实际上可能是有意义的尽管我相信这在严格的数学意义上是不正确的. 我站得更正了。

于 2009-01-26T20:10:33.860 回答
39
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;
}

这更有效,更易读。它避免了昂贵的平方根运算。我还添加了一个检查以确定该点是否在圆的边界矩形内。

矩形检查是不必要的,除非有很多点或很多圆。如果大多数点都在圆圈内,那么边界矩形检查实际上会使事情变慢!

与往常一样,请务必考虑您的用例。

于 2011-06-10T20:01:06.513 回答
19

您应该检查从圆心到点的距离是否小于半径

使用 Python

if (x-center_x)**2 + (y-center_y)**2 <= radius**2:
    # inside circle
于 2009-01-26T20:10:54.450 回答
14

求圆心与给定点之间的距离。如果它们之间的距离小于半径,则该点在圆内。如果它们之间的距离等于圆的半径,则该点位于圆的圆周上。如果距离大于半径,则该点在圆外。

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");
于 2016-07-06T07:31:04.250 回答
12

计算距离

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

那是在 C# 中...转换为在 python 中使用...

于 2009-01-26T20:10:10.473 回答
6

如上所述 - 使用欧几里得距离。

from math import hypot

def in_radius(c_x, c_y, r, x, y):
    return math.hypot(c_x-x, c_y-y) <= r
于 2009-01-28T14:45:08.320 回答
5

下面的等式是一个表达式,用于测试一个点是否在给定的圆内,其中xPyP是该点的坐标,xCyC是圆心的坐标,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;
    }
于 2019-06-28T18:08:12.070 回答
2

这与Jason Punyon 提到的解决方案相同,但它包含一个伪代码示例和更多细节。我在写完这篇文章后看到了他的回答,但我不想删除我的。

我认为最容易理解的方法是首先计算圆心到点之间的距离。我会使用这个公式:

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

然后,只需将该公式的结果,即距离 ( d) 与 进行比较radius。如果距离 ( d) 小于或等于半径 ( r),则该点在圆内(如果dr相等,则在圆的边缘上)。

这是一个可以轻松转换为任何编程语言的伪代码示例:

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_xcircle_y是圆的中心坐标, 是圆r的半径,xy是点的坐标。

于 2015-06-09T14:35:55.720 回答
2

我在 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)) { }
于 2017-01-21T21:21:54.573 回答
1

如前所述,要显示该点是否在圆圈中,我们可以使用以下命令

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)
于 2016-09-15T12:52:01.793 回答
0

我为像我这样的初学者使用了下面的代码:)。

公共课 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");
    } 
}



    }
}}
于 2015-11-14T23:37:36.860 回答
0

如果您想检查 3D 点是否在 Unit Sphere 中,则进入 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;
    }
于 2017-11-16T03:11:06.600 回答
0

这是解决这个问题的简单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;
}
于 2018-11-17T16:26:23.610 回答
0

PHP

if ((($x - $center_x) ** 2 + ($y - $center_y) ** 2) <=  $radius **2) {
    return true; // Inside
} else {
    return false; // Outside
}
于 2019-12-16T14:47:36.713 回答