web-dev-qa-db-ja.com

C ++コードでの角度ラップの処理

安全性を確保し、最小限のcaseステートメントでアングルラップを処理する方法はありますか。

角度の特定の表現(0〜360度または-180〜180度(またはラジアンで同等))を使用して、角度を折り返すと、角度ラップが発生します。たとえば、角度が-170で、50度を減算するとします。数学的に-220まで加算しますが、実際には+140度になります。

明らかにあなたはこれを使用してこれを確認できます:

_if (deg < -180) { 180 - abs(deg + 180); }
_

または類似。しかし、最初に多数のチェックが必要であり、2回目にラップすると機能しません。

これが一般的な2番目のケースは、2つの角度間の補間です。

たとえば、-170 degと160 degの角度があり、それらの中間にしたいとします。これを行う一般的な方法はang1 + 0.5(ang2-ang1)ですが、この例では175になるはずの角度を-5度にします。

これらのシナリオで角度の折り返しを処理する一般的な方法はありますか?

31

完全を期すために、[0, 360)[-180, 180)の両方の正規化を含めます。

#include <math.h>が必要です。


[0,360):に正規化

double constrainAngle(double x){
    x = fmod(x,360);
    if (x < 0)
        x += 360;
    return x;
}

[-180,180):に正規化

double constrainAngle(double x){
    x = fmod(x + 180,360);
    if (x < 0)
        x += 360;
    return x - 180;
}

パターンは、ラジアンに一般化できるほど認識しやすいものでなければなりません。


角度二等分:

double angleDiff(double a,double b){
    double dif = fmod(b - a + 180,360);
    if (dif < 0)
        dif += 360;
    return dif - 180;
}
double bisectAngle(double a,double b){
    return constrainAngle(a + angleDiff(a,b) * 0.5);
}

これは、「小さい」側の角度を二等分する必要があります。 (警告:完全にはテストされていません)

56
Mysticial

数学ライブラリの remainder() を使用すると便利です。角度aが与えられ、-180、180に制限するには、次のようにします。

remainder(a, 360.0);

360.0から2.0 * M_PIラジアン

13
dmuir

したがって、角度を制限するMysticalのアプローチを使用して、必要なことを効果的に行う方法を見つけた場合。ここにあります:

enter image description here

これは私が考えることができる任意の例で動作するようです。

5

角度を範囲に正規化する[-180, 180)

deg -= 360. * std::floor((deg + 180.) * (1. / 360.));

角度を範囲に正規化する[0, 360)

deg -= 360. * std::floor(deg * (1. / 360.));

例:

deg = -90-> [0, 360)

deg -= 360. * std::floor(-90 / 360.);
deg -= 360. * -1;
deg = 270

deg = 270-> [-180, 180)

deg -= 360. * std::floor((deg + 180.) / 360.);
deg -= 360. * std::floor(480. / 360.);
deg -= 360. * 1.;
deg = -90;

参照: http://en.cppreference.com/w/cpp/numeric/math/floor

4
Charles Beattie