Quaternion Class
To download:
1 | bzr branch http://bazaar.enseed.com/lib/Generic/ look under Geometry/Quaternion.h |
I used quaternions mainly for rotations around an axis (for example, to implement a trackball that doesn’t suffer from the gimbal lock like matrix-based trackballs do).
Rotation of Points Around an Axis
Rotation around an axis is done in three steps. First you create a quaternion q based on the axis and angle of rotation that you want. Then, you create a quaternion pt that will act as the point that you want to rotate. Finally, you multiply: q*pt*q.inverse().
You have to take extra care that the axis that you supply is a unit vector. You will then obtain a unit quaternion, and instead of taking q.inverse(), you can use q.unitInverse() which is faster.
1 2 3 4 5 6 7 8 9 10 11 | Point3d axis = Point3d(1.0, 1.0, 0.0).normalized(); Quatd q(axis, 2*M_PI/9); // 40 degrees Quatd pt(0, 1, 0, 0); // w = 0, x = 1, y =0, z = 0 // do a 360 around the axis for (int i = 0; i < 9; ++i) { pt = q*pt*q.unitInverse(); printf("(%f %f %f)\n", pt.x, pt.y, pt.z); } |
Executing the above code, you should obtain:
1 2 3 4 5 6 7 8 9 | (0.883022 0.116978 -0.454519) (0.586824 0.413176 -0.696364) (0.250000 0.750000 -0.612372) (0.030154 0.969846 -0.241845) (0.030154 0.969846 0.241845) (0.250000 0.750000 0.612372) (0.586824 0.413176 0.696364) (0.883022 0.116978 0.454519) (1.000000 0.000000 -0.000000) |
Obtaining a Rotation Matrix from a Quaternion
You can also choose to work with matrices instead and convert a quaternion to a 3×3 or 4×4 matrix:
1 2 3 4 5 6 7 8 9 10 11 12 13 | Point3d axis = Point3d(1.0, 1.0, 0.0).normalized(); Quatd q(axis, 2*M_PI/9); Point4d pt(1.0, 0.0, 0.0, 1.0); // x = 1, y = 0, z = 0 (homogeneous w = 1) Matrix4d m; q.to4x4Matrix(&m); printf("rotation matrix:\n %s\n", m.serialize().c_str()); for (int i = 0; i < 9; ++i) { pt = m*pt; printf("(%f %f %f)\n", pt.x, pt.y, pt.z); } |
And you obtain the following output
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | rotation matrix : { { 0.8830221891, 0.1169777811, -0.4545194805, 0.0000000000 } { 0.1169777811, 0.8830221891, 0.4545194805, 0.0000000000 } { 0.4545194805, -0.4545194805, 0.7660444379, 0.0000000000 } { 0.0000000000, 0.0000000000, 0.0000000000, 1.0000000000 } } (0.883022 0.116978 0.454519) (0.586824 0.413176 0.696364) (0.250000 0.750000 0.612372) (0.030154 0.969846 0.241845) (0.030154 0.969846 -0.241845) (0.250000 0.750000 -0.612372) (0.586824 0.413176 -0.696364) (0.883022 0.116978 -0.454519) (1.000000 -0.000000 0.000000) |
Concatenating Several Multiplications
You can concatenate several multiplcations by simply multiplicating your rotation quaternions together. It’s important to make sure that each quaternion is a unit quaternion though. If you created them with a unit axis, it should always be the case.
