IMP logo
IMP Reference Guide  2.11.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  *
4  * Copyright 2007-2019 IMP Inventors. All rights reserved.
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 <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  // When copying preserve the cached rotation matrix, if present
75  void copy_cache(const Rotation3D &rot) {
76  has_cache_ = rot.has_cache_;
77  if (has_cache_) {
78  matrix_[0] = rot.matrix_[0];
79  matrix_[1] = rot.matrix_[1];
80  matrix_[2] = rot.matrix_[2];
81  }
82  }
83 
84  public:
85  //! Rotation3D copy constructor
86  Rotation3D(const Rotation3D &rot) : v_(rot.v_) {
87  copy_cache(rot);
88  }
89 
90  Rotation3D &operator=(const Rotation3D &rot) {
91  v_ = rot.v_;
92  copy_cache(rot);
93  return *this;
94  }
95 
96  //! Create a rotation from a vector of 4 quaternion coefficients.
97  //! @note: use assume_normalized with care - inputting an unnormalized
98  //! vector would result in unexpected results if it is true
99  explicit Rotation3D(const VectorD<4> &v,
100  bool assume_normalized=false)
101  : v_(assume_normalized ? v : v.get_unit_vector()),
102  has_cache_(false) {}
103 
104  //! Create an invalid rotation
105  Rotation3D() : v_(0, 0, 0, 0), has_cache_(false) {}
106  //! Create a rotation from a quaternion
107  /** \throw ValueException if the rotation is not a unit vector.
108  */
109  Rotation3D(double a, double b, double c, double d)
110  : v_(a, b, c, d), has_cache_(false) {
112  v_.get_squared_magnitude(), 1.0,
113  "Attempting to construct a rotation from a "
114  << " non-quaternion value. The coefficient vector"
115  << " must have a length of 1. Got: " << a << " " << b << " " << c
116  << " " << d << " gives " << v_.get_squared_magnitude());
117  if (a < 0) {
118  // make them canonical
119  v_ = -v_;
120  }
121  }
122  ~Rotation3D(){}
123 
124 #ifndef IMP_DOXYGEN
125  Vector3D get_rotated_no_cache(const Vector3D &o) const {
126  IMP_USAGE_CHECK(get_is_valid(),
127  "Attempting to access uninitialized rotation");
128  return Vector3D(
129  (v_[0] * v_[0] + v_[1] * v_[1] - v_[2] * v_[2] - v_[3] * v_[3]) * o[0] +
130  2 * (v_[1] * v_[2] - v_[0] * v_[3]) * o[1] +
131  2 * (v_[1] * v_[3] + v_[0] * v_[2]) * o[2],
132  2 * (v_[1] * v_[2] + v_[0] * v_[3]) * o[0] +
133  (v_[0] * v_[0] - v_[1] * v_[1] + v_[2] * v_[2] - v_[3] * v_[3]) *
134  o[1] +
135  2 * (v_[2] * v_[3] - v_[0] * v_[1]) * o[2],
136  2 * (v_[1] * v_[3] - v_[0] * v_[2]) * o[0] +
137  2 * (v_[2] * v_[3] + v_[0] * v_[1]) * o[1] +
138  (v_[0] * v_[0] - v_[1] * v_[1] - v_[2] * v_[2] + v_[3] * v_[3]) *
139  o[2]);
140  }
141 
142  //! Get only the requested rotation coordinate of the vector
143  double get_rotated_one_coordinate_no_cache(const Vector3D &o,
144  unsigned int coord) const {
145  IMP_USAGE_CHECK(get_is_valid(),
146  "Attempting to apply uninitialized rotation");
147  switch (coord) {
148  case 0:
149  return (v_[0] * v_[0] + v_[1] * v_[1] - v_[2] * v_[2] - v_[3] * v_[3]) *
150  o[0] +
151  2 * (v_[1] * v_[2] - v_[0] * v_[3]) * o[1] +
152  2 * (v_[1] * v_[3] + v_[0] * v_[2]) * o[2];
153  break;
154  case 1:
155  return 2 * (v_[1] * v_[2] + v_[0] * v_[3]) * o[0] +
156  (v_[0] * v_[0] - v_[1] * v_[1] + v_[2] * v_[2] - v_[3] * v_[3]) *
157  o[1] +
158  2 * (v_[2] * v_[3] - v_[0] * v_[1]) * o[2];
159 
160  break;
161  case 2:
162  return 2 * (v_[1] * v_[3] - v_[0] * v_[2]) * o[0] +
163  2 * (v_[2] * v_[3] + v_[0] * v_[1]) * o[1] +
164  (v_[0] * v_[0] - v_[1] * v_[1] - v_[2] * v_[2] + v_[3] * v_[3]) *
165  o[2];
166  break;
167  default:
168  IMP_THROW("Out of range coordinate " << coord, IndexException);
169  }
170  }
171 #endif
172  //! Rotate a vector around the origin
173  Vector3D get_rotated(const Vector3D &o) const {
174  if (!has_cache_) fill_cache();
175  return Vector3D(o * matrix_[0], o * matrix_[1], o * matrix_[2]);
176  }
177 
178  //! Get only the requested rotation coordinate of the vector
180  unsigned int coord) const {
181  if (!has_cache_) fill_cache();
182  return o * matrix_[coord];
183  }
184 
185  //! Rotate a vector around the origin
186  Vector3D operator*(const Vector3D &v) const { return get_rotated(v); }
187  Vector3D get_rotation_matrix_row(int i) const {
188  IMP_USAGE_CHECK((i >= 0) && (i <= 2), "row index out of range");
189  if (!has_cache_) fill_cache();
190  return matrix_[i];
191  }
192  IMP_SHOWABLE_INLINE(Rotation3D,
193  { out << v_[0] << " " << v_[1] << " " << v_[2] << " " << v_[3]; });
194 
195  //! Return the rotation which undoes this rotation.
196  inline Rotation3D get_inverse() const {
197  IMP_USAGE_CHECK(get_is_valid(),
198  "Attempting to invert uninitialized rotation");
199  Rotation3D ret(v_[0], -v_[1], -v_[2], -v_[3]);
200  return ret;
201  }
202 
203  //! Return the quaternion so that it can be stored
204  /** Note that there is no guarantee on which of the two
205  equivalent quaternions is returned.
206  */
207  const Vector4D &get_quaternion() const {
208  IMP_USAGE_CHECK(get_is_valid(),
209  "Attempting to access uninitialized rotation");
210  return v_;
211  }
212 
213  //! Multiply two rotations
214  Rotation3D operator*(const Rotation3D &q) const {
215  IMP_USAGE_CHECK(get_is_valid(),
216  "Attempting to compose uninitialized rotation");
217  return compose(*this, q);
218  }
219 
220  //! Compute the rotation which when composed with r gives this
221  Rotation3D operator/(const Rotation3D &r) const {
222  IMP_USAGE_CHECK(get_is_valid(),
223  "Attempting to compose uninitialized rotation");
224  return compose(*this, r.get_inverse());
225  }
226 
227  const Rotation3D &operator/=(const Rotation3D &r) {
228  *this = *this / r;
229  return *this;
230  }
231 
232  //! Return the derivative of rotated vector wrt the ith quaternion element.
233  /** Given the rotation \f$x = R(q) v\f$, where \f$v\f$ is a vector,
234  \f$q=(q_0,q_1,q_2,q_3)\f$ is the quaternion of the rotation with
235  elements \f$q_i\f$, and \f$R(q)\f$ is the corresponding rotation matrix,
236  the function returns the derivative \f$\frac{d x}{d q_i}\f$.
237 
238  This function just returns a single column from get_gradient(), so it is
239  more efficient to call that function if all columns are needed.
240 
241  \param[in] v vector to be rotated by rotation \f$R(q)\f$
242  \param[in] projected project derivative onto tangent space to \f$q\f$.
243  Equivalent to differentiating wrt
244  \f$\frac{q_i}{\|q\|}\f$ instead of \f$q_i\f$.
245  */
246  Vector3D get_derivative(const Vector3D &v, unsigned int i,
247  bool projected = true) const;
248 
249  //! Return the gradient of rotated vector wrt the quaternion.
250  /** Given the rotation \f$x = R(q) v\f$, where \f$v\f$ is a vector,
251  \f$q\f$ is the quaternion of the rotation, and \f$R(q)\f$ is the
252  corresponding rotation matrix, the function returns the 3x4 matrix
253  \f$M = \nabla_q x\f$ with elements \f$M_{ij}=\frac{d x_i}{d q_j}\f$.
254 
255  \param[in] v vector to be rotated by rotation \f$R(q)\f$
256  \param[in] projected project gradient onto tangent space to \f$q\f$.
257  Equivalent to differentiating wrt
258  \f$\frac{q_i}{\|q\|}\f$ instead of \f$q_i\f$.
259  */
260  Eigen::MatrixXd get_gradient(
261  const Eigen::Vector3d &v, bool projected = true) const;
262 
263  /** Return true is the rotation is valid, false if
264  invalid or not initialized (e.g., only initialized by
265  the empty constructor)
266  */
267  bool get_is_valid() const {
268  return v_.get_squared_magnitude() > 0; // TODO: add that magnitude ~ 1?
269  }
270 };
271 
273 
274 
275 //! Get gradient of quaternion product with respect to first quaternion.
276 /** Given the rotation \f$R(p)\f$ followed by \f$R(q)\f$, where \f$p\f$ and
277  \f$q\f$ are quaternions, the quaternion of the composed rotation
278  \f$R(s)=R(q) R(p)\f$ can be expressed through the Hamilton product of the
279  two quaternions \f$s(q,p) = q p\f$. This function returns the matrix
280  \f$M = \nabla_q s(q, p)\f$ with elements \f$M_{ij}=\frac{d s_i}{d q_j}\f$.
281 
282  \param[in] q rotation corresponding to first quaternion
283  \param[in] p rotation corresponding to second quaternion
284  \param[in] projected project derivative onto tangent space to \f$q\f$.
285  Equivalent to differentiating wrt
286  \f$\frac{q_i}{\|q\|}\f$ instead of \f$q_i\f$.
287  */
288 IMPALGEBRAEXPORT Eigen::MatrixXd get_gradient_of_composed_with_respect_to_first(
289  const Rotation3D &q, const Rotation3D &p, bool projected = true);
290 
291 //! Get gradient of quaternion product with respect to second quaternion.
292 /** Given the rotation \f$R(p)\f$ followed by \f$R(q)\f$, where \f$p\f$ and
293  \f$q\f$ are quaternions, the quaternion of the composed rotation
294  \f$R(s)=R(q) R(p)\f$ can be expressed through the Hamilton product of the
295  two quaternions \f$s(q,p) = q p\f$. This function returns the matrix
296  \f$\nabla_p s(q, p)\f$ with elements \f$M_{ij}=\frac{d s_i}{d p_j}\f$.
297 
298  \param[in] q rotation corresponding to first quaternion
299  \param[in] p rotation corresponding to second quaternion
300  \param[in] projected project derivative onto tangent space to \f$p\f$.
301  Equivalent to differentiating wrt
302  \f$\frac{p_i}{\|p\|}\f$ instead of \f$p_i\f$.
303  */
304 IMPALGEBRAEXPORT Eigen::MatrixXd get_gradient_of_composed_with_respect_to_second(
305  const Rotation3D &q, const Rotation3D &p, bool projected = true);
306 
307 //! Return a rotation that does not do anything
308 /** \see Rotation3D */
309 inline Rotation3D get_identity_rotation_3d() { return Rotation3D(1, 0, 0, 0); }
310 
311 //! Return a distance between the two rotations
312 /** The distance runs between 0 and 1. More precisely,
313  the distance returned is distance between the two
314  quaternion vectors properly normalized, divided
315  by sqrt(2).
316 
317  A vector with distance d from the unit vector
318  represents a rotation of
319 
320  \f$ \theta= \cos^{-1}\left(1-\sqrt{2}d\right)\f$
321  \see Rotation3D
322 */
323 inline double get_distance(const Rotation3D &r0, const Rotation3D &r1) {
324  double dot =
325  (r0.get_quaternion() - r1.get_quaternion()).get_squared_magnitude();
326  double odot =
327  (r0.get_quaternion() + r1.get_quaternion()).get_squared_magnitude();
328  double ans = std::min(dot, odot);
329  // TODO: barak - added static for efficiency
330  static const double s2 = std::sqrt(2.0);
331  double ret = ans / s2;
332  return std::max(std::min(ret, 1.0), 0.0);
333 }
334 
335 //! Generate a Rotation3D object from a rotation around an axis
336 //! that is assumed to be normalized
337 /**
338  \param[in] axis_norm the normalized rotation axis passing through (0,0,0)
339  \param[in] angle the rotation angle in radians in the
340  clockwise direction
341  \note http://en.wikipedia.org/wiki/Rotation_matrix
342  \note www.euclideanspace.com/maths/geometry/rotations/conversions/
343  angleToQuaternion/index.htm
344  \see Rotation3D
345 */
346 inline Rotation3D
348 (const Vector3D &axis_norm, double angle)
349 {
350  IMP_USAGE_CHECK(axis_norm.get_magnitude() - 1.0 < 1e-6,
351  "expected normalized vector as axis of rotation");
352  double s = std::sin(angle / 2);
353  double a, b, c, d;
354  a = std::cos(angle / 2);
355  b = axis_norm[0] * s;
356  c = axis_norm[1] * s;
357  d = axis_norm[2] * s;
358  return Rotation3D(a, b, c, d);
359 }
360 
361 
362 //! Generate a Rotation3D object from a rotation around an axis
363 /**
364  \param[in] axis the rotation axis passes through (0,0,0)
365  \param[in] angle the rotation angle in radians in the
366  clockwise direction
367  \note http://en.wikipedia.org/wiki/Rotation_matrix
368  \note www.euclideanspace.com/maths/geometry/rotations/conversions/
369  angleToQuaternion/index.htm
370  \see Rotation3D
371 */
372 inline Rotation3D
374 (const Vector3D &axis, double angle)
375 {
376  // normalize the vector
377  Vector3D axis_norm = axis.get_unit_vector();
378  return get_rotation_about_normalized_axis(axis_norm, angle);
379 }
380 
381 //! Create a rotation from the first vector to the second one.
382 /** \see Rotation3D
383  */
384 IMPALGEBRAEXPORT Rotation3D
386 
387 //! Generate a Rotation3D object from a rotation matrix
388 /**
389  \see Rotation3D
390 */
391 IMPALGEBRAEXPORT Rotation3D
392  get_rotation_from_matrix(double m00, double m01, double m02, double m10,
393  double m11, double m12, double m20, double m21,
394  double m22);
395 
396 //! Generate a Rotation3D object from a rotation matrix
397 /**
398  \see Rotation3D
399 */
400 IMPALGEBRAEXPORT Rotation3D get_rotation_from_matrix(Eigen::Matrix3d m);
401 
402 //! Pick a rotation at random from all possible rotations
403 /** \see Rotation3D */
404 IMPALGEBRAEXPORT Rotation3D get_random_rotation_3d();
405 
406 //! Pick a rotation at random near the provided one
407 /** This method generates a rotation that is within the provided
408  distance of center.
409  \param[in] center The center of the rotational volume
410  \param[in] distance See
411  get_distance(const Rotation3D&,const Rotation3D&)
412  for a full definition.
413 
414  \note The cost of this operation increases as distance goes to 0.
415 
416  \see Rotation3D
417 */
418 IMPALGEBRAEXPORT Rotation3D
419  get_random_rotation_3d(const Rotation3D &center, double distance);
420 
421 //! Cover the space of rotations evenly
422 /** If you care about the distance between samples instead of the number
423  of samples, the "surface area" of the set of rotations is pi^2. If
424  you allocate each sample a volume of 4/3 pi d^3 (to space them d apart),
425  Then you want 3/4 pi/d^3 points.
426 
427  Creates at least num_points rotations.
428 */
429 IMPALGEBRAEXPORT Rotation3Ds
430  get_uniform_cover_rotations_3d(unsigned int num_points);
431 
432 //! Generates a nondegenerate set of Euler angles with a delta resolution
433 /**
434 \param[in] delta sample every delta angles in radians.
435  */
437  double delta);
438 
439 //! Compute a rotation from an unnormalized quaternion
440 /** \see Rotation3D */
442  VectorD<4> uv = v.get_unit_vector();
443  return Rotation3D(uv[0], uv[1], uv[2], uv[3]);
444 }
445 
446 /** \see Rotation3D
447  */
448 inline Rotation3D compose(const Rotation3D &a, const Rotation3D &b) {
449  return Rotation3D(a.v_[0] * b.v_[0] - a.v_[1] * b.v_[1] - a.v_[2] * b.v_[2] -
450  a.v_[3] * b.v_[3],
451  a.v_[0] * b.v_[1] + a.v_[1] * b.v_[0] + a.v_[2] * b.v_[3] -
452  a.v_[3] * b.v_[2],
453  a.v_[0] * b.v_[2] - a.v_[1] * b.v_[3] + a.v_[2] * b.v_[0] +
454  a.v_[3] * b.v_[1],
455  a.v_[0] * b.v_[3] + a.v_[1] * b.v_[2] - a.v_[2] * b.v_[1] +
456  a.v_[3] * b.v_[0]);
457 }
458 
459 /** \name Euler Angles
460  There are many conventions for how to define Euler angles, based on choices
461  of which of the x,y,z axis to use in what order and whether the rotation
462  axis is in the body frame (and hence affected by previous rotations) or in
463  in a fixed frame. See
464  http://en.wikipedia.org/wiki/Conversion_between_quaternions_and_Euler_angles
465  for a general description.
466 
467  - All Euler angles are specified in radians.
468  - Only x-y-z order is currently supported.
469  - To convert Euler angles in a different order, one can compose a Rotation3D
470  from three rotations using get_rotation_about_axis function.
471  @{
472 */
473 
474 //! Initialize a rotation in x-y-z order from three angles
475 /** \param[in] xr Rotation around the X axis in radians
476  \param[in] yr Rotation around the Y axis in radians
477  \param[in] zr Rotation around the Z axis in radians
478  \note The three rotations are represented in the original (fixed)
479  coordinate frame.
480  \see Rotation3D
481  \see FixedXYZ
482 */
483 IMPALGEBRAEXPORT Rotation3D
484  get_rotation_from_fixed_xyz(double xr, double yr, double zr);
485 
486 //! Initialize a rotation from Euler angles
487 /**
488  \param[in] phi Rotation around the Z axis in radians
489  \param[in] theta Rotation around the X axis in radians
490  \param[in] psi Rotation around the Z axis in radians
491  \note The first rotation is by an angle phi about the z-axis.
492  The second rotation is by an angle theta in [0,pi] about the
493  former x-axis , and the third rotation is by an angle psi
494  about the former z-axis.
495  \see Rotation3D
496 */
497 IMPALGEBRAEXPORT Rotation3D
498  get_rotation_from_fixed_zxz(double phi, double theta, double psi);
499 
500 //! Generate a rotation object from Euler Angles
501 /** \note The first rotation is by an angle about the z-axis.
502  The second rotation is by an angle about the new y-axis.
503  The third rotation is by an angle about the new z-axis.
504  \param[in] Rot First Euler angle (radians) defining the rotation (Z axis)
505  \param[in] Tilt Second Euler angle (radians) defining the rotation (Y axis)
506  \param[in] Psi Third Euler angle (radians) defining the rotation (Z axis)
507  \see Rotation3D
508 */
509 IMPALGEBRAEXPORT Rotation3D
510  get_rotation_from_fixed_zyz(double Rot, double Tilt, double Psi);
511 
512 //! A simple class for returning XYZ Euler angles
513 class FixedXYZ : public GeometricPrimitiveD<3> {
514  double v_[3];
515 
516  public:
517  FixedXYZ() {}
518  FixedXYZ(double x, double y, double z) {
519  v_[0] = x;
520  v_[1] = y;
521  v_[2] = z;
522  }
523  double get_x() const { return v_[0]; }
524  double get_y() const { return v_[1]; }
525  double get_z() const { return v_[2]; }
527  { out << v_[0] << " " << v_[1] << " " << v_[2]; });
528 };
529 
531 
532 //! The inverse of rotation_from_fixed_xyz()
533 /**
534  \see rotation_from_fixed_xyz()
535  \see Rotation3D
536  \see FixesXYZ
537 */
538 IMPALGEBRAEXPORT FixedXYZ get_fixed_xyz_from_rotation(const Rotation3D &r);
539 
540 /** @}*/
541 
542 //! Interpolate between two rotations
543 /** It f ==0, return b, if f==1 return a.
544  \see Rotation3D */
546  double f) {
547  VectorD<4> bq = b.get_quaternion(), aq = a.get_quaternion();
548  if (bq * aq < 0) bq = -bq;
549  return Rotation3D(f * aq + (1 - f) * bq);
550 }
551 
552 /** Return the rotation which takes the native x and y axes to the
553  given x and y axes.
554  The two axes must be perpendicular unit vectors.
555 */
556 IMPALGEBRAEXPORT Rotation3D
557  get_rotation_from_x_y_axes(const Vector3D &x, const Vector3D &y);
558 
559 //! Decompose a Rotation3D object into a rotation around an axis
560 /** For all identity rotations, returns the axis [1,0,0] and the angle 0.0.
561 
562  \note http://en.wikipedia.org/wiki/Rotation_matrix
563  \note www.euclideanspace.com/maths/geometry/rotations/conversions/
564  angleToQuaternion/index.htm
565  \see Rotation3D
566 
567  @return axis direction and rotation about the axis in Radians
568 */
569 IMPALGEBRAEXPORT std::pair<Vector3D, double> get_axis_and_angle(
570  const Rotation3D &rot);
571 
572 typedef std::pair<Vector3D, double> AxisAnglePair;
573 #ifndef IMP_DOXYGEN
574 typedef Vector<AxisAnglePair> AxisAnglePairs;
575 #endif
576 
577 IMPALGEBRA_END_NAMESPACE
578 #endif /* IMPALGEBRA_ROTATION_3D_H */
Vector3D get_rotated(const Vector3D &o) const
Rotate a vector around the origin.
Definition: Rotation3D.h:173
Rotation3D get_rotation_about_normalized_axis(const Vector3D &axis_norm, double angle)
Definition: Rotation3D.h:348
Rotation3D(const Rotation3D &rot)
Rotation3D copy constructor.
Definition: Rotation3D.h:86
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:105
#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:221
A simple class for returning XYZ Euler angles.
Definition: Rotation3D.h:513
Rotation3D(const VectorD< 4 > &v, bool assume_normalized=false)
Definition: Rotation3D.h:99
Vector3D operator*(const Vector3D &v) const
Rotate a vector around the origin.
Definition: Rotation3D.h:186
Rotation3D compose(const Rotation3D &a, const Rotation3D &b)
Definition: Rotation3D.h:448
double get_rotated_one_coordinate(const Vector3D &o, unsigned int coord) const
Get only the requested rotation coordinate of the vector.
Definition: Rotation3D.h:179
VT get_unit_vector(VT vt)
Returns a unit vector pointing at the same direction as this vector.
Definition: VectorBaseD.h:229
Eigen::MatrixXd get_gradient_of_composed_with_respect_to_second(const Rotation3D &q, const Rotation3D &p, bool projected=true)
Get gradient of quaternion product with respect to second quaternion.
bool get_is_valid() const
Definition: Rotation3D.h:267
const Vector4D & get_quaternion() const
Return the quaternion so that it can be stored.
Definition: Rotation3D.h:207
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:374
#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:196
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:323
Rotation3D get_interpolated(const Rotation3D &a, const Rotation3D &b, double f)
Interpolate between two rotations.
Definition: Rotation3D.h:545
#define IMP_NO_SWIG(x)
Hide the line when SWIG is compiled or parses it.
Definition: swig_macros.h:18
Rotation3D get_rotation_from_vector4d(const VectorD< 4 > &v)
Compute a rotation from an unnormalized quaternion.
Definition: Rotation3D.h:441
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:214
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:109
VectorD< 3 > Vector3D
Definition: VectorD.h:395
Rotation3D get_identity_rotation_3d()
Return a rotation that does not do anything.
Definition: Rotation3D.h:309
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
Eigen::MatrixXd get_gradient_of_composed_with_respect_to_first(const Rotation3D &q, const Rotation3D &p, bool projected=true)
Get gradient of quaternion product with respect to first quaternion.
Logging and error reporting support.
Rotation3D get_rotation_from_fixed_zxz(double phi, double theta, double psi)
Initialize a rotation from Euler angles.
Rotation3D get_rotation_from_matrix(Eigen::Matrix3d m)
Generate a Rotation3D object from a rotation matrix.
IMP::Vector< Rotation3D > Rotation3Ds
Definition: Rotation3D.h:272