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