直線(ベクトル)の角度を求める

プログラミングで図形を扱っていると、ある直線とある直線が交わっている時にその角度を求めたい、という事があります。しかし、プログラムの中では分度器で計るというわけにはいきません。

そんな時にはどうしたら良いのか、まず原点を一端とする直線(つまりx,y座標を成分とするベクトル)とX軸との角度を計算で求める数学的なアルゴリズムを考えてみましょう。

コサインから2直線(ベクトル)の角度を求める

直線(ベクトル)がなす角度を求めるには、中学校や高校の数学でやったように三角比を計算しその値に対応する角度を求めるのが楽でしょう。今回はコサインを計算して角度を求めてみました。

原点とある点を結んだ直線とx 軸とのなす角度を求めるわけですから、原点と点を結ぶ線を斜辺とする直角2等辺三角形の三角比を求める事になりますね。

この直角2等辺三角形のx 軸と斜辺のなす角のコサインを求めるのは簡単で、底辺(x 軸。長さは直線のx 成分)の長さを斜辺の長さで割るだけです。ベクトル(x,y) なら斜辺の長さ(ベクトルの大きさ)がx2+y2の平方根で、底辺はxです。つまり、コサインの値はx/Math.sqrt(x*x+y*y) としてやれば計算できます。
こうしてコサインが求まれば、後はコサインの逆関数アークコサインで角度(ラジアン) に変換するだけですね。幸いJava のMath クラスにはdouble acos(double)というアークコサイン関数そのものがあるのでそれを使う事にします。

ただし、コサインは0からπまでは減少し続け、π(180°)で最小(ー1)になった後また増加していくので、角度がπより大きい(今回の場合はy<0)場合は、2π(360°)から角度を引いた値のコサインを求めています。

このアルゴリズムで、ベクトルの成分(x、y)を引数とし、そのベクトルとx軸(x≧0)との角度を度数(0ー360度)で返す関数はJava で書くと以下のような感じになります

public int kakudo(double x,double y) { /*ベクトルの角度を計算*/

  double s;
  int deg;

  s=Math.acos(x/Math.sqrt(x*x+y*y)); /*角度θを求める*/

  s=(s/pie)*180.0; /* ラジアンを度に変換 */

  if (y<0) /* θ>πの時 */
      s=360-s;

  deg=(int)Math.floor(s);

  if ((s-deg)>=0.5) /*小数点を四捨五入*/
      deg++;

  return deg; /*角度θを返す*/

}

ベクトルの角度を求めるプログラム

今回のプログラムは、Javaアプレットです。グラフの上でマウスカーソルを動かすと、その点と原点を結んだ直線が描かれ、その直線とx軸との角度(ラジアンではなくおなじみの度数)の計算結果、直線の成分が表示されます。

プログラムソース表示