1 /*=========================================================================
2 
3   Program:   Visualization Toolkit
4   Module:    vtkTransform.h
5 
6   Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
7   All rights reserved.
8   See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
9 
10      This software is distributed WITHOUT ANY WARRANTY; without even
11      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12      PURPOSE.  See the above copyright notice for more information.
13 
14 =========================================================================*/
15 
16 /**
17  * @class   vtkTransform
18  * @brief   describes linear transformations via a 4x4 matrix
19  *
20  * A vtkTransform can be used to describe the full range of linear (also
21  * known as affine) coordinate transformations in three dimensions,
22  * which are internally represented as a 4x4 homogeneous transformation
23  * matrix.  When you create a new vtkTransform, it is always initialized
24  * to the identity transformation.
25  * <P>The SetInput() method allows you to set another transform,
26  * instead of the identity transform, to be the base transformation.
27  * There is a pipeline mechanism to ensure that when the input is
28  * modified, the current transformation will be updated accordingly.
29  * This pipeline mechanism is also supported by the Concatenate() method.
30  * <P>Most of the methods for manipulating this transformation,
31  * e.g. Translate, Rotate, and Concatenate, can operate in either
32  * PreMultiply (the default) or PostMultiply mode.  In PreMultiply
33  * mode, the translation, concatenation, etc. will occur before any
34  * transformations which are represented by the current matrix.  In
35  * PostMultiply mode, the additional transformation will occur after
36  * any transformations represented by the current matrix.
37  * <P>This class performs all of its operations in a right handed
38  * coordinate system with right handed rotations. Some other graphics
39  * libraries use left handed coordinate systems and rotations.
40  * @sa
41  * vtkPerspectiveTransform vtkGeneralTransform vtkMatrix4x4
42  * vtkTransformCollection vtkTransformFilter vtkTransformPolyDataFilter
43  * vtkImageReslice
44 */
45 
46 #ifndef vtkTransform_h
47 #define vtkTransform_h
48 
49 #include "vtkCommonTransformsModule.h" // For export macro
50 #include "vtkLinearTransform.h"
51 
52 #include "vtkMatrix4x4.h" // Needed for inline methods
53 
54 class VTKCOMMONTRANSFORMS_EXPORT vtkTransform : public vtkLinearTransform
55 {
56  public:
57   static vtkTransform *New();
58   vtkTypeMacro(vtkTransform,vtkLinearTransform);
59   void PrintSelf(ostream& os, vtkIndent indent) override;
60 
61   /**
62    * Set the transformation to the identity transformation.  If
63    * the transform has an Input, then the transformation will be
64    * reset so that it is the same as the Input.
65    */
66   void Identity();
67 
68   /**
69    * Invert the transformation.  This will also set a flag so that
70    * the transformation will use the inverse of its Input, if an Input
71    * has been set.
72    */
73   void Inverse() override;
74 
75   //@{
76   /**
77    * Create a translation matrix and concatenate it with the current
78    * transformation according to PreMultiply or PostMultiply semantics.
79    */
Translate(double x,double y,double z)80   void Translate(double x, double y, double z) {
81     this->Concatenation->Translate(x,y,z); };
Translate(const double x[3])82   void Translate(const double x[3]) { this->Translate(x[0], x[1], x[2]); };
Translate(const float x[3])83   void Translate(const float x[3]) { this->Translate(x[0], x[1], x[2]); };
84   //@}
85 
86   //@{
87   /**
88    * Create a rotation matrix and concatenate it with the current
89    * transformation according to PreMultiply or PostMultiply semantics.
90    * The angle is in degrees, and (x,y,z) specifies the axis that the
91    * rotation will be performed around.
92    */
RotateWXYZ(double angle,double x,double y,double z)93   void RotateWXYZ(double angle, double x, double y, double z) {
94     this->Concatenation->Rotate(angle,x,y,z); };
RotateWXYZ(double angle,const double axis[3])95   void RotateWXYZ(double angle, const double axis[3]) {
96     this->RotateWXYZ(angle, axis[0], axis[1], axis[2]); };
RotateWXYZ(double angle,const float axis[3])97   void RotateWXYZ(double angle, const float axis[3]) {
98     this->RotateWXYZ(angle, axis[0], axis[1], axis[2]); };
99   //@}
100 
101   //@{
102   /**
103    * Create a rotation matrix about the X, Y, or Z axis and concatenate
104    * it with the current transformation according to PreMultiply or
105    * PostMultiply semantics.  The angle is expressed in degrees.
106    */
RotateX(double angle)107   void RotateX(double angle) { this->RotateWXYZ(angle, 1, 0, 0); };
RotateY(double angle)108   void RotateY(double angle) { this->RotateWXYZ(angle, 0, 1, 0); };
RotateZ(double angle)109   void RotateZ(double angle) { this->RotateWXYZ(angle, 0, 0, 1); };
110   //@}
111 
112   //@{
113   /**
114    * Create a scale matrix (i.e. set the diagonal elements to x, y, z)
115    * and concatenate it with the current transformation according to
116    * PreMultiply or PostMultiply semantics.
117    */
Scale(double x,double y,double z)118   void Scale(double x, double y, double z) {
119     this->Concatenation->Scale(x,y,z); };
Scale(const double s[3])120   void Scale(const double s[3]) { this->Scale(s[0], s[1], s[2]); };
Scale(const float s[3])121   void Scale(const float s[3]) { this->Scale(s[0], s[1], s[2]); };
122   //@}
123 
124   //@{
125   /**
126    * Set the current matrix directly. Note: First, the current
127    * matrix is set to the identity, then the input matrix is concatenated.
128    */
SetMatrix(vtkMatrix4x4 * matrix)129   void SetMatrix(vtkMatrix4x4 *matrix) {
130     this->SetMatrix(*matrix->Element); };
SetMatrix(const double elements[16])131   void SetMatrix(const double elements[16]) {
132     this->Concatenation->Identity(); this->Concatenate(elements); };
133   //@}
134 
135   //@{
136   /**
137    * Concatenates the matrix with the current transformation according
138    * to PreMultiply or PostMultiply semantics.
139    */
Concatenate(vtkMatrix4x4 * matrix)140   void Concatenate(vtkMatrix4x4 *matrix) {
141     this->Concatenate(*matrix->Element); };
Concatenate(const double elements[16])142   void Concatenate(const double elements[16]) {
143     this->Concatenation->Concatenate(elements); };
144   //@}
145 
146   /**
147    * Concatenate the specified transform with the current transformation
148    * according to PreMultiply or PostMultiply semantics.
149    * The concatenation is pipelined, meaning that if any of the
150    * transformations are changed, even after Concatenate() is called,
151    * those changes will be reflected when you call TransformPoint().
152    */
153   void Concatenate(vtkLinearTransform *transform);
154 
155   /**
156    * Sets the internal state of the transform to PreMultiply. All subsequent
157    * operations will occur before those already represented in the
158    * current transformation.  In homogeneous matrix notation, M = M*A where
159    * M is the current transformation matrix and A is the applied matrix.
160    * The default is PreMultiply.
161    */
PreMultiply()162   void PreMultiply() {
163     if (this->Concatenation->GetPreMultiplyFlag()) { return; }
164     this->Concatenation->SetPreMultiplyFlag(1); this->Modified(); };
165 
166   /**
167    * Sets the internal state of the transform to PostMultiply. All subsequent
168    * operations will occur after those already represented in the
169    * current transformation.  In homogeneous matrix notation, M = A*M where
170    * M is the current transformation matrix and A is the applied matrix.
171    * The default is PreMultiply.
172    */
PostMultiply()173   void PostMultiply()  {
174     if (!this->Concatenation->GetPreMultiplyFlag()) { return; }
175     this->Concatenation->SetPreMultiplyFlag(0); this->Modified(); };
176 
177   /**
178    * Get the total number of transformations that are linked into this
179    * one via Concatenate() operations or via SetInput().
180    */
GetNumberOfConcatenatedTransforms()181   int GetNumberOfConcatenatedTransforms() {
182     return this->Concatenation->GetNumberOfTransforms() +
183       (this->Input == nullptr ? 0 : 1); };
184 
185   //@{
186   /**
187    * Get one of the concatenated transformations as a vtkAbstractTransform.
188    * These transformations are applied, in series, every time the
189    * transformation of a coordinate occurs.  This method is provided
190    * to make it possible to decompose a transformation into its
191    * constituents, for example to save a transformation to a file.
192    */
GetConcatenatedTransform(int i)193   vtkLinearTransform *GetConcatenatedTransform(int i)
194   {
195       vtkAbstractTransform *t;
196       if (this->Input == nullptr)
197       {
198         t=this->Concatenation->GetTransform(i);
199       }
200       else if (i < this->Concatenation->GetNumberOfPreTransforms())
201       {
202         t=this->Concatenation->GetTransform(i);
203       }
204       else if (i > this->Concatenation->GetNumberOfPreTransforms())
205       {
206         t=this->Concatenation->GetTransform(i-1);
207       }
208       else if (this->GetInverseFlag())
209       {
210         t=this->Input->GetInverse();
211       }
212       else
213       {
214         t=this->Input;
215       }
216       return static_cast<vtkLinearTransform *>(t);
217   }
218   //@}
219 
220   //@{
221   /**
222    * Get the x, y, z orientation angles from the transformation matrix as an
223    * array of three floating point values.
224    */
225   void GetOrientation(double orient[3]);
GetOrientation(float orient[3])226   void GetOrientation(float orient[3]) {
227     double temp[3]; this->GetOrientation(temp);
228     orient[0] = static_cast<float>(temp[0]);
229     orient[1] = static_cast<float>(temp[1]);
230     orient[2] = static_cast<float>(temp[2]); };
GetOrientation()231   double *GetOrientation() VTK_SIZEHINT(3) {
232     this->GetOrientation(this->ReturnValue); return this->ReturnValue; };
233   //@}
234 
235   /**
236    * Convenience function to get the x, y, z orientation angles from
237    * a transformation matrix as an array of three floating point values.
238    */
239   static void GetOrientation(double orient[3], vtkMatrix4x4 *matrix);
240 
241   //@{
242   /**
243    * Return the wxyz angle+axis representing the current orientation.
244    * The angle is in degrees and the axis is a unit vector.
245    */
246   void GetOrientationWXYZ(double wxyz[4]);
GetOrientationWXYZ(float wxyz[4])247   void GetOrientationWXYZ(float wxyz[4]) {
248     double temp[4]; this->GetOrientationWXYZ(temp);
249     wxyz[0]=static_cast<float>(temp[0]);
250     wxyz[1]=static_cast<float>(temp[1]);
251     wxyz[2]=static_cast<float>(temp[2]);
252     wxyz[3]=static_cast<float>(temp[3]);};
GetOrientationWXYZ()253   double *GetOrientationWXYZ() VTK_SIZEHINT(4) {
254     this->GetOrientationWXYZ(this->ReturnValue); return this->ReturnValue; };
255   //@}
256 
257   //@{
258   /**
259    * Return the position from the current transformation matrix as an array
260    * of three floating point numbers. This is simply returning the translation
261    * component of the 4x4 matrix.
262    */
263   void GetPosition(double pos[3]);
GetPosition(float pos[3])264   void GetPosition(float pos[3]) {
265     double temp[3]; this->GetPosition(temp);
266     pos[0] = static_cast<float>(temp[0]);
267     pos[1] = static_cast<float>(temp[1]);
268     pos[2] = static_cast<float>(temp[2]); };
GetPosition()269   double *GetPosition() VTK_SIZEHINT(3) {
270     this->GetPosition(this->ReturnValue); return this->ReturnValue; };
271   //@}
272 
273   //@{
274   /**
275    * Return the scale factors of the current transformation matrix as
276    * an array of three float numbers.  These scale factors are not necessarily
277    * about the x, y, and z axes unless unless the scale transformation was
278    * applied before any rotations.
279    */
280   void GetScale(double scale[3]);
GetScale(float scale[3])281   void GetScale(float scale[3]) {
282     double temp[3]; this->GetScale(temp);
283     scale[0] = static_cast<float>(temp[0]);
284     scale[1] = static_cast<float>(temp[1]);
285     scale[2] = static_cast<float>(temp[2]); };
GetScale()286   double *GetScale() VTK_SIZEHINT(3) {
287     this->GetScale(this->ReturnValue); return this->ReturnValue; };
288   //@}
289 
290   /**
291    * Return a matrix which is the inverse of the current transformation
292    * matrix.
293    */
294   void GetInverse(vtkMatrix4x4 *inverse);
295 
296   /**
297    * Return a matrix which is the transpose of the current transformation
298    * matrix.  This is equivalent to the inverse if and only if the
299    * transformation is a pure rotation with no translation or scale.
300    */
301   void GetTranspose(vtkMatrix4x4 *transpose);
302 
303   //@{
304   /**
305    * Set the input for this transformation.  This will be used as the
306    * base transformation if it is set.  This method allows you to build
307    * a transform pipeline: if the input is modified, then this transformation
308    * will automatically update accordingly.  Note that the InverseFlag,
309    * controlled via Inverse(), determines whether this transformation
310    * will use the Input or the inverse of the Input.
311    */
312   void SetInput(vtkLinearTransform *input);
GetInput()313   vtkLinearTransform *GetInput() { return this->Input; };
314   //@}
315 
316   /**
317    * Get the inverse flag of the transformation.  This controls
318    * whether it is the Input or the inverse of the Input that
319    * is used as the base transformation.  The InverseFlag is
320    * flipped every time Inverse() is called.  The InverseFlag
321    * is off when a transform is first created.
322    */
GetInverseFlag()323   int GetInverseFlag() {
324     return this->Concatenation->GetInverseFlag(); };
325 
326   //@{
327   /**
328    * Pushes the current transformation onto the transformation stack.
329    */
Push()330   void Push() { if (this->Stack == nullptr) {
331                     this->Stack = vtkTransformConcatenationStack::New(); }
332                 this->Stack->Push(&this->Concatenation);
333                 this->Modified(); };
334   //@}
335 
336   //@{
337   /**
338    * Deletes the transformation on the top of the stack and sets the top
339    * to the next transformation on the stack.
340    */
Pop()341   void Pop() { if (this->Stack == nullptr) { return; }
342                this->Stack->Pop(&this->Concatenation);
343                this->Modified(); };
344   //@}
345 
346   /**
347    * Check for self-reference.  Will return true if concatenating
348    * with the specified transform, setting it to be our inverse,
349    * or setting it to be our input will create a circular reference.
350    * CircuitCheck is automatically called by SetInput(), SetInverse(),
351    * and Concatenate(vtkXTransform *).  Avoid using this function,
352    * it is experimental.
353    */
354   int CircuitCheck(vtkAbstractTransform *transform) override;
355 
356   // Return an inverse transform which will always update itself
357   // to match this transform.
GetInverse()358   vtkAbstractTransform *GetInverse() {
359     return vtkLinearTransform::GetInverse(); }
360 
361   /**
362    * Make a new transform of the same type.
363    */
364   vtkAbstractTransform *MakeTransform() override;
365 
366   /**
367    * Override GetMTime to account for input and concatenation.
368    */
369   vtkMTimeType GetMTime() override;
370 
371   //@{
372   /**
373    * Use this method only if you wish to compute the transformation in
374    * homogeneous (x,y,z,w) coordinates, otherwise use TransformPoint().
375    * This method calls this->GetMatrix()->MultiplyPoint().
376    */
MultiplyPoint(const float in[4],float out[4])377   void MultiplyPoint(const float in[4], float out[4]) {
378     this->GetMatrix()->MultiplyPoint(in,out);};
MultiplyPoint(const double in[4],double out[4])379   void MultiplyPoint(const double in[4], double out[4]) {
380     this->GetMatrix()->MultiplyPoint(in,out);};
381   //@}
382 
383 protected:
384   vtkTransform ();
385   ~vtkTransform () override;
386 
387   void InternalDeepCopy(vtkAbstractTransform *t) override;
388 
389   void InternalUpdate() override;
390 
391   vtkLinearTransform *Input;
392   vtkTransformConcatenation *Concatenation;
393   vtkTransformConcatenationStack *Stack;
394 
395   // this allows us to check whether people have been fooling
396   // around with our matrix
397   vtkMTimeType MatrixUpdateMTime;
398 
399   float Point[4];
400   double DoublePoint[4];
401   double ReturnValue[4];
402 private:
403   vtkTransform (const vtkTransform&) = delete;
404   void operator=(const vtkTransform&) = delete;
405 };
406 
407 #endif
408