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) { this->Concatenation->Translate(x, y, z); }
Translate(const double x[3])81   void Translate(const double x[3]) { this->Translate(x[0], x[1], x[2]); }
Translate(const float x[3])82   void Translate(const float x[3]) { this->Translate(x[0], x[1], x[2]); }
83   ///@}
84 
85   ///@{
86   /**
87    * Create a rotation matrix and concatenate it with the current
88    * transformation according to PreMultiply or PostMultiply semantics.
89    * The angle is in degrees, and (x,y,z) specifies the axis that the
90    * rotation will be performed around.
91    */
RotateWXYZ(double angle,double x,double y,double z)92   void RotateWXYZ(double angle, double x, double y, double z)
93   {
94     this->Concatenation->Rotate(angle, x, y, z);
95   }
RotateWXYZ(double angle,const double axis[3])96   void RotateWXYZ(double angle, const double axis[3])
97   {
98     this->RotateWXYZ(angle, axis[0], axis[1], axis[2]);
99   }
RotateWXYZ(double angle,const float axis[3])100   void RotateWXYZ(double angle, const float axis[3])
101   {
102     this->RotateWXYZ(angle, axis[0], axis[1], axis[2]);
103   }
104   ///@}
105 
106   ///@{
107   /**
108    * Create a rotation matrix about the X, Y, or Z axis and concatenate
109    * it with the current transformation according to PreMultiply or
110    * PostMultiply semantics.  The angle is expressed in degrees.
111    */
RotateX(double angle)112   void RotateX(double angle) { this->RotateWXYZ(angle, 1, 0, 0); }
RotateY(double angle)113   void RotateY(double angle) { this->RotateWXYZ(angle, 0, 1, 0); }
RotateZ(double angle)114   void RotateZ(double angle) { this->RotateWXYZ(angle, 0, 0, 1); }
115   ///@}
116 
117   ///@{
118   /**
119    * Create a scale matrix (i.e. set the diagonal elements to x, y, z)
120    * and concatenate it with the current transformation according to
121    * PreMultiply or PostMultiply semantics.
122    */
Scale(double x,double y,double z)123   void Scale(double x, double y, double z) { this->Concatenation->Scale(x, y, z); }
Scale(const double s[3])124   void Scale(const double s[3]) { this->Scale(s[0], s[1], s[2]); }
Scale(const float s[3])125   void Scale(const float s[3]) { this->Scale(s[0], s[1], s[2]); }
126   ///@}
127 
128   ///@{
129   /**
130    * Set the current matrix directly. Note: First, the current
131    * matrix is set to the identity, then the input matrix is concatenated.
132    */
SetMatrix(vtkMatrix4x4 * matrix)133   void SetMatrix(vtkMatrix4x4* matrix) { this->SetMatrix(*matrix->Element); }
SetMatrix(const double elements[16])134   void SetMatrix(const double elements[16])
135   {
136     this->Concatenation->Identity();
137     this->Concatenate(elements);
138   }
139   ///@}
140 
141   ///@{
142   /**
143    * Concatenates the matrix with the current transformation according
144    * to PreMultiply or PostMultiply semantics.
145    */
Concatenate(vtkMatrix4x4 * matrix)146   void Concatenate(vtkMatrix4x4* matrix) { this->Concatenate(*matrix->Element); }
Concatenate(const double elements[16])147   void Concatenate(const double elements[16]) { this->Concatenation->Concatenate(elements); }
148   ///@}
149 
150   /**
151    * Concatenate the specified transform with the current transformation
152    * according to PreMultiply or PostMultiply semantics.
153    * The concatenation is pipelined, meaning that if any of the
154    * transformations are changed, even after Concatenate() is called,
155    * those changes will be reflected when you call TransformPoint().
156    */
157   void Concatenate(vtkLinearTransform* transform);
158 
159   /**
160    * Sets the internal state of the transform to PreMultiply. All subsequent
161    * operations will occur before those already represented in the
162    * current transformation.  In homogeneous matrix notation, M = M*A where
163    * M is the current transformation matrix and A is the applied matrix.
164    * The default is PreMultiply.
165    */
PreMultiply()166   void PreMultiply()
167   {
168     if (this->Concatenation->GetPreMultiplyFlag())
169     {
170       return;
171     }
172     this->Concatenation->SetPreMultiplyFlag(1);
173     this->Modified();
174   }
175 
176   /**
177    * Sets the internal state of the transform to PostMultiply. All subsequent
178    * operations will occur after those already represented in the
179    * current transformation.  In homogeneous matrix notation, M = A*M where
180    * M is the current transformation matrix and A is the applied matrix.
181    * The default is PreMultiply.
182    */
PostMultiply()183   void PostMultiply()
184   {
185     if (!this->Concatenation->GetPreMultiplyFlag())
186     {
187       return;
188     }
189     this->Concatenation->SetPreMultiplyFlag(0);
190     this->Modified();
191   }
192 
193   /**
194    * Get the total number of transformations that are linked into this
195    * one via Concatenate() operations or via SetInput().
196    */
GetNumberOfConcatenatedTransforms()197   int GetNumberOfConcatenatedTransforms()
198   {
199     return this->Concatenation->GetNumberOfTransforms() + (this->Input == nullptr ? 0 : 1);
200   }
201 
202   ///@{
203   /**
204    * Get one of the concatenated transformations as a vtkAbstractTransform.
205    * These transformations are applied, in series, every time the
206    * transformation of a coordinate occurs.  This method is provided
207    * to make it possible to decompose a transformation into its
208    * constituents, for example to save a transformation to a file.
209    */
GetConcatenatedTransform(int i)210   vtkLinearTransform* GetConcatenatedTransform(int i)
211   {
212     vtkAbstractTransform* t;
213     if (this->Input == nullptr)
214     {
215       t = this->Concatenation->GetTransform(i);
216     }
217     else if (i < this->Concatenation->GetNumberOfPreTransforms())
218     {
219       t = this->Concatenation->GetTransform(i);
220     }
221     else if (i > this->Concatenation->GetNumberOfPreTransforms())
222     {
223       t = this->Concatenation->GetTransform(i - 1);
224     }
225     else if (this->GetInverseFlag())
226     {
227       t = this->Input->GetInverse();
228     }
229     else
230     {
231       t = this->Input;
232     }
233     return static_cast<vtkLinearTransform*>(t);
234   }
235   ///@}
236 
237   ///@{
238   /**
239    * Get the x, y, z orientation angles from the transformation matrix as an
240    * array of three floating point values.
241    */
242   void GetOrientation(double orient[3]);
GetOrientation(float orient[3])243   void GetOrientation(float orient[3])
244   {
245     double temp[3];
246     this->GetOrientation(temp);
247     orient[0] = static_cast<float>(temp[0]);
248     orient[1] = static_cast<float>(temp[1]);
249     orient[2] = static_cast<float>(temp[2]);
250   }
GetOrientation()251   double* GetOrientation() VTK_SIZEHINT(3)
252   {
253     this->GetOrientation(this->ReturnValue);
254     return this->ReturnValue;
255   }
256   ///@}
257 
258   /**
259    * Convenience function to get the x, y, z orientation angles from
260    * a transformation matrix as an array of three floating point values.
261    */
262   static void GetOrientation(double orient[3], vtkMatrix4x4* matrix);
263 
264   ///@{
265   /**
266    * Return the wxyz angle+axis representing the current orientation.
267    * The angle is in degrees and the axis is a unit vector.
268    */
269   void GetOrientationWXYZ(double wxyz[4]);
GetOrientationWXYZ(float wxyz[4])270   void GetOrientationWXYZ(float wxyz[4])
271   {
272     double temp[4];
273     this->GetOrientationWXYZ(temp);
274     wxyz[0] = static_cast<float>(temp[0]);
275     wxyz[1] = static_cast<float>(temp[1]);
276     wxyz[2] = static_cast<float>(temp[2]);
277     wxyz[3] = static_cast<float>(temp[3]);
278   }
GetOrientationWXYZ()279   double* GetOrientationWXYZ() VTK_SIZEHINT(4)
280   {
281     this->GetOrientationWXYZ(this->ReturnValue);
282     return this->ReturnValue;
283   }
284   ///@}
285 
286   ///@{
287   /**
288    * Return the position from the current transformation matrix as an array
289    * of three floating point numbers. This is simply returning the translation
290    * component of the 4x4 matrix.
291    */
292   void GetPosition(double pos[3]);
GetPosition(float pos[3])293   void GetPosition(float pos[3])
294   {
295     double temp[3];
296     this->GetPosition(temp);
297     pos[0] = static_cast<float>(temp[0]);
298     pos[1] = static_cast<float>(temp[1]);
299     pos[2] = static_cast<float>(temp[2]);
300   }
GetPosition()301   double* GetPosition() VTK_SIZEHINT(3)
302   {
303     this->GetPosition(this->ReturnValue);
304     return this->ReturnValue;
305   }
306   ///@}
307 
308   ///@{
309   /**
310    * Return the scale factors of the current transformation matrix as
311    * an array of three float numbers.  These scale factors are not necessarily
312    * about the x, y, and z axes unless unless the scale transformation was
313    * applied before any rotations.
314    */
315   void GetScale(double scale[3]);
GetScale(float scale[3])316   void GetScale(float scale[3])
317   {
318     double temp[3];
319     this->GetScale(temp);
320     scale[0] = static_cast<float>(temp[0]);
321     scale[1] = static_cast<float>(temp[1]);
322     scale[2] = static_cast<float>(temp[2]);
323   }
GetScale()324   double* GetScale() VTK_SIZEHINT(3)
325   {
326     this->GetScale(this->ReturnValue);
327     return this->ReturnValue;
328   }
329   ///@}
330 
331   /**
332    * Return a matrix which is the inverse of the current transformation
333    * matrix.
334    */
335   void GetInverse(vtkMatrix4x4* inverse);
336 
337   /**
338    * Return a matrix which is the transpose of the current transformation
339    * matrix.  This is equivalent to the inverse if and only if the
340    * transformation is a pure rotation with no translation or scale.
341    */
342   void GetTranspose(vtkMatrix4x4* transpose);
343 
344   ///@{
345   /**
346    * Set the input for this transformation.  This will be used as the
347    * base transformation if it is set.  This method allows you to build
348    * a transform pipeline: if the input is modified, then this transformation
349    * will automatically update accordingly.  Note that the InverseFlag,
350    * controlled via Inverse(), determines whether this transformation
351    * will use the Input or the inverse of the Input.
352    */
353   void SetInput(vtkLinearTransform* input);
GetInput()354   vtkLinearTransform* GetInput() { return this->Input; }
355   ///@}
356 
357   /**
358    * Get the inverse flag of the transformation.  This controls
359    * whether it is the Input or the inverse of the Input that
360    * is used as the base transformation.  The InverseFlag is
361    * flipped every time Inverse() is called.  The InverseFlag
362    * is off when a transform is first created.
363    */
GetInverseFlag()364   int GetInverseFlag() { return this->Concatenation->GetInverseFlag(); }
365 
366   ///@{
367   /**
368    * Pushes the current transformation onto the transformation stack.
369    */
Push()370   void Push()
371   {
372     if (this->Stack == nullptr)
373     {
374       this->Stack = vtkTransformConcatenationStack::New();
375     }
376     this->Stack->Push(&this->Concatenation);
377     this->Modified();
378   }
379   ///@}
380 
381   ///@{
382   /**
383    * Deletes the transformation on the top of the stack and sets the top
384    * to the next transformation on the stack.
385    */
Pop()386   void Pop()
387   {
388     if (this->Stack == nullptr)
389     {
390       return;
391     }
392     this->Stack->Pop(&this->Concatenation);
393     this->Modified();
394   }
395   ///@}
396 
397   /**
398    * Check for self-reference.  Will return true if concatenating
399    * with the specified transform, setting it to be our inverse,
400    * or setting it to be our input will create a circular reference.
401    * CircuitCheck is automatically called by SetInput(), SetInverse(),
402    * and Concatenate(vtkXTransform *).  Avoid using this function,
403    * it is experimental.
404    */
405   int CircuitCheck(vtkAbstractTransform* transform) override;
406 
407   // Return an inverse transform which will always update itself
408   // to match this transform.
GetInverse()409   vtkAbstractTransform* GetInverse() { return vtkLinearTransform::GetInverse(); }
410 
411   /**
412    * Make a new transform of the same type.
413    */
414   vtkAbstractTransform* MakeTransform() override;
415 
416   /**
417    * Override GetMTime to account for input and concatenation.
418    */
419   vtkMTimeType GetMTime() override;
420 
421   ///@{
422   /**
423    * Use this method only if you wish to compute the transformation in
424    * homogeneous (x,y,z,w) coordinates, otherwise use TransformPoint().
425    * This method calls this->GetMatrix()->MultiplyPoint().
426    */
MultiplyPoint(const float in[4],float out[4])427   void MultiplyPoint(const float in[4], float out[4]) { this->GetMatrix()->MultiplyPoint(in, out); }
MultiplyPoint(const double in[4],double out[4])428   void MultiplyPoint(const double in[4], double out[4])
429   {
430     this->GetMatrix()->MultiplyPoint(in, out);
431   }
432   ///@}
433 
434 protected:
435   vtkTransform();
436   ~vtkTransform() override;
437 
438   void InternalDeepCopy(vtkAbstractTransform* t) override;
439 
440   void InternalUpdate() override;
441 
442   vtkLinearTransform* Input;
443   vtkTransformConcatenation* Concatenation;
444   vtkTransformConcatenationStack* Stack;
445 
446   // this allows us to check whether people have been fooling
447   // around with our matrix
448   vtkMTimeType MatrixUpdateMTime;
449 
450   float Point[4];
451   double DoublePoint[4];
452   double ReturnValue[4];
453 
454 private:
455   vtkTransform(const vtkTransform&) = delete;
456   void operator=(const vtkTransform&) = delete;
457 };
458 
459 #endif
460