空間群 P3 における 120度回転の演算子が (-y, x - y) であるのが不思議であるという話を聞いた。私も同じことを昔思っていたが、別にどうということはない。分数座標で考えるからそうなるのである。
120 度の回転は、複素数で考えると となり、明らかにルートが含まれる。ただし、これは直交座標系での話。求めたいのは分数座標系での演算子だ。そのためには、(分数座標系→直交座標系)→回転→(直交座標系→分数座標系) というふうに座標変換をサンドイッチにすればよい。最初の変換を直交化 (orthogonalization)、最後の変換を分数化 (fractionalization) という。
直交化変換は、a 軸を x 軸に移し替えるのでそのまま。b 軸は 図で 11 時方向に移りかわる。したがって、(1, 0) → (1, 0)、(0, 1) → (-1/2, ) と変換すればよいので、これを縦に並べた行列を作ればよい。このように、座標変換の行列は、変換元の世界での単位ベクトルが何に変換されるかを考えて、縦に並べるだけである! 分数化変換はその逆なので、逆行列を取るだけ。
以上を通して行うと、以下のようなコードになる。
orthogonalization <- matrix(c(1, -1/2, 0, sqrt(3)/2), 2, byrow=TRUE) orthogonalization %*% c(1, 0) orthogonalization %*% c(0, 1) fractionalization <- solve(orthogonalization) fractionalization %*% c(1, 0) fractionalization %*% c(-1/2, sqrt(3)/2) angle <- 120 / 180 * pi rotation_120 <- matrix(c(cos(angle), -sin(angle), sin(angle), cos(angle)), 2, byrow=TRUE) rotation_120 %*% c(1, 0) rotation_120 %*% c(0, 1) fractionalization %*% rotation_120 %*% orthogonalization
厳密解が得られる Maxima でやったほうが見やすい。行列としての掛け算は "." で行う。
ortho: matrix([1, -1/2],[0, sqrt(3)/2]); ortho . [1, 0] ortho . [0, 1] frac: ortho ^^ -1; frac . [1, 0] frac . [-1/2, sqrt(3)/2] angle: 120 / 180 * %pi; rot: matrix([cos(angle), -sin(angle)], [sin(angle), cos(angle)]); (ortho ^^ -1) . rot . ortho; ratsimp((ortho ^^ -1) . rot . ortho . [x, y]);
ただし、上に書いたように「座標変換の行列は、変換元の世界での単位ベクトルが何に変換されるかを考えて、縦に並べるだけ」なので、図形的に考えたほうが簡単である。分数座標での a 軸、b 軸は、図の 3 時と 11 時方向。a 軸は 120 度回転でもとの b 軸 にうつるので x → y。11 時方向にあった b 軸 は、7時の方向にうつるが、上の六角形の図から分かるように、 9 時方向 (-a 方向) に進んでから 5 時方向 (-b 方向) に進むことで 7 時の場所に到達できる。したがって、y → -x-y となる。これを縦に並べると、 となる。