检验点是否在圆内的方程

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

347903 次浏览

通常,xy必须满足(x - center_x)² + (y - center_y)² < radius²

请注意,满足上述方程,将<替换为==的点视为圆中的点,将满足上述方程,将<替换为>的点视为圆中的点。

计算距离

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

这是用c#写的……转换为python中使用…

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

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

编辑(向Paul致敬)

实际上,取平方根通常比取平方根便宜得多,因为我们只对排序感兴趣,我们当然可以放弃取平方根:

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还指出,<=应该被<取代,根据使用情况,这实际上可能是有意义的尽管我认为这在严格的数学意义上是不对的我接受纠正。

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

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

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

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

像往常一样,一定要考虑您的用例。

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

(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获得了执行时间

我实现了这个方法,一个正常的方法和一个虚拟的方法来确定定时开销。

< p > <代码>正常:21.3 s : 19.1秒 开销:16.5 s < /代码> < / p >

因此,这个方法在这个实现中似乎更有效。

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

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

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

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






}
}}
求圆心到给定点之间的距离。如果它们之间的距离小于半径,则该点在圆内。 如果它们之间的距离等于圆的半径,那么这个点就在圆的周长上。 如果距离大于半径,则该点在圆外
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");

如前所述,为了显示点是否在圆中,我们可以使用下面的方法

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)

我的答案在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;
}

下面是解决这个问题的简单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;
}

下面的方程是一个表达式,它测试一个点是否在给定的圆内,其中xP &yP是该点的坐标,xC &yC是圆心的坐标,R是给定圆的半径。

enter image description here

如果上述表达式为真,则该点在圆内。

下面是一个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;
}

PHP

if ((($x - $center_x) ** 2 + ($y - $center_y) ** 2) <=  $radius **2) {
return true; // Inside
} else {
return false; // Outside
}

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
}