三角比と三角関数
要点
<三角関数が定義されるおおまかな流れ>
三角比の定義 → ラジアンと単位円、三角比を用いた三角関数の定義 → 三角関数に関わる各公式の導出 → 加法定理
☆三角比の定義
三角比は以下の様に定義される。相似する図形の直角三角形の三角比は"比"なので同一となる事に注意
rは斜辺(hypotenuse)となる。直角三角形において直角と相対する位置にある最も長い辺を指す
xは隣辺(adjacent)となる。直角三角形において内角θに隣接する2つの辺の内、斜辺でない方を指す
yは対辺(opposite)となる。直角三角形において内角θと向かい合った辺を指す
sin(サイン:正弦:せいげん)
cos(コサイン:余弦:よげん)
tan(タンジェント:正接:せいせつ)
(個人的メモ):斜めが母(分母)と憶える。正規化の基準になる
各辺の長さに注目すると斜辺rとラジアン角θが基準となって長さが導き出される式へと変形される
tanθは傾きとして扱うと良い
☆同じ辺でも内角θの位置を変える事で別のラジアン角と同一の斜辺を基準に長さを計算する事が出来る。これは重要なテクニックで証明等でも利用される
(慣れるとθの位置を反対にしてsinとcosを切換えるような計算感覚になる)
コード例:
float x = 1 * Mathf.Cos (45 * Mathf.Deg2Rad);
(θに対する三角比という名前の陽関数(unityで言えばfloatの返り値を持った関数(引数と返り値が1:1)))
☆ラジアン(RadianAngles:弧度法)
三角関数では角の大きさを測る引数に弧の長さの実数であるラジアンを利用する
日本人が日常で角度を測る際、分度器などで使う°はオイラー角(EulerAngles)と呼ばれる単位値であり実数ではない(メートルやキログラム等の単位値と同類)
1回転 = 360° = 2 * Mathf.PI
通常、角はギリシャ文字θ(シータ)を用いて表される
aを°によるオイラー角度とするとラジアンを求める式は以下になる
基本的にLの長さによる単位の無い実数となり y=cos(x)等の実数の関数式に対して比の値として扱える事になる(だから三角関数に対してラジアンが利用される)
unityでMathf.sin関数に喰わせる引数もラジアンでありオイラー角ではないので注意。また相互変換には上記の式を利用すると良い
☆三角関数の定義
ラジアンと単位円、三角比を用いた三角関数の定義
原点を中心とした半径1の円周上にあってx軸正の方向から反時計回りにラジアン角θを取った座標位置を(cosθ,sinθ)とする
この定義よりθはオイラー角90°を超える角度が扱える事となる。三角形OABは常に直角三角形になるのでピタゴラスの定理(三平方の定理)が適用できる
(尚、半径1の円を単位円と呼びます)
コード例:
using UnityEngine;
using System.Collections;
public class Rad1 : MonoBehaviour
{
void Start () { print (Method (30 * Mathf.Deg2Rad)); }
Vector2 Method (float theta) { return new Vector2 (Mathf.Cos (theta), Mathf.Sin (theta)); }
}
θを時計回りに進めると負角(-)となり、以下の負角の公式が利用できる
直角(π/2)からθを引いた余りの角を余角と呼び、以下の余角の公式が利用できる
※unityのMathfクラスsin,cos関数ではマイナスの引数でも上記の公式を内部で処理し正確に値を算出します
atan
atan(アークタンジェント:逆正接)
atan は tan の逆関数になる(つまり傾きから角度を得る)。atanを利用する事により内角θを求める事が出来る。角度が判らない時に使うと便利
引数はtanθ=(sinθ/cosθ)を渡す。返り値はラジアン角θとなる
<サンプルコード>
using UnityEngine;
using System.Collections;
public class Atan : MonoBehaviour
{
void Start () { print (Mathf.Cos (Mathf.Deg2Rad * 30)); print (Mathf.Sin (Mathf.Deg2Rad * 30)); print (Mathf.Sin (Mathf.Deg2Rad * 30) / Mathf.Cos (Mathf.Deg2Rad * 30)); //tan30° print (Mathf.Tan (Mathf.Deg2Rad * 30));
Vector2 vec = Vector2.right; //三角関数は数学的にX+が基準になる為、atanも例外ではない print (vec); vec = Quaternion.AngleAxis (30, Vector3.forward) * vec; //クォータニオンの後にベクトルを掛ける(反対はエラーが出るので注意) print (vec); print (Mathf.Atan (vec.y / vec.x) * Mathf.Rad2Deg); print (Mathf.Atan2 (vec.y, vec.x) * Mathf.Rad2Deg); print (Mathf.Atan (Mathf.Sin (Mathf.Deg2Rad * 30) / Mathf.Cos (Mathf.Deg2Rad * 30)) * Mathf.Rad2Deg); //tan30° }
}
出力
0.8660254
0.5
0.5773503
0.5773503
(1.0, 0.0)
(0.9, 0.5)
30
30
30
この場合のvecは正規化が必要ない(引数にtanθを渡すという事は比だから)
有名なsin,cos値
最低限、暗記しておいた方が良いsin,cos値
cos(0°) | 1 | sin(0°) | 0 |
cos(30°) | √0.75 = 0.866~ | sin(30°) | √0.25= 0.5 |
cos(45°) | √0.5= 0.7071~ | sin(45°) | √0.5= 0.7071~ |
cos(60°) | √0.25= 0.5 | sin(60°) | √0.75 = 0.866~ |
cos(90°) | 0 | sin(90°) | 1 |
オイラー角45度を境にsin,cosの関係が対称になっている
上の表から以下の式で三平方の定理が成立している事が確認できる
cos(30°)^2 + sin(30°)^2 = 1
0.866^2 + 0.5^2 = 1
0.75 + 0.25 = 1
三角関数の表記注意点
三角関数同士の掛算では以下の様に表記する必要がある
sinABの様な書き方はNGなので注意
累乗表記は
のように関数側の右肩に書く事が約束となっている
三角関数プレーヤー_for_Unity
簡単な三角関数が理解できるサンプルプログラムを作ってみました
以下のURLよりUnityWebPlayerにてプレイできます
GitHubにてソースコードを公開しました
一応、扱いはフリーライセンスです
Sinθの微分を求めてみて分る事
f(θ)=sin(θ)として微分する際、式の途中でsin(θ+Δθ)するが、この部分の計算は単純な計算ではうまく行かない
その原因は関数にあると考えられる
f(x-Δx)が正しく計算できる「その関数が持つ加法定理」を明確にしなければ、その関数に対する微分は出来ない
たとえばsin、cosの三角関数の場合、sin(θ+Δθ)をsin(a+b)として
- sin(a+b) = sin(a)cos(b)+cos(a)sin(b)
- sin(a-b) = sin(a)cos(b)-cos(a)sin(b)
- cos(a+b) = cos(a)cos(b)-sin(a)sin(b)
- cos(a-b) = cos(a)cos(b)+sin(a)sin(b)
という基本的な定理が単位円内の二つの直角三角形の相似関係から導ける
ここから式の足し算による変形で
- sin(a)cos(b) = 1/2{sin(a+b)+sin(a-b)}
- cos(a)sin(b) = 1/2{sin(a+b)-sin(a-b)}
- cos(a)cos(b) = 1/2{cos(a+b)+cos(a-b)}
- sin(a)sin(b) = -1/2{cos(a+b)-cos(a-b)}
という式が作れる。ここからさらにsin(a+b)-sin(a-b)をsinA-sinBとして考えると...
(以下省略)
三角関数サンプルプログラム解説
一応ソースコードの解説をするとScripts/baseフォルダ内のスクリプトがグラフ描画用の汎用性を持たせたつもりのベクターメッシュ用ライブラリです。シーンに配置したGameObjectとしての個々のライン描画(VectorMesh)をunityのParticleSystem的にDictionaryクラスで辞書管理させています。ユーザーはこの辞書を使ってシーン内のベクターメッシュオブジェクトを一元管理できます(ベクターメッシュはゲームオブジェクトなので、ゲームオブジェクトとして消したりも出来ますが、そういう使い方を想定したつくりにしていません。削除には辞書クラスを経由して行うのが想定している使い方です。それによりパーティクルのライフタイムのような機能や一時的な非表示機能なども正常に運用できるようになります)。Scripts/meshLib/内のコードが個々のメッシュの作画用コードです。たとえばラインや円、グリッドなどを具体的に作画するコードです。Scripts / userLib / 内はVectorMeshクラスを継承したカスタム化された描画オブジェクトのクラスを作成しています。これは今回サインコサインカーブの逐次変化するリアルタイム描画をするベクターメッシュの仕様を担当させています。ここにあるコードのようにVectorMeshクラス継承すると様々なベクター描画が可能となるようなならないような感じです(汗)。正直使い易い形になってるとは思えないので、後々この辺りの仕様等は他のプログラムなどで改良していく予定は未定
とりあえず数学的に色々な作画が可能になってきたので何か数学を使って面白い表現が出来るコードを今後も書いてみるつもりです
資料
T:??
L:重心からの長さ
g:重力
T = 2 * Mathf.PI * Mathf.Sqrt(L/g)
- 最終更新:2015-03-09 21:02:30