IMP logo
IMP Reference Guide  2.20.0
The Integrative Modeling Platform
Transformation3D.h
Go to the documentation of this file.
1 /**
2  * \file IMP/algebra/Transformation3D.h
3  * \brief Simple 3D transformation class.
4  *
5  * Copyright 2007-2022 IMP Inventors. All rights reserved.
6  *
7  */
8 
9 #ifndef IMPALGEBRA_TRANSFORMATION_3D_H
10 #define IMPALGEBRA_TRANSFORMATION_3D_H
11 
12 #include <IMP/algebra/algebra_config.h>
13 #include "Vector3D.h"
14 #include "Line3D.h"
15 #include "Rotation3D.h"
16 #include "BoundingBoxD.h"
17 #include "GeometricPrimitiveD.h"
18 #include <cereal/access.hpp>
19 
20 IMPALGEBRA_BEGIN_NAMESPACE
21 
22 #if !defined(IMP_DOXYGEN) && !defined(SWIG)
23 class Transformation3D;
24 Transformation3D compose(const Transformation3D &a, const Transformation3D &b);
25 #endif
26 
27 typedef std::pair<Vector4D, Vector3D> Transformation3DAdjoint;
28 typedef std::pair<Vector3D, Transformation3DAdjoint> TransformedVector3DAdjoint;
29 typedef std::pair<Transformation3DAdjoint, Transformation3DAdjoint>
30  ComposeTransformation3DAdjoint;
31 
32 //! Simple 3D transformation class
33 /** The rotation is applied first, and then the point is translated.
34  \see IMP::core::Transform
35  \geometry
36 */
37 class IMPALGEBRAEXPORT Transformation3D : public GeometricPrimitiveD<3> {
38  public:
39  IMP_CXX11_DEFAULT_COPY_CONSTRUCTOR(Transformation3D);
40  //! Default construct (makes an invalid transformation)
42  //! Basic constructor
43  Transformation3D(const Rotation3D &r, const Vector3D &t = Vector3D(0, 0, 0))
44  : trans_(t), rot_(r) {}
45  //! Construct a transformation with an identity rotation.
47  : trans_(t), rot_(get_identity_rotation_3d()) {}
49  //! Transform
50  Vector3D get_transformed(const Vector3D &o) const {
51  return rot_.get_rotated(o) + trans_;
52  }
53 
54 #ifndef SWIG
55  //! Get adjoint of inputs to `get_transformed` from adjoint of output
56  /** Compute the adjoint (reverse-mode sensitivity) of input vector
57  to `get_transformed` and this transformation from the adjoint of the
58  output vector.
59  */
60  void get_transformed_adjoint(const Vector3D &v, const Vector3D &Dw,
61  Vector3D *Dv, Transformation3DAdjoint *DT) const;
62 #endif
63 
64  //! Get adjoint of inputs to `get_transformed` from adjoint of output
65  /** Compute the adjoint (reverse-mode sensitivity) of input vector
66  to `get_transformed` and this transformation from the adjoint of the
67  output vector.
68  */
69  TransformedVector3DAdjoint
70  get_transformed_adjoint(const Vector3D &v, const Vector3D &Dw) const;
71 
72  //! Apply transformation (rotate and then translate)
73  Vector3D operator*(const Vector3D &v) const { return get_transformed(v); }
74  /** Compose two rigid transformation such that for any vector v
75  (rt1*rt2)*v = rt1*(rt2*v) */
77  return compose(*this, tr);
78  }
79  const Transformation3D &operator*=(const Transformation3D &o) {
80  *this = compose(*this, o);
81  return *this;
82  }
83  //! Compute the transformation which, when composed with b, gives *this.
84  /** That is a(x)== d(b(x)) for all x.
85 
86  For consistency, this should probably have a nice name, but
87  I don't know what name to give it.
88  */
90  Transformation3D ret = compose(*this, b.get_inverse());
91  return ret;
92  }
93  const Transformation3D &operator/=(const Transformation3D &o) {
94  *this = *this / o;
95  return *this;
96  }
97 
98  //! Return the rotation associated with this transformation
99  const Rotation3D &get_rotation() const { return rot_; }
100 
101  //! Return the translation vector associated with this transformation
102  const Vector3D &get_translation() const { return trans_; }
103 
105  rot_.show(out);
106  out << " || " << trans_;
107  });
108  Transformation3D get_inverse() const;
109 
110  /** @return true if the 3D transformation is valid; false if the
111  transformation was initialized only with the empty constructor,
112  or it was initialized with an invalid rotation.
113  */
114  bool get_is_valid() const {
115  return rot_.get_is_valid();
116  }
117 
118 private:
119  Vector3D trans_; // translation
120  Rotation3D rot_; // rotation
121 
122  friend class cereal::access;
123 
124  template<class Archive> void serialize(Archive &ar) {
125  ar(trans_, rot_);
126  }
127 
128 };
129 
131 
132 //! Return a transformation that does not do anything
133 /** \see Transformation3D */
135  return Transformation3D(get_identity_rotation_3d(), Vector3D(0.0, 0.0, 0.0));
136 }
137 
138 //! Generate a Transformation3D object from a rotation around a point
139 /** Rotate about a point rather than the origin.
140  \param[in] point Center to rotate about
141  \param[in] rotation The rotation to perform
142 
143  \see Transformation3D
144 */
146  const Rotation3D &rotation) {
147  return Transformation3D(rotation, (rotation * (-point) + point));
148 }
149 
150 //! Compose two transformations
151 /** For any vector v (a*b)*v = a*(b*v).
152  \see Transformation3D
153  */
155  const Transformation3D &b) {
157  "composing an invalid transformation");
160 }
161 
162 #ifndef SWIG
163 //! Get adjoint of inputs to `compose` from adjoint of output
164 /** Compute the adjoint (reverse-mode sensitivity) of input transformations
165  to `compose` from the adjoint of the output transformation.
166  */
167 IMPALGEBRAEXPORT void
168 compose_adjoint(const Transformation3D &TA, const Transformation3D &TB,
169  const Transformation3DAdjoint &DTC,
170  Transformation3DAdjoint *DTA, Transformation3DAdjoint *DTB);
171 #endif
172 
173 //! Get adjoint of inputs to `compose` from adjoint of output
174 /** Compute the adjoint (reverse-mode sensitivity) of input transformations
175  to `compose` from the adjoint of the output transformation.
176  */
177 IMPALGEBRAEXPORT ComposeTransformation3DAdjoint
178 compose_adjoint(const Transformation3D &TA, const Transformation3D &TB,
179  const Transformation3DAdjoint &DTC);
180 
181 class Transformation2D;
182 
183 //! Build a 3D transformation from a 2D one.
184 /**
185  \note The 3D transformation is built with the 2D rotation becoming a rotation
186  around the z axis.
187  **/
188 IMPALGEBRAEXPORT Transformation3D
189  get_transformation_3d(const Transformation2D &t2d);
190 
191 //! Get a local transformation
192 /**
193  \note randomly select an axis that passes through the input point
194  and rotate around it
195  \param[in] origin the origin of the rotation
196  \param[in] max_translation default value is 5
197  \param[in] max_angle_in_rad default value is 15 degree in radians
198  **/
199 IMPALGEBRAEXPORT Transformation3D
201  double max_translation = 5.,
202  double max_angle_in_rad = 0.26);
203 
204 //! Return a bounding box containing the transformed box
206  const Transformation3D &tr) {
207  BoundingBoxD<3> nbb;
208  for (unsigned int i = 0; i < 2; ++i) {
209  for (unsigned int j = 0; j < 2; ++j) {
210  for (unsigned int k = 0; k < 2; ++k) {
211  algebra::Vector3D v(bb.get_corner(i)[0], bb.get_corner(j)[1],
212  bb.get_corner(k)[2]);
213  nbb += tr.get_transformed(v);
214  }
215  }
216  }
217  return nbb;
218 }
219 
221  const Transformation3D &tr) {
222  return Line3D(tr.get_rotation().get_rotated(l.get_direction()),
223  tr.get_transformed(l.get_point_on_line()));
224 }
225 
226 IMPALGEBRA_END_NAMESPACE
227 
228 #endif /* IMPALGEBRA_TRANSFORMATION_3D_H */
Base class for geometric types.
Simple 3D transformation class.
Simple implementation of lines in 3D.
Definition: Line3D.h:29
#define IMP_SHOWABLE_INLINE(Name, how_to_show)
Declare the methods needed by an object that can be printed.
const VectorD< D > & get_corner(unsigned int i) const
For 0 return lower corner and for 1, the upper corner.
Definition: BoundingBoxD.h:140
Simple implementation of lines in 3D.
Rotation2D compose(const Rotation2D &a, const Rotation2D &b)
Compose two rotations a and b.
Definition: Rotation2D.h:121
Vector3D get_point_on_line() const
Get the point on the line closest to the origin.
Definition: Line3D.h:48
Transformation3D get_rotation_about_point(const Vector3D &point, const Rotation3D &rotation)
Generate a Transformation3D object from a rotation around a point.
Transformation3D()
Default construct (makes an invalid transformation)
const Rotation3D & get_rotation() const
Return the rotation associated with this transformation.
#define IMP_VALUES(Name, PluralName)
Define the type for storing sets of values.
Definition: value_macros.h:23
Base class for geometric types.
A bounding box in D dimensions.
Transformation3D operator/(const Transformation3D &b) const
Compute the transformation which, when composed with b, gives *this.
Vector3D get_transformed(const Vector3D &o) const
Transform.
Transformation3D compose(const Transformation3D &a, const Transformation3D &b)
Compose two transformations.
Simple 3D rotation class.
3D rotation class.
Definition: Rotation3D.h:52
Transformation3D get_identity_transformation_3d()
Return a transformation that does not do anything.
Transformation3D operator*(const Transformation3D &tr) const
Transformation3D get_transformation_3d(const Transformation2D &t2d)
Build a 3D transformation from a 2D one.
Vector3D operator*(const Vector3D &v) const
Apply transformation (rotate and then translate)
Transformation3D(const Vector3D &t)
Construct a transformation with an identity rotation.
const Vector3D & get_direction() const
Get the unit vector in the direction of the line.
Definition: Line3D.h:45
VectorD< 3 > Vector3D
Definition: VectorD.h:425
Rotation3D get_identity_rotation_3d()
Return a rotation that does not do anything.
Definition: Rotation3D.h:351
Simple 3D vector class.
ComposeTransformation3DAdjoint compose_adjoint(const Transformation3D &TA, const Transformation3D &TB, const Transformation3DAdjoint &DTC)
Get adjoint of inputs to compose from adjoint of output.
#define IMP_USAGE_CHECK(expr, message)
A runtime test for incorrect usage of a class or method.
Definition: check_macros.h:168
Transformation3D(const Rotation3D &r, const Vector3D &t=Vector3D(0, 0, 0))
Basic constructor.
DensityMap * get_transformed(const DensityMap *input, const algebra::Transformation3D &tr, double threshold)
Return a new density map containing a rotated version of the old one.
const Vector3D & get_translation() const
Return the translation vector associated with this transformation.
Transformation3D get_random_local_transformation(Vector3D origin, double max_translation=5., double max_angle_in_rad=0.26)
Get a local transformation.