HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
rotation.h
Go to the documentation of this file.
1 //
2 // Copyright 2016 Pixar
3 //
4 // Licensed under the Apache License, Version 2.0 (the "Apache License")
5 // with the following modification; you may not use this file except in
6 // compliance with the Apache License and the following modification to it:
7 // Section 6. Trademarks. is deleted and replaced with:
8 //
9 // 6. Trademarks. This License does not grant permission to use the trade
10 // names, trademarks, service marks, or product names of the Licensor
11 // and its affiliates, except as required to comply with Section 4(c) of
12 // the License and to reproduce the content of the NOTICE file.
13 //
14 // You may obtain a copy of the Apache License at
15 //
16 // http://www.apache.org/licenses/LICENSE-2.0
17 //
18 // Unless required by applicable law or agreed to in writing, software
19 // distributed under the Apache License with the above modification is
20 // distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
21 // KIND, either express or implied. See the Apache License for the specific
22 // language governing permissions and limitations under the Apache License.
23 //
24 #ifndef PXR_BASE_GF_ROTATION_H
25 #define PXR_BASE_GF_ROTATION_H
26 
27 /// \file gf/rotation.h
28 /// \ingroup group_gf_LinearAlgebra
29 
30 #include "pxr/pxr.h"
31 #include "pxr/base/gf/quaternion.h"
32 #include "pxr/base/gf/quatd.h"
33 #include "pxr/base/gf/matrix4d.h"
34 #include "pxr/base/gf/vec3d.h"
35 #include "pxr/base/gf/vec3f.h"
36 #include "pxr/base/gf/api.h"
37 #include "pxr/base/tf/hash.h"
38 
39 #include <iosfwd>
40 
42 
43 /// \class GfRotation
44 /// \ingroup group_gf_LinearAlgebra
45 ///
46 /// Basic type: 3-space rotation specification.
47 ///
48 /// This class represents a rotation in 3-space. This stores an axis as a
49 /// normalized vector of 3 \c doubles and an angle in degrees (as a double).
50 /// Rotations follow the right-hand rule: a positive rotation about an axis
51 /// vector appears counter-clockwise when looking from the end of the vector
52 /// toward the origin.
53 ///
54 class GfRotation {
55 
56  public:
57 
58  /// The default constructor leaves the rotation undefined.
60  }
61 
62  /// This constructor initializes the rotation to be \p angle
63  /// degrees about \p axis.
64  GfRotation(const GfVec3d &axis, double angle) {
65  SetAxisAngle(axis, angle);
66  }
67 
68  /// This constructor initializes the rotation from a quaternion.
69  GfRotation(const GfQuaternion &quaternion) {
70  SetQuaternion(quaternion);
71  }
72 
73  /// This constructor initializes the rotation from a quaternion. Note that
74  /// this constructor accepts GfQuatf and GfQuath since they implicitly
75  /// convert to GfQuatd.
76  GfRotation(const GfQuatd &quat) { SetQuat(quat); }
77 
78  /// This constructor initializes the rotation to one that brings
79  /// the \p rotateFrom vector to align with \p rotateTo. The passed
80  /// vectors need not be unit length.
81  GF_API
82  GfRotation(const GfVec3d &rotateFrom, const GfVec3d &rotateTo) {
83  SetRotateInto(rotateFrom, rotateTo);
84  }
85 
86  /// Sets the rotation to be \p angle degrees about \p axis.
87  GfRotation & SetAxisAngle(const GfVec3d &axis, double angle) {
88  _axis = axis;
89  _angle = angle;
90  if (!GfIsClose(_axis * _axis, 1.0, 1e-10))
91  _axis.Normalize();
92  return *this;
93  }
94 
95  /// Sets the rotation from a quaternion. Note that this method accepts
96  /// GfQuatf and GfQuath since they implicitly convert to GfQuatd.
97  GF_API
98  GfRotation & SetQuat(const GfQuatd &quat);
99 
100  /// Sets the rotation from a quaternion.
102  return SetQuat(GfQuatd(quat.GetReal(), quat.GetImaginary()));
103  }
104 
105  /// Sets the rotation to one that brings the \p rotateFrom vector
106  /// to align with \p rotateTo. The passed vectors need not be unit
107  /// length.
108  GF_API
109  GfRotation & SetRotateInto(const GfVec3d &rotateFrom,
110  const GfVec3d &rotateTo);
111 
112  /// Sets the rotation to an identity rotation.
113  /// (This is chosen to be 0 degrees around the positive X axis.)
115  _axis.Set(1.0, 0.0, 0.0);
116  _angle = 0.0;
117  return *this;
118  }
119 
120  /// Returns the axis of rotation.
121  const GfVec3d & GetAxis() const {
122  return _axis;
123  }
124 
125  /// Returns the rotation angle in degrees.
126  double GetAngle() const {
127  return _angle;
128  }
129 
130  /// Returns the rotation expressed as a quaternion.
132  auto quat = GetQuat();
133  return GfQuaternion(quat.GetReal(), quat.GetImaginary());
134  }
135 
136  /// Returns the rotation expressed as a quaternion.
137  GF_API
138  GfQuatd GetQuat() const;
139 
140  /// Returns the inverse of this rotation.
142  return GfRotation(_axis, -_angle);
143  }
144 
145  /// Decompose rotation about 3 orthogonal axes.
146  /// If the axes are not orthogonal, warnings will be spewed.
147  GF_API
148  GfVec3d Decompose( const GfVec3d &axis0,
149  const GfVec3d &axis1,
150  const GfVec3d &axis2 ) const;
151 
152  // Full-featured method to Decompose a rotation matrix into Cardarian
153  // angles.
154  // Axes have must be normalized. If useHint is specified
155  // then the current values stored within thetaTw, thetaFB, thetaLR,
156  // and thetaSw will be treated as hint and used to help choose
157  // an equivalent rotation that is as close as possible to the hints.
158  //
159  // One can use this routine to generate any combination of the three
160  // angles by passing in nullptr for the angle that is to be omitted.
161  //
162  // Passing in valid pointers for all four angles will decompose into
163  // Tw, FB, and LR but allows Sw to be used for best matching of hint
164  // values. It also allows an swShift value to be passed in as a
165  // Sw that is applied after the rotation matrix to get a best fit rotation
166  // in four angles.
167  //
168  // Angles are in radians.
169  //
170  // Specify \p handedness as -1.0 or 1.0, same as for MultiRotate.
171  //
172  // NOTE:
173  // Geppetto math function Originally brought over to extMover
174  // from //depot/main/tools/src/menv/lib/gpt/util.h [10/16/06]
175  // And moved into GfRotation[12/1/08]. Updated for any
176  // combination of three angles [12/1/11].
177  //
178  GF_API
179  static void DecomposeRotation(const GfMatrix4d &rot,
180  const GfVec3d &TwAxis,
181  const GfVec3d &FBAxis,
182  const GfVec3d &LRAxis,
183  double handedness,
184  double *thetaTw,
185  double *thetaFB,
186  double *thetaLR,
187  double *thetaSw = nullptr,
188  bool useHint=false,
189  const double *swShift=nullptr);
190 
191  // This function projects the vectors \p v1 and \p v2 onto the plane
192  // normal to \p axis, and then returns the rotation about \p axis that
193  // brings \p v1 onto \p v2.
194  GF_API
196  const GfVec3d &v2,
197  const GfVec3d &axis);
198 
199  /// Replace the hint angles with the closest rotation of the given
200  /// rotation to the hint.
201  ///
202  /// Each angle in the rotation will be within Pi of the corresponding
203  /// hint angle and the sum of the differences with the hint will
204  /// be minimized. If a given rotation value is null then that angle will
205  /// be treated as 0.0 and ignored in the calculations.
206  ///
207  /// All angles are in radians. The rotation order is Tw/FB/LR/Sw.
208  GF_API
209  static void MatchClosestEulerRotation(
210  double targetTw, double targetFB, double targetLR, double targetSw,
211  double *thetaTw, double *thetaFB, double *thetaLR, double *thetaSw);
212 
213  /// Transforms row vector \p vec by the rotation, returning the result.
214  GF_API
215  GfVec3f TransformDir( const GfVec3f &vec ) const;
216 
217  /// \overload
218  GF_API
219  GfVec3d TransformDir( const GfVec3d &vec ) const;
220 
221  /// Hash.
222  friend inline size_t hash_value(const GfRotation &r) {
223  return TfHash::Combine(r._axis, r._angle);
224  }
225 
226  /// Component-wise rotation equality test. The axes and angles must match
227  /// exactly for rotations to be considered equal. (To compare equality of
228  /// the actual rotations, you can convert both to quaternions and test the
229  /// results for equality.)
230  bool operator ==(const GfRotation &r) const {
231  return (_axis == r._axis &&
232  _angle == r._angle);
233  }
234 
235  /// Component-wise rotation inequality test. The axes and angles must
236  /// match exactly for rotations to be considered equal. (To compare
237  /// equality of the actual rotations, you can convert both to quaternions
238  /// and test the results for equality.)
239  bool operator !=(const GfRotation &r) const {
240  return ! (*this == r);
241  }
242 
243  /// Post-multiplies rotation \p r into this rotation.
244  GF_API
246 
247  /// Scales rotation angle by multiplying by \p scale.
249  _angle *= scale;
250  return *this;
251  }
252 
253  /// Scales rotation angle by dividing by \p scale.
255  _angle /= scale;
256  return *this;
257  }
258 
259  /// Returns composite rotation of rotations \p r1 and \p r2.
260  friend GfRotation operator *(const GfRotation &r1,
261  const GfRotation &r2) {
262  GfRotation r = r1;
263  return r *= r2;
264  }
265 
266  /// Returns a rotation equivalent to \p r with its angle multiplied
267  /// by \p scale.
268  friend GfRotation operator *(const GfRotation &r, double scale) {
269  GfRotation rTmp = r;
270  return rTmp *= scale;
271  }
272 
273  /// Returns a rotation equivalent to \p r with its angle multiplied
274  /// by \p scale.
275  friend GfRotation operator *(double scale, const GfRotation &r) {
276  return (r * scale);
277  }
278 
279  /// Returns a rotation equivalent to \p r with its angle divided
280  /// by \p scale.
281  friend GfRotation operator /(const GfRotation &r, double scale) {
282  GfRotation rTmp = r;
283  return rTmp /= scale;
284  }
285 
286  private:
287  /// Axis storage.
288  /// This axis is normalized to unit length whenever it is set.
289  GfVec3d _axis;
290  /// Angle storage (represented in degrees).
291  double _angle;
292 };
293 
294 /// Output a GfRotation using the format [(x y z) a].
295 /// \ingroup group_gf_DebuggingOutput
296 GF_API std::ostream& operator<<(std::ostream&, const GfRotation&);
297 
299 
300 #endif // PXR_BASE_GF_ROTATION_H
GF_API GfVec3f TransformDir(const GfVec3f &vec) const
Transforms row vector vec by the rotation, returning the result.
GfRotation & SetAxisAngle(const GfVec3d &axis, double angle)
Sets the rotation to be angle degrees about axis.
Definition: rotation.h:87
GfRotation GetInverse() const
Returns the inverse of this rotation.
Definition: rotation.h:141
bool operator!=(const GfRotation &r) const
Definition: rotation.h:239
SIM_API const UT_StringHolder angle
GF_API GfQuatd GetQuat() const
Returns the rotation expressed as a quaternion.
GfRotation(const GfQuatd &quat)
Definition: rotation.h:76
GfRotation(const GfQuaternion &quaternion)
This constructor initializes the rotation from a quaternion.
Definition: rotation.h:69
friend size_t hash_value(const GfRotation &r)
Hash.
Definition: rotation.h:222
GA_API const UT_StringHolder rot
double GetReal() const
Returns the real part of the quaternion.
Definition: quaternion.h:84
Definition: vec3f.h:62
GF_API GfRotation(const GfVec3d &rotateFrom, const GfVec3d &rotateTo)
Definition: rotation.h:82
GF_API GfRotation & SetQuat(const GfQuatd &quat)
GLfloat GLfloat GLfloat v2
Definition: glcorearb.h:818
friend GfRotation operator*(const GfRotation &r1, const GfRotation &r2)
Returns composite rotation of rotations r1 and r2.
Definition: rotation.h:260
GA_API const UT_StringHolder scale
GfRotation()
The default constructor leaves the rotation undefined.
Definition: rotation.h:59
GF_API GfRotation & SetRotateInto(const GfVec3d &rotateFrom, const GfVec3d &rotateTo)
GfRotation & SetQuaternion(const GfQuaternion &quat)
Sets the rotation from a quaternion.
Definition: rotation.h:101
GF_API std::ostream & operator<<(std::ostream &, const GfRotation &)
GfRotation & SetIdentity()
Definition: rotation.h:114
GfRotation & operator/=(double scale)
Scales rotation angle by dividing by scale.
Definition: rotation.h:254
PXR_NAMESPACE_OPEN_SCOPE bool GfIsClose(double a, double b, double epsilon)
Definition: math.h:42
GfQuaternion GetQuaternion() const
Returns the rotation expressed as a quaternion.
Definition: rotation.h:131
static GF_API void DecomposeRotation(const GfMatrix4d &rot, const GfVec3d &TwAxis, const GfVec3d &FBAxis, const GfVec3d &LRAxis, double handedness, double *thetaTw, double *thetaFB, double *thetaLR, double *thetaSw=nullptr, bool useHint=false, const double *swShift=nullptr)
GF_API GfRotation & operator*=(const GfRotation &r)
Post-multiplies rotation r into this rotation.
GfRotation(const GfVec3d &axis, double angle)
Definition: rotation.h:64
friend GfRotation operator/(const GfRotation &r, double scale)
Definition: rotation.h:281
static size_t Combine(Args &&...args)
Produce a hash code by combining the hash codes of several objects.
Definition: hash.h:519
PXR_NAMESPACE_CLOSE_SCOPE PXR_NAMESPACE_OPEN_SCOPE
Definition: path.h:1441
GfVec3d & Set(double s0, double s1, double s2)
Set all elements with passed arguments.
Definition: vec3d.h:129
bool operator==(const GfRotation &r) const
Definition: rotation.h:230
Definition: vec3d.h:62
const GfVec3d & GetAxis() const
Returns the axis of rotation.
Definition: rotation.h:121
GLfloat GLfloat v1
Definition: glcorearb.h:817
#define PXR_NAMESPACE_CLOSE_SCOPE
Definition: pxr.h:91
GF_API GfVec3d Decompose(const GfVec3d &axis0, const GfVec3d &axis1, const GfVec3d &axis2) const
static GF_API void MatchClosestEulerRotation(double targetTw, double targetFB, double targetLR, double targetSw, double *thetaTw, double *thetaFB, double *thetaLR, double *thetaSw)
GLboolean r
Definition: glcorearb.h:1222
Definition: quatd.h:59
static GF_API GfRotation RotateOntoProjected(const GfVec3d &v1, const GfVec3d &v2, const GfVec3d &axis)
const GfVec3d & GetImaginary() const
Returns the imaginary part of the quaternion.
Definition: quaternion.h:89
#define GF_API
Definition: api.h:40
double GetAngle() const
Returns the rotation angle in degrees.
Definition: rotation.h:126