A Quick Calculation: 3D Rotation Matrix
I recently thought of creating a (very simple) 3D graphics display in Processing.
So I did that, and here it is. Its current functionalities are placing points based on \((x, y, z)\) coordinates, connecting two points, and rotating around axes. The axes pass through a fixed point on the canvas, which is the center (labeled as the origin). It’s a bit boring, but I really like the way I calculated the linear transformations for each rotation, so I’ll explain them here.
Linear Transformations
So each time you rotate a 3D figure about a fixed axis, you’re performing a linear transformation. To rotate a point \((x, y, z)\) about an axis (let’s say, the \(z\)-axis), you essentially fix the \(z\) coordinate, and map your point to its rotated image in the translated \(xy\) plane. Within the \(3\)-space, angles and lengths are preserved, so your transformation is linear. Also note that the angles for each axis are stored as variables (and every \(\theta\) is marked with a subscript for that axis).
And when this is displayed on the canvas, another transformation is performed. To give each point an \(x\) and \(y\) on the canvas, the figure is projected down onto the \(xy\) plane and, in my case, scaled and translated for visibility.
Here’s a transformation for a point with given x, y, z:
(x, y, z) -> ( 20*x+200, 20*y+200 )
Now, for rotations:
Rotation Time
We’ll treat each point \((x, y, z)\) as independent, and say we want to rotate it about, first, the \(z\)-axis. What’s good about this is that the \(z\) coordinate is fixed, so we’re essentially rotating within a translated \(xy\) plane, where we can ignore the last coordinate.
A useful fact is that rotation is a lot easier in the complex plane. Note that:
\[(a+bi)(\operatorname{cis}{\theta})\]Rotates a complex number by \(\theta\), so, for the purposes of calculation, we’ll treat a point \((x, y, z)\) as \(x+iy\), where the \(y\)-axis is now our imaginary axis. Now we can multiply:
\[(x+iy)(\operatorname{cis}{\theta_z}) = (x+iy)(\cos{\theta_z} + i\sin{\theta_z})\] \[= x\cos{\theta_z} + ix\sin{\theta_z} + iy\cos{\theta_z} - y\sin{\theta_z}\] \[= ( x\cos{\theta_z} - y\sin{\theta_z} ) + ( x\sin{\theta_z} + y\cos{\theta_z} )i\]Separating real and imaginary parts gives us that:
\[(x, y, z) \mapsto ( x\cos{\theta_z} - y\sin{\theta_z}, x\sin{\theta_z} + y\cos{\theta_z}, z )\]And we can do this again for the other two axes.
For y:
\[(x, y, z) \mapsto ( x\cos{\theta_y} + z\sin{\theta_y}, y, -x\sin{\theta_y} + z\cos{\theta_y})\]For x:
\[(x, y, z) \mapsto ( x, y\cos{\theta_x} - z\sin{\theta_x}, y\sin{\theta_x} + z\cos{\theta_x} )\]Matrix Notation
The matrix for these maps are then:
\[X: \begin{bmatrix} 1 & 0 & 0\\ 0 & \cos{\theta_x} & -\sin{\theta_x}\\ 0 & \sin{\theta_x} & \cos{\theta_x} \end{bmatrix} \\\] \[Y: \begin{bmatrix} \cos{\theta_y} & 0 & \sin{\theta_y}\\ 0 & 1 & 0\\ -\sin{\theta_y} & 0 & \cos{\theta_y} \end{bmatrix} \\\] \[Z: \begin{bmatrix} \cos{\theta_z} & -\sin{\theta_z} & 0\\ \sin{\theta_z} & \cos{\theta_z} & 0\\ 0 & 0 & 1 \end{bmatrix} \\\]And we’ll say the projection map for display is:
\[P: \begin{bmatrix} 20 & 0 & 0 \\ 0 & 20 & 0 \end{bmatrix}\]which is then translated.
So for vector \(\begin{bmatrix} x\\ y\\ z\end{bmatrix}\), \(PZYX\begin{bmatrix} x\\ y\\ z\end{bmatrix} + \begin{bmatrix} 200 \\ 200\end{bmatrix}\) is the transformation that the graphics display performs.