サイトトップ

Director Flash 書籍 業務内容 プロフィール

ActionScript 3.0 for 3D

□Math01 三角関数

三角関数は、x軸とy軸さらにはz軸が互いに垂直に交わる「直交座標」(Word Math01-001)で角度を扱うための関数です。円や楕円の運動、あるいは座標の回転を表すには、三角関数による演算が必要となります。


Word Math01-001■直交座標
直交座標」とは、互いに垂直に交わる数直線を軸として、各軸の対応する値によって示される座標をいいます。一般に2次元平面の水平軸をx、垂直軸をy、3次元空間における奥行きはzで表されます。

1637年に『方法序説』で平面上の座標という概念を確立したルネ・デカルトの名を取ってデカルト座標(Cartesian coordinate)とも呼ばれます。

[*筆者用参考] コトバンク「直交座標」、TOMAC「座標」。


Math01-01 角度を座標にする三角関数sinとcos
三角関数のsin(サイン)とcos(コサイン)は、ごく簡単にいうと、角度を座標にする関数です。cosを「余弦」、sinは「正弦」と呼ばれることがあります。これらの三角関数の意味を、順に説明していきましょう。


位置を距離と角度で表す − 極座標
2次元平面の座標は普通、x軸とy軸の直交座標(x, y)で表されます。けれど、位置の表し方は、ほかにもあります。たとえば、レーダーです。「北東1kmの地点」というように、位置を方向と距離で示します。方向とはつまり角度で、北東はx軸方向である東に対して、反時計回りに45度を意味します。このように距離と角度で示す座標を「極座標」(Word Math01-002)といいます。

図Math01-001■位置を方向と距離で示す
北東はx軸方向である東に対して、反時計回りに45度。

Word Math01-002■極座標
「極座標」とは、原点からの距離と、原点から延ばした半直線との角度によって示される座標をいいます。

2次元平面であれば、原点からの距離r、正のx軸と成す角θにより、座標(r, θ)で表されます。3次元空間の場合には、正のz軸と成す角φを加えて、座標は(r, θ, φ)となります(Maniac! Math01-001「経度・緯度と極座標」参照)。

[*筆者用参考] Wikipedia「極座標系」、「極座標」、コトバンク「極座標」、TOMAC「極座標」。


Maniac! Math01-001■経度・緯度と極座標
地球上の位置を表すとき、経度と緯度を用います。これは、3次元空間の極座標の捉え方を示しています。イギリスの旧王立グリニッジ天文台を通って北極と南極結ぶ半円を「グリニッジ子午線」と呼びます。経度はこのグリニッジ子午線から定めた東西の角度です。また、緯度は赤道から南北に角度を測ります。つまり、地球の中心を原点に距離は地表までとし、ふたつの角度で位置を決めていることになります。

ちなみに、日本の経緯度は、原点が東経139度44分28秒8759、北緯35度39分29秒1572と定められています(「日本経緯度原点」と呼ばれます)。住所は、東京都港区麻布台2-18-1です。

極座標で2次元平面上の点Pは、つぎのように定められます。原点O(0, 0)からの距離OPがr、正のx軸とOPの成す角はθとするとき、点Pの極座標は(r, θ)で表します(図Math01-002)。

図Math01-002■極座標は原点からの距離と正のx軸と成す角によって表される
距離OPをr、正のx軸と成す角はθとすると、点Pの極座標は(r, θ)。

距離と角度で座標が示せると、便利なことがあります。Flashのムービーでも、飛行機の操縦とか砲弾の発射などのアニメーションはつくりやすいでしょう。もっとも、その位置を(x, y)座標に直さないと、直交座標の平面に表せません。そのための関数が三角関数のsinとcosです。


三角関数のsinとcosの定義
三角関数はxy軸の直交座標で、原点O(0, 0)を中心とした半径1の円にもとづいて定義されます。なお、半径1の円を「単位円」といいます。単位円上の任意の点Pについて、原点Oと結ぶOPが正のx軸と成す角をθとすると、点Pの座標は(cosθ, sinθ)で表します(シンタックスMath01-001)。

図Math01-003■単位円上の点がx軸と成す角をθとすると座標は(cosθ, sinθ)で表す
単位円上の任意の点Pについて、OPが正のx軸と成す角をθとすると、点Pの座標は(cosθ, sinθ)。

つまり、極座標(1, θ)は、xy軸の直交座標(cosθ, sinθ)だということです。すると、任意の極座標(r, θ)は、半径を距離r分だけ伸ばすつまり掛け算すればよいのですから、直交座標(r cosθ, r sinθ)で表せます。三角関数sinおよびcosを使うことにより、極座標がただちに直交座標に直せるのです。

シンタックスMath01-001■三角関数sinとcos
三角関数sinとcosの定義
単位円上の任意の点Pについて、原点Oと結ぶOPが正のx軸と成す角をθとすると、点Pの座標は(cosθ, sinθ)で表す(前掲図Math01-003)。なお、角度は正のx軸から正のy軸に回る方向を正とする。
原点からの距離がrで正のx軸と成す角θのxy座標

原点からの距離がrで正のx軸と成す角θの点の極座標(r, θ)をxy軸の直交座標で表すと(r cosθ, r sinθ)となる。

極座標(r, θ) → 直交座標(r cosθ, r sinθ)

三角関数というと、直角三角形の3辺の比率で覚えている人も多いでしょう(図Math01-004)。これを「三角比」といいます。けれど、三角比はもはや忘れて構いません。理由はふたつあります。

図Math01-004■三角比によるsinとcosおよびtan

sinθ = 高さ/斜辺

cosθ = 底辺/斜辺

tanθ = 高さ/底辺

直角三角形の底辺と斜辺の成す角をθとする。

ひとつ目は、三角比はいわば三角関数の計算の仕方であって、使い途がわかりにくいからです。たとえば、円周率πは、円周の長さを直径で割った比率です。けれども、そんなことは忘れている人が少なくないでしょう。実際に割り算をしてみた人はほとんどいないと思いますし、今後そんな機会は皆無のはずです。でも、πを使って円の面積が求まることは覚えているのではありませんか。三角関数のsinとcosも、角度から座標を求めるために使うのが基本です。また、普通の人はsinとcosを用いるときに、その値を計算する必要などありません。


距離と角度をxy座標に直すのがsinとcos。計算はコンピュータがやってくれる。

三角比を使わない理由のふたつ目は、角度θが直角以上になると直角三角形自体が描けなくなるからです(Tips Math01-001「三角形の内角の和は180度」参照)。直角以上の場合に、三角比の定義を修正することもできないではありません。けれど、単位円による定義なら、角度θが直角さらには360度を超えても、sinとcosの値を問題なく求められます。

Tips Math01-001■三角形の内角の和は180度
三角形の内角(3頂点それぞれの角度)の和は、180度であることが知られています。直角三角形は、そのうちのひとつの角が90度です。したがって、他の2角を足すと、90度になります。つまり、直角三角形の直角以外のふたつの角は鋭角(90度未満)です。

三角形の内角の和が180度であることは、以下の図Math01-005で確かめることができます。補助線として底辺を一方に延ばし、その頂点から他方の辺と平行な直線を引いています。平行線と直線が交わったとき、「同位角」あるいは「錯角」がそれぞれ等しくなることを利用します。

図Math01-005■三角形の内角の和が180度であることを示す

底辺を一方に延ばし、さらにその頂点から他方の辺と平行な直線を引く。

sinとcosと角度の関係
角度は360度で1周します。ですから、単位円上の点P(cosθ, sinθ)の角θに360度を加えると、またもとの座標に戻ります。したがって、つぎの式が成り立つことは、すぐにおわかりになるでしょう。

sin(θ + 360°) = sinθ
cos(θ + 360°) = cosθ

つぎに、角θに180度を加えた点Q(cos(θ + 180), sin(θ + 180))の座標値を考えてみます(図Math01-006)。すると、点Qはもとの点Pの原点Oを挟んだ反対側の座標になります。すると、xy座標値も原点Oの反対側、つまりともに正負が逆の値になります。

sin(θ + 180°) = -sinθ
cos(θ + 180°) = -cosθ
図Math01-006■角θに180度を加えたときのsinとcosの値

xy座標が原点Oの反対側となり、ともに負の値に変わる。

もうひとつ、角θに90度を加えた場合、点Q(cos(θ + 90), sin(θ + 90))の座標値はどうなるでしょう。90度回すということは、正のx軸が正のy軸に、正のy軸が負のx軸に重なる回転です(図Math01-007)。したがって、x座標値が-sinθ、y座標値がcosθになります。

sin(θ + 90°) = cosθ
cos(θ + 90°) = -sinθ
図Math01-007■角θに90度を加えたときのsinとcosの値

全体を90度回すと、x座標値が-sinθ、y座標値がcosθになる。

三角関数を使った式では、異なる角度の三角関数に変形することがたびたびあります。sinとcosのおもな関係式をシンタックスMath01-002に掲げました。いずれも、これまでの説明と同じように、単位円の図を用いて簡単に導けます。興味のある方は、確かめてみてください。

シンタックスMath01-002■角度の異なるsinとcosのおもな関係式
sinとcosと角度の関係式
sin(-θ) = -sinθ cos(-θ) = cosθ
sin(90°±θ) = cosθ cos(90°±θ) = -+sinθ
sin(180°±θ) = -+sinθ cos(180°±θ) = -cosθ

[*編集者用注釈]「-+」は、「±」の上下逆の記号を使います。


Math01-02 ラジアン
三角関数を使った計算をするとき、角度の単位に度数ではなくラジアンを使うことが少なくありません。実際、ActionScriptで三角関数をメソッドとして備えるMathクラスでは、引数に渡す角度はラジアンが単位とされています。

ラジアンは、角度を単位円の弧の長さで示す単位です。原点O(0, 0)と単位円の円周上の点Pとを結んだOPがx軸と成す角をθとすると、単位円と正のx軸との交点A(1, 0)から点Pまでの円弧APの長さが、ラジアンを単位としたθの角度になります(図Math01-008)。

図Math01-008■ラジアンは角度を単位円の弧の長さで示す

360°= 2πラジアン
単位円の弧APの長さが、ラジアンを単位としたθの角度。

単位円の半径は1ですから、円周の長さは2π(= 1×2×π)になります。つまり、1周の角度は2πラジアンです。360度が2πラジアンに等しいので、1ラジアンは約57.30度(= 360/2π)という半端な値になってしまいます。そもそも、1周のラジアン角2πからして、小数で表せば約6.28という切りの悪い数値です。

このような半端な値であっても、数学の解析や物理で運動を扱う際には、ラジアンを単位とした方が便利です。たとえば、半径1mの円周上を、等速で回転している物体があったとします。測ってみたら、1秒間に1ラジアン回転しました。そのときの物体の速さは、一瞬で秒速1mと求まります。

半径1mの円周上の角度1ラジアン分の弧の長さは、半径と等しくなるからです。これがもし度数で約60度と示されたら、60度の弧の長さを計算しなければなりません。ラジアンを使えば、角度と長さとの換算が、単に半径を掛合わせるだけで済むのです。

とはいえ、ActioinScriptには角度を度数で扱うプロパティやメソッドも数多くあります。たとえば、Matrix3D.appendRotation()Matrix3D.prependRotation()メソッドは、回転角を度数で第1引数に指定しました(Tips Math01-002「角度を扱うプロパティやメソッドとその単位」参照)。インスタンスのアニメーションで三角関数を使う際には、度数とラジアンとの間の換算が必要になる場合も少なくありません。そこで、度数とラジアンの変換比率をシンタックスMath01-003に掲げました(Tips Math01-003「ラジアンと度数の変換比率を定数にもつ」参照)。360度が2πラジアンであることから、比率は簡単に求められます。

シンタックスMath01-003■度数とラジアンの換算式
度数とラジアンの換算式

同じ角度を度数とラジアンのふたとおりで表したとすると、度数/360 = ラジアン/2πになります。両辺に2を掛ければ、度数/180 = ラジアン/πです。よって、つぎの式が導かれます。

度数 = (ラジアン/π)×180 = ラジアン×(180/π)
ラジアン = (度数/180)×π = 度数×(π/180)

Tips Math01-002■角度を扱うプロパティやメソッドとその単位
本書で使った角度を扱うプロパティやメソッドについて、角度の単位を確かめると下表Math01-001のとおりです。Matrix.rotate()メソッドは引数にラジアン角を渡すのに対して、Matrix3D.appendRotation()Matrix3D.prependRotation()メソッドには回転角を度数で指定します。角度を扱うプロパティやメソッドでは、その単位に注意しましょう。

表Math01-001■角度を扱うプロパティやメソッドとその角度の単位(一部)
単位 プロパティ シンタックス
度数 DisplayObject.rotation -
度数 DisplayObject.rotationX/DisplayObject.rotationY/DisplayObject.rotationZ 04-001
単位 メソッド 角度の引数または戻り値 シンタックス
ラジアン Math.cos()/Math.sin()/Math.tan() 第1引数 01-003
ラジアン Matrix.rotate() 第1引数 03-001
度数 Matrix3D.appendRotation()/Matrix3D.prependRotation() 第1引数 04-007/ 04-005
ラジアン Matrix3D.decompose() 戻り値となるVectorインスタンスの回転のエレメント 04-011
ラジアン Matrix3D.recompose() 第1引数となるVectorインスタンスの回転のエレメント 04-011

Tips Math01-003■ラジアンと度数の変換比率を定数にもつ
ActionScriptでラジアンと度数の値の変換が必要な場合には、180/πまたはπ/180を定数(const)としてもっておくと便利です。

const RADIAN_TO_DEGREE:Number = 180 / Math.PI;   // ラジアン→度数
const DEGREE_TO_RADIAN:Number = 1 / RADIAN_TO_DEGREE;   // 度数→ラジアン
// テスト
var nRadian:Number = Math.PI / 4;   // π/4ラジアン = 45°
trace(nRadian);   // 出力: 0.7853981633974483
var nDegree:Number = nRadian * RADIAN_TO_DEGREE;
trace(nDegree);   // 出力: 45
trace(nDegree * DEGREE_TO_RADIAN);   // 出力: 0.7853981633974483

Math01-03 三角関数tanと逆三角関数tan-1
三角関数には、もうひとつtan(タンジェント)があります。tanは「正接」とも呼ばれます。また、角度から比率を求める三角関数に対して、その値から角度を導く逆三角関数も定義されています。


三角関数のtanの定義
tanをxy軸の直交座標で表すには、単位円は必ずしも要りません。原点O(0, 0)から正のx軸と成す角がθの直線を延ばします。そして、その直線がもうひとつの直線x = 1と交わる点をQとします。このとき、点Qの座標は(1, tanθ)となります(図Math01-009)。

図Math01-009■tanは正のx軸と成す角がθの直線と直線x = 1との交点のy座標
原点Oから延ばした正のx軸と角θを成す直線と、もうひとつの直線x = 1との交点Qが(1, tanθ)。

正のx軸と角θを成す直線が単位円と交わる点P(x, y)でtanθを示すこともできます。x = 1のときのy座標値ということは、すなわちx座標値に対するy座標値の比率を意味します。

tanθ = y/x

これは、前述の三角比によるtanの計算式です(前掲図Math01-004)。x座標値の変化に対するy座標値の増減は、直線の方程式ではその傾きを表します。

さらに、前述sinとcosの定義として述べたとおり、点Pのxy座標は(cosθ, sinθ)で表されます(シンタックスMath01-001)。したがって、tanθはつぎのように示すこともできます。

tanθ = sinθ/cosθ

この式から、三角関数のsinとcosおよびtanのうち、ふたつの値がわかれば残りのひとつの値も導けることになります。

シンタックスMath01-004■三角関数tan
三角関数tanの定義

単位円上の任意の点P(x, y)について、原点Oと結ぶOPが正のx軸と成す角をθとすると、tanθはつぎの式で表される(前掲図Math01-009参照)。なお、角度は正のx軸から正のy軸に回る方向を正とする。

tanθ = y/x = sinθ/cosθ

tanについても、sinやcosと同じく、異なる角度に対する関係式が挙げられます(シンタックスMath01-002参照)。シンタックスMath01-005に、改めてsinやcosも含め、角度の異なる三角関数の関係式をラジアン単位で掲げます。

シンタックスMath01-005■角度の異なる三角関数のおもな関係式
三角関数と角度の関係式
sin(-θ) = -sinθ cos(-θ) = cosθ tan(-θ) = -tanθ
sin(π/2±θ) = cosθ cos(π/2±θ) = -+sinθ tan(π/2±θ) = -+1/tanθ
sin(180°±θ) = -+sinθ cos(180°±θ) = -cosθ tan(π±θ) = ±tanθ

[*編集者用注釈]「-+」は、「±」の上下逆の記号を使います。

π/2(= 90度)に角度θを加えたtan(π/2+θ)についてだけ、簡単に説明します。sinやcosについて前に述べたとおり、これは正のx軸が正のy軸に、正のy軸が負のx軸に重なる回転です(前掲図Math01-007参照)。そのため、xとyの値が入れ替わり、符号が反転するのです。

あるいは、xy軸の直交座標で示すなら、下図Math01-010において、三角形OAQとQ'AOは相似であることがわかります(直角とθの角が等しいので)。したがって、つぎの等式が導けるのです。つまり、符号を別にすると、tanを表す式の分子分母が入れ替わり、yに対するxの比になるということです。

AQ/OA = AO/Q'A
Q'A = OA×AO/AQ = 1/AQ   (OA = AO = 1より)
Q'A = 1/tanθ
図Math01-010■角θをπ/2に加えてtanの値を比べる
三角形OAQとQ'AOは相似。tan(π/2+θ)は、yに対するxの比になる。

Tips Math01-004■直線の方程式とその傾き
直線は、xy軸の直交座標に、xのyに対する一次関数として表されます(図Math01-011)。直線を定めるのは、ふたつの値です。

ひとつ目は、xに対するyの比例係数です。この比例係数つまり「yの値の増減/xの値の増減」の比率は、直線の「傾き」(m)を定めます。ふたつ目に、直線が通る点をひとつ指定します。もっともわかりやすいのはy軸との交点(0, n)で、このy座標値(n)は「y切片」と呼ばれます。直線の傾き(m)とy切片(n)のふたつの値が定まると、直線の方程式はつぎのように表されます。

y = mx + n
図Math01-011■直線は傾きとy切片で定まる
傾き(m)は「yの値の増減/xの値の増減」の比率で、y切片(n)はy軸との交点のy座標値。

直線がx軸と成す角をθとすると、その傾きはtanθで示されます。したがって、同じ直線の式はつぎのように書替えられます。

y = (tanθ)x + n

三角関数tanの逆三角関数tan-1
三角関数は、角度から直交座標に関わる比率を示します。逆に、その比率から角度を求めたい場合もあるでしょう。一般にxからyを導く関数y = f(x)について、逆にyからxを求める関数が考えられるとき、その関数をf(x)の「逆関数」と呼び、x = f-1(y)と表します(Word Math01-003「関数と逆関数」参照)。

Word Math01-003■関数と逆関数
ふたつの変数xとyがあって、あるxの値に対して、ただひとつのyの値が対応するとき、yをxの「関数」といいます。これを一般的に、つぎのような式で表します。なお、xを独立変数、yを従属変数と呼びます。

y = f(x)

逆にyの値に対して、xの値がただひとつ決まるとき、xもyの関数として表すことができます。

x = g(y)

この関数g(y)を関数f(x)の「逆関数」といい、f-1(y)で表します。ただ一般的には、独立変数にx、従属変数にはyを使う習わしなので、f(x)の逆関数はつぎのように示されます。

y = f-1(x)

Maniac! Math01-002■逆関数を意味する-1は「インバース」
f-1(y)の-1は逆関数を意味する記号で、「インバース」(inverse)と読みます。逆数(nの逆数は、n-1 = 1/n)を示す-1乗(マイナス1乗)ではありません。

三角関数にも逆三角関数が定義されています。sin、cos、tanのそれぞれに対応して、sin-1(アークサイン)、cos-1(アークコサイン)、tan-1(アークタンジェント)と表します。それぞれsin、cos、tanの比率を指定すると、その値に対応した角度が得られます。

逆三角関数を使って角度が知りたいときは、これらのうちtan-1が便利です。角度を測る原点からの座標(x, y)がわかれば、tanθ = y/xはすぐに求まります。よって、角度θ = tan-1(y/x)になるからです。sinやcosでは、原点からの距離r = √x2+y2を計算しなければなりません。

ただし、逆三角関数には、重大な注意があります。tan-1でご説明しましょう。前掲シンタックスMath01-005のとおり、tan(π±θ) = ±tanθです。単位円上の角度θの点をP(x, y)とすると、θ+πの点はR(-x, -y)となり(θ-πも点Rになります)、tan(θ+π) = -y/-x = y/xです。つまり、tanθ = y/xに等しくなるからです(図Math01-012)。

図Math01-012■tanθはtan(θ+π)と等しい
単位円上の角度θの点をP(x, y)とすると、θ+πの点はR(-x, -y)となり、tanθ = tan(θ+π)。

するとたとえば、tan(π/3)である√3を指定してtan-1√3を求めようとしたとき、角度はπ/3(60度)だけでなく、4π/3(240度)ほか無数に考えられます。しかし、関数には値がただひとつに定まらなければならないという決まりがあります(Word Math01-003「関数と逆関数」参照)。

そこで、tan-1の値は-π/2(-90度)より大きくπ/2(90度)未満の値にかぎることとされました。いわば、単位円の座標のうち、x > 0となる右半分のみで考えるということです。そうすれば、与えられたtanの値(y/x)に対して、tan-1の角度(θ)がただひとつに決まります。

逆三角関数は、具体的な最低値と最高値は異なるものの、いずれもtan-1と同じ理由で値が単位円の半分、つまりπ(180度)の範囲にかぎられています(Tips Math01-005「Mathクラスの三角関数と逆三角関数」参照)。

Tips Math01-005■Mathクラスの三角関数と逆三角関数
Mathクラスの三角関数と逆三角関数のメソッドは、シンタックスMath01-005のとおりです。まず、sinとcos、tanが、それぞれMath.sin()Math.cos()Math.tan()メソッドとして定められています(Math.sin()Math.cos()については、前掲シンタックス01-003参照)。つぎに、逆三角関数はアークを意味する"a"がメソッド名の頭につき、Math.acos()およびMath.acos()Math.atan()の各メソッドになります。

シンタックスMath01-005■Mathクラスの三角関数と逆三角関数のメソッド
三角関数 逆三角関数
メソッド 引数 メソッド 引数
戻り値 戻り値
Math.cos() ラジアンの角度を示す数値。 Math.acos() -1以上1以下のcosを示す数値。
-1以上1以下のcosを示す数値。 0以上π以下のラジアンの角度を示す数値。
Math.sin() ラジアンの角度を示す数値。 Math.asin() -1以上1以下のsinを示す数値。
-1以上1以下のsinを示す数値。 -π/2以上π/2以下のラジアンの角度を示す数値。
Math.tan() ラジアンの角度を示す数値。 Math.atan() tan示す数値。
tanを示す数値。 -π/2より大きくπ/2未満のラジアンの角度を示す数値。

もっとも、実際に角度を知りたいときは、円の半分のπ(180度)では役に立たず、1周の2π(360度)が必要なはずです。tan-1を使ってプログラムで処理するなら、x座標が正か負かで場合分けすることになるでしょう。

そのメソッドは、すでにMathクラスに備わっています。それがMath.atan2()で(シンタックス01-003)、数学の逆三角関数ではなく、角度を調べるためにプログラミング用につくられたメソッドです。数学のtan-1と異なり、引数にxyふたつの座標を渡すことにより±πの範囲で角度が返されます。

したがって、角度はMath.atan2()メソッドで求めればよく、スクリプトで逆三角関数を使うことはほとんどないでしょう。三角関数の性質を知るために、知識として覚えておくだけで構いません。


Math01-04 円と楕円の方程式
三角関数のsinとcosは、角度θに対して単位円上の点(cosθ, sinθ)を定めます。このふたつの三角関数を使うと、円や楕円の方程式を導くことができます。


円の方程式
Math01-01「角度を座標にする三角関数sinとcos」でご説明したとおり、角度θに対する単位円上の点(x, y)を定めたのが、三角関数sinとcosです。つまり、x = cosθ、y = sinθは単位円の円周を表します。したがって、半径rの円の方程式は、シンタックスMath01-006のように定められます。

シンタックスMath01-006■三角関数sinとcosによる半径rの円の方程式
半径rの円の方程式

原点O(0, 0)を中心とする半径rの円周上の任意の点P(x, y)は、直線OPと正のx軸が成す角をθとすると、つぎの方程式で表される。

x = r cosθ
y = r sinθ

円の中心を点C(a, b)にするには、xy座標に中心Cの座標値をそれぞれ加えればよい。したがって、点Cを中心とする半径rの円の方程式は、つぎのようになる。

x = a + r cosθ
y = b + r sinθ

Maniac! Math01-003■媒介変数
xy軸の直交座標空間上の曲線は、多くの場合xとyの関数として示されます。原点O(0, 0)を中心とした半径rの円の方程式も、補助的な変数θを使わずに表せます。円周上の点(x, y)はすべて中心からの距離がrです。すると、三平方の定理から、つぎのような円の方程式が導かれます。

x2+y2 = r2

変数xyがともに2次になりますので、ひとつのxの値に対してyの値が最大ふたつ(円の上半分と下半分)得られます。また、この方程式で円周上を等速でアニメーションする座標を求めることは難しいでしょう。本文のように変数θを加えることで、式は1次になって、扱いやすくなります。このような変数を「媒介変数」と呼びます。

一般に、曲線上の点(x, y)を方程式で表すとき、新たな変数tを用いて、xとyそれぞれを以下のようにtの関数fとgとして示せる場合があります。このときのtが、媒介変数です。

x = f(t)
y = g(t)

[*筆者用参考] 教えて進路Q&A「媒介変数とはなんでしょうか?


楕円の方程式
円に対して垂直方向もしくは水平方向に、拡大したり縮小すれば楕円になります。具体的には、円の方程式のxy座標いずれかに、拡大・縮小比率としての係数を掛合わせます。それは、円の方程式で三角関数sinおよびcosに乗じていた半径の値を、xy座標それぞれについて異なった値にするということです。

原点O(0, 0)を中心として、x軸と±a、y軸とは±bで交わる楕円の方程式は、シンタックスMath01-007のとおりです。これは原点Oが中心で半径aの円の方程式をもとに、y座標に拡大・縮小比率b/aを掛合わせたことになります。

シンタックスMath01-007■三角関数sinとcosによる楕円の方程式
xy軸方向の半径がそれぞれaとbの楕円の方程式

原点O(0, 0)を中心としてx軸方向とy軸方向の半径がそれぞれa、bの楕円上の任意の点Q(x, y)は、角θに対してつぎの方程式で表される。

x = a cosθ
y = b sinθ

楕円の中心を点A(a, b)にするには、xy座標にそれぞれ中心Aの座標値を加えればよい。したがって、点Aを中心とする楕円の方程式は、つぎのようになる。

x = c + a cosθ
y = d + b sinθ

Maniac! Math01-004■楕円の方程式における角度θ
前掲シンタックスMath01-007の図に示した楕円の方程式における角度θは、中心となる原点Oと楕円上の点Qを結んだ直線OQではなく、変形する前の円の周上の点Pに対して延ばした直線OPとx軸とが成す角です。


楕円軌道のアニメーションをさせるフレームアクション
楕円軌道のアニメーションをフレームアクションにしてみましょう。後に掲げるスクリプトMath01-001を、アニメーションさせるMovieClipシンボルのフレームに記述します。おもな処理はつぎのとおり、DisplayObject.enterFrameイベント(定数Event.ENTER_FRAME)のリスナー関数xRotate()で、楕円軌道の座標家を計算してインスタンスに設定します。

  1. var nRadian:Number = 0;
  2. var nSpeed:Number = Math.PI / 30;
  3. var nCenterX:Number = stage.stageWidth / 2;
  4. var nCenterY:Number = stage.stageHeight / 2;
  5. var nRadiusX:Number = 100;
  6. var nRadiusY:Number = 50;
  1. addEventListener(Event.ENTER_FRAME, xRotate);
  2. xRotate(null);
  3. function xRotate(eventObject:Event):void {
  4.   var nCos:Number = Math.cos(nRadian);
  5.   var nSin:Number = Math.sin(nRadian);
  1.   x = nCenterX + nCos * nRadiusX;
  2.   y = nCenterY + nSin * nRadiusY;
  1.   scaleX = nSin;
  2.   nRadian += nSpeed;
  3.   nRadian %= Math.PI * 2;
  4. }

スクリプト第11〜12行目でラジアン角からcosおよびsin値を得て、第15〜16行目は前掲シンタックスMath01-007の楕円の方程式により求めたyx座標をインスタンスに設定します。そして、第19行目は変数(nRadian)のラジアン角を増やし、第20行目でその値の範囲を0から2πまでの範囲に収めています(Tips 04-001「回転角のプロパティで±180の範囲を超える値の扱い」参照)。

ふたつ補足します。ひとつ目は、スクリプト第18行目でDisplayObject.scaleXプロパティにsin値を設定していることです。sinは、軌道中心から見た最下部で最大値1、最上部で最小値-1、両端では0になります。すると、最下部で実寸、最上部では実寸の裏向き、そして両端に近づくほど幅が縮まります。そのため、平面のインスタンスが3次元空間でメリーゴーラウンドのように回って見えるアニメーションになります。

補足のふたつ目は、スクリプト第9行目で関数xRotate()を呼出していることです。DisplayObject.enterFrameイベントが初めて発生するまでには、少しだけ時間間隔(1/fps秒)が空きます。そこで、インスタンスが直ちに初期位置に置かれるように、関数を呼出しました。なお、引数がないとエラーになりますので、nullを渡しています。

以上の基本的な処理に透視投影の計算を加えたのが、つぎのスクリプトMath01-001です。インスタンスの位置と大きさに遠近法が適用されて、より3次元空間の表現力が増します。

スクリプトMath01-001■楕円軌道のアニメーションに遠近法を適用したフレームアクション
    // フレームアクション
    // MovieClip: 楕円軌道をアニメーションするインスタンス
  1. var nRadian:Number = 0;
  2. var nSpeed:Number = Math.PI / 30;
  3. var nCenterX:Number = stage.stageWidth / 2;
  4. var nCenterY:Number = stage.stageHeight / 2;
  5. var nRadiusX:Number = 100;
  6. var nRadiusY:Number = 50;
  7. var nFocalLength:Number = 2;
  8. addEventListener(Event.ENTER_FRAME, xRotate);
  9. xRotate(null);
  10. function xRotate(eventObject:Event):void {
  11.   var nCos:Number = Math.cos(nRadian);
  12.   var nSin:Number = Math.sin(nRadian);
  13.   var nZ:Number = (1 - nSin) / 2;
  14.   var nScale:Number = nFocalLength / (nFocalLength + nZ);
  15.   // x = nCenterX + nCos * nRadiusX;
      x = nCenterX + nCos * nRadiusX * nScale;
  16.   // y = nCenterY + nSin * nRadiusY;
      y = nCenterY + nSin * nRadiusY * nScale;
  17.   scaleX = scaleY = nScale;
  18.   // scaleX = nSin;
      scaleX *= nSin;
  19.   nRadian += nSpeed;
  20.   nRadian %= Math.PI * 2;
  21. }

透視投影の比率は、スクリプト第14行目で計算しています。比率はつぎの式により求められました(Tips 02-004「焦点距離と遠近法投影(透視投影)の比率」)。

焦点距離 / (焦点距離 + z位置)

仮想のz座標は第13行目でsin値つまり垂直位置をもとに、軌道最下部は0、最上部が1となるように調整しています(変数nZ)。z座標が0から1の範囲の値ですので、それに見合うようにスクリプト第7行目は、焦点距離(変数nFocalLength)を2としました。

求められた透視投影の比率は、スクリプト第15〜16行目で位置座標に乗じ、また第17行目で拡大・縮小率にも設定しています。なお、水平方向の伸縮も加えなければなりませんので、第18行目は代入演算子=でなく、乗算後代入演算子*=に替えています。

図Math01-013■遠近法が適用された楕円軌道のアニメーション
インスタンスの位置と大きさに遠近法が適用されて、3次元空間の回転を表現。

Math01-05 三角関数の性質
三角関数の性質から導かれる関係式や定理は少なくありません。その中でも、重要なものを採上げてご説明します。


三角関数の互いの関係と式
まずは、定理というより、三角関数の定義や基本的な性質から導かれる式を挙げましょう。第1に、すでにシンタックスMath01-004「三角関数tan」で解説したsinとcosおよびtanの関係式です。3つの三角関数のうちふたつの値から、残りのひとつの値を求めるのに用いられます。

tanθ = sinθ/cosθ

第2は、sinとcosの定義から導かれる式です(図Math01-003)。原点Oと単位円上の点Pを結ぶOPが斜辺となる直角三角形を考えると、斜辺の長さは1、底辺が|cosθ|で高さは|sinθ|になります。すると、三平方の定理から以下の等式が得られます。

|sinθ|2 + |cosθ|2 = 1
(sinθ)2 + (cosθ)2 = 1

三角関数は、2乗の指数をsinやcosの記号のすぐ後に書きます。したがって、等式はつぎのように表されます。

sin2θ + cos2θ = 1
図Math01-003■単位円上の点がx軸と成す角をθとすると座標は(cosθ, sinθ)で表す(再掲)
単位円上の任意の点Pについて、OPが正のx軸と成す角をθとすると、点Pの座標は(cosθ, sinθ)。

第1と第2の式から、第3の関係式が導けます。まず、第1の式の両辺を2乗します。

tan2θ = (sinθ/cosθ)2 = sin2θ/cos2θ

第2の式より、sin2θ = 1 - cos2θを代入します。

tan2θ = (1 - cos2θ)/cos2θ = 1/cos2θ - 1
tan2θ + 1 = 1/cos2θ

以上3つの等式を、つぎのシンタックスMath01-008にまとめます。

シンタックスMath01-008■三角関数の互いの関係式
sinとcosおよびtanの関係式
  1. tanθ = sinθ/cosθ
  2. sin2θ + cos2θ = 1
  3. tan2θ + 1 = 1/cos2θ

もうひとつ、三角形の面積を2辺とその成す角で表したのが、つぎのシンタックスMath01-009です。底辺の長さをa、底辺と角θを成すもうひとつの辺の長さがbだとすると、高さはb sinθになります。したがって、三角形の面積は、ab sinθ/2で求められるのです。

シンタックスMath01-009■三角形の面積
sinとcosおよびtanの関係式

三角形の2辺の長さがaおよびbで、角θを成すとき、その面積はつぎの式により求められる。

ab sinθ/2

[*筆者用参考]「三角関数の性質」、「三角形の面積」、「三角関数(三角比)の相互関係」。


三角関数の余弦定理
三角関数の余弦定理は、三角形の3辺の長さとひとつの角度との関係を表す式です。その等式は、つぎのシンタックスMath01-010のとおりです。

シンタックスMath01-010■三角関数の余弦定理
余弦定理

三角形の3辺の長さをそれぞれa、b、cとし、aとbとの成す角をθとすると、つぎの等式が成立つ(図Math01-014参照)。

c2 = a2 + b2 - 2ab cosθ

図Math01-014■2辺が鈍角を成す三角形
三角形BCDについて三平方の定理を考える。そのとき、BC = c、BD = b sinθ、CD = a - b cosθ。

三角形ABCの辺AC、AB、BCの長さがそれぞれa、b、cで、角BACをθとするとき、θが鈍角の場合について余弦定理を証明します(図Math01-014)。頂点Bから下ろした垂線と辺ACがDで交わるとすると、三角形BCDについて三平方の定理からつぎの式が導かれます。

BC2 = BD2 + CD2 = BD2 + (AC - CD)2

ここで、BD = b sinθ、AD = b cosθですので、以下の等式が成り立ちます。

c2 = (b sinθ)2 + (a - b cosθ)2
= b2 sin2θ + a2 -2ab cosθ + b2 cos2θ
= a2 b2(sin2θ + cos2θ) - 2ab cosθ

シンタックスMath01-008よりsin2θ + cos2θ = 1ですので、これで余弦定理が導かれます。

c2 = a2 + b2 - 2ab cosθ

角θが鈍角の場合の証明は省きます。考え方は、鋭角のときと基本的に変わりません。θが直角のときcosθは0ですので、余弦定理の式はc2 = a2 + b2となり、三平方の定理になります。つまり、三平方の定理は、余弦定理で角θが直角という特別な場合の等式なのです。

なお、余弦定理は次章Math02「ベクトル」で、内積を解説するときに使います。

[*筆者用参考]「余弦定理」、「余弦定理」。


三角関数の加法定理
三角関数の加法定理は、角度αとβとの加減算を、αβそれぞれの角度の三角関数の計算式で表します。その等式は、シンタックスMath01-011のとおりです。

シンタックスMath01-011■三角関数の加法定理
加法定理
sin(α±β) = sinαcosβ±cosαsinβ
cos(α±β) = cosαcosβ-+sinαsinβ

[*編集者用注釈]「-+」は、「±」の上下逆の記号を使います。

加法定理の証明は、つぎのとおりです。まず、単位円上にふたつの点A(cos(-α), sin(-α))と点B(cosβ, sinβ)をとります(図Math01-015左図)。線分ABの長さの2乗は、三平方の定理により求められます。

|AB|2 = (cos(-α) - cosβ)2 + (sin(-α) - sinβ)2
= cos2(-α) - 2cos(-α)cosβ + cos2β + sin2(-α) - 2sin(-α)sinβ + sin2β
= (sin2(-α) + cos2(-α)) + (sin2β + cos2β) - 2(cos(-α)cosβ + sin(-α)sinβ)
= 2 - 2(cos(-α)cosβ + sin(-α)sinβ)   (シンタックスMath01-008より)
= 2 - 2(cosαcosβ - sinαsinβ)   (シンタックスMath01-005より)

つぎに、点Aと点Bを原点Oでα回転させた点は、それぞれ点A'(1, 0)と点B'(cos(α+β), sin(α+β))となります(図Math01-015右図)。すると、線分A'B'の長さの2乗は、同じように導けます。

|A'B'|2 = (1 - cos(α+β))2 + (0 - sin(α+β))2
= 1 - 2cos(α+β) + cos2(α+β) + sin2(α+β)
= 2 - 2cos(α+β)   (シンタックスMath01-008より)

点Aと点Bをそれぞれ同じ角度α回転させたのが点A'と点B'ですので、線分ABと線分A'B'の長さは等しくなります。したがって、上記ふたつの式から、つぎの等式が成り立ちます。

|AB|2 = |A'B'|2
2 - 2(cosαcosβ - sinαsinβ) = 2 - 2cos(α+β)
cos(α+β) = cosαcosβ - sinαsinβ
図Math01-015■角-αの点Aと角βの点Bをそれぞれα回転する
点A(cos(-α), sin(-α))と点B(cosβ, sinβ)を結ぶ線分ABの長さの2乗と、それぞれをα回転した点A'(1, 0)と点B'(cos(α+β), sin(α+β))との線分A'B'の長さの2乗とを計算する。

これで、シンタックスMath01-011のcos(α+β)についての加法定理が導けました。この等式とシンタックスMath01-005を用いて、つぎのふたつの場合が求められます。

cos(α-β) = cos(α+(-β))
= cosαcos(-β) - sinαsin(-β)
= cosαcosβ + sinαsinβ
sin(α-β) = cos(π/2-(α-β))
= cos((π/2-α)+β)
= cos(π/2-α)cosβ - sin(π/2-α)sin(β)
= sinαcosβ - cosαsinβ

さらに後者の式から、4つ目の等式が導けます。

sin(α+β) = sin(α-(-β))
= sinαcos(-β) - cosαsin(-β)
= sinαcosβ + cosαsinβ

[*筆者用参考]「加法定理」、「加法定理」、Wikipedia「三角関数」「加法定理」。

加法定理を使う例として、任意の点P(x, y)を原点Oで角度θ回転した座標Q(x', y')の計算が挙げられます。OPの長さをr、正のx軸と成す角をαとすると、点Pの座標(x, y)はつぎのとおりです(シンタックスMath01-001)。

x = r cosα
y = r sinα

すると、この点Pを原点で角度θ回転した点Qの座標(x', y')は、つぎのように表せます。

x' = r cos(α+θ)
y' = r sin(α+θ)

この座標x'とy'の式の右辺に、それぞれ加法定理を当てはめます。

r cos(α+θ) = r(cosαcosθ-sinαsinθ)
= (r cosα)cosθ - (r sinα)sinθ
r sin(α+θ) = r(sinαcosθ + cosαsinθ)
= (r sinα)cosθ + (r cosα)sinθ

前記の座標xとyの式より、r cosα = x、r sinθ = yです。これらを代入すると、点Qの座標(x', y')が導けます(シンタックスMath01-012)。

x' = x cosθ - y sinθ
y' = y cosθ + x sinθ = x sinθ + y cosθ
シンタックスMath01-012■任意の点を原点でθ回転する
座標(x, y)を原点でθ回転した座標の計算

任意の点(x, y)を原点Oでθ回転した点の座標(x', y')は、つぎの式で表される。

x' = x cosθ - y sinθ
y' = x sinθ + y cosθ

シンタックスMath01-012の座標(x', y')の式は、前記のつぎのような座標の表し方と比べて、あまりお得な感じがないかもしれません。

x' = r cos(α+θ)
y' = r sin(α+θ)

原点からの距離rやもとの角度αがわからなかったとしても、座標(x, y)から三平方の定理やMath.atan2()メソッドで求めれば済むことです。計算の手間として、さほど差があるように見えません。

しかし、数多くの座標を同じ角度回すときには、シンタックスMath01-012の計算の方がずっと有利になります。そのサンプルのフレームアクションを、スクリプトMath01-002として後に掲げます。その中で、シンタックスMath01-012の計算式に関わる処理は、つぎのとおりです。

  1. var nRadian:Number = Math.PI / 30;
  2. var nSin:Number = Math.sin(nRadian);
  3. var nCos:Number = Math.cos(nRadian);
  1. var children:Vector.<Shape> = new Vector.<Shape>();
  1. addEventListener(Event.ENTER_FRAME, xRotate);
  1. function xRotate(eventObject:Event):void {
  2.   var i:uint = 0;
  1.     var child:Shape = children[i];
  2.     var nX:Number = child.x;
  3.     var nY:Number = child.y;
  4.     child.x = nX * nCos - nY * nSin;
  5.     child.y = nX * nSin + nY * nCos;
  1. }

スクリプト第36〜39行目は、シンタックスMath01-012の計算により、Shapeインスタンスの座標を定めています。このスクリプトでは、数多くのShapeインスタンスを第10行目で生成したVectorオブジェクト(変数children)に格納し、DisplayObject.enterFrameイベントのリスナー関数xRotate()でそれらのインスタンスの座標を回転します(第30〜42行目)。

そのとき、インスタンスを回転する角度は、スクリプト第4行目でひとつの値(π/30)に決めました。そのため、第38〜39行目で用いているsinおよびcosの値も、第5〜6行目で変数(nSinおよびnCos)に入れた値をそのままずっと使い続けています。その結果、毎回Mathクラスのメソッドを呼出して角度や三角関数を求めることなく、単純な四則演算しか行っていませんので、処理の負荷は軽くなります(Tips Math01-006「変換行列による回転」参照)。

[イラスト] いつもより多めに同じ角度回すときはお得。

Tips Math01-006■変換行列による回転
変換行列による回転は、内部的にシンタックスMath01-012の計算式を使っています。[ヘルプ]の[ActionScript 3.0言語およびコンポーネントリファレンス]で[Matrixクラス]のMatrix.rotate()メソッドの項を見ると、以下の行列が掲げられています(なお、Tips 03-003「[ヘルプ]のMatrixクラスの説明における変換行列の誤り」参照)。

この行列に(x, y)座標を適用(乗算)すると、回転後の座標(x', y')はつぎのとおりです。

x' = x cos(q) - y sin(q)
y' = x sin(q) + y cos(q)

3次元空間の回転も、基本的に3つの軸を中心として、同じように座標を変換することになります。2次元平面の回転は、このうちz軸のみの変換に当たります。

スクリプトMath01-002の全体は、以下のとおりです。第16〜29行目の関数xCreateChildren()を呼出すとき渡した引数(変数nAmount)の数だけランダムな色と位置のShapeインスタンスがつくられ、第9行目で生成したSpriteインスタンス(変数mySprite)の子に加えられます。また、前述のとおりVectorオブジェクト(変数children)のエレメントにも納められます。

リスナー関数xRotate()は、Vectorオブジェクトから10未満のランダムな間隔でエレメントのShapeインスタンスを取出し(スクリプト第8、33および35行目)、前述のとおりシンタックスMath01-012の計算による回転を加えています(ただし、Maniac! Math01-005「回転の計算の処理効率」参照)。したがって、ランダムなShapeインスタンスが、決まった角度ずつ回り続けます(図Math01-016)。

スクリプトMath01-002■数多くのインスタンスをランダムに描いて回すフレームアクション
    // フレームアクション
  1. var nStageWidth:int = stage.stageWidth;
  2. var nStageHeight:int = stage.stageHeight;
  3. var nRadius:Number = (nStageWidth + nStageHeight) / 4;
  4. var nRadian:Number = Math.PI / 30;
  5. var nSin:Number = Math.sin(nRadian);
  6. var nCos:Number = Math.cos(nRadian);
  7. var nAmount:uint = 1000;
  8. var nCount:uint = 10;
  9. var mySprite:Sprite = new Sprite();
  10. var children:Vector.<Shape> = new Vector.<Shape>();
  11. addChild(mySprite);
  12. mySprite.x = nStageWidth / 2;
  13. mySprite.y = nStageHeight / 2;
  14. xCreateChildren(nAmount);
  15. addEventListener(Event.ENTER_FRAME, xRotate);
  16. function xCreateChildren(n:uint) {
  17.   for (var i:uint = 0; i < n; i++) {
  18.     var myRadius:Number = Math.random() * nRadius;
  19.     var myRadian:Number = Math.random() * Math.PI * 2;
  20.     var child:Shape = new Shape();
  21.     var myGraphics:Graphics = child.graphics;
  22.     children.push(child);
  23.     mySprite.addChild(child);
  24.     child.x = myRadius * Math.cos(myRadian);
  25.     child.y = myRadius * Math.sin(myRadian);
  26.     myGraphics.beginFill(Math.floor(Math.random() * 0xFFFFFF));
  27.     myGraphics.drawCircle(0, 0, 2);
  28.   }
  29. }
  30. function xRotate(eventObject:Event):void {
  31.   var i:uint = 0;
  32.   var nLength:uint = children.length;
  33.   i += Math.floor(Math.random() * nCount);
  34.   while (i < nLength) {
  35.     var child:Shape = children[i];
  36.     var nX:Number = child.x;
  37.     var nY:Number = child.y;
  38.     child.x = nX * nCos - nY * nSin;
  39.     child.y = nX * nSin + nY * nCos;
  40.     i += Math.floor(Math.random() * nCount);
  41.   }
  42. }

図Math01-016■色と位置をランダムに配置したインスタンスが部分的に回転し続ける
毎フレームランダムに取出したインスタンスを、シンタックスMath01-012の計算式で決まった角度回している。

Maniac! Math01-005■回転の計算の処理効率
本文に述べたとおり、数多くの座標を同じ角度回転するときは、シンタックスMath01-012の計算が効率は高いといえます。ただ、スクリプトMath01-002のリスナー関数xRotate()では、インスタンスのランダムな取出しにかかる負荷が高いので、処理速度に差は見られないでしょう。

[Prev/Next]


作成者: 野中文雄
作成日: 2010年2月11日


Copyright © 2001-2010 Fumio Nonaka.  All rights reserved.