指定された中心点、半径、および次数を持つ円上の点を見つけます


84

このような計算をしてから10年になります...私は2Dでゲームをプログラミングし、プレーヤーを動かしています。プレーヤーを動かしながら、-360〜360の正または負の角度(度)を指定して、プレーヤーの位置から200ピクセル離れた円上の点を計算しようとしています。画面は1280x720で、0,0が中心点です。画面の。プレーヤーは、このデカルト座標系全体を移動します。私が見つけようとしているポイントは、画面外にある可能性があります。

記事「半径と角度で点を見つける」の数式を試しましたが、角度を-360から360としてCos(angle)またはSinに渡すと奇妙な結果が得られるため、「角度」が何であるかを理解していないと思います。 (角度)。

だから例えば私は持っています...

  • デカルト平面上の1280x720
  • センターポイント(プレーヤーの位置):
    • x =最小-640から最大640までの数値とします。
    • y =最小-360から最大360までの数値とします。
  • プレーヤーの周りの円の半径:rを常に= 200とします
  • 角度:a = -360〜360の範囲の数値とします(負の数は下向き、正の数は上向きにするため、-10と350で同じ答えが得られます)

円にXを返す式は何ですか?

円にYを返す式は何ですか?

ここに画像の説明を入力してください ここに画像の説明を入力してください


16
これは良い質問です!!! +1
FrostyFire 2012

1
質問:ほとんどのゲームでは、左上に0,0の座標がありませんか?そしてy軸は上ではなく下になりますか?
persijn 2016年

回答:


74

リンクからの簡単な方程式は、円の中心を基準にした円上の点のX座標とY座標を示します。

X = r * cosine(angle)  
Y = r * sine(angle)

これは、ポイントが円の中心からどれだけオフセットされているかを示します。中心の座標(Cx、Cy)があるので、計算されたオフセットを追加するだけです。

円上の点の座標は次のとおりです。

X = Cx + (r * cosine(angle))  
Y = Cy + (r * sine(angle))

1
私の混乱は、最初にANGLEとDEGREEの違いでした。同じものだと思いました。次に、平面上の点(x、y)を取得していると思いましたが、実際にはxとyの辺の長さを取得していました。私はそれを紙に描き、それをエクセルで落とし、度の範囲をカバーして式をチェックしました。これで私のコードで機能します。
カイルアンダーソン

3
すべきではX = xcircle + (r * sine(angle))ありませんX = xcircle + (r * cosine(angle))(およびその逆Y)?
txtechhelp 2016年

4
角度はラジアン単位の値である必要があることに注意してください。
ローマ

17

使用しているコードを投稿する必要があります。それは問題を正確に特定するのに役立ちます。

ただし、角度を-360〜360で測定するとおっしゃっていたので、数学ライブラリに間違った単位を使用している可能性があります。三角関数のほとんどの実装では、入力にラジアンを使用します。そして、代わりに度を使用すると...あなたの答えは奇妙に間違っています。

x_oncircle = x_origin + 200 * cos (degrees * pi / 180)
y_oncircle = y_origin + 200 * sin (degrees * pi / 180)

また、象限が期待したものではない状況に遭遇する可能性があることに注意してください。これは、角度ゼロがどこにあるかを注意深く選択するか、予想する象限を手動でチェックして、結果値に独自の符号を適用することで修正できます。


1
これは実際には回答ではなくコメントである必要があります。ただし、ラジアン対度の良いキャッチ。
yoozer8 2012

ゾンビの投稿の質問:親では、(deg * (pi / 180))それはそれともその逆((deg * pi) / 180)ですか?また、ラジアンと度の差を指定していただきありがとうございます。
monsto 2017

@monstoゾンビは引き続き通知を送信します。:)。乗算と除算は可換なデモンストレーションであるため、内部の親は関係ありません。wolfram.com/… 。私は自分のコードに過剰な親を入れたことで長い間罪を犯しています。私はそれが明快さのためであるふりをします、しかし明らかにそれは厳密に真実ではありません、さもなければあなたはそれによって悩まされなかっただろう。
セスバティン2017

6

このタイプの操作には行列を使用することを強くお勧めします。これは最も一般的なアプローチです。以下の例を参照してください。

// The center point of rotation
var centerPoint = new Point(0, 0);
// Factory method creating the matrix                                        
var matrix = new RotateTransform(angleInDegrees, centerPoint.X, centerPoint.Y).Value;
// The point to rotate
var point = new Point(100, 0);
// Applying the transform that results in a rotated point                                      
Point rotated = Point.Multiply(point, matrix); 
  • ちなみに、慣例では、反時計回りの開始形状(正)のX軸の角度を測定します。

5

Angleを-360から360としてCos(angle)またはSin(angle)に渡すと、奇妙な結果が得られます。

あなたの試みがうまくいかなかった理由は、あなたが度単位で角度を通過していたからだと思います。sinそしてcos数字からでなければならないので、三角関数は、ラジアン単位の角度を期待0します2*M_PId度については合格しM_PI*d/180.0ます。ヘッダーでM_PI定義された定数math.hです。


角度と度はおそらく同じではないと思ったので、Angle = M_PI * d / 180.0と言って正しいですか?dは-360から360までの数値にすることができますか、それとも別の手順が必要ですか?
カイルアンダーソン

1
@Kyledは、0to360またはfrom -180to 180(完全な円)であり、from -360to 360(2つの完全な円)ではありません。
Sergey Kalinichenko 2012

4

また、コードで時計の針の動きを形成するためにもこれが必要でした。私はいくつかの数式を試しましたが、それらは機能しませんでした、それでこれは私が思いついたものです:

  • モーション-時計回り
  • ポイント-6度ごと(360度を60分で割ると6度になるため)
  • 手の長さ-65ピクセル
  • 中央-x = 75、y = 75

したがって、式は次のようになります。

x=Cx+(r*cos(d/(180/PI))
y=Cy+(r*sin(d/(180/PI))

ここで、xとyは円の円周上の点、CxとCyは中心のx、y座標、rは半径、dは度数です。


2

これがc#の実装です。このメソッドはradiuscenterangle intervalをパラメータとして取る円形の点を返します。角度はラジアンとして渡されます。

public static List<PointF> getCircularPoints(double radius, PointF center, double angleInterval)
        {
            List<PointF> points = new List<PointF>();

            for (double interval = angleInterval; interval < 2 * Math.PI; interval += angleInterval)
            {
                double X = center.X + (radius * Math.Cos(interval));
                double Y = center.Y + (radius * Math.Sin(interval));

                points.Add(new PointF((float)X, (float)Y));
            }

            return points;
        }

および呼び出し例:

List<PointF> LEPoints = getCircularPoints(10.0f, new PointF(100.0f, 100.0f), Math.PI / 6.0f);

丸め誤差のため、これにより予想よりも1つ少ないアイテムが返される可能性があることに注意してください。したがって、最終的に正しい量のアイテムを取得できるように、いくつかのマーリングを追加しました(私の例では、doubleではなくfloatがあります)。用(= angleInterval間隔フロート;間隔<2 *にMath.PI + 0.0000099f;インターバル+ = angleInterval)
sommmen

1

上記の貢献がArduinoLCDコンパスの作成にどのように役立ったかを共有したいと思います。これが正しいエチケットであることを願っています...私はstackoverflowに参加したばかりなので、すばらしい人々に感謝することができます。

上の幾何学の巨人の肩の上に立っている間、私はこのサンプルコンパスを作成することができました: 複数のベアリングを備えたArduinoTFTコンパス

私が繰り返し呼び出した関数のコード(小さな黄色のテキストに表示されるさまざまなベアリング用)は、Arduino(「C」のようなもの)で書かれています...そしてかなり翻訳可能です:

void PaintCompassNeedle( int pBearingInDegrees, int pRadius, TSPoint pCentrePt ) {
    // ******************************************************************************
    // * Formula for finding pointX on the circle based on degrees around the circle:
    // * x_oncircle = x_origin + radius * cos (degrees * pi / 180)  
    // * y_oncircle = y_origin - radius * sin (degrees * pi / 180) //minus explained
    // * Thanks to folks at stackoverflow...standing on the shoulders of giants. :) 

    float bearingInRads = (pBearingInDegrees) * PI / 180; 
    // Degrees vs Rads...The math folks use Rads in their formulas

    // *******************************************************************
    // * bearingPt is the point on the circle that we are trying to find
    TSPoint bearingPt;
    // Find the X on the circle starting with orgin (centre)
    bearingPt.x = pCentrePt.x + pRadius * sin(bearingInRads); 
    // Notice the "minus" R * cos()...because TFT the y is upside down bearingPt.y = 
    pCentrePt.y - pRadius * cos(bearingInRads); 
    // * Extra Explanation: The TFT is the graphical display I'm using and it
    // * calculates x & y from the top left of screen (portrait mode) as (0,0)
    // * ...so by Subtracting from the Y orgin...I flip it vertically
    // * Other folks using x,y as increasing to the right and up respectively
    // * would keep the plus sign after the pCentrePt.y
    // *************************************************************************

    // ***************************************************************
    // * This part will change for the final product...but leaving
    // * it because when call numerous times it shows it working for
    // * a number of different quadrants (displaying yellow degrees text)
    tft.fillCircle( bearingPt.x, bearingPt.y, 5, RED); 
    tft.setCursor( bearingPt.x, bearingPt.y );
    tft.setTextSize( 1 );
    tft.setTextColor( YELLOW );
    tft.print( pBearingInDegrees );

    TSPoint innerPt;
    innerPt.x = pCentrePt.x + pRadius/2 * sin(bearingInRads);
    innerPt.y = pCentrePt.y - pRadius/2 * cos(bearingInRads);
    tft.drawLine(innerPt.x, innerPt.y, bearingPt.x, bearingPt.y, RED);

}

0

答えは正反対でなければなりません。

X = Xc + rSin(angle)

Y = Yc + rCos(角度)

ここで、XcとYcは円の中心座標であり、rは半径です。


0

推奨:

 public static Vector3 RotatePointAroundPivot(Vector3 point, Vector3 
pivot, Vector3 angles)
    {
	    return Quaternion.Euler(angles) * (point - pivot) + pivot;
    }


-3

あなたはこれを使うことができます:

円の方程式ここで

(xk)2 +(yv)2 = R 2

ここで、kとvは定数で、Rは半径です。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.