Suppose I have a three-dimensional vector $\bf{a}$ and another vector $\bf{u}$. I want to transform $\bf{a}$ into any orthogonal basis where $\bf{u}$ is one of the axes, such that $\bf{a} = (0, 1, 0)$ maps to $\bf{u}$. The use case is I am generating a vector in the standard basis and want to make a change of basis to an orthonormal basis where $\bf{u}$ is one of the axes. I don't care how $\bf{a}$ is rotated about $\bf{u}$ because I am only drawing $\bf{a}$ from radially symmetrical distributions.
So far I have been doing this as follows:
- pick an arbitrary vector $\bf{v} \neq \bf{u}$
- construct an orthonormal basis $B$ using $\bf{u}$, $\bf{u} \times \bf{v}$ and $\bf{u} \times (\bf{u} \times \bf{v})$ (all suitably normalized)
- transform $\bf{a}$ from standard basis to $B$ by multiplying with the orthonormal matrix built in (2)
But this is not great computationally and "feels" very wasteful, not to mention the awkward use of some arbitrary vector that causes the algorithm to not work on all inputs (or need an extra check to handle it). Is there a more efficient way to obtain the same result? Something that does not require precomputing a basis for $\bf{u}$?
Rodrigues’ rotation formula might be what you’re looking for: given a unit vector $\mathbf k$ that represents the rotation axis and a rotation angle $\theta$, the image of $\mathbf a$ under that rotation is $$\mathbf a\cos\theta + (\mathbf k\times\mathbf a)\sin\theta+\mathbf k(\mathbf k\cdot\mathbf a)(1-\cos\theta).$$ A convenient choice for $\mathbf k$ is $(0,1,0)\times\mathbf u$, normalized, i.e., $$\mathbf k = \left({u_z\over\sqrt{u_x^2+u_z^2}},0,-{u_x\over\sqrt{u_x^2+u_z^2}}\right).$$ With this choice, you have $\cos\theta=(0,1,0)\cdot\mathbf u/\|\mathbf u\|=u_y/\|\mathbf u\|$ and by the properties of the cross product, $0\le\theta\le\pi/2$ so you can use the positive square root of $1-\cos^2\theta$ for $\sin\theta$. If $(0,1,0)\times\mathbf u=0$, then either $\mathbf u$ points in the direction of the positive $y$-axis, in which case you’re done, or you need some 180-degree rotation, so you could simply map $\mathbf a$ to $-\mathbf a$.
If you don’t care about changing the orientation (handedness) of the coordinate system, which doesn’t matter if there’s only one vector $a$ that you’re going to transform in this way for instance, you could use a reflection in the angle bisector of $(0,1,0)$ and $\mathbf u$ instead: Let $\mathbf v$ = $\mathbf u/\|\mathbf u\|-(0,1,0)$. This vector is normal to the angle bisector, so the reflection of $\mathbf a$ is $$\mathbf a - 2{\mathbf a\cdot\mathbf v\over\mathbf v\cdot\mathbf v}\mathbf v,$$ which is even less expensive to compute than the rotation. With this approach, there’s only one special case, $\mathbf v=0$, in which case there’s nothing to do.
The orientation can be rectified by applying a second reflection about the plane with normal $((0,1,0)\times\mathbf u)\times\mathbf u = (u_xu_y,-(u_x^2+u_z^2),u_yu_z)$. The net result of these two reflections is the above rotation, in fact, but this is starting to look like at least as much work as applying Rodrigues' formula. (Indeed, this double reflection is one way to derive the formula.) It does avoid at least two square roots, though.