Merkez (center_x, center_y)
ve yarıçaplı bir daireniz radius
varsa, koordinatlarla belirli bir noktanın (x, y)
dairenin içinde olup olmadığını nasıl test edersiniz ?
Merkez (center_x, center_y)
ve yarıçaplı bir daireniz radius
varsa, koordinatlarla belirli bir noktanın (x, y)
dairenin içinde olup olmadığını nasıl test edersiniz ?
Yanıtlar:
Genel olarak x
ve y
tatmin etmek gerekir (x - center_x)^2 + (y - center_y)^2 < radius^2
.
Lütfen not bununla yukarıdaki denklemi tatmin noktaları <
yerini ==
noktaları olarak kabul edilir üzerindeki daire ve yukarıda denklemi tatmin noktaları <
yerine >
kabul edilir dışında çember.
<=
dairenin içinde veya kenarında noktalar bulacağı belirtilmelidir .
Matematiksel olarak, Pisagor muhtemelen daha önce de belirttiğimiz gibi basit bir yöntemdir.
(x-center_x)^2 + (y - center_y)^2 < radius^2
Hesaplamalı olarak, daha hızlı yollar var. Tanımlamak:
dx = abs(x-center_x)
dy = abs(y-center_y)
R = radius
Bir noktanın bu dairenin dışında olma olasılığı daha yüksekse, etrafının çizildiği bir kare hayal edin ki kenarları bu daireye teğet olacak:
if dx>R then
return false.
if dy>R then
return false.
Şimdi, bu çemberin içine çizilen kare bir elmas hayal edin, böylece köşeleri bu daireye değecektir:
if dx + dy <= R then
return true.
Şimdi alanımızın çoğunu kapladık ve bu dairenin sadece küçük bir alanı test edilecek kare ve elmas arasında kalıyor. Burada yukarıdaki gibi Pisagor'a dönüyoruz.
if dx^2 + dy^2 <= R^2 then
return true
else
return false.
Bir noktanın bu dairenin içinde olma olasılığı daha yüksekse , ilk 3 adımın tersini uygulayı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.
Alternatif yöntemler, bu dairenin içinde bir elmas yerine bir kare hayal eder, ancak bu, hesaplama avantajı olmayan biraz daha fazla test ve hesaplama gerektirir (iç kare ve elmaslar aynı alanlara sahiptir):
k = R/sqrt(2)
if dx <= k and dy <= k then
return true.
Güncelleme:
Performansla ilgilenenler için bu yöntemi c'de uyguladım ve -O3 ile derledim.
Tarafından icra süreleri elde ettim time ./a.out
Zamanlama yükünü belirlemek için bu yöntemi, normal bir yöntemi ve bir kukla yöntemi uyguladım.
Normal: 21.3s
This: 19.1s
Overhead: 16.5s
Yani, bu yöntem bu uygulamada daha verimli görünüyor.
// 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
gereksiz ABS kullanıyorsunuz. Muhtemelen ABS farkı olmadan inCircle
ve inCircleN
daha küçük olacaktır.
Noktanız ile merkez arasındaki mesafeyi ölçmek ve yarıçaptan daha düşük olup olmadığını görmek için Pisagor'u kullanabilirsiniz:
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 (Paul'e şapka ucu)
Pratikte, kareleme genellikle kare kökünü almaktan çok daha ucuzdur ve sadece bir siparişle ilgilendiğimizden, elbette kare kökünü almayı bırakabiliriz:
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
Ayrıca, Jason <=
bunun değiştirilmesi gerektiğini belirtti <
ve kullanıma bağlı olarak bu aslında mantıklı olabilirkatı matematiksel anlamda doğru olmadığına inansam bile. Ben düzeltilmiş duruyorum.
**
veya yoktur ^
. Sadece x ^ 2 veya x ^ 3 "elle" bunu yapmak için ise gerektiğinde en hızlı şekilde yapmak: 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;
}
Bu daha verimli ve okunabilir. Pahalı karekök işleminden kaçınır. Ayrıca noktanın dairenin sınırlayıcı dikdörtgeni içinde olup olmadığını belirlemek için bir kontrol ekledim.
Dikdörtgen kontrolü, çok sayıda nokta veya çok sayıda daire haricinde gereksizdir. Noktaların çoğu dairelerin içindeyse, sınırlayıcı dikdörtgen kontrolü aslında işleri yavaşlatır!
Her zaman olduğu gibi, kullanım durumunuzu dikkate aldığınızdan emin olun.
Mesafeyi Hesapla
D = Math.Sqrt(Math.Pow(center_x - x, 2) + Math.Pow(center_y - y, 2))
return D <= radius
Bu C # ... python kullanmak için dönüştürmek ...
Yukarıda belirtildiği gibi Öklid mesafesini kullanın.
from math import hypot
def in_radius(c_x, c_y, r, x, y):
return math.hypot(c_x-x, c_y-y) <= r
Dairenin merkezi ile verilen noktalar arasındaki mesafeyi bulun. Aralarındaki mesafe yarıçaptan daha azsa, nokta dairenin içindedir. aralarındaki mesafe dairenin yarıçapına eşitse, nokta dairenin çevresindedir. mesafe yarıçaptan büyükse nokta dairenin dışındadı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");
Aşağıdaki denklem, bir nokta belirli bir dairenin içinde bir test ise bir ifade xP ve yP noktasının koordinatları, xC ve yC dairenin merkezinin koordinatları ve R verilen dairenin yarıçapıdır.
Yukarıdaki ifade doğruysa, nokta dairenin içindedir.
Aşağıda C # ile ilgili örnek bir uygulama yer almaktadır:
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;
}
Bu, Jason Punyon tarafından belirtilenle aynı çözümdür , ancak sözde kod örneği ve daha fazla ayrıntı içerir. Bunu yazdıktan sonra cevabını gördüm, ama benimkini kaldırmak istemedim.
Bence en kolay anlaşılır yol önce dairenin merkezi ile nokta arasındaki mesafeyi hesaplamaktır. Bu formülü kullanırdım:
d = sqrt((circle_x - x)^2 + (circle_y - y)^2)
Ardından, bu formülün sonucunu, uzaklık ( d
) ile radius
. Distance ( d
), yarıçaptan ( r
) küçük veya ona eşitse , nokta dairenin içindedir ( d
ve r
eşitse dairenin kenarında ).
İşte herhangi bir programlama diline kolayca dönüştürülebilen bir sözde kod örneği:
function is_in_circle(circle_x, circle_y, r, x, y)
{
d = sqrt((circle_x - x)^2 + (circle_y - y)^2);
return d <= r;
}
Burada circle_x
ve circle_y
dairenin merkez koordinatları olan, r
dairenin yarıçapıdır, ve x
ve y
noktasının koordinatları olan.
Tam bir kes ve yapıştır (optimize edilmemiş) çözümü olarak C #'daki cevabım:
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));
}
Kullanımı:
if (!PointIsWithinCircle(3, 3, 3, .5, .5)) { }
Daha önce belirtildiği gibi, noktanın daire içinde olup olmadığını göstermek için aşağıdakileri kullanabiliriz
if ((x-center_x)^2 + (y - center_y)^2 < radius^2) {
in.circle <- "True"
} else {
in.circle <- "False"
}
Grafiksel olarak temsil etmek için şunları kullanabiliriz:
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)
Benim gibi yeni başlayanlar için aşağıdaki kodu kullandım :).
kamu sınıfı 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");
}
}
}
}}
Bir 3D noktasının Birim Kürede olup olmadığını kontrol etmek istiyorsanız, 3D dünyasına geçmek, sonunda benzer bir şey yaparsınız. 2D'de çalışmak için gereken tek şey 2D vektör işlemlerini kullanmaktır.
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;
}
En iyi oyu alan yanıttan birkaç yıl geçtiğini biliyorum, ancak hesaplama süresini 4 oranında azaltmayı başardım.
Dairenin yalnızca 1 / 4'ünden pikselleri hesaplamanız ve ardından 4 ile çarpmanız gerekir.
Bu benim ulaştığım çözüm:
#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));
}
İşte bu sorunu çözmek için basit java kodu:
ve arkasındaki matematik: /math/198764/how-to-know-if-a-point-is-inside-a-ircle
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;
}