ベクトルと座標を使いこなそう
プログラマ向けの内容です。
ベクトルと座標の違いを正しく知っておくと惑わされずに使いこなすことができます。
※位置ベクトルという概念もありますが、混乱を招くのでベクトルと座標の話に絞っています。
ベクトルとは?
向きと大きさを持った量
※北に100m、東に20mといった向きと大きさを表現したものがベクトル
座標とは?
点の位置を示した数値
※北緯35度39分17秒5148、東経139度44分40秒5020といった位置を示すものが座標
はい、何を当たり前のことを言ってるのだと思われるかも知れないですが
意外と素直に受け止められていなかったりします。迷ったらこの定義に戻ってきてください。
まず最初に紛らわしい問題から解き放たれる必要があります。
数学系のライブラリ、シェーダーはベクトルと座標に型を分けておらず十中八九ベクトルの皮を被っています。
多くの場合、vector2, vector3といった型になっていないでしょうか?
中身は浮動小数が次元の数だけあり、x,y,zといった形で構成されています。
頭を切り替えていただきたいのですが、見た目は同じでも、ベクトルと座標は別の概念と認識していただきたいです。
同じものと思い込むと酷い目にあいます。
では、概念を変えるとどうなるかということですが、座標はベクトルではないので
ベクトル演算全てが使えません。ベクトルの性質を持たない為です。
・大きさ? そんなものは存在しません。
・向き? そんなものは存在しません。
・加算、乗算、除算? そんなものは存在しません。
・内積、外積? そんなものは存在しません。
・正規化? そんな事はできません。
座標は経度、緯度だと思ってください。座標は単純に位置を示しています。
座標同士の演算は、減算を除いて意味を持ちません。
したがって、最初にやるべき事は、目の前で扱っているデータ(変数)が、ベクトルなのか座標なのかを正しく認識することです。
これが出来れば、多くの問題は解決しているはず。
ベクトルと座標の計算式
ベクトルの演算を除いて使うのはこの2つだけです。(たぶん)
- 座標(x1,y1) + ベクトル(x2,y2) = 移動後の座標(x1+x2, y1+y2)
- 座標A(x1,y1) - 座標B(x2,y2) = 座標BからAに向かうベクトル(x1-x2, y1-y2)
※次元が増えても同じことを繰り返すだけです。
ではベクトルと座標をどのように扱うかの具体例を紹介します。
ベクトルと座標の扱い方
前提情報となる座標
自宅の座標( 10, 20 )
郵便局の座標( 150, 200 )
スーパーの座標( 50, 50 )
警察署の座標( 290, 380 )
ベクトル
自宅からスーパーまでのベクトル( 40, 30 )
ケース1. 自宅からスーパーに向かってみる。
自宅( 10, 20 ) + 自宅からスーパーまで( 40, 30 ) = スーパーの座標( 50, 50 )
ケース2. 自宅から郵便局までのベクトルを求めてみる。
郵便局の座標( 150, 200 ) - 自宅の座標( 10, 20 ) = 自宅から郵便局までのベクトル( 140, 180 )
はい、ここは何のことはないですね。
直感的な部分と結果が一致していると思います。
それでは続いて、自宅から警察署までは、郵便局の2倍の距離を進んだ場所にあります
といった場合どうでしょう。
正しくベクトルを使用した場合は次の演算になります。
自宅( 10, 20 ) + 自宅から郵便局まで( 140, 180 ) × 2 = 警察署( 290, 380 )
ベクトルを使わずにやるとこうなります。
正確に言えば、ベクトルから向き(角度)と大きさ(距離)を抽出して演算しなおしています。
・自宅から郵便局までの距離
郵便局( 150, 200 ) - 自宅( 10, 20 ) = 自宅から郵便局まで( 140, 180 )
root( 140 * 140 + 180 * 180 ) ≒ 228.035
※三平方の定理
・自宅から郵便局までの角度
郵便局( 150, 200 ) - 自宅( 10, 20 ) = 自宅から郵便局まで( 140, 180 )
atan( 180 / 140 ) ≒ 0.910 rad
・距離を2倍にする
228.035 × 2 = 456.07
・求めた角度に回転する ※(456.07, 0.0)とみなして回転
x' = x × cos(0.910) - y × sin(0.910)
y' = x × sin(0.910) + y × cos(0.910)
x'= 456.07 × cos(0.910) - 0 × sin(0.910)
y'= 456.07 × sin(0.910) + 0 × cos(0.910)
x'= 456.07 × cos(0.910)
y'= 456.07 × sin(0.910)
x'= 456.07 × 0.614
y'= 456.07 × 0.790
x'= 280.0270
y'= 360.2953
自宅( 10, 20 ) + (280.0270, 360.2953) ≒ 警察署の座標( 290.0270, 380.2953 )
途中計算を四捨五入したので、誤差が出ています。しなくても多少の誤差は出ます。
また、ルートおよび三角関数の演算が複数回あり、速度的にも不利ですよね。
ベクトルに苦手意識を持ってるいる方もしくは、ベクトルを知っていても
座標との関係を認知できていないとこの状態に陥ってしまいます。
ベクトルは向きと大きさの成分を既に持っているので、そのまま使うのがオススメです!
以下の公式を合わせることで、ベクトルを扱いやすくなります。
ベクトルの実数倍は、向き(角度)を変えずに大きさだけ変えれます。
2倍すれば大きさは2倍になり、0.5倍すれば半分になります。
信じられないって? では試してみましょう。
基準のベクトルを( 3, 4 )とする
・ベクトル( 3, 4 )の長さ
root( 3 × 3 + 9 × 9 ) = 5
※三平方の定理
・ベクトル( 3, 4 )の角度
atan( 4 / 3 ) = 0.927295 rad
基準のベクトルを2倍
・ベクトル( 3, 4 )を2倍した大きさ
root( 3 × 3 + 9 × 9 ) = 5 ← 基準のベクトル
root( 6 × 6 + 8 × 8 ) = 10 ※2倍になっています
※三平方の定理
・ベクトル( 3, 4 )を2倍した角度
atan( 4 / 3 ) = 0.927295 rad ← 基準のベクトル
atan( 8 / 6 ) = 0.927295 rad
※何倍しても比率は変わらないので同じ結果になります。
基準のベクトルを0.5倍
・ベクトル( 3, 4 )を0.5倍した大きさ
root( 3 × 3 + 9 × 9 ) = 5 ← 基準のベクトル
root( 1.5 × 1.5 + 2 × 2 ) = 2.5 ※0.5倍になっています
※三平方の定理
・ベクトル( 3, 4 )を0.5倍した角度
atan( 4 / 3 ) = 0.927295 rad ← 基準のベクトル
atan( 2 / 1.5 ) = 0.927295 rad
※何倍しても比率は変わらないので同じ結果になります。
単位ベクトル(大きさが1のベクトル)の実数倍は、向き(角度)を変えずに指定した大きさになります。
2倍すれば大きさは2になり、0.5にすれば0.5になります。
信じられないって? では試してみましょう。
単位ベクトル( 1, 0 )を2倍した時の大きさ
単位ベクトル( 1, 0 ) × 2 = ベクトル( 2, 0 )
root( 2 × 2 + 0 × 0 ) = 2
※三平方の定理
※角度は0度に変化がないので割愛
単位ベクトル( 1, 0 )を0.5倍した時の大きさ
単位ベクトル( 1, 0 ) × 2 = ベクトル( 0.5, 0 )
root( 0.5 × 0.5 + 0 × 0 ) = 0.5
※三平方の定理
※角度は0度に変化がないので割愛
単位ベクトル( 1, 0 )がうさん臭いって?
では30度に傾けて試してみましょう。
30度の単位ベクトル( 0.866025, 0.5 )
30度の単位ベクトルの求め方
※0.52359877559829887307710723054658は30度をラジアン角で表したもの
x' = x × cos(0.52359877559829887307710723054658) - y × sin(0.52359877559829887307710723054658)
y' = x × sin(0.52359877559829887307710723054658) + y × cos(0.52359877559829887307710723054658)
※回転行列
x' = 1 × cos(0.52359877559829887307710723054658) - 0 × sin(0.52359877559829887307710723054658)
y' = 1 × sin(0.52359877559829887307710723054658) + 0 × cos(0.52359877559829887307710723054658)
※xとyに代入する。ベクトル(1, 0)を回転するものとする。
x' = 1 × cos(0.52359877559829887307710723054658)
y' = 1 × sin(0.52359877559829887307710723054658)
※0と掛け算している部分を消す
x = cos(0.52359877559829887307710723054658)
y = sin(0.52359877559829887307710723054658)
x = 0.866025
y = 0.5
検算
root( 0.866025 × 0.866025 + 0.5 × 0.5 )
root( 0.749999300625 + 0.25 )
root( 0.999999300625 ) ≒ 1
※三平方の定理
大きさが1であること、つまり単位ベクトルであることが証明できます
30度の単位ベクトルを2倍
・30度の単位ベクトル( 0.866025, 0.5 )を2倍した時の大きさ
30度の単位ベクトル( 0.866025, 0.5 ) × 2 = ベクトル( 1.73205, 1.0 )
root( 1.73205 × 1.73205 + 1.0 × 1.0 ) ≒ 2
※三平方の定理
30度の単位ベクトル( 0.866025, 0.5 )を2倍した時の角度
30度の単位ベクトル( 0.866025, 0.5 ) × 2 = ベクトル( 1.73205, 1.0 )
atan( 1.0 / 1.73205 ) = 0.523599 rad = 30度
30度の単位ベクトルを0.5倍
・30度の単位ベクトル( 0.866025, 0.5 )を0.5倍した時の大きさ
30度の単位ベクトル( 0.866025, 0.5 ) × 0.5 = ベクトル( 0.4330125, 0.25 )
root( 0.4330125 × 0.4330125 + 0.25 × 0.25 ) ≒ 0.5
※三平方の定理
・30度の単位ベクトル( 0.866025, 0.5 )を0.5倍した時の角度
30度の単位ベクトル( 0.866025, 0.5 ) × 0.5 = ベクトル( 0.4330125, 0.25 )
atan( 0.25 / 0.4330125 ) = 0.523599 rad = 30度
上記の事から、何倍しても向き(角度)を変えずに大きさが変わることが分かります。
【参考】単位ベクトルの求め方
x' = x / root( x × x + y × y )
y' = y / root( x × x + y × y )
※x, y成分ともにベクトルの大きさで割ればよい。
ただし、xとy成分が共に0の場合は、0除算に注意です。この場合の単位ベクトルは存在しません。
最後に
この様にベクトルと座標を正しく認識できれば、空間の扱いが上手く出来るようになるのではないでしょうか。
それでは良いベクトルライフを!