หากคุณมีวงกลมที่มีศูนย์กลาง(center_x, center_y)
และรัศมีradius
คุณจะทดสอบได้อย่างไรว่าจุดใดที่มีพิกัด(x, y)
อยู่ภายในวงกลม?
หากคุณมีวงกลมที่มีศูนย์กลาง(center_x, center_y)
และรัศมีradius
คุณจะทดสอบได้อย่างไรว่าจุดใดที่มีพิกัด(x, y)
อยู่ภายในวงกลม?
คำตอบ:
โดยทั่วไปx
และต้องตอบสนองy
(x - center_x)^2 + (y - center_y)^2 < radius^2
โปรดทราบว่าจุดที่ตอบสนองสมการข้างต้นกับ<
แทนที่โดย==
มีการพิจารณาจุดบนวงกลมและจุดที่ตอบสนองสมการข้างต้นกับ<
แทนที่ด้วย>
ถือว่าเป็นนอกวงกลม
<=
จะพบจุดภายในวงกลมหรือบนขอบของมัน
ในทางคณิตศาสตร์ Pythagoras อาจเป็นวิธีที่ง่ายอย่างที่หลายคนได้กล่าวถึงแล้ว
(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.
ตอนนี้เราได้ครอบคลุมพื้นที่ส่วนใหญ่ของเราและมีเพียงพื้นที่เล็ก ๆ ของวงกลมนี้ที่ยังคงอยู่ในระหว่างสี่เหลี่ยมและเพชรของเราที่จะทดสอบ ที่นี่เรากลับไปใช้ Pythagoras ดังที่กล่าวมา
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);
}
inCircleN
คุณใช้ ABS ที่ไม่จำเป็น อาจไม่มีความแตกต่าง ABS ระหว่างinCircle
และinCircleN
จะมีขนาดเล็กลง
คุณสามารถใช้ Pythagoras เพื่อวัดระยะทางระหว่างจุดของคุณกับจุดศูนย์กลางและดูว่ามันต่ำกว่ารัศมีหรือไม่:
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
นอกจากนี้เจสันยังกล่าวอีกว่า <=
ควรแทนที่ด้วย<
และขึ้นอยู่กับการใช้งานซึ่งอาจสมเหตุสมผลแม้ว่าฉันเชื่อว่ามันไม่เป็นความจริงในแง่คณิตศาสตร์ที่เข้มงวด. ฉันยืนแก้ไขแล้ว
**
^
วิธีที่เร็วที่สุดที่จะทำเมื่อคุณเพียงแค่ต้อง x ^ 2 หรือ x ^ 3 คือการทำมัน 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;
}
สิ่งนี้มีประสิทธิภาพมากขึ้นและสามารถอ่านได้ มันหลีกเลี่ยงการดำเนินการรากที่สองราคาแพง ฉันยังเพิ่มการตรวจสอบเพื่อตรวจสอบว่าจุดนั้นอยู่ในขอบเขตสี่เหลี่ยมผืนผ้าของวงกลมหรือไม่
การตรวจสอบรูปสี่เหลี่ยมผืนผ้านั้นไม่จำเป็นยกเว้นในหลาย ๆ จุดหรือหลาย ๆ วงกลม หากคะแนนส่วนใหญ่อยู่ในวงกลมการตรวจสอบสี่เหลี่ยมผืนผ้าที่ล้อมรอบจะทำให้สิ่งต่าง ๆ ช้าลงจริง ๆ !
เช่นเคยให้แน่ใจว่าได้พิจารณากรณีการใช้งานของคุณ
คำนวณระยะทาง
D = Math.Sqrt(Math.Pow(center_x - x, 2) + Math.Pow(center_y - y, 2))
return D <= radius
ที่อยู่ใน C # ... แปลงเพื่อใช้ในหลาม ...
คุณควรตรวจสอบว่าระยะทางจากจุดศูนย์กลางของวงกลมไปยังจุดนั้นเล็กกว่ารัศมีหรือไม่
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
ค้นหาระยะห่างระหว่างศูนย์กลางของวงกลมและจุดที่กำหนด หากระยะห่างระหว่างพวกเขาน้อยกว่ารัศมีจุดนั้นจะอยู่ในวงกลม ถ้าระยะห่างระหว่างพวกเขาเท่ากับรัศมีของวงกลมแล้วจุดนั้นอยู่ในเส้นรอบวงของวงกลม ถ้าระยะทางมากกว่ารัศมีแล้วจุดนั้นอยู่นอกวงกลม
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");
สมการดังต่อไปนี้คือการแสดงออกว่าการทดสอบถ้าจุดอยู่ภายในวงกลมที่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;
}
นี่เป็นวิธีเดียวกับที่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
เป็นพิกัดของจุด
คำตอบของฉันใน 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)) { }
ตามที่ระบุไว้ก่อนหน้านี้เพื่อแสดงว่าจุดอยู่ในวงกลมเราสามารถใช้ต่อไปนี้
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)
ฉันใช้รหัสด้านล่างสำหรับผู้เริ่มต้นเช่นฉัน :)
ชั้นสาธารณะ 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");
}
}
}
}}
การย้ายเข้าสู่โลกของ 3D ถ้าคุณต้องการตรวจสอบว่าจุด 3D นั้นอยู่ใน Unit Sphere หรือไม่คุณต้องทำสิ่งที่คล้ายกัน สิ่งที่ต้องใช้ในการทำงานในแบบ 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;
}
ฉันรู้ว่าไม่กี่ปีจากคำตอบที่ได้รับการโหวตดีที่สุด แต่ฉันสามารถลดเวลาในการคำนวณได้ 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));
}
นี่คือรหัส java อย่างง่ายสำหรับการแก้ปัญหานี้:
และคณิตศาสตร์ที่อยู่เบื้องหลัง: /math/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;
}
PHP
if ((($x - $center_x) ** 2 + ($y - $center_y) ** 2) <= $radius **2) {
return true; // Inside
} else {
return false; // Outside
}