web-dev-qa-db-ja.com

2つの角度の最小の違い

座標の周りの-PI-> PIの範囲に2つの角度がある場合、それらの間の2つの角度のうち最小の値は何ですか?

PIと-PIの差は2 PIではなくゼロであることを考慮してください。

例:

中心から2本の線が出ている円を想像してください。これらの線の間には2つの角度があり、内側の角度は小さい方の角度、外側の角度は別名より大きな角度。両方の角度を合計すると、完全な円が形成されます。各角度が特定の範囲内に収まる場合、ロールオーバーを考慮した小さい角度の値

121
Tom J Nowell

これにより、あらゆる角度に符号付き角度が与えられます。

a = targetA - sourceA
a = (a + 180) % 360 - 180

多くの言語でmodulo操作は、配当と同じ符号の値を返します(C、C++、C#、JavaScript、 ここに完全なリスト など)。これには、次のようなカスタムmod関数が必要です。

mod = (a, n) -> a - floor(a/n) * n

とか、ぐらい:

mod = (a, n) -> (a % n + n) % n

角度が[-180、180]以内であれば、これも機能します。

a = targetA - sourceA
a += (a>180) ? -360 : (a<-180) ? 360 : 0

より冗長な方法で:

a = targetA - sourceA
a -= 360 if a > 180
a += 360 if a < -180
168
bennedich

xはターゲット角度です。 yはソースまたは開始角度です。

atan2(sin(x-y), cos(x-y))

符号付きデルタ角度を返します。 APIによっては、atan2()関数のパラメーターの順序が異なることに注意してください。

134
Peter B

2つの角度がxとyの場合、それらの間の角度の1つはabs(x-y)です。他の角度は(2 * PI)-abs(x-y)です。したがって、2つの角度の最小値は次のとおりです。

min((2 * PI) - abs(x - y), abs(x - y))

これにより、角度の絶対値が得られ、入力が正規化されている(つまり、範囲[0, 2π))。

角度の符号(つまり、方向)を保持し、範囲外の角度[0, 2π)上記を一般化できます。 Python一般化バージョンのコード:

PI = math.pi
TAU = 2*PI
def smallestSignedAngleBetween(x, y):
    a = (x - y) % TAU
    b = (y - x) % TAU
    return -a if a < b else b

%演算子は、特に負の値が関係する場合、すべての言語で同じように動作するわけではないため、移植する場合は、符号の調整が必要になる場合があります。

34

私は署名済みの回答を提供するという課題に直面します。

def f(x,y):
  import math
  return min(y-x, y-x+2*math.pi, y-x-2*math.pi, key=abs)
8
David Jones

UnityEngineユーザーの場合、簡単な方法は Mathf.DeltaAngle を使用することです。

6
Josh

算術(アルゴリズムではなく)ソリューション:

angle = Pi - abs(abs(a1 - a2) - Pi);
5

C++の効率的なコードは次のとおりです。

inline double getAbsoluteDiff2Angles(const double x, const double y, const double c)
{
    // c can be PI or 180;
    return c - fabs(fmod(fabs(x - y), 2*c) - c);
}
1
Adriel Jr

三角関数を計算する必要はありません。 C言語の単純なコードは次のとおりです。

#include <math.h>
#define PIV2 M_PI+M_PI
#define C360 360.0000000000000000000
double difangrad(double x, double y)
{
double arg;

arg = fmod(y-x, PIV2);
if (arg < 0 )  arg  = arg + PIV2;
if (arg > M_PI) arg  = arg - PIV2;

return (-arg);
}
double difangdeg(double x, double y)
{
double arg;
arg = fmod(y-x, C360);
if (arg < 0 )  arg  = arg + C360;
if (arg > 180) arg  = arg - C360;
return (-arg);
}

let dif = a-b、ラジアン単位

dif = difangrad(a,b);

度でdif = a-bをみましょう

dif = difangdeg(a,b);

difangdeg(180.000000 , -180.000000) = 0.000000
difangdeg(-180.000000 , 180.000000) = -0.000000
difangdeg(359.000000 , 1.000000) = -2.000000
difangdeg(1.000000 , 359.000000) = 2.000000

罪も、コスも、日焼けも、幾何学だけではありません!!!!

1
Uli Gue