# Maths - AxisAngle to Matrix

## Equations

We can express the 3×3 rotation matrix in terms of a 3×3 matrix representing the axis (The 'tilde' matrix is explained here):

[R] = [I] + s*[~axis] + t*[~axis]2

or equivalently:

[R] = c*[I] + s*[~axis] + t*([~axis]2 + [I])

which can be expanded out to give the terms of the matrix components:

[R] =
 t*x*x + c t*x*y - z*s t*x*z + y*s t*x*y + z*s t*y*y + c t*y*z - x*s t*x*z - y*s t*y*z + x*s t*z*z + c

where,

• c =cos(angle)
• s = sin(angle)
• t =1 - c
• x = normalised axis x coordinate
• y = normalised axis y coordinate
• z = normalised axis z coordinate

This can be written as the sum of 3 matricies:

• The identity matrix times c.
• A matrix which is antisymmetrical about the leading diagonal (term on other side of diagonal is negative).
 t*x*x + c t*x*y - z*s t*x*z + y*s t*x*y + z*s t*y*y + c t*y*z - x*s t*x*z - y*s t*y*z + x*s t*z*z + c
= c*
 1 0 0 0 1 0 0 0 1
+ t*
 x*x x*y x*z x*y y*y y*z x*z y*z z*z
+s*
 0 -z y z 0 -x -y x 0

## Code

``` public void matrixFromAxisAngle(AxisAngle4d a1) {

double c = Math.cos(a1.angle);
double s = Math.sin(a1.angle);
double t = 1.0 - c;
//  if axis is not already normalised then uncomment this
// double magnitude = Math.sqrt(a1.x*a1.x + a1.y*a1.y + a1.z*a1.z);
// if (magnitude==0) throw error;
// a1.x /= magnitude;
// a1.y /= magnitude;
// a1.z /= magnitude;

m00 = c + a1.x*a1.x*t;
m11 = c + a1.y*a1.y*t;
m22 = c + a1.z*a1.z*t;

double tmp1 = a1.x*a1.y*t;
double tmp2 = a1.z*s;
m10 = tmp1 + tmp2;
m01 = tmp1 - tmp2;
tmp1 = a1.x*a1.z*t;
tmp2 = a1.y*s;
m20 = tmp1 - tmp2;
m02 = tmp1 + tmp2;    tmp1 = a1.y*a1.z*t;
tmp2 = a1.x*s;
m21 = tmp1 + tmp2;
m12 = tmp1 - tmp2;
}```

## Derivation of Equations Imagine we want to rotate a point P1 (denoted in the above diagram by the blue vector). The axis we want to rotate around is denoted by the red vector.

The track of the point as it rotates will form a circle (shown in green) in a given plane.

In the diagram below this plane has been moved down so that it passes through the origin. This plane is defined by the rotation axis (the plane is perpendicular to the axis). We now want to generate two basis vectors in the plane which we can use to define the circle in our global coordinate system. To get one of these basis vectors we can cross multiply axis with P1, this gives a vector in the plane at 90° to the projection of P1 onto the plane. For information about vector algebra and cross products see this page.

basis2 = axis × P1

where:

• basis2 = second basis vector
• axis = direction of rotation as a normalised (unit length) vector
• × = vector cross product.
• P1 = point being rotated.

The first basis vector is just the projection of the vector P1 onto the plane (Projection of a line onto a plane is explained on this page).

This will be a vector mutually perpendicular to axis and basis2, so,

basis1 = basis2 × axis

basis1 = (axis × P1) × axis

These basis vectors are shown on the following diagram: Therefore the track of the circle is given by a linear product of these vectors as follows:

cos(angle) * basis1 + sin(angle) * basis2

actually this is not quite the circle required as the circle has been offset to the origin therefore we need to move it back therefore:

P2 = offset + cos(angle) * basis1 + sin(angle) * basis2

where:

• P2 = transform of point P1
• offset = distance of centre of circle from origin
• angle = angle that we are rotating around the axis From the diagram we can see that:

offset = P1 - basis1

Therefore substituting this values gives:

P2 = P1 - basis1 + cos(angle) * basis1 + sin(angle) * basis2

P2 = P1 + (cos(angle) - 1) * basis1 + sin(angle) * basis2

substituting the basis values above gives:

P2 = P1 + (cos(angle) - 1) * ((axis × P1)×axis) + sin(angle)*(axis × P1)

However this uses vector algebra, we need to convert this into matrix algebra, we can do this by using the skew symmetric or 'tilde' matrix as described on this page.

if V = A × B

then V = [~A]B

where:

[~A] =
 0 -az ay az 0 -ax -ay ax 0

So converting to matrix form gives:

P2 = P1 + (cos(angle) -1)*([~axis]P1 × axis) + sin(angle)*[~axis]P1

There is still one vector cross product here, to remove it we will first change the order by using the anticommute law:

P2 = P1 + (1 - cos(angle))*(axis× [~axis]P1) + sin(angle)*[~axis]P1

Now we can substitute the skew symmetric [~axis] as before:

P2 = P1 + (1 - cos(angle))*([~axis]²P1) + sin(angle)*[~axis]P1

gathering the P1 terms together gives:

P2 = [I + (1 - cos(angle))[~axis]2 + sin(angle)[~axis]] P1

Let the rotation matrix be [R] where:

P2 = [R] P1

so the rotation matrix is

[R] = [I] + sin(angle)[~axis] + (1-cos(angle))[~axis]2

where:

For information about the derivation of this see message from Sven.

[I] =
 1 0 0 0 1 0 0 0 1
[~axis] =
 0 -z y z 0 -x -y x 0
[~axis]2 =
 -z*z - y*y x*y x*z x*y -z*z - x*x y*z x*z y*z -y*y - x*x

since x*x + y*y + z*z = 1 then,

[~axis]2 =
 x*x-1 x*y x*z x*y y*y-1 y*z x*z y*z z*z-1

therefore:

[R] =
 1 + (1-cos(angle))*(x*x-1) -z*sin(angle)+(1-cos(angle))*x*y y*sin(angle)+(1-cos(angle))*x*z z*sin(angle)+(1-cos(angle))*x*y 1 + (1-cos(angle))*(y*y-1) -x*sin(angle)+(1-cos(angle))*y*z -y*sin(angle)+(1-cos(angle))*x*z x*sin(angle)+(1-cos(angle))*y*z 1 + (1-cos(angle))*(z*z-1)

let,

• c =cos(angle)
• s = sin(angle)
• t =1 - c
[R] =
 t*x*x + c t*x*y - z*s t*x*z + y*s t*x*y + z*s t*y*y + c t*y*z - x*s t*x*z - y*s t*y*z + x*s t*z*z + c

An alternative way to do this conversion might be to represent the rotation as two reflections as described here.

## Example

 we take the 90 degree rotation from this: to this: As shown here the axis angle for this rotation is:

angle = 90 degrees
axis = 1,0,0

So using the above result:

• c =cos(angle) = 0
• s = sin(angle) = 1
• t =1 - c =1
• x=1
• y=0
• z=0
[R] =
 t*x*x + c t*x*y - z*s t*x*z + y*s t*x*y + z*s t*y*y + c t*y*z - x*s t*x*z - y*s t*y*z + x*s t*z*z + c
[R] =
 1 0 0 0 0 -1 0 1 0

As you can see here, this gives the result that we are looking for.

## Angle Calculator and Further examples

I have put a java applet here which allows the values to be entered and the converted values shown along with a graphical representation of the orientation.

Also further examples in 90 degree steps here