ゲーム数学 第4回

講師:大森田不可止



三角関数の基礎





spaceshift + space での操作が快適です。

今日の授業

  • 今日は、 三角関数 を勉強します。
  • ゲームでは良く使われるので、具体的な使い方も勉強します。
  • JavaScript で、確認しながら進めます。
  • 前回の「ピタゴラスの定理」との関連もあります。

累乗と階乗

  • 「べき乗」「累乗」(英: exponentiation 発音) : 冪あるいは冪乗(べきじょう)、累乗(るいじょう) とは、ある一つの数同士を繰り返し掛け合わせるという操作のこと、あるいはそれによって得られる数のことである。
    「冪」 の文字はもともと 「覆う、覆うもの」 という意味の漢字である。常用漢字・当用漢字に含まれなかったことから1950年代以降、出版物などでは仮名書きの「べき乗」、または「累乗」への書き換えが進められた。結果として初等数学の教科書ではもっぱら「累乗」が用いられる。

  • 階乗(かいじょう、英: factorial) : 数学において非負整数 \(n\) の階乗 「\(n !\)」 は、\(1\) から \(n\) までのすべての整数の積である。例えば、\( 6! = 6 \times 5 \times 4 \times 3 \times 2 \times 1 = 720 \) である。空積の規約のもと \(0! = 1\) と定義する。

角度の単位: 度とラジアン

  • 一回転を360度で表すのは、度数法 と呼ばれます。単位は「度 (degree, \(^\circ\))」。
  • 1年の日数に由来すると言われるが、360 という数字は、\(2^3 3^2 5\) なので、約数が多く、使い勝手の良い数字です。

  • 数学では、弧度法 を使います。単位はラジアン (radian, \(rad\))で表す。
  • 単位円(半径1の円) で、その中心角で切り取られる弧の長さである。

※ 360 の約数: 24個
1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 15, 18, 20, 24, 30, 36, 40, 45, 60, 72, 90, 120, 180, 360

度とラジアンの変換

  • \(180^\circ = \pi \ rad \) であることから、以下の式で変換できる。
    \[ degree \times \color[rgb]{0,0,1} \frac{\pi}{180} \color[rgb]{0,0,0} = radian \qquad \color[rgb]{0,0,1} \frac{\pi}{180} \color[rgb]{0,0,0} = 0.01745329 \ldots \]
    \[ radian \times \color[rgb]{0.6,0,0} \frac{180}{\pi} \color[rgb]{0,0,0} = degree \qquad \color[rgb]{0.6,0,0} \frac{180}{\pi} \color[rgb]{0,0,0} = 57.2957795 \ldots \]
  • JavaScript:
  • 
    function deg2rad( deg ){
      return deg * Math.PI / 180;
    }
    function rad2deg( rad ){
      return rad * 180 / Math.PI;
    }
                    

度とラジアン

degreeradian
30°\(\pi/6\)
45°\(\pi/4\)
60°\(\pi/3\)
90°\(\pi/2\)
180°\(\pi\)
270°\(\frac{3}{2} \pi\)
360°\(2\pi\)
540°\(3\pi\)
720°\(4\pi\)

\[ \begin{align} 15 deg &= 15 \times \color[rgb]{0,0,1} \frac{ \pi }{180} \color[rgb]{0,0,0} \\ &= \frac{ \pi }{12} rad \end{align} \]
\[ \begin{align} \frac{2 \pi}{5} rad &= \frac{2 \not \pi }{5} \times \color[rgb]{0.6,0,0} \frac{180}{\not \pi} \color[rgb]{0,0,0} \\ &= \frac{2×180}{5} \\ &= 72 deg \end{align} \]

計算機

  • 電卓アプリ: Windows10 の電卓アプリは結構使えます。 + R または、エクスプローラのアドレスバーに、 calc と入力して起動。メニューから関数電卓を選択。
  • SpeedCrunch: USBメモリから起動。キーボードから数式を入れられるので楽。
  • エクセル: excel で起動。複数の計算が可能。結果を保存できる。
  • JavaScript / IPython: プログラム言語なら、複雑な計算も 解決可能。
calc SpeedCrunch Excel IPython

例題

Windows 付属の電卓、関数電卓、Excel などのスプレッドシート、スマホの電卓アプリなど、自分の好みのツールを使って、具体的に計算してみます。

以下の角度をラジアンに変換

  • 75度
  • 120度

以下のラジアンを角度に変換

  • \( \frac{2}{5} \pi \)
  • \( \frac{1}{3} \pi \)

直角三角形と三角関数

左図の直角三角形で、

\( \sin \alpha = \frac{b}{c} \) : 斜辺に対する高さの割合

\( \cos \alpha = \frac{a}{c} \) : 斜辺に対する底辺の割合

\( \tan \alpha = \frac{b}{a} = \frac{\sin \alpha}{\cos \alpha}\) : 見上げた高さ

斜辺\(c\) の長さを1とした場合の、底辺\(a\) の長さが \(\cos \alpha\)、高さ\(b\) の長さが \(\sin \alpha\) となります。

また、底辺\(a\) を1とした場合の、高さ\(b\) の長さが \(\tan \alpha\) となります。

直角三角形と三角関数(2)

  • \( \sin \alpha = \frac{b}{c} \)
  • \( \cos \alpha = \frac{a}{c} \)
  • \( \tan \alpha = \frac{b}{a} = \frac{b/c}{a/c} = \frac{\sin \alpha}{\cos \alpha}\)

定義とピタゴラスの定理から、 \[ \begin{align} sin^2 \alpha + \cos^2 \alpha & = \frac{b^2}{c^2} + \frac{a^2}{c^2} = \frac{a^2 + b^2}{c^2} \\ & = \frac{c^2}{c^2} = 1 \end{align} \]

\(a=4,b=3,c=5\) の直角三角形では \[ \sin \alpha = \frac{3}{5} = 0.6 \] \[ \cos \alpha = \frac{4}{5} = 0.8 \] \[ \tan \alpha = \frac{3}{4} = 0.75 \]

代表的な直角三角形

  • 直角二等辺三角形の各辺の長さから、
    \( \sin 45^\circ = \cos 45^\circ = \frac{1}{\sqrt{2}} = \frac{\sqrt{2}}{2}\)
    \( \tan 45^\circ = 1 \)

  • 正三角形の半分の直角三角形から、
    \( \cos 60^\circ = \sin 30^\circ = \frac{1}{2} \)
    \( \sin 60^\circ = \cos 30^\circ = \frac{\sqrt{3}}{2} \)
    \( \tan 60^\circ = \sqrt{3}, \tan 30^\circ = \frac{1}{\sqrt{3}} = \frac{\sqrt{3}}{3} \)

単位円と三角関数(三角関数の拡張)

  • 単位円で、角\(\alpha\)だけ動いた点の
    • Y座標が \(\sin\)
    • X座標が \(\cos\)
    • 動径が \(x=1\) と交わるY座標が \(\tan\)
  • 単位円と三角関数
    • \(\sin\), \(\cos\) は周期関数。則ち、
      \(\sin ( \alpha + 2\pi n) = \sin \alpha\)
      \(\cos ( \alpha + 2\pi n) = \cos \alpha\)
    • これで、\( \alpha\) は、どんな値でも取れるように拡張された。
    • \(-\infty < \alpha < \infty, \quad -1 \le sin,cos \le 1\)

拡張された意味

  • 三角関数は、直角三角形の辺の長さの比(割合)から発想されたが、単位円の場合に拡張したことによって、直角三角形に囚われる必要は無くなった。角度の値も自由になった。
  • 三角関数は半径1の単位円の場合の値であるが、半径を \(r\) とすれば、\(r\) を掛けることでことで、どんな半径の円にでも適用できる。
  • 半径10mの円の、60度の \(\cos\) は、 \[ 10(m) \cos 60^\circ = 10(m) \cdot 0.5 = 5(m) \]

三角関数の性質

  • 周期関数なので、\( \sin( \alpha \pm 2\pi) = \sin \alpha, \quad \cos( \alpha ± 2\pi) = \cos \alpha \) : 左右に \(2\pi\) 動かしても同じ形
  • \( \cos \alpha = \sin(\alpha + \frac{\pi}{2}) \)
  • \( \cos(-\alpha) = \cos \alpha\): 偶関数(x軸で線対称)、 \(\sin(-\alpha) = -\sin \alpha \): 奇関数(原点で点対称)

\(\tan\) のグラフ

\(\tan\) の注意

  • \(\tan\) は、見上げた角度から、高さを求める場合に便利な関数。例えば、スカイツリーから300m離れた地点から、見上げた角度 \(\alpha\) を測定すれば、\(150 \tan \alpha \) を計算して高さを求めることができる。
  • ただし、真上と真下、つまり \(n\) を整数とすれば、\( 90 \pm 180 n (deg) = \frac{\pi}{2} \pm n \pi (rad)\) では、計算不能になる。
  • 特にプログラムで使う場合は、慎重になる必要がある。不用意に使うと、極まれに計算不能で正常に動かなくなるという、厄介なバグの原因になる。

三角関数の代表的値

degreeradiansincostan
0010
30°\(\frac{\pi}{6}\)0.5\( \frac{\sqrt{3}}{2}\) = 0.866\( \frac{1}{\sqrt{3}}\) = 0.577
45°\(\frac{\pi}{4}\)\( \frac{1}{\sqrt{2}}\) = 0.7071\( \frac{1}{\sqrt{2}}\) = 0.70711
60°\(\frac{\pi}{3}\)\( \frac{\sqrt{3}}{2}\) = 0.8660.5\( \sqrt{3}\) = 1.732
90°\(\frac{\pi}{2}\)10Undefined
180°\(\pi\)0-10
270°\(\frac{3}{2} \pi\)-10Undefined
360°\(2\pi\)010

三角関数の算出

前回やったように、以下の式で三角関数が計算できる。この時の角度の単位は radian である。数学で radian を単位として採用する理由である。

  • sin (ただし、\(-\frac{\pi}{4} < x < \frac{\pi}{4} \) 辺りで収束が早い) \[\sin x = x - \frac{x^3}{3!} + \frac{x^5}{5!} - \frac{x^7}{7!} + \cdots \]
  • cos (ただし、\(-\frac{\pi}{4} < x < \frac{\pi}{4} \) 辺りで収束が早い) \[\cos x = 1 - \frac{x^2}{2!} + \frac{x^4}{4!} - \frac{x^6}{6!} + \cdots \]

三角関数の計算

\(\sin 30^\circ = \sin \frac{\pi}{6} = \sin 0.523598775598 \ldots = 0.5 \) を級数で計算する。

\[\sin 30^\circ = x - \frac{x^3}{3!} = 0.4996741 \ldots\] \[\sin 30^\circ = x - \frac{x^3}{3!} + \frac{x^5}{5!} = 0.500002132 \ldots\] \[\sin 30^\circ = x - \frac{x^3}{3!} + \frac{x^5}{5!} - \frac{x^7}{7!} = 0.499999991869 \ldots\] \[\sin 30^\circ = x - \frac{x^3}{3!} + \frac{x^5}{5!} - \frac{x^7}{7!} - \frac{x^9}{9!} = 0.50000000002027 \ldots\]

収束は比較的早い。 JsBin

グラフの描画

関数グラフ描画スクリプト・SVGGraph.js

<svg width="640" height="200" style="background-color: #fff;"
script="
  setRange(-4.8, 4.8,-1.2,1.2);
  axis('full',0.5,0.5,2,2);
  style.stroke = 'red';
  plot('sin(x)');
  style.stroke = 'blue';
  plot('cos(x)');"/>
Function Plot - 2d function plotter powered by d3

     functionPlot({
       target: '#sinplot',
       width: 640, height:200,
       xAxis: { label: 'X' },
       yAxis: { label: 'Y' },
       grid: true,
       data: [{ fn: 'cos(x)' },
              { fn: 'sin(x)' }]
     })

JavaScript で計算

degree:
HTML

              <div style="border: 1px solid #888; width: 10em; padding: 0.3em;">
                degree: <input id="inputDegree" type="number" value="60" style="font-size: 1em; width: 4em;"/>
              </div>
              <div id="outputDegree"></div>
JavaScript

(function(){
  function calcTri(deg){
    var rad = deg * Math.PI / 180;
    var html = "

rad:" + rad.toFixed(8) + "

"; html += "

sin: " + Math.sin(rad).toFixed(8) + "

"; html += "

cos: " + Math.cos(rad).toFixed(8) + "

"; html += "

tan: " + Math.tan(rad).toFixed(8) + "

"; document.getElementById("outputDegree").innerHTML = html; } document.getElementById("inputDegree").addEventListener('input', function(e){ calcTri(e.currentTarget.value); }, true); calcTri(60); })();

calctri.html JsBin

プログラムの説明

  • 数値入力欄は、input タグの type=number 浮動小数点数を入力する。id="inputDegree" を付与してある。input 要素|MDN
  • id から、このエレメントに、addEventListener で、inputイベントが発生した時に、以下が実行される。
    
      document.getElementById("inputDegree").addEventListener('input', function(e){
        calcTri(e.currentTarget.value);
      }, true);
    
    input要素から取得した数値で、calcTri を呼び出して、入力欄下の情報を更新している。
  • 関数 calcTri(deg) は、角度を degree で受け取り、radian に変換し、Math で、sin、cos、tan を計算して、結果を id="outputDegree" の、innerHTML に入力して、入力欄下の情報表示。
  • 
      function calcTri(deg){
        var rad = deg * Math.PI / 180;
        var html = "

    rad:" + rad.toFixed(8) + "

    "; html += "

    sin: " + Math.sin(rad).toFixed(8) + "

    "; html += "

    cos: " + Math.cos(rad).toFixed(8) + "

    "; html += "

    tan: " + Math.tan(rad).toFixed(8) + "

    "; document.getElementById("outputDegree").innerHTML = html; }

三角関数で回転運動

jCanvas

HTML


<html lang="jp">
  <head>
    <meta charset="UTF-8"/>
    <title>Rotate Polygons</title>
    <script src="http://techc.omorita.com/js/jquery.min.js"></script>
    <script src="http://techc.omorita.com/jslib/jcanvas-master/dist/min/jcanvas.min.js"></script>
  </head>
  <body>
    <canvas width="800" height="800">
  </body>
</html>
JavaScript

(function(){
  var deg = 0;
  function interval(){
    requestAnimationFrame(interval);

    $("canvas")
        .clearCanvas()
        .drawPolygon({
          fillStyle: '#589',  // 図形の色
          strokeStyle: '#000',
          x: 400, y: 400,     // 中心
          radius: 250,        // 半径
          sides: 5,    // ここの値を変えると形が変わる
          rotate: deg
        });

    deg -= 3;
  }
  interval();
})();

逆三角関数

  • 三角関数それぞれに、逆関数が存在し、それぞれ \(\arcsin,\ \arccos,\ \arctan\) と呼ぶ。英語では、逆三角関数は inverse trigonometric function なので注意。arcは円の「弧」のこと、つまり角度を求めるという意味。
  • \(\arcsin,\ \arccos\) は-1~1の値に対して、角度(radian)を返す。
  • 数学では、sin-1 cos-1 tan-1 という表記も用いられる。

\(\arctan\)

  • \(\arctan\) は、全ての値に、角度(radian)を返す。\(\arctan\)が使われる場面が多い。
  • 例えば、富士山から25Km離れた駿河湾から、富士山頂(3776m)を見上げるとその角度は、\(\arctan(\frac{3776}{25000}) = 0.15 rad = 8.6^\circ \) になる。
  • 逆三角関数は、Math.asin() Math.acos() Math.atan() を使う。atan はよく使うため Math.atan2(a, b) も用意されている。上の例で言えば、Math.atan2(3776, 25000) = で富士山頂の仰角が得られる。

\(\arctan\)使用例

  • ゲームでは、目標物に向かって動く場合によく使われる。
  • 対象物に対する角度 \(\alpha\) が分かれば、\(V_x = V \cos \alpha, V_y = V \sin \alpha \) とすれば、その方向に向かって進む。\(V\) は、1フレームに動く距離。

if ( Math.abs(myShip.x - enemy.x) < 0.0001 ){
  bullet[i].vx = 0;
  bullet[i].vy = v;
} else {
  var alpha = Math.atan2(enemy.x - myShip.x, enemy.y - myShip.y);
  bullet[i].vx = v * Math.sin(alpha);
  bullet[i].vy = v * Math.cos(alpha);
}

\(\arctan\) を使わない方法

  • myShip と enemy の距離が、直角三角形の斜辺であることから、これが極小値になることは無い。従って、斜辺と \(b\) の値から、\(\arcsin\) を使って角度を得る方が安全である。
  • 具体的には、
    a: (myShip.y - enemy.y)
    b: (enemy.x - myShip.x)
    c: Math.sqrt(a*a+b*b)
    なので、
  • 
    var a = myShip.y - enemy.y;
    var b = myShip.x - enemy.x;
    var c = Math.sqrt(a*a + b*b);
    var alpha = Math.asin(b/c);
    bullet[i].vx = v * Math.sin(alpha);
    bullet[i].vy = v * Math.cos(alpha);
    

正弦定理

\[ \color[rgb]{0,0,0.6} \frac{a}{sin \alpha} = \frac{b}{sin \beta} = \frac{c}{sin \gamma} = 2R \]

  • \(\triangle ABC\) の外接円を描く。
  • \(B\) から中心を通る直線を描き、円周との交点を\(D\)とする。
  • \(\triangle DBC\) は\(\angle C\)が直角の直角三角形。
  • 円周角により、\(\angle A = \angle D\)。
  • 従って、\(\sin\)の定義により、\(2R \sin \alpha = a\)

三角形の角と対辺が分かれば外接円の直径が求まる。他の角が分かれば対辺が求まる。

例題

3:4:5 の直角三角形の2鋭角の角度を求めよ。

  1. 直角三角形なので、直角の対辺、斜辺の5が、外接円の直径。
  2. 従って、正弦定理から、
    \[\frac{3}{sin \alpha} = \frac{4}{sin \beta} = \frac{5}{sin \frac{\pi}{2}} = 5 \]
  3. ゆえに、
    \( \sin \alpha = \frac{3}{5} \ \Rightarrow\ \alpha = sin^{-1} \frac{3}{5} = 0.6435 rad = 36.87^\circ \)
    \( \sin \beta = \frac{4}{5} \ \Rightarrow\ \beta = sin^{-1} \frac{4}{5} = 0.9273 rad = 53.13^\circ\)

余弦定理

「ピタゴラスの定理」を一般の三角形に拡張したものと言えます。\(\cos (\pi / 2) = 0\) なので、直角の対辺に適用すると、ピタゴラスの定理になります。

\(\color[rgb]{0,0,0.6}a^2 = b^2 + c^2 − 2bc \cos\alpha \)

\(\color[rgb]{0,0,0.6}b^2 = c^2 + a^2 − 2ca \cos\beta \)

\(\color[rgb]{0,0,0.6}c^2 = a^2 + b^2 − 2ab \cos\gamma \)

\[ \begin{align} c^2 &= ( a - b \cos \gamma )^2 + (b \sin \gamma)^2 \\ &= a^2 - 2ab \cos \gamma + b^2 ( \cos^2 \gamma + \sin^2 \gamma ) \\ &= a^2 + b^2 - 2ab \cos \gamma \end{align} \]

三角形の2辺と間の角が分かれば、残りの辺も求まる。

例題

5の長さの辺と、7の長さのの辺が、\( 5 * \pi / 18 \) の角度で交わってる三角形の、残りの辺の長さを求めなさい。

  1. \(\alpha = 5*\pi/18\)、\( b = 5 \)、\( c = 7 \) と置く。
  2. 余弦定理から
    \[ \begin{align} a^2 & = b^2 + c^2 − 2bc \cos\alpha = 5^2 + 7^2 - 2*5*7*\cos(5*\pi/18) \\ & = 74 - 70 * 0.6428 = 29 \\ a & = \sqrt{29} = 5.385 \end{align} \]

加法定理

\(\color[rgb]{0,0,0.6} \sin(\alpha \pm \beta) = \sin\alpha \cos\beta \pm \cos\alpha \sin\beta \)

\(\color[rgb]{0,0,0.6} \cos(\alpha \pm \beta) = \cos\alpha \cos\beta \mp \sin\alpha \sin\beta \)

  • 余弦定理から、
    \(PQ^2 = 2 - 2 \cos(\alpha - \beta) \)
  • 座標から、
    \[ \begin{align} PQ^2 &= (\cos \beta - \cos \alpha )^2 + (\sin \beta - \sin \alpha )^2 \\ &= \cos^2 \beta - 2\cos\alpha\cos\beta + \cos^2 \beta + \sin^2 \beta- 2\sin\alpha \sin\beta + \sin^2 \beta \\ &= 2 - 2(\cos\alpha\cos\beta + \sin\alpha\sin\beta) \end{align} \]
  • \(\cos(\alpha - \beta) = \cos\alpha\cos\beta + \sin\alpha\sin\beta\)

例題

  • 一辺 \(a\) の正三角形に外接する円の半径を求めよ。
  • 加法定理を用いて \(\sin 15^\circ\) \(\cos 15^\circ\) を求めよ。
  • 加法定理を用いて \(\sin 75^\circ\) \(\cos 75^\circ\) を求めよ。

Mathオブジェクト

Math

  • 数学で良く使われる計算を提供するグローバルオブジェクト。
  • オブジェクトを new しないで利用する。C++ 等のstatic クラスに相当する。
  • 精度は C++ のdouble 相当。
  • IEEE 754 (64bit浮動小数点フォーマット)
  • Math.random() の乱数の生成は、現在のところ一番信頼されてるメルセンヌ・ツイスターで実装されている。(使って安心)

練習問題

  • \(\sin 156^\circ\) \(\cos 156^\circ\) を求めなさい。
  • \( \tan 30^\circ\) を求めなさい。
  • 加法定理を使って \(\sin 2\alpha \) を求めなさい。
  • \(\cos 2\alpha\) を求めなさい。