web-dev-qa-db-ja.com

点が円の内側にあるかどうかをテストするための方程式

中心が(center_x, center_y)で半径がradiusの円がある場合、座標(x, y)を持つ特定の点が円の内側にあるかどうかをどのようにテストしますか?

283
directedition

一般に、xおよびy(x - center_x)^2 + (y - center_y)^2 < radius^2を満たす必要があります。

<==に置き換えて上記の式を満たす点は点onとみなし、<>に置き換えて上記の式を満たす点はoutside)と見なすことに注意してください円。

453
jason

数学的には、ピタゴラスはおそらく多くの人がすでに述べたようにおそらく簡単な方法です。

(x-center_x)^2 + (y - center_y)^2 < radius^2

計算上、より速い方法があります。定義します。

dx = abs(x-center_x)
dy = abs(y-center_y)
R = radius

ある点がoutsideこの円になる可能性が高い場合それから辺がこの円の接線になるように、その周りに描かれた正方形を想像してみてください。

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.

もしある点がinsideこの円になる可能性が高い場合その後、最初の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);
}
120
philcolbourn

ピタゴラスを使用して、ポイントと中心の間の距離を測定し、それが半径より小さいかどうかを確認できます。

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(ポールへのハットチップ)

実際には、平方根は平方根をとるよりはるかに安いことが多く、順序付けだけに興味があるので、もちろん平方根を取ることを差し控えることができます。

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は<=<に置き換えられるべきであり、使用法によってはこれが実際には意味があるかもしれないと述べました 厳密な数学的意味では真実ではないと私は信じていますが正しい立場です

71
Konrad Rudolph
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;
}

これはより効率的で読みやすいです。それは高価な平方根演算を避けます。また、ポイントが円の境界矩形内にあるかどうかを確認するためのチェックも追加しました。

四角形のチェックは、多数の点または多数の円を除いては不要です。ほとんどの点が円の内側にある場合、境界矩形チェックは実際には物事を遅くします。

いつものように、必ずあなたのユースケースを考慮してください。

35

距離を計算する

D = Math.Sqrt(Math.Pow(center_x - x, 2) + Math.Pow(center_y - y, 2))
return D <= radius

これはC#に含まれています... pythonで使用するために変換しています...

12
Jason Punyon

円の中心から点までの距離が半径より小さいかどうかを確認する必要があります。

if (x-center_x)**2 + (y-center_y)**2 <= radius**2:
    # inside circle
10
dF.

上記のように - ユークリッド距離を使用してください。

from math import hypot

def in_radius(c_x, c_y, r, x, y):
    return math.hypot(c_x-x, c_y-y) <= r
5
i0cus

円の中心から与えられた点までの距離を求めます。それらの間の距離が半径より小さい場合、点は円の内側にあります。それらの間の距離が円の半径に等しい場合、点は円の円周上にあります。距離が半径よりも大きい場合、点は円の外側にあります。

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");
4

これは Jason Punyonによる と同じ解決策ですが、擬似コードの例と詳細が含まれています。私はこれを書いた後彼の答えを見ましたが、私は私のものを削除したくありませんでした

最も分かりやすい方法は、まず円の中心と点の間の距離を計算することです。私はこの公式を使います:

d = sqrt((circle_x - x)^2 + (circle_y - y)^2)

次に、その式の結果である距離(d)とradiusを単純に比較します。距離(d)が半径(r)以下の場合、点は円の内側にあります(drが等しい場合は円の端にあります)。

これは、どのプログラミング言語にも簡単に変換できる疑似コードの例です。

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_xcircle_yは円の中心座標、rは円の半径、xyは点の座標です。

2
Daniel Kvist

完全なカットアンドペースト(最適化されていない)ソリューションとしての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)) { }
2
Adam Cox

次の式は、ポイントがxPyPはポイントの座標、xCyCは円の中心の座標であり、Rはその円の半径です。

enter image description here

上記の式が真の場合、ポイントは円内にあります。

以下は、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;
    }
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)
1
Selrac

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;
    }
0
user5747799

私は最善の回答から数年後のことを知っていますが、私は計算時間を4分の1に短縮することに成功しました。

あなたはただ円の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));
}
0
graffitiMSX

これは、この問題を解決するための簡単な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;
}
0
Ketan Ramteke

私は私のような初心者のために以下のコードを使いました:)。

パブリッククラスの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");
    } 
}



    }
}}
0
user5560892