Nếu bạn có một vòng tròn có tâm (center_x, center_y)
và bán kính radius
, làm thế nào để kiểm tra xem một điểm đã cho có tọa độ (x, y)
có nằm trong vòng tròn không?
Nếu bạn có một vòng tròn có tâm (center_x, center_y)
và bán kính radius
, làm thế nào để kiểm tra xem một điểm đã cho có tọa độ (x, y)
có nằm trong vòng tròn không?
Câu trả lời:
Nói chung, x
và y
phải thỏa mãn (x - center_x)^2 + (y - center_y)^2 < radius^2
.
Xin lưu ý rằng các điểm thỏa mãn phương trình trên được <
thay thế bằng ==
được coi là các điểm trên đường tròn và các điểm thỏa mãn phương trình trên được <
thay thế bằng >
được coi là bên ngoài vòng tròn.
<=
sẽ tìm thấy các điểm bên trong vòng tròn hoặc trên cạnh của nó.
Về mặt toán học, Pythagoras có lẽ là một phương pháp đơn giản như nhiều người đã đề cập.
(x-center_x)^2 + (y - center_y)^2 < radius^2
Tính toán, có những cách nhanh hơn. Định nghĩa:
dx = abs(x-center_x)
dy = abs(y-center_y)
R = radius
Nếu một điểm có nhiều khả năng nằm ngoài vòng tròn này thì hãy tưởng tượng một hình vuông được vẽ xung quanh nó sao cho các cạnh của nó là tiếp tuyến của vòng tròn này:
if dx>R then
return false.
if dy>R then
return false.
Bây giờ hãy tưởng tượng một viên kim cương vuông được vẽ bên trong vòng tròn này sao cho các đỉnh của nó chạm vào vòng tròn này:
if dx + dy <= R then
return true.
Bây giờ chúng tôi đã bao phủ hầu hết không gian của chúng tôi và chỉ còn lại một khu vực nhỏ của vòng tròn này nằm giữa hình vuông và hình thoi của chúng tôi để thử nghiệm. Ở đây chúng tôi trở lại Pythagoras như trên.
if dx^2 + dy^2 <= R^2 then
return true
else
return false.
Nếu một điểm có nhiều khả năng nằm trong vòng tròn này thì hãy đảo ngược thứ tự 3 bước đầu tiê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.
Các phương pháp thay thế tưởng tượng một hình vuông bên trong vòng tròn này thay vì một viên kim cương nhưng điều này đòi hỏi nhiều thử nghiệm và tính toán hơn một chút không có lợi thế tính toán (hình vuông bên trong và hình thoi có các khu vực giống hệt nhau):
k = R/sqrt(2)
if dx <= k and dy <= k then
return true.
Cập nhật:
Đối với những người quan tâm đến hiệu suất, tôi đã triển khai phương pháp này trong c và được biên dịch với -O3.
Tôi đã đạt được thời gian thực hiện bởi time ./a.out
Tôi đã thực hiện phương pháp này, một phương pháp bình thường và một phương pháp giả để xác định chi phí thời gian.
Normal: 21.3s
This: 19.1s
Overhead: 16.5s
Vì vậy, có vẻ như phương pháp này hiệu quả hơn trong việc thực hiện này.
// 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);
}
inCircleN
bạn đang sử dụng ABS không cần thiết. Có lẽ không có sự khác biệt giữa ABS inCircle
và inCircleN
sẽ nhỏ hơn.
Bạn có thể sử dụng Pythagoras để đo khoảng cách giữa điểm của bạn và trung tâm và xem liệu nó có thấp hơn bán kính không:
def in_circle(center_x, center_y, radius, x, y):
dist = math.sqrt((center_x - x) ** 2 + (center_y - y) ** 2)
return dist <= radius
EDIT (mũ cho Paul)
Trong thực tế, bình phương thường rẻ hơn nhiều so với lấy căn bậc hai và vì chúng ta chỉ quan tâm đến việc đặt hàng, nên tất nhiên chúng ta có thể từ bỏ việc lấy căn bậc hai:
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
Ngoài ra, Jason lưu ý rằng <=
nên được thay thế bởi <
và tùy thuộc vào cách sử dụng, điều này thực sự có thể có ý nghĩamặc dù tôi tin rằng nó không đúng theo nghĩa toán học nghiêm ngặt. Tôi đứng sửa.
**
hay ^
. Cách nhanh nhất để làm điều đó khi bạn chỉ cần x ^ 2 hoặc x ^ 3 là làm "thủ công" : x*x
.
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;
}
Điều này là hiệu quả hơn, và có thể đọc được. Nó tránh các hoạt động căn bậc hai tốn kém. Tôi cũng đã thêm một kiểm tra để xác định xem điểm có nằm trong hình chữ nhật giới hạn của hình tròn không.
Kiểm tra hình chữ nhật là không cần thiết ngoại trừ với nhiều điểm hoặc nhiều vòng tròn. Nếu hầu hết các điểm nằm trong vòng tròn, kiểm tra hình chữ nhật giới hạn sẽ thực sự làm mọi thứ chậm hơn!
Như mọi khi, hãy chắc chắn xem xét trường hợp sử dụng của bạn.
Tính khoảng cách
D = Math.Sqrt(Math.Pow(center_x - x, 2) + Math.Pow(center_y - y, 2))
return D <= radius
đó là trong C # ... chuyển đổi để sử dụng trong python ...
Như đã nói ở trên - sử dụng khoảng cách Euclide.
from math import hypot
def in_radius(c_x, c_y, r, x, y):
return math.hypot(c_x-x, c_y-y) <= r
Tìm khoảng cách giữa tâm của đường tròn và các điểm đã cho. Nếu khoảng cách giữa chúng nhỏ hơn bán kính thì điểm nằm trong vòng tròn. nếu khoảng cách giữa chúng bằng bán kính của vòng tròn thì điểm nằm trên chu vi của vòng tròn. nếu khoảng cách lớn hơn bán kính thì điểm nằm ngoài đường tròn.
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");
Phương trình dưới đây là một biểu thức kiểm tra nếu một điểm nằm trong một đường tròn đã cho trong đó xP & yP là tọa độ của điểm, xC & yC là tọa độ của tâm của đường tròn và R là bán kính của đường tròn đã cho.
Nếu biểu thức trên là đúng thì điểm nằm trong vòng tròn.
Dưới đây là một triển khai mẫu trong 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;
}
Đây là giải pháp tương tự như Jason Punyon đã đề cập , nhưng nó chứa một ví dụ mã giả và một số chi tiết khác. Tôi đã thấy câu trả lời của anh ấy sau khi viết bài này, nhưng tôi không muốn xóa câu trả lời của tôi.
Tôi nghĩ rằng cách dễ hiểu nhất là trước tiên hãy tính khoảng cách giữa tâm của vòng tròn và điểm. Tôi sẽ sử dụng công thức này:
d = sqrt((circle_x - x)^2 + (circle_y - y)^2)
Sau đó, chỉ cần so sánh kết quả của công thức đó, khoảng cách ( d
), với radius
. Nếu khoảng cách ( d
) nhỏ hơn hoặc bằng bán kính ( r
), điểm nằm trong vòng tròn (trên cạnh của vòng tròn nếu d
và r
bằng nhau).
Dưới đây là một ví dụ mã giả có thể dễ dàng chuyển đổi sang bất kỳ ngôn ngữ lập trình nào:
function is_in_circle(circle_x, circle_y, r, x, y)
{
d = sqrt((circle_x - x)^2 + (circle_y - y)^2);
return d <= r;
}
Trong đó circle_x
và circle_y
là tọa độ trung tâm của vòng tròn, r
là bán kính của vòng tròn x
và y
là tọa độ của điểm.
Câu trả lời của tôi trong C # là giải pháp cắt & dán hoàn chỉnh (không được tối ưu hóa):
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));
}
Sử dụng:
if (!PointIsWithinCircle(3, 3, 3, .5, .5)) { }
Như đã nêu trước đây, để hiển thị nếu điểm nằm trong vòng tròn, chúng ta có thể sử dụng như sau
if ((x-center_x)^2 + (y - center_y)^2 < radius^2) {
in.circle <- "True"
} else {
in.circle <- "False"
}
Để biểu thị nó bằng đồ họa, chúng ta có thể sử dụng:
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)
Tôi đã sử dụng mã dưới đây cho người mới bắt đầu như tôi :).
lớp học công cộng 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");
}
}
}
}}
Di chuyển vào thế giới 3D nếu bạn muốn kiểm tra xem điểm 3D có trong Đơn vị hình cầu không, cuối cùng bạn sẽ làm điều gì đó tương tự. Tất cả những gì cần thiết để làm việc trong 2D là sử dụng các hoạt động vectơ 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;
}
Tôi biết rằng vài năm sau câu trả lời được bình chọn tốt nhất, nhưng tôi đã cố gắng giảm thời gian tính toán xuống 4.
Bạn chỉ cần tính toán các pixel từ 1/4 vòng tròn, sau đó nhân với 4.
Đây là giải pháp tôi đạt được:
#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));
}
Đây là mã java đơn giản để giải quyết vấn đề này:
và toán học đằng sau nó: /math/198764/how-to-ledge-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;
}