内積

次は、内積です
内積は、当たり判定を行う際によく使われているので、
概念を覚える必要があります
また、内積はDotProduct,ScalarProduct,InnterProduct
とも呼ばれます。

2Dの内積の定義

2次元ベクトルvec1とvec2があるとすると、 2Dの内積は以下のように定義されます


vec1.x * vec2.y + vec1.y * vec2.y
		

これをjavascriptに置き換えるとこう書くことができます。


/*
	vec1:Vector2D
	vec2:Vector2D
*/
function dotProduct(vec1,vec2){
	return vec1.x * vec2.x + vec1.y * vec2.y;
}
		

また、もう一つ内積の定義方法があります。 2つのベクトルのなす角をθとした時に、
cosθと2つのベクトルの長さをかけたものに一致します。


|vec1| * |vec2| * cosθ
		

プログラムで書くと以下のように定義できます。


/*
	vec1:Vector2D
	vec2:Vector2D
	cos:vec1とvec2のなす角のcos
*/
function dotProduct(vec1,vec2,cos){
	return cos * length(vec1) * length(vec2);
}
		

内積の意味

内積の定義を確認しましたが、どういった場面で使うのでしょうか?
内積の以下の性質があります

1.なす角が90°の時に0になる

2.内積が正の時になす角は90°未満である

3.内積が負の時になす角は90°以上である

内積を使って二つのベクトルのなす角を求める

また、内積を使って二つのベクトルのなす角の角度を求めることができます。
以下の関数を定義できます


/*
	2つのベクトルがなす角を返す
*/
function getEnclosedAngle(vec1,vec2){
	// 単位ベクトルを返す
	var unitVec1 = getUnitVector(vec1);
	var unitVec2 = getUnitVector(vec2);
	// 内積取得
	var dp = dotProduct(unitVec1,unitVec2);
	return getRadianToDegree(Math.acos(dp));
}
		

では、解析していきましょう。

まず、内積の定義から確認します。

1.
dotProduct(v1,v2) = cos(a) * length(v1) * length(v2);

これが内積の定義でした。これを展開します。

2.
dotProduct(v1,v2) / (length(v1) * length(v2)) = cos(a)

内積を以下のように展開できることをこと考えます

3.
dotProduct(s1 * v1,s2 * v2) = s1 * s2 * dotProduct(v1,v2);

2と3を組み合わせましょう

4.
cos(a) = dotProduct(v1 / length(v1),v2 / length(v2));

4から
v1 / length(v1)は単位ベクトルなので、以下のように展開できます

5.
cos(a) = dotProduct(unitVector(v1),unitVector(v2));

cosの角度を求めるacos関数を5の両辺に適応しましょう

6.
acos(cos(a)) = acos(dotProduct(unitVector(v1),unitVector(v2))) = a;

となり、内積を利用して二つのベクトルのなす角をもとめることができました。

内積まとめ

ここでは、内積を使って求めることができる情報の一部をまなびました。
当たり判定のサンプルでは、内積を使って情報を求めていますので、確認してみてください