IMP Reference Guide  2.7.0 The Integrative Modeling Platform
Rotation3D.h
Go to the documentation of this file.
1 /**
2  * \file IMP/algebra/Rotation3D.h \brief Simple 3D rotation class.
3  *
5  *
6  */
7
8 #ifndef IMPALGEBRA_ROTATION_3D_H
9 #define IMPALGEBRA_ROTATION_3D_H
10
11 #include <IMP/algebra/algebra_config.h>
12 #include "Vector3D.h"
13 #include "utility.h"
14 #include "constants.h"
15 #include "GeometricPrimitiveD.h"
16 #include <IMP/algebra/eigen3/Eigen/Dense>
17
18 #include <IMP/log.h>
19 #include <cmath>
20 #include <iostream>
21 #include <algorithm>
22
23 IMPALGEBRA_BEGIN_NAMESPACE
24
25 #if !defined(IMP_DOXYGEN) && !defined(SWIG)
26 class Rotation3D;
27 Rotation3D compose(const Rotation3D &a, const Rotation3D &b);
28 #endif
29
30 //! 3D rotation class.
31 /** Rotations are currently represented using quaternions and a cached
32  copy of the rotation matrix. The quaternion allows for fast and
33  stable composition and the cached rotation matrix means that
34  rotations are performed quickly. See
35  http://en.wikipedia.org/wiki/Quaternions_and_spatial_rotation for
36  a comparison of different implementations of rotations.
37
38  Currently the rotation can be initialized from either:
39  - XYZ Euler angles
40  - Rotation Matrix
41  - Quaternion
42  - angle/axis representation
43
44  \geometry
45 */
46 class IMPALGEBRAEXPORT Rotation3D : public GeometricPrimitiveD<3> {
47  VectorD<4> v_;
48  mutable bool has_cache_;
49  mutable Vector3D matrix_[3];
50  IMP_NO_SWIG(friend Rotation3D compose(const Rotation3D &a,
51  const Rotation3D &b));
52  void fill_cache() const {
53  IMP_USAGE_CHECK(get_is_valid(),
54  "Attempting to apply uninitialized rotation");
55  has_cache_ = true;
56  double v0s = get_squared(v_[0]);
57  double v1s = get_squared(v_[1]);
58  double v2s = get_squared(v_[2]);
59  double v3s = get_squared(v_[3]);
60  double v12 = v_[1] * v_[2];
61  double v01 = v_[0] * v_[1];
62  double v02 = v_[0] * v_[2];
63  double v23 = v_[2] * v_[3];
64  double v03 = v_[0] * v_[3];
65  double v13 = v_[1] * v_[3];
66  matrix_[0] =
67  Vector3D(v0s + v1s - v2s - v3s, 2 * (v12 - v03), 2 * (v13 + v02));
68  matrix_[1] =
69  Vector3D(2 * (v12 + v03), v0s - v1s + v2s - v3s, 2 * (v23 - v01));
70  matrix_[2] =
71  Vector3D(2 * (v13 - v02), 2 * (v23 + v01), v0s - v1s - v2s + v3s);
72  }
73
74  public:
75  //! Rotation3D copy constructor, faster than default copy constructor
76  //! in some cases
77  Rotation3D(const Rotation3D &rot) :
78  v_(rot.v_), has_cache_(rot.has_cache_)
79  {
80  if(has_cache_){
81  matrix_[0]=rot.matrix_[0];
82  matrix_[1]=rot.matrix_[1];
83  matrix_[2]=rot.matrix_[2];
84  }
85  }
86
87  //! IMP_CXX11_DEFAULT_COPY_CONSTRUCTOR(Rotation3D);
88
89  //! Create a rotation from a vector of 4 quaternion coefficients.
90  //! @note: use assume_normalized with care - inputting an unnormalized
91  //! vector would result in unexpected results if it is true
92  explicit Rotation3D(const VectorD<4> &v,
93  bool assume_normalized=false)
94  : v_(assume_normalized ? v : v.get_unit_vector()),
95  has_cache_(false) {}
96
97  //! Create an invalid rotation
98  Rotation3D() : v_(0, 0, 0, 0), has_cache_(false) {}
99  //! Create a rotation from a quaternion
100  /** \throw ValueException if the rotation is not a unit vector.
101  */
102  Rotation3D(double a, double b, double c, double d)
103  : v_(a, b, c, d), has_cache_(false) {
105  v_.get_squared_magnitude(), 1.0,
106  "Attempting to construct a rotation from a "
107  << " non-quaternion value. The coefficient vector"
108  << " must have a length of 1. Got: " << a << " " << b << " " << c
109  << " " << d << " gives " << v_.get_squared_magnitude());
110  if (a < 0) {
111  // make them canonical
112  v_ = -v_;
113  }
114  }
115  ~Rotation3D(){}
116
117 #ifndef IMP_DOXYGEN
118  Vector3D get_rotated_no_cache(const Vector3D &o) const {
119  IMP_USAGE_CHECK(get_is_valid(),
120  "Attempting to access uninitialized rotation");
121  return Vector3D(
122  (v_[0] * v_[0] + v_[1] * v_[1] - v_[2] * v_[2] - v_[3] * v_[3]) * o[0] +
123  2 * (v_[1] * v_[2] - v_[0] * v_[3]) * o[1] +
124  2 * (v_[1] * v_[3] + v_[0] * v_[2]) * o[2],
125  2 * (v_[1] * v_[2] + v_[0] * v_[3]) * o[0] +
126  (v_[0] * v_[0] - v_[1] * v_[1] + v_[2] * v_[2] - v_[3] * v_[3]) *
127  o[1] +
128  2 * (v_[2] * v_[3] - v_[0] * v_[1]) * o[2],
129  2 * (v_[1] * v_[3] - v_[0] * v_[2]) * o[0] +
130  2 * (v_[2] * v_[3] + v_[0] * v_[1]) * o[1] +
131  (v_[0] * v_[0] - v_[1] * v_[1] - v_[2] * v_[2] + v_[3] * v_[3]) *
132  o[2]);
133  }
134
135  //! Get only the requested rotation coordinate of the vector
136  double get_rotated_one_coordinate_no_cache(const Vector3D &o,
137  unsigned int coord) const {
138  IMP_USAGE_CHECK(get_is_valid(),
139  "Attempting to apply uninitialized rotation");
140  switch (coord) {
141  case 0:
142  return (v_[0] * v_[0] + v_[1] * v_[1] - v_[2] * v_[2] - v_[3] * v_[3]) *
143  o[0] +
144  2 * (v_[1] * v_[2] - v_[0] * v_[3]) * o[1] +
145  2 * (v_[1] * v_[3] + v_[0] * v_[2]) * o[2];
146  break;
147  case 1:
148  return 2 * (v_[1] * v_[2] + v_[0] * v_[3]) * o[0] +
149  (v_[0] * v_[0] - v_[1] * v_[1] + v_[2] * v_[2] - v_[3] * v_[3]) *
150  o[1] +
151  2 * (v_[2] * v_[3] - v_[0] * v_[1]) * o[2];
152
153  break;
154  case 2:
155  return 2 * (v_[1] * v_[3] - v_[0] * v_[2]) * o[0] +
156  2 * (v_[2] * v_[3] + v_[0] * v_[1]) * o[1] +
157  (v_[0] * v_[0] - v_[1] * v_[1] - v_[2] * v_[2] + v_[3] * v_[3]) *
158  o[2];
159  break;
160  default:
161  IMP_THROW("Out of range coordinate " << coord, IndexException);
162  }
163  }
164 #endif
165  //! Rotate a vector around the origin
166  Vector3D get_rotated(const Vector3D &o) const {
167  if (!has_cache_) fill_cache();
168  return Vector3D(o * matrix_[0], o * matrix_[1], o * matrix_[2]);
169  }
170
171  //! Get only the requested rotation coordinate of the vector
173  unsigned int coord) const {
174  if (!has_cache_) fill_cache();
175  return o * matrix_[coord];
176  }
177
178  //! Rotate a vector around the origin
179  Vector3D operator*(const Vector3D &v) const { return get_rotated(v); }
180  Vector3D get_rotation_matrix_row(int i) const {
181  IMP_USAGE_CHECK((i >= 0) && (i <= 2), "row index out of range");
182  if (!has_cache_) fill_cache();
183  return matrix_[i];
184  }
185  IMP_SHOWABLE_INLINE(Rotation3D,
186  { out << v_[0] << " " << v_[1] << " " << v_[2] << " " << v_[3]; });
187
188  //! Return the rotation which undoes this rotation.
189  inline Rotation3D get_inverse() const {
190  IMP_USAGE_CHECK(get_is_valid(),
191  "Attempting to invert uninitialized rotation");
192  Rotation3D ret(v_[0], -v_[1], -v_[2], -v_[3]);
193  return ret;
194  }
195
196  //! Return the quaternion so that it can be stored
197  /** Note that there is no guarantee on which of the two
198  equivalent quaternions is returned.
199  */
200  const Vector4D &get_quaternion() const {
201  IMP_USAGE_CHECK(get_is_valid(),
202  "Attempting to access uninitialized rotation");
203  return v_;
204  }
205
206  //! Multiply two rotations
207  Rotation3D operator*(const Rotation3D &q) const {
208  IMP_USAGE_CHECK(get_is_valid(),
209  "Attempting to compose uninitialized rotation");
210  return compose(*this, q);
211  }
212
213  //! Compute the rotation which when composed with r gives this
214  Rotation3D operator/(const Rotation3D &r) const {
215  IMP_USAGE_CHECK(get_is_valid(),
216  "Attempting to compose uninitialized rotation");
217  return compose(*this, r.get_inverse());
218  }
219
220  const Rotation3D &operator/=(const Rotation3D &r) {
221  *this = *this / r;
222  return *this;
223  }
224
225  /** \brief Return the derivative of the local position o with respect to
226  the i'th internal quaternion coefficient, for i in [0..3],
227  namely (dx/dQi, dy/dQi, dz/dQi)
228  */
229  const Vector3D get_derivative(const Vector3D &o, unsigned int i) const;
230
231  /** Return true is the rotation is valid, false if
232  invalid or not initialized (e.g., only initialized by
233  the empty constructor)
234  */
235  bool get_is_valid() const {
236  return v_.get_squared_magnitude() > 0; // TODO: add that magnitude ~ 1?
237  }
238 };
239
241
242 //! Return a rotation that does not do anything
243 /** \see Rotation3D */
244 inline Rotation3D get_identity_rotation_3d() { return Rotation3D(1, 0, 0, 0); }
245
246 //! Return a distance between the two rotations
247 /** The distance runs between 0 and 1. More precisely,
248  the distance returned is distance between the two
249  quaternion vectors properly normalized, divided
250  by sqrt(2).
251
252  A vector with distance d from the unit vector
253  represents a rotation of
254
255  \f$\theta= \cos^{-1}\left(1-\sqrt{2}d\right)\f$
256  \see Rotation3D
257 */
258 inline double get_distance(const Rotation3D &r0, const Rotation3D &r1) {
259  double dot =
260  (r0.get_quaternion() - r1.get_quaternion()).get_squared_magnitude();
261  double odot =
262  (r0.get_quaternion() + r1.get_quaternion()).get_squared_magnitude();
263  double ans = std::min(dot, odot);
264  // TODO: barak - added static for efficiency
265  static const double s2 = std::sqrt(2.0);
266  double ret = ans / s2;
267  return std::max(std::min(ret, 1.0), 0.0);
268 }
269
270 //! Generate a Rotation3D object from a rotation around an axis
271 //! that is assumed to be normalized
272 /**
273  \param[in] axis_norm the normalized rotation axis passing through (0,0,0)
274  \param[in] angle the rotation angle in radians in the
275  clockwise direction
276  \note http://en.wikipedia.org/wiki/Rotation_matrix
277  \note www.euclideanspace.com/maths/geometry/rotations/conversions/
278  angleToQuaternion/index.htm
279  \see Rotation3D
280 */
281 inline Rotation3D
283 (const Vector3D &axis_norm, double angle)
284 {
285  IMP_USAGE_CHECK(axis_norm.get_magnitude() - 1.0 < 1e-6,
286  "expected normalized vector as axis of rotation");
287  double s = std::sin(angle / 2);
288  double a, b, c, d;
289  a = std::cos(angle / 2);
290  b = axis_norm[0] * s;
291  c = axis_norm[1] * s;
292  d = axis_norm[2] * s;
293  return Rotation3D(a, b, c, d);
294 }
295
296
297 //! Generate a Rotation3D object from a rotation around an axis
298 /**
299  \param[in] axis the rotation axis passes through (0,0,0)
300  \param[in] angle the rotation angle in radians in the
301  clockwise direction
302  \note http://en.wikipedia.org/wiki/Rotation_matrix
303  \note www.euclideanspace.com/maths/geometry/rotations/conversions/
304  angleToQuaternion/index.htm
305  \see Rotation3D
306 */
307 inline Rotation3D
309 (const Vector3D &axis, double angle)
310 {
311  // normalize the vector
312  Vector3D axis_norm = axis.get_unit_vector();
314 }
315
316 //! Create a rotation from the first vector to the second one.
317 /** \see Rotation3D
318  */
319 IMPALGEBRAEXPORT Rotation3D
321
322 //! Generate a Rotation3D object from a rotation matrix
323 /**
324  \see Rotation3D
325 */
326 IMPALGEBRAEXPORT Rotation3D
327  get_rotation_from_matrix(double m00, double m01, double m02, double m10,
328  double m11, double m12, double m20, double m21,
329  double m22);
330
331 //! Generate a Rotation3D object from a rotation matrix
332 /**
333  \see Rotation3D
334 */
335 IMPALGEBRAEXPORT Rotation3D get_rotation_from_matrix(IMP_Eigen::Matrix3d m);
336
337 //! Pick a rotation at random from all possible rotations
338 /** \see Rotation3D */
339 IMPALGEBRAEXPORT Rotation3D get_random_rotation_3d();
340
341 //! Pick a rotation at random near the provided one
342 /** This method generates a rotation that is within the provided
343  distance of center.
344  \param[in] center The center of the rotational volume
345  \param[in] distance See
346  get_distance(const Rotation3D&,const Rotation3D&)
347  for a full definition.
348
349  \note The cost of this operation increases as distance goes to 0.
350
351  \see Rotation3D
352 */
353 IMPALGEBRAEXPORT Rotation3D
354  get_random_rotation_3d(const Rotation3D &center, double distance);
355
356 //! Cover the space of rotations evenly
357 /** If you care about the distance between samples instead of the number
358  of samples, the "surface area" of the set of rotations is pi^2. If
359  you allocate each sample a volume of 4/3 pi d^3 (to space them d apart),
360  Then you want 3/4 pi/d^3 points.
361
362  Creates at least num_points rotations.
363 */
364 IMPALGEBRAEXPORT Rotation3Ds
365  get_uniform_cover_rotations_3d(unsigned int num_points);
366
367 //! Generates a nondegenerate set of Euler angles with a delta resolution
368 /**
369 \param[in] delta sample every delta angles in radians.
370  */
372  double delta);
373
374 //! Compute a rotation from an unnormalized quaternion
375 /** \see Rotation3D */
377  VectorD<4> uv = v.get_unit_vector();
378  return Rotation3D(uv[0], uv[1], uv[2], uv[3]);
379 }
380
381 /** \see Rotation3D
382  */
383 inline Rotation3D compose(const Rotation3D &a, const Rotation3D &b) {
384  return Rotation3D(a.v_[0] * b.v_[0] - a.v_[1] * b.v_[1] - a.v_[2] * b.v_[2] -
385  a.v_[3] * b.v_[3],
386  a.v_[0] * b.v_[1] + a.v_[1] * b.v_[0] + a.v_[2] * b.v_[3] -
387  a.v_[3] * b.v_[2],
388  a.v_[0] * b.v_[2] - a.v_[1] * b.v_[3] + a.v_[2] * b.v_[0] +
389  a.v_[3] * b.v_[1],
390  a.v_[0] * b.v_[3] + a.v_[1] * b.v_[2] - a.v_[2] * b.v_[1] +
391  a.v_[3] * b.v_[0]);
392 }
393
394 /** \name Euler Angles
395  There are many conventions for how to define Euler angles, based on choices
396  of which of the x,y,z axis to use in what order and whether the rotation
397  axis is in the body frame (and hence affected by previous rotations) or in
398  in a fixed frame. See
399  http://en.wikipedia.org/wiki/Conversion_between_quaternions_and_Euler_angles
400  for a general description.
401
402  - All Euler angles are specified in radians.
403  - Only x-y-z order is currently supported.
404  - To convert Euler angles in a different order, one can compose a Rotation3D
405  from three rotations using get_rotation_about_axis function.
406  @{
407 */
408
409 //! Initialize a rotation in x-y-z order from three angles
410 /** \param[in] xr Rotation around the X axis in radians
411  \param[in] yr Rotation around the Y axis in radians
412  \param[in] zr Rotation around the Z axis in radians
413  \note The three rotations are represented in the original (fixed)
414  coordinate frame.
415  \see Rotation3D
416  \see FixedXYZ
417 */
418 IMPALGEBRAEXPORT Rotation3D
419  get_rotation_from_fixed_xyz(double xr, double yr, double zr);
420
421 //! Initialize a rotation from Euler angles
422 /**
423  \param[in] phi Rotation around the Z axis in radians
424  \param[in] theta Rotation around the X axis in radians
425  \param[in] psi Rotation around the Z axis in radians
426  \note The first rotation is by an angle phi about the z-axis.
427  The second rotation is by an angle theta in [0,pi] about the
428  former x-axis , and the third rotation is by an angle psi
430  \see Rotation3D
431 */
432 IMPALGEBRAEXPORT Rotation3D
433  get_rotation_from_fixed_zxz(double phi, double theta, double psi);
434
435 //! Generate a rotation object from Euler Angles
436 /** \note The first rotation is by an angle about the z-axis.
437  The second rotation is by an angle about the new y-axis.
438  The third rotation is by an angle about the new z-axis.
439  \param[in] Rot First Euler angle (radians) defining the rotation (Z axis)
440  \param[in] Tilt Second Euler angle (radians) defining the rotation (Y axis)
441  \param[in] Psi Third Euler angle (radians) defining the rotation (Z axis)
442  \see Rotation3D
443 */
444 IMPALGEBRAEXPORT Rotation3D
445  get_rotation_from_fixed_zyz(double Rot, double Tilt, double Psi);
446
447 //! A simple class for returning XYZ Euler angles
448 class FixedXYZ : public GeometricPrimitiveD<3> {
449  double v_[3];
450
451  public:
452  FixedXYZ() {}
453  FixedXYZ(double x, double y, double z) {
454  v_[0] = x;
455  v_[1] = y;
456  v_[2] = z;
457  }
458  double get_x() const { return v_[0]; }
459  double get_y() const { return v_[1]; }
460  double get_z() const { return v_[2]; }
462  { out << v_[0] << " " << v_[1] << " " << v_[2]; });
463 };
464
466
467 //! The inverse of rotation_from_fixed_xyz()
468 /**
469  \see rotation_from_fixed_xyz()
470  \see Rotation3D
471  \see FixesXYZ
472 */
473 IMPALGEBRAEXPORT FixedXYZ get_fixed_xyz_from_rotation(const Rotation3D &r);
474
475 /** @}*/
476
477 //! Interpolate between two rotations
478 /** It f ==0, return b, if f==1 return a.
479  \see Rotation3D */
481  double f) {
482  VectorD<4> bq = b.get_quaternion(), aq = a.get_quaternion();
483  if (bq * aq < 0) bq = -bq;
484  return Rotation3D(f * aq + (1 - f) * bq);
485 }
486
487 /** Return the rotation which takes the native x and y axes to the
488  given x and y axes.
489  The two axes must be perpendicular unit vectors.
490 */
491 IMPALGEBRAEXPORT Rotation3D
492  get_rotation_from_x_y_axes(const Vector3D &x, const Vector3D &y);
493
494 //! Decompose a Rotation3D object into a rotation around an axis
495 /** For all identity rotations, returns the axis [1,0,0] and the angle 0.0.
496
497  \note http://en.wikipedia.org/wiki/Rotation_matrix
498  \note www.euclideanspace.com/maths/geometry/rotations/conversions/
499  angleToQuaternion/index.htm
500  \see Rotation3D
501
503 */
504 IMPALGEBRAEXPORT std::pair<Vector3D, double> get_axis_and_angle(
505  const Rotation3D &rot);
506
507 typedef std::pair<Vector3D, double> AxisAnglePair;
508 #ifndef IMP_DOXYGEN
509 typedef Vector<AxisAnglePair> AxisAnglePairs;
510 #endif
511
512 IMPALGEBRA_END_NAMESPACE
513 #endif /* IMPALGEBRA_ROTATION_3D_H */
Vector3D get_rotated(const Vector3D &o) const
Rotate a vector around the origin.
Definition: Rotation3D.h:166
Rotation3D get_rotation_about_normalized_axis(const Vector3D &axis_norm, double angle)
Definition: Rotation3D.h:283
Rotation3D(const Rotation3D &rot)
Definition: Rotation3D.h:77
Base class for geometric types.
#define IMP_SHOWABLE_INLINE(Name, how_to_show)
Declare the methods needed by an object that can be printed.
Rotation3D get_rotation_from_x_y_axes(const Vector3D &x, const Vector3D &y)
Rotation3D get_rotation_from_fixed_xyz(double xr, double yr, double zr)
Initialize a rotation in x-y-z order from three angles.
Rotation3D()
Create an invalid rotation.
Definition: Rotation3D.h:98
#define IMP_USAGE_CHECK_FLOAT_EQUAL(expra, exprb, message)
Definition: check_macros.h:178
Rotation2D compose(const Rotation2D &a, const Rotation2D &b)
Compose two rotations a and b.
Definition: Rotation2D.h:108
algebra::Rotation3Ds get_uniformly_sampled_rotations(double delta)
Generates a nondegenerate set of Euler angles with a delta resolution.
Rotation3D get_random_rotation_3d(const Rotation3D &center, double distance)
Pick a rotation at random near the provided one.
Rotation3D operator/(const Rotation3D &r) const
Compute the rotation which when composed with r gives this.
Definition: Rotation3D.h:214
A simple class for returning XYZ Euler angles.
Definition: Rotation3D.h:448
Rotation3D(const VectorD< 4 > &v, bool assume_normalized=false)
IMP_CXX11_DEFAULT_COPY_CONSTRUCTOR(Rotation3D);.
Definition: Rotation3D.h:92
Vector3D operator*(const Vector3D &v) const
Rotate a vector around the origin.
Definition: Rotation3D.h:179
Rotation3D compose(const Rotation3D &a, const Rotation3D &b)
Definition: Rotation3D.h:383
double get_rotated_one_coordinate(const Vector3D &o, unsigned int coord) const
Get only the requested rotation coordinate of the vector.
Definition: Rotation3D.h:172
VT get_unit_vector(VT vt)
Returns a unit vector pointing at the same direction as this vector.
Definition: VectorBaseD.h:229
bool get_is_valid() const
Definition: Rotation3D.h:235
const Vector4D & get_quaternion() const
Return the quaternion so that it can be stored.
Definition: Rotation3D.h:200
VectorD< 4 > Vector4D
Definition: VectorD.h:399
Rotation3D get_rotation_about_axis(const Vector3D &axis, double angle)
Generate a Rotation3D object from a rotation around an axis.
Definition: Rotation3D.h:309
#define IMP_VALUES(Name, PluralName)
Define the type for storing sets of values.
Definition: value_macros.h:23
Base class for geometric types.
Functions to deal with very common math operations.
A Cartesian vector in D-dimensions.
Definition: VectorD.h:52
FixedXYZ get_fixed_xyz_from_rotation(const Rotation3D &r)
The inverse of rotation_from_fixed_xyz()
Rotation3D get_inverse() const
Return the rotation which undoes this rotation.
Definition: Rotation3D.h:189
Rotation3D get_rotation_from_fixed_zyz(double Rot, double Tilt, double Psi)
Generate a rotation object from Euler Angles.
std::pair< Vector3D, double > get_axis_and_angle(const Rotation3D &rot)
Decompose a Rotation3D object into a rotation around an axis.
double get_distance(const Rotation3D &r0, const Rotation3D &r1)
Return a distance between the two rotations.
Definition: Rotation3D.h:258
Rotation3D get_interpolated(const Rotation3D &a, const Rotation3D &b, double f)
Interpolate between two rotations.
Definition: Rotation3D.h:480
#define IMP_NO_SWIG(x)
Hide the line when SWIG is compiled or parses it.
Definition: swig_macros.h:18
Rotation3D get_rotation_from_matrix(IMP_Eigen::Matrix3d m)
Generate a Rotation3D object from a rotation matrix.
Rotation3D get_rotation_from_vector4d(const VectorD< 4 > &v)
Compute a rotation from an unnormalized quaternion.
Definition: Rotation3D.h:376
Rotation3D get_rotation_taking_first_to_second(const Vector3D &v1, const Vector3D &v2)
Create a rotation from the first vector to the second one.
Rotation3Ds get_uniform_cover_rotations_3d(unsigned int num_points)
Cover the space of rotations evenly.
Various useful constants.
Rotation3D operator*(const Rotation3D &q) const
Multiply two rotations.
Definition: Rotation3D.h:207
3D rotation class.
Definition: Rotation3D.h:46
#define IMP_THROW(message, exception_name)
Throw an exception with a message.
Definition: check_macros.h:50
Rotation3D(double a, double b, double c, double d)
Create a rotation from a quaternion.
Definition: Rotation3D.h:102
VectorD< 3 > Vector3D
Definition: VectorD.h:395
Rotation3D get_identity_rotation_3d()
Return a rotation that does not do anything.
Definition: Rotation3D.h:244
Simple 3D vector class.
#define IMP_USAGE_CHECK(expr, message)
A runtime test for incorrect usage of a class or method.
Definition: check_macros.h:168
Logging and error reporting support.
Rotation3D get_rotation_from_fixed_zxz(double phi, double theta, double psi)
Initialize a rotation from Euler angles.
IMP::Vector< Rotation3D > Rotation3Ds
Definition: Rotation3D.h:240