ゲームで使用されるatanとatan2は何ですか?


48

私は理解するのに苦労Math.tan()Math.atan()ていMath.atan2()ます。

私は三角法の基本的な知識を持っていますが、ゲーム開発のためのSIN、COS、TANなどの使用法は私にとって非常に新しいものです。

私はいくつかのチュートリアルを読んでいますが、接線を使用すると、マウスなどの別のオブジェクトとどれだけ向き合うかによって、あるオブジェクトを回転させる必要がある角度を取得できることがわかります。では、なぜatanまたはatan2を使用する必要があるのでしょうか?


atanは、角度を決定するために使用されます。その使用について実際に質問がありますか、それとも一般的な数学のヘルプを探していますか?
BlueRaja-ダニーPflughoeft

5
これらの関数の背後にある数学/ジオメトリを確実に理解する必要があります。それらを習得すると、毎日使う基本的な文法のように、「世界理解」の一部になります。「数学/幾何学を話す」ことができたら、それらの関数は、最も自然な結果を達成するための簡単なツールであることがわかります。
FxIII

これらのチュートリアルは間違っているか、誤解されています。atan2()を使用して、あるオブジェクトから別のオブジェクトへの角度を取得します。以下にその仕組みを説明します。
11

人々に答えてくれてありがとう、今はクラスでもっと注意を払っていないことを後悔している
sutoL

回答:


94

正接式は次のとおりです。

tan(angle) = opposite/adjacent

この図面を参照してください。

角度シータとその反対側および隣接する辺にマークが付いた直角三角形の図

a隣接する辺はどこo、反対側thetaは角である。同様に、サインとコサインはsin(ang)= o / hおよびcos(ang)= a / hです。ここhで、長辺は次のとおりです。http//www.mathwords.com/s/sohcahtoa.htm

一方atan(ショートアークタンジェントとしても知られ、逆正接)の逆であるtanようなので、:

atan(opposite/adjacent) = angle

したがって、反対側と隣接側の両方の値がわかっている場合(たとえば、マウスの座標からオブジェクトの座標を減算することによって)、角度の値を取得できますatan

ただし、ゲーム開発では、隣接する辺が0に等しいことがかなり頻繁に発生します(たとえば、ベクトルのx座標が0)。tan(angle) = opposite/adjacent致命的なゼロ除算エラーの可能性は明らかであることを忘れないでください。だからライブラリの多くは、呼び出された関数を提供atan2しますが、両方指定することができます、xそしてyあなたのためのゼロ除算を避けるために、右象限に角度を与えるために、パラメータを。

atan2ダイアグラム

(ガレスの礼儀、彼の答えも投票してください)


ゲーム開発での三角法の使用は、特にベクトルではかなり一般的ですが、通常、ライブラリは三角法の作業を隠します。sin / cos / tanは、三角形から値を見つけるための幾何学的操作を伴う多くのタスクに使用できます。必要なのは、長方形の三角形の他の値を見つけるための3つの値(辺の長さ/角度の値)だけなので、非常に便利です。

ゲームの特別な動作には、サイン関数とコサイン関数の「サイクリング」の性質を使用することもできます。たとえば、cos / sinがオブジェクトを他のオブジェクトの向きを変えるのによく使用するのを見てきました。


8
ウィキペディアでは、ゼロによる除算を回避するだけでなく、Atan2(atanではない)の他の使用法について説明していることに注意してください。たとえば、使用されている四分円に合わせて自動的に修正します。通常は、すべてを自分で行う必要があります。
-doppelgreener

確かに、非常に重要な注意がそこにあります。私の答えを更新します。
ジェシーエモンド

あなたの最初の長い段落で日焼けとアタンを後方に取得しませんでしたか?atanを使用して角度を取得し(つまり、方程式を逆にし)、tanを使用して辺の比率を取得します(つまり、方程式の正確な内容)。
11

o / aが例えば3に等しいことがわかっている場合、atan(3)を行う角度が必要な場合、それは私が意味することです。角度を分離したい場合は、比率にatanを使用します。比率を分離する場合は、角度にtanを使用します。
ジェシーエモンド

あなたが反対を言っていたように聞こえるので、私はその時あなたの言い回しを変えます。
11

64

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


1
この図を含めるためにトップアンサーを編集するのは失礼でしょうか?この図は素晴らしいものであり、Jesseがatan2()について説明した直後にうまく収まります。
11

1
さあ、私のゲストになろう!完了したら、この回答を削除します。
ガレスリース

7
いやいや がんばり続ける!それは信用されており、人々は図のためにまだここに賛成するべきです。
ジェシーエモンド

12

atri()とatan2()を含むtrig関数についての少し異なる考え方があります( "反対/隣接"の説明は何らかの理由で混乱させられます)。

x、y、r、シータ

1つのポイントから別のポイントに移動するには、xユニットを水平方向に移動し、yユニットを垂直方向に移動する(長方形またはデカルト座標と呼ばれる)か、距離rをangleの角度で移動します(2Dの極座標と呼ばれます)。

極座標(r、Ɵ)があり、それを(x、y)に変換するとします。

cos(Ɵ)は、x軸に沿ったrの割合を示します。

  • r = 1の場合、x = cos(Ɵ)。
  • r = 100の場合、x = 100 * cos(Ɵ)。
  • 一般的に、x = r * cos(Ɵ)。

同様に、sin(Ɵ)はy軸に沿ったrの割合を示します。

  • r = 1の場合、y = sin(Ɵ)。
  • r = 100の場合、y = 100 * sin(Ɵ)。
  • 一般に、y = r * sin(Ɵ)。

直交座標(x、y)を極座標(r、Ɵ)に変換するのはどうですか?

rxyによって形成される直角三角形の斜辺です。したがって、

  • r = sqrt(x x + y y)

tan(Ɵ)は、長さrの線の勾配(ランに対する上昇)を与えます。そう:

  • tan(Ɵ)= y / x
  • Ɵ= atan(y / x)

ただし、y / xを実行する場合、3/4を計算すると-3 / -4を計算するのと同じ答えが得られます。同様に、-3 / 4は3 / -4と同じ答えを返します。したがって、個々の符号を正しく処理し、ゼロ除算/無限大エラーを防ぐatan2(y、x)があります。

  • Ɵ= atan2(y、x)

4

ジェシーとシドは基本的に正しいですが、あなたは本当にあなたが問題を洞察した後だと思います。

atan()は、象限に対応していないため、必要な水平からの角度を通知しないため、Atan2()が必要です。

これは、ベクトル(-2,2)と(2、-2)にatanを使用すると同じ値が得られることを意味します。次に、引数の符号をオンにして、結果にpiを追加します。さらに、Jesseが言及したことを考慮するために、ゼロ除算の特殊なケースがあります。また、xが0に近い場合、atan2()はatanよりも適切に動作します。

したがって、-piとpiの間のベクトルの角度が必要な場合は、

x = -2
y = 2
angle = Math.Atan2(y, x)

または

x = -2
y = 2
angle = calculateAngle(y, x);

double CalculateAngle(double y, double x)
{
    double angle = 0;
    if (x == 0)
    {
        if (y == 0)
            angle = 0;
        else if (y > 0)
            angle = Math.PI/2;
        else
            angle = -Math.PI/2;
    }
    else
    {
        angle = Math.Atan(y/x);
        if (x < 0)
        {
            if (y > 0)
            {
                angle += Math.PI;
            }
            else if (y < 0)
            {
                angle -= Math.PI;
            }
            else
            {
                angle = Math.PI;
            }
        }
    }
    return angle;
}

1
「これは、ベクトル(-2,2)と(2,2)にatanを使用すると同じ値が得られることを意味します。」これが当てはまる場合、アタンの1つは-π/ 4で、もう1つはπ/ 4であるため、アタンは信じられないほど壊れています。このごみを投票したすべての人に恥を知れ。

コードはまだ間違っています。他のブランチでy==0分割してテストしますx
サムホセバー

0

簡潔にいくつかのことを明確にします。詳細な説明については、オンラインの三角法チュートリアルを参照してください。

aを角度にします。次に、tan(a)= tan(a + 2 * pi)。

atanはtan逆関数です。つまり、tanが与えられると角度が与えられます。atan(tan(a + 2 * pi))を呼び出すと、答えはaになります。これはアプリケーションには不十分です。

atan2は、この正確な状況を支援するために2つの引数を取ります。atanはxとyを取ります。これらは基本的にcos(a)とsin(a)です。

atan2(sin(a)、cos(a))= a atan2(sin(a + 2 * pi)、cos(a + 2 * pi))= a + 2 * pi / * sinとcosは異なる符号を持ち、先頭に別の答えへ* /

これがこのようになっている理由を説明するチュートリアルを見つけてください。

コードは次のようになります。

if (mouseMoved)
{
  double angle = atan2(mousey - objecty, mousex - objectx);

  object. setTransform to Rotate(angle);

  // If you want to print it
  print radian_to_degrees(angle); // Because angle is in radian 360 degrees = 2*Pi radians
}

tan(a) = - tan(-a)、あなたが表現したい方程式はおそらくtan(a) = tan(pi+a)
-Ali1S232

0

atan2私のコードで見つけた1つの用途は、「符号付き角度」です。

通常、2つのベクトル間の角度を見つける方法は

inline float angleWith( const Vector2f& o ) const
{
    return acosf( this->normalizedCopy().dot(o.normalizedCopy()) ) ;
}

しかし、これはどちらが「リード」するか(つまり、時計回りに他よりも「先に進む」)かどうかはわかりません。この情報は、ジェスチャの追跡に重要な場合があります。

(1,0)両方のベクトルのx軸から角度を見つけることはできましたが、あいまいさというこの厄介な問題があります。315度の角度のベクトルは、cos上記の方法を使用して45度を返し、45度の角度も返します。あなたはそれyを修正するためにサインチェックを行うことができますatan2

// Returns + if this leads o.
// more expensive than unsigned angle.
inline float signedAngleWith( const Vector2f& o ) const
{
  float aThis = atan2f( y, x );
  float aO = atan2f( o.y, o.x ) ;
  return aThis - aO ;
}

0

atanが壊れていないことに注意してください。arctanまたはtan逆関数は、-PI / 2とPI / 2の間の関数のみです。このパターンを繰り返しますが、複数の回答を処理しないため、コンピューターにとって問題となる機能ではありません。

これは、-PI / 2とPI / 2の間のasinと0とPIの間のacosで同じです。これらは、機能が発生する最も単純な範囲です。アタンとアシンの場合、それは最もネガティブなものから最もポジティブなものになります。エイコスにとっては、最もポジティブなものからネガティブなものへと変わります。(これは、より正確な回答を補間するのに役立ちます)

asin、acos、atanは数学関数です。

ただし、atan2は完全な革命(ラジアンまたは360度または400グラジアン単位のPI)を提供するため、プログラミングにははるかに役立ちます。彼らは罪や余韻のためではなく、日焼けのためだけのものを作り出したことに注意してください。Tanは水平および垂直(x、y)を使用する唯一のものです

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