みさご解体新書

内積

解説/アルゴリズム

ab=abcosθ\vec{a} \cdot \vec{b} = |\vec{a}||\vec{b}|cos\theta
ab=a1b1+a2b2\vec{a} \cdot \vec{b} = a_1b_1+a_2b_2

function dot(a: Vector, b: Vector): number {
  return a.x * b.x + a.y * b.y;
}

2 つのベクトル a, b があり、aの大きさ * bの大きさ * cosθ、あるいは、a.x * b.x + a.y * b.yのように各成分同士を掛けたあと足し合わせたものを内積と呼び、前者と後者の値は一致する。

前者の cosθ の θ はどこの角度なのかというと、2 つのベクトルの始点を原点に置いたときのベクトル間の角度、いわゆるなす角になる。

// 2つのベクトルを用意する
const a = create(100, 0); // 3時の向きを指すベクトル
const b = create(0, 10000); // 6時の向きを指すベクトル

const d = dot(a, b); // 内積を計算
const cos = d / (length(a) * length(b)); // aの大きさ*bの大きさで割ることでcosθを取得
const rad = Math.acos(cos); // cosθから逆三角関数でθを取得
const deg = (rad * 180) / Math.PI; // ラジアンから角度に変換

console.log(deg); // 90;

abcosθ|\vec{a}||\vec{b}|cos\thetaab|\vec{a}||\vec{b}| で割ると cosθcos\theta だけが残るので、後者の式で内積を計算したものを ab|\vec{a}||\vec{b}| で割るだけで cosθcos\theta を得ることができる。

// 2つのベクトルを用意する
let a = create(100, 0); // 3時の向きを指すベクトル
let b = create(0, 10000); // 6時の向きを指すベクトル

a = normalize(a); // 大きさが1になるように正規化する
b = normalize(b); // 大きさが1になるように正規化する

const cos = dot(a, b); // 2つのベクトルが正規化済みなので、内積の結果がcosθになる
const rad = Math.acos(cos); // cosθから逆三角関数でθを取得
const deg = (rad * 180) / Math.PI; // ラジアンから角度に変換

console.log(deg); // 90;

2 つのベクトルを前もって正規化しておけば、内積の結果が 11cosθ1 \cdot 1 \cdot cos\theta と直接 cosθ になる。