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