Explaining Affine Rotation

If you are working on 2D or 3D graphics you have probably encountered 3x3 or 4x4 matrices used to translate or rotate the points of a geometrical figure.

You could lookup the definition of affine transformations on wikipedia. However unless you already understand the math well it does not explain very well why the affine transformation matrices look the way they do.

Here we are going to focus on explaining the rotation matrix, because that is I believe least obvious to people. But for the sake of completeness here are the scale, translate and rotation matrices.

If you want to scale a vector uu by the factor cxc_x along the x-axis and the factor cyc_y along the y-axis to get a new vector vv you can use the matrix SS as follows:

In similar fashion if you want to translate vector uu by dxd_x along the x-axis and dyd_y along the y-axis to produce vector vv you use translation matrix TT:

Next comes the rotation. How this works is less obvious. Here we are representing a point pp as a vector uu extending from the origin of our coordinate system to the point pp. Then we are rotating this vector by an angle θ\theta. This is done with a rotation matrix RR.

If you remember the definition of cos(θ)\cos(\theta) is equal to the the length of the side adjacent to the angle θ\theta. While sin(θ)\sin(\theta) is equal to the equal to the length of the side opposite of the angle θ\theta.

This is for a unit circle. That is a circle where the radius is 1. We can draw a triangle inside it where the hypothenuse is equal to the radius.

We can also think of the opposite side as representing the y-axis and the adjacent side representing the x-axis. So for a vector vv of length rr forming an angle θ\theta with the x-axis you can easily calculate its components:

The coordinates for a vector is always given relative to some basis. The basis are a bunch vectors representing each axis. By default the basis is defined as [1,0][1, 0] vector for the x-axis and [0,1][0, 1] vector for the y-axis. Thus a vector with coordinates xx and yy can be seen as the addition of two formed from the unit vectors defining the basis.

Here is an example in coded in the Julia programming language where x=3x = 3 and y=4y = 4.

v = 3*[1, 0] + 4*[0, 1]
linear-algebra (Julia)
2-element Array{Int64,1}: 3 4

Which again you can express equally through matrix multiplication:

An example from Julia using matrix multiplication.

A = [1 0;
     0 1]
v = A*[3, 4]
linear-algebra (Julia)
2-element Array{Int64,1}: 3 4

Basically you can make any vector by combining two other vectors. This allows us to simplify how we look at rotation. You can think of the vector uu being rotated as being made up of vector representing its x-component and another one representing its y-component. These two vectors can be combined to create the uu vector.

So when calculating a rotation of uu by θ\theta degrees, we can handle this as two separate rotations. One rotation of the x-axis basis [1,0][1, 0] and a rotation of the y-axis basis [0,1][0, 1].

We can study the circle below to see what happens if we try to rotate the x-axis basis by θ\theta degrees. We can imagine that the basis vector starts of as ABAB and then gets rotated to its new orientation ACAC. We can easily see that the x-component of ACAC is cos(θ)\cos(\theta) while the y-component is sin(θ)\sin(\theta)

This lets us conclude that the new x-basis bxb_x should be defined as the vector:

We can perform a similar analysis for the y-basis defined by ABAB in the circle below. It gets rotated counter-clockwise θ\theta degrees giving us a new y-basis ACAC.

In this case we can see the x-component of this new basis is defined by BCBC. The length is sin(θ)\sin(\theta). But since this is in the negative half of the circle, the x-coordinate will be sin(θ)-\sin(\theta). In this case the y-coordinate is defined by ABAB which is of length cos(θ)\cos(\theta). We can thus write the new y-basis as:

We can thus write our vector as a combination of these two basis vectors. Which gives us:

To make this 2x2 matrix also usable to express translation, it is often expanded to a 3x3 matrix like this:

Runtimes (1)