第 7 章 座標変換
7.4 変換の合成
}
return t;
} };
for (int j = 0; j < 4; ++j) {
for (int i = 0; i < 4; ++i) {
const int ji(j * 4 + i);
t.matrix[ji] = 0.0f;
for (int k = 0; k < 4; ++k)
t.matrix[ji] += matrix[k * 4 + i] * m.matrix[j * 4 + k];
} }
return t;
}
ただし、これは三重のループになっているので、性能が少し気になります。たとえば次のよう に書けば、ループを一重にできます。
// 乗算
Matrix operator*(const Matrix &m) const {
Matrix t;
for (int i = 0; i < 16; ++i) {
const int j(i & 3), k(i & ~3);
t.matrix[i] =
matrix[ 0 + j] * m.matrix[k + 0] + matrix[ 4 + j] * m.matrix[k + 1] + matrix[ 8 + j] * m.matrix[k + 2] + matrix[12 + j] * m.matrix[k + 3];
}
return t;
}
7.4.2 剛体変換
平行移動と回転は、立体の形状に影響を与えません。そのため、この二つを組み合わせた変換 は剛体変換と呼ばれます。
(32)
したがって、この Mは回転の変換行列 𝐑" と平行移動のベクトル t で構成されます。
(33) M=T(t)R(l, m, n,✓) =
0 BB
@
r00 r10 r20 tx
r01 r11 r21 ty
r02 r12 r22 tz
0 0 0 1
1 CC A
R¯ = 0
@ r00 r10 r20
r01 r11 r21
r02 r12 r22
1 A, t=
0
@ tx
ty
tz
1
A ) M= 0
@ R¯ t 0T 1
1 A
7.4.3 任意の点を中心にした回転
7.3.6 で示した回転の変換は、いずれも原点を通る軸を中心としたものでした。任意の点を点を
通る軸を中心に回転するには、一旦その点を原点に移す平行移動を行い、回転した後に元の位置 に戻すという処理を行います。これは次の三つの変換の合成変換 M = T(p) Rz(q) T(-p) です。
図 81 任意の点を中心とする回転
7.4.4 任意の点を中心にした拡大縮小
7.3.4で示した拡大縮小は、原点を基準にしています。そのため、拡大縮小を行うとする図形が
原点から離れていると、図形全体の位置も変ってしまいます。
図 82 拡大縮小に伴う図形の移動
図形を、その図形の位置で拡大するためには、拡大縮小を行う際の基準点を図形の位置に移す 必要があります。これは基準点が原点になるように図形を平行移動し、その後に拡大縮小して、
元の位置に戻すことで実現します。これは次の三つの変換の合成変換 M = T(p) S(s) T(-p) です。
p
x y
x y
x y
p
T( p)
θ"
R
z( θ ) T(p)
M = T(p) R
z( θ ) T( p)
O O O
O x
y
(移動)
図 83 任意の基準点による拡大縮小
7.4.5 特定方向への拡大縮小
7.3.4 で示した拡大縮小は、また x、y、z のそれぞれの軸方向に対する拡大縮小しか行うこと
ができません。任意の方向に対して拡大縮小を行うためには、その方向を一旦 x、y、z 軸の方向 に合わせてから拡大縮小を行い、それから元の向きに戻します。いま、軸ベクトル (x y z) をそれ ぞれ (r s t) 方向に回転する変換行列を F、sr、ss、st をそれぞれ x、y、z 軸方向の拡大率とする 拡大縮小の変換行列 S とするとき、この変換は M = FSFT となります。
(34)
(35)
図 84 特定方向への拡大縮小
x y
x y
p
T(-p) T(p)
M = T(p) S (s) T( p) S(s)
p
x y
O O O
F=
✓ r s t 0 0 0 0 1
◆
S= 0 BB
@
sr 0 0 0 0 ss 0 0 0 0 st 0 0 0 0 1
1 CC A
F
TS F
x s y
r O
s O r
s
O r x
s y
r O
M = F S F
T7.4.6 オイラー変換
原点を中心とした任意の回転は、x, y, z の三つの軸中心の回転を合成して表すことができます。
この回転を表す各軸中心の回転角の組をオイラー角といい、それらによって表される回転の変換 をオイラー変換といいます。
図 85 オイラー角
合成変換は変換行列の積で表されますが、行列の積には交換法則が成り立たちません。したが ってオイラー変換の結果は、各軸中心の回転を合成する順序によって変化します。ここでは、z 軸 中心の回転 (roll, bank) → x 軸中心の回転 (pitch) → y 軸中心の回転 (heading, yaw) の順に変 換するものとします。また、それぞれの角度を r, p, h で表します。
• r: roll, bank (z 軸中心の回転角)
• p: pitch (x 軸中心の回転角)
• h: heading, yaw (y 軸中心の回転角)
このとき、オイラー変換 E(h, p, r) は次式で表されます。
(36) heading
pitch roll
z x
y
E(h, p, r) =Ry(h)Rx(p)Rz(r)
= 0 BB
@
cosh 0 sinh 0
0 1 0 0
sinh 0 cosh 0
0 0 0 1
1 CC A
0 BB
@
1 0 0 0
0 cosp sinp 0 0 sinp cosp 0
0 0 0 1
1 CC A
0 BB
@
cosr sinr 0 0 sinr cosr 0 0
0 0 1 0
0 0 0 1
1 CC A
= 0 BB
@
sinhsinpsinr+ coshcosr sinhsinpcosr coshsinr sinhcosp 0
cospsinr cospcosr sinp 0
coshsinpsinr sinhcosr coshsinpcosr+ sinhsinr coshcosp 0
0 0 0 1
1 CC A
l ジンバルロック
オイラー角のうち、p = π/ 2 の場合を考えます。このとき sin p = 1, cos p = 0 になるので、式
(36) は次のようになります。
(37)
これは、加法定理により、次のように書き換えられます。
(38)
この回転は h - r という単一の角度で決定される、一つの軸による回転です。このため、r と h のどちらを変化させても同じ回転になり、自由度が一つ減ってしまいます。p = π/ 2 の回転によ って r の回転軸 (z 軸) が h の回転軸と一致します。この現象をジンバルロックといいます。
l 回転変換行列からオイラー角の算出
ある回転変換行列 M がオイラー変換 E(h, p, r) にもとづくものであったとします。
(39)
m1 と m5 の関係から、r を求めることができます。
(40)
同様に、m8 と m10 の関係から、h を求めることができます。
(41)
p は m9 から求めることができます。
(42) ただし、m1 = m5 = 0 のときは cos p = 0 なので、p = ±π/ 2 となります。これはジンバルロッ
E(h,⇡/2, r) = 0 BB
@
sinhsinr+ coshcosr sinhcosr coshsinr 0 0
0 0 1 0
coshsinr sinhcosr coshcosr+ sinhsinr 0 0
0 0 0 1
1 CC A
E(h,⇡/2, r) = 0 BB
@
cos(h r) sin(h r) 0 0
0 0 1 0
sin(h r) cos(h r) 0 0
0 0 0 1
1 CC A
M= 0 BB
@
m0 m4 m8 m12
m1 m5 m9 m13
m2 m6 m10 m14
m3 m7 m11 m15
1 CC
A=E(h, p, r)
m1 = cospsinr
m5 = cospcosr ! r=atan2(m5, m1)
m8 = sinhcosp
m10= coshcosp ! h=atan2(m10, m8)
m9= sinp! p=asin( m9)
クが発生している状態であり、式 (40) や式 (41) で r や h を求めることができません。その場 合は、たとえば h = 0 とし、m0 と m14 の関係から、h を求めることができます。
(43)
7.4.7 変換の順序
変換の合成は行列の積で表されますが、行列の積は交換の法則が成り立ちません。したがって、
同じ変換行列を合成した場合でも、その順序が異なれば、合成変換の結果は異なります。図 86 の 例では、正方形を回転してから x 軸方向に引き伸ばすとひし形になりますが、x 軸方向に引き伸 ばしてから回転すると回転した長方形になります。
図 86 変換の順序による合成変換の結果の違い