三角関数逆変換

Tweet


 三角関数y=sin(x)やy=cos(x)などの値は、xが与えられた時、yを計算する事ができる。逆に、yが与えられた時、xを求めたい時にはどうしたらいいだろうか。その値は、x=asin(y)やx=acos(y)によって求まる。ただし、xが0°~360°の範囲では、xに2つの解の候補が出てきてしまう。この曖昧性を除去するには、sinの値とcosの値の両方を使えば良い。

 普通のC言語(ANSIに準拠したもの)のasin関数が返す値の範囲は、-π/2~π/2、acos関数が返す値の範囲は、0~πである。

 今、入力値として、ys=sin(x)、yc=cos(x)とする。xは求めたい出力値である。ysとycは定数として取得可能であるとする。例えば、方向ベクトルが分かれば、ysとycは三角関数の定義より、求める事ができる。

 続いて、xs=asin(ys)、xc=acos(yc)とする。ここで計算された、asinの値xsとacosの値xcの値をそれぞれ2つの範囲に分割して考える。すなわち、asinを-π/2~0の範囲と0~π/2の範囲に、acosを0~π/2の範囲とπ/2~πの範囲に場合分けをする。これらを組み合わせると、4つの場合に分けられる。下の表が、それを表している。

asin\acos 0~π/2 π/2~π
-π/2~0 asin+2π
-acos+2π
-asin+π/2
-acos+2π
0~π/2 asin
acos
-asin+π/2
acos

 この表は、一番上の行が、acosの値xcであり、一番左の列が、asinの値xsである。右下の2×2の部分は、xの値に等しい値を示す。例えば、xcが0~π/2の間の値として計算され、xsが-π/2~0の間の値として計算された場合は、x=xs+2πもしくはx=-xc+2πとしてxを計算できる。なお、xの範囲は、0~2π[rad]として出力するものとする。これを基にプログラムを作った一例が以下である。

const double PI2 = 6.28318530717958647692528676655901;

// sinとcosの値から角度を求める
double SinCosToAngle(double sinval, double cosval)
{
    double asinval = asin(sinval);
    double acosval = acos(cosval);
    if(asinval > 0.0) return acosval;
    else return PI2 - acosval;
}

 上のプログラムを見てもらえば分かるが、本来、変数を用いなくても関数を定義する事が可能である。そうすると、C言語で#define文でも定義する事が可能となる。

 以上が、sinの値とcosの値から角度を求める方法である。


もっといい方法

 もっといい方法を最近になってようやく発見した。それはatan2関数である。

double atan2(double y, double x);

という定義になっている。yの値(=上で言うsinval)とxの値(=上で言うcosval)を引数として与えれば、-π~πの値を返してくれる。

 ちなみに、-π~πではなく、0~2πにしたければ、返った値が負のときに2πを足してやれば良い。


もどる