判断一个点是否在圆内的公式
判断一个点是否在圆内的公式
如果您有一个中心坐标为(center_x, center_y)
、半径为radius
的圆,您如何测试具有坐标(x, y)
的给定点是否在圆内?
admin 更改状态以发布 2023年5月23日
从数学上讲,如众人所述,毕达哥拉斯定理可能是一种简单的方法。 \n\n
(x-center_x)^2 + (y - center_y)^2 < radius^2
\n\n 计算上,有更快的方式。定义: \n\n
dx = abs(x-center_x) dy = abs(y-center_y) R = radius
\n\n 如果一个点更可能在这个圆外,那么想象一个正方形画在它周围,它的边是这个圆的切线:\n\n
if dx>R then return false. if dy>R then return false.
\n\n现在想象一个正方形的钻石图案画在里面,它的顶点靠近这个圆:\n\n
if dx + dy <= R then return true.
\n\n现在我们覆盖了我们的大多数空间,只有这个圆的一小部分仍然在我们的正方形和钻石之间进行测试。在这里我们回到了毕达哥拉斯理论,如上所述。 \n\n
if dx^2 + dy^2 <= R^2 then return true else return false.
\n\n如果一个点更可能在这个圆内,那么就倒序第一步三步: \n\n
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.
\n\n替代方法想象一个正方形在这个圆内而不是钻石,但这需要稍微多一些测试和计算,并且没有计算上的优势(内部正方形和钻石具有相同的面积):\n\n
k = R/sqrt(2) if dx <= k and dy <= k then return true.
\n\n更新:\n\n对于那些对性能感兴趣的人,我使用C实现了这个方法,并编译了-O3。 \n\n我通过time ./a.out
获取执行时间。\n\n我实现了这个方法,一个普通的方法和一个虚拟的方法来确定时间开销。 \n\n普通: 21.3秒 这: 19.1秒 开销:16.5秒
\n\n因此,似乎这种方法在这种实现中更有效率。 \n\n
// compile gcc -O3.c // run: time ./a.out #include #include #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