如果您有一个中心为(center_x, center_y)
且半径为radius
的圆圈,那么如何测试坐标为(x, y)
的给定点是否在圆圈内?
答案 0 :(得分:452)
通常,x
和y
必须满足(x - center_x)^2 + (y - center_y)^2 < radius^2
。
请注意,满足<
取代==
的上述等式的点被视为 on 圆上的点,以及满足上述等式的点{被<
取代的{1}}被视为外部圈。
答案 1 :(得分:120)
数学上,毕达哥拉斯可能是一个很多人已经提到过的简单方法。
(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);
}
答案 2 :(得分:71)
您可以使用毕达哥拉斯来测量您的点与中心之间的距离,看它是否低于半径:
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指出<=
应该被<
取代,并且取决于使用情况,这实际上可能有意义,即使我认为在严格的数学意义上它不是真的。 我的立场得到了纠正。
答案 3 :(得分:35)
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;
}
这更有效,更易读。它避免了昂贵的平方根操作。我还添加了一个检查,以确定该点是否在圆的边界矩形内。
除非有许多点或多个圆圈,否则不需要进行矩形检查。如果大多数点在圆圈内,则边界矩形检查实际上会使事情变慢!
一如既往,请务必考虑您的使用案例。
答案 4 :(得分:12)
计算距离
D = Math.Sqrt(Math.Pow(center_x - x, 2) + Math.Pow(center_y - y, 2))
return D <= radius
在C#中转换为在python中使用...
答案 5 :(得分:10)
你应该检查从圆心到点的距离是否小于半径,即
if (x-center_x)**2 + (y-center_y)**2 <= radius**2:
# inside circle
答案 6 :(得分:5)
如上所述 - 使用欧几里德距离。
from math import hypot
def in_radius(c_x, c_y, r, x, y):
return math.hypot(c_x-x, c_y-y) <= r
答案 7 :(得分:4)
找出圆心与给定点之间的距离。如果它们之间的距离小于半径,则该点在圆内。 如果它们之间的距离等于圆的半径,则该点位于圆的圆周上。 如果距离大于半径,则该点在圆圈之外。
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");
答案 8 :(得分:2)
这与mentioned by Jason Punyon的解决方案相同,但它包含一个伪代码示例和一些更多细节。写完这篇文章后我看到了他的答案,但我不想删除我的答案。
我认为最容易理解的方法是首先计算圆心和点之间的距离。我会用这个公式:
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
是坐标重点。
答案 9 :(得分:2)
我在C#中的答案是一个完整的剪辑&amp;粘贴(未优化)解决方案:
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)) { }
答案 10 :(得分: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)
答案 11 :(得分:1)
下面的方程式是一个测试点的表达式,其中 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;
}
答案 12 :(得分:0)
PHP
if ((($x - $center_x) ** 2 + ($y - $center_y) ** 2) <= $radius **2) {
return true; // Inside
} else {
return false; // Outside
}
答案 13 :(得分: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;
}
答案 14 :(得分:0)
我知道最好的答案还有几年的时间,但是我设法将计算时间减少了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));
}
答案 15 :(得分:0)
如果要检查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;
}
答案 16 :(得分:0)
我为以下的初学者使用了以下代码:)。
public class 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");
}
}
}
}}