用于testing点是否在圆内的等式

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

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

请注意,满足上述方程式的<==代替的点被认为是圆上的点,满足上述方程式的<代替>被认为是圆的点。

在math上,毕达哥拉斯可能是很多已经提到过的简单方法。

 (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. 

现在我们已经覆盖了我们的大部分空间,只有这个圈子的一小部分留在我们的方形和钻石之间进行testing。 这里我们回到上面的毕达哥拉斯。

 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. 

替代方法想象这个圆形内的正方形,而不是钻石,但是这需要稍微更多的testing和计算,没有计算优势(内部正方形和钻石具有相同的区域):

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

更新:

对于那些对性能感兴趣的人,我用c实现了这个方法,并用-O3编译。

我按time ./a.out获得执行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 

另外,杰森指出<=应该被replace为< ,根据使用情况,这实际上是有意义的 尽pipe我相信在严格的math意义上这不是真的 我纠正了。

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

这是更高效,可读性强。 它避免了昂贵的平方根操作。 我还添加了一个检查来确定点是否在圆的边界矩形内。

除了多点或多圈之外,矩形检查是不必要的。 如果大多数点在圆圈内,则边界矩形检查实际上会使事情变慢。

一如既往,一定要考虑你的用例。

计算距离

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

这是在C#中…在Python中使用转换…

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

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

如上所述 – 使用欧几里德距离。

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

这与Jason Punyon提到的解决scheme是一样的,但它包含一个伪代码示例和一些更多的细节。 写完这个之后我看到了他的回答,但是我不想把它移走。

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

 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是点的坐标。

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

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

我在C#中的答案作为一个完整的剪切和粘贴(未优化)解决scheme:

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

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

公共课程incirkel {

 public static void main(String[] args) { int x; int y; int middelx; int middely; int straal; { // Adjust the coordinates of x and yx = -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"); } } } }} 

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

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

要用graphics表示,我们可以使用:

 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)