三角関数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πを足してやれば良い。