First written in 2006.
Last updated 2014-06-29.

Rotate a point, \((x_1, y_1)\), around the origin, by the angle \(\phi\), resulting in a new point, \((x_2, y_2)\):

(diagram showing rotation)

$$ \begin{eqnarray*} x_2 & = & x_1 \cos \phi - y_1 \sin \phi\\ y_2 & = & y_1 \cos \phi + x_1 \sin \phi \end{eqnarray*} $$

How to derive the rotation formulas

Start with a point: $$p_1 = (x_1, y_1)$$

In polar coordinates, this is: $$ \begin{eqnarray*} x_1 = r \cos \theta_1\\ y_1 = r \sin \theta_1 \end{eqnarray*} $$

The rotated point will be: $$ \begin{eqnarray*} x_2 & = & r \cos \left(\theta_1 + \phi\right) \\ y_2 & = & r \sin \left(\theta_1 + \phi\right) \end{eqnarray*} $$

Remember the trigonometric identities for addition of angles: (we'll get to these later) $$ \begin{eqnarray*} \sin \left(a + b\right) & = & \sin a \cos b + \cos a \sin b \\ \cos \left(a + b\right) & = & \cos a \cos b - \sin a \sin b \end{eqnarray*} $$

Substituting these in, we get: $$ \begin{eqnarray*} x_2 & = & r \cos \left(\theta_1 + \phi\right) \\ x_2 & = & r \left( \cos \theta_1 \cos \phi - \sin \theta_1 \sin \phi \right) \end{eqnarray*} $$

Using the equations for \(x_1\) and \(y_1\), we can simplify this: $$ \begin{eqnarray*} x_2 & = & \left( r \cos \theta_1 \right) \cos \phi - \left( r \sin \theta_1 \right) \sin \phi\\ x_2 & = & x_1 \cos \phi - y_1 \sin \phi \end{eqnarray*} $$

Likewise, for \(y_2\): $$ \begin{eqnarray*} y_2 & = & r \sin \left(\theta_1 + \phi\right) \\ y_2 & = & r \left( \sin \theta_1 \cos \phi + \cos \theta_1 \sin \phi \right) \\ y_2 & = & y_1 \cos \phi + x_1 \sin \phi \end{eqnarray*} $$

How to derive the addition-of-angles formulas

A complex number on the unit circle, in exponential form: $$e^{\theta i} = \cos \theta + i \sin \theta$$

Multiplying two such complex numbers: $$e^{ai} \times e^{bi} = e^{\left(a+b\right)i}$$

So: $$ \begin{eqnarray*} e^{\left(a+b\right)i} & = & \cos\left(a+b\right) + i \sin\left(a+b\right) \\ e^{ai} \times e^{bi} & = & \left(\cos a + i \sin a\right) \times\\ & & \left(\cos b + i \sin b\right)\\ & = & \cos a \cos b + i \cos a \sin b +\\ & & i \sin a \cos b - \sin a \sin b\\ \end{eqnarray*} $$

Separating the real and complex components: $$ \begin{eqnarray*} \cos\left(a+b\right) & = & \cos a \cos b - \sin a \sin b\\ \sin\left(a+b\right) & = & \cos a \sin b + \sin a \cos b \end{eqnarray*} $$

Implementation and optimization

Here's a straightforward implementation of rotation in C++:

void rot1(const double x1, const double y1, const double theta,
          double* x2, double* y2) {
  const double s = sin(theta);
  const double c = cos(theta);
  *x2 = x1 * c - y1 * s;
  *y2 = y1 * c + x1 * s;
}

The above costs 4 multiplies, 1 add, 1 subtract.

We can trade one of the multiplies for 2 adds and 1 subtract:

void rot2(const double x1, const double y1, const double theta,
          double* x2, double* y2) {
  const double s = sin(theta);
  const double c = cos(theta);
  const double z = x1 * (s + c);
  *x2 = z - (x1 + y1) * s;
  *y2 = z + (y1 - x1) * c;
}

The above costs 3 multiplies, 3 adds, 2 subtracts.

If the angle is fixed, there's a further optimization possible:

void rot3(const double x1, const double y1,
          double* x2, double* y2) {
  const double s = sin(1. * M_PI / 16.);
  const double c = cos(1. * M_PI / 16.);
  const double z = c * (x1 + y1);
  *x2 = (-s-c) * y1 + z;
  *y2 = ( s-c) * x1 + z;
}

The above costs 3 multiplies and 3 adds, because -s-c and s-c are turned into constants.

All the code is here: rot.cc

I'm not counting operations by looking at the C++ code, but by looking at the generated assembler. There are instructions and results in the file.