/*========================================================================= Program: Visualization Toolkit Module: $RCSfile: vtkAbstractTransform.h,v $ Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ // .NAME vtkAbstractTransform - superclass for all geometric transformations // .SECTION Description // vtkAbstractTransform is the superclass for all VTK geometric // transformations. The VTK transform hierarchy is split into two // major branches: warp transformations and homogeneous (including linear) // transformations. The latter can be represented in terms of a 4x4 // transformation matrix, the former cannot. //
Transformations can be pipelined through two mechanisms: //
1) GetInverse() returns the pipelined // inverse of a transformation i.e. if you modify the original transform, // any transform previously returned by the GetInverse() method will // automatically update itself according to the change. //
2) You can do pipelined concatenation of transformations through // the vtkGeneralTransform class, the vtkPerspectiveTransform class, // or the vtkTransform class. // .SECTION see also // vtkGeneralTransform vtkWarpTransform vtkHomogeneousTransform // vtkLinearTransform vtkIdentityTransform // vtkTransformPolyDataFilter vtkTransformFilter vtkImageReslice // vtkImplicitFunction #ifndef __vtkAbstractTransform_h #define __vtkAbstractTransform_h #include "vtkObject.h" class vtkDataArray; class vtkMatrix4x4; class vtkPoints; class vtkSimpleCriticalSection; class VTK_COMMON_EXPORT vtkAbstractTransform : public vtkObject { public: vtkTypeRevisionMacro(vtkAbstractTransform,vtkObject); void PrintSelf(ostream& os, vtkIndent indent); // Description: // Apply the transformation to a coordinate. You can use the same // array to store both the input and output point. void TransformPoint(const float in[3], float out[3]) { this->Update(); this->InternalTransformPoint(in,out); }; // Description: // Apply the transformation to a double-precision coordinate. // You can use the same array to store both the input and output point. void TransformPoint(const double in[3], double out[3]) { this->Update(); this->InternalTransformPoint(in,out); }; // Description: // Apply the transformation to a double-precision coordinate. // Use this if you are programming in Python, tcl or Java. double *TransformPoint(double x, double y, double z) { return this->TransformDoublePoint(x,y,z); } double *TransformPoint(const double point[3]) { return this->TransformPoint(point[0],point[1],point[2]); }; // Description: // Apply the transformation to an (x,y,z) coordinate. // Use this if you are programming in Python, tcl or Java. float *TransformFloatPoint(float x, float y, float z) { this->InternalFloatPoint[0] = x; this->InternalFloatPoint[1] = y; this->InternalFloatPoint[2] = z; this->TransformPoint(this->InternalFloatPoint,this->InternalFloatPoint); return this->InternalFloatPoint; }; float *TransformFloatPoint(const float point[3]) { return this->TransformFloatPoint(point[0],point[1],point[2]); }; // Description: // Apply the transformation to a double-precision (x,y,z) coordinate. // Use this if you are programming in Python, tcl or Java. double *TransformDoublePoint(double x, double y, double z) { this->InternalDoublePoint[0] = x; this->InternalDoublePoint[1] = y; this->InternalDoublePoint[2] = z; this->TransformPoint(this->InternalDoublePoint,this->InternalDoublePoint); return this->InternalDoublePoint; }; double *TransformDoublePoint(const double point[3]) { return this->TransformDoublePoint(point[0],point[1],point[2]); }; // Description: // Apply the transformation to a normal at the specified vertex. If the // transformation is a vtkLinearTransform, you can use TransformNormal() // instead. void TransformNormalAtPoint(const float point[3], const float in[3], float out[3]); void TransformNormalAtPoint(const double point[3], const double in[3], double out[3]); double *TransformNormalAtPoint(const double point[3], const double normal[3]) { this->TransformNormalAtPoint(point,normal,this->InternalDoublePoint); return this->InternalDoublePoint; }; // Description: // Apply the transformation to a double-precision normal at the specified // vertex. If the transformation is a vtkLinearTransform, you can use // TransformDoubleNormal() instead. double *TransformDoubleNormalAtPoint(const double point[3], const double normal[3]) { this->TransformNormalAtPoint(point,normal,this->InternalDoublePoint); return this->InternalDoublePoint; }; // Description: // Apply the transformation to a single-precision normal at the specified // vertex. If the transformation is a vtkLinearTransform, you can use // TransformFloatNormal() instead. float *TransformFloatNormalAtPoint(const float point[3], const float normal[3]) { this->TransformNormalAtPoint(point,normal,this->InternalFloatPoint); return this->InternalFloatPoint; }; // Description: // Apply the transformation to a vector at the specified vertex. If the // transformation is a vtkLinearTransform, you can use TransformVector() // instead. void TransformVectorAtPoint(const float point[3], const float in[3], float out[3]); void TransformVectorAtPoint(const double point[3], const double in[3], double out[3]); double *TransformVectorAtPoint(const double point[3], const double vector[3]) { this->TransformVectorAtPoint(point,vector,this->InternalDoublePoint); return this->InternalDoublePoint; }; // Description: // Apply the transformation to a double-precision vector at the specified // vertex. If the transformation is a vtkLinearTransform, you can use // TransformDoubleVector() instead. double *TransformDoubleVectorAtPoint(const double point[3], const double vector[3]) { this->TransformVectorAtPoint(point,vector,this->InternalDoublePoint); return this->InternalDoublePoint; }; // Description: // Apply the transformation to a single-precision vector at the specified // vertex. If the transformation is a vtkLinearTransform, you can use // TransformFloatVector() instead. float *TransformFloatVectorAtPoint(const float point[3], const float vector[3]) { this->TransformVectorAtPoint(point,vector,this->InternalFloatPoint); return this->InternalFloatPoint; }; // Description: // Apply the transformation to a series of points, and append the // results to outPts. virtual void TransformPoints(vtkPoints *inPts, vtkPoints *outPts); // Description: // Apply the transformation to a combination of points, normals // and vectors. virtual void TransformPointsNormalsVectors(vtkPoints *inPts, vtkPoints *outPts, vtkDataArray *inNms, vtkDataArray *outNms, vtkDataArray *inVrs, vtkDataArray *outVrs); // Description: // Get the inverse of this transform. If you modify this transform, // the returned inverse transform will automatically update. If you // want the inverse of a vtkTransform, you might want to use // GetLinearInverse() instead which will type cast the result from // vtkAbstractTransform to vtkLinearTransform. vtkAbstractTransform *GetInverse(); // Description: // Set a transformation that this transform will be the inverse of. // This transform will automatically update to agree with the // inverse transform that you set. void SetInverse(vtkAbstractTransform *transform); // Description: // Invert the transformation. virtual void Inverse() = 0; // Description: // Copy this transform from another of the same type. void DeepCopy(vtkAbstractTransform *); // Description: // Update the transform to account for any changes which // have been made. You do not have to call this method // yourself, it is called automatically whenever the // transform needs an update. void Update(); // Description: // This will calculate the transformation without calling Update. // Meant for use only within other VTK classes. virtual void InternalTransformPoint(const float in[3], float out[3]) = 0; virtual void InternalTransformPoint(const double in[3], double out[3]) = 0; // Description: // This will transform a point and, at the same time, calculate a // 3x3 Jacobian matrix that provides the partial derivatives of the // transformation at that point. This method does not call Update. // Meant for use only within other VTK classes. virtual void InternalTransformDerivative(const float in[3], float out[3], float derivative[3][3]) = 0; virtual void InternalTransformDerivative(const double in[3], double out[3], double derivative[3][3]) = 0; // Description: // Make another transform of the same type. virtual vtkAbstractTransform *MakeTransform() = 0; // Description: // Check for self-reference. Will return true if concatenating // with the specified transform, setting it to be our inverse, // or setting it to be our input will create a circular reference. // CircuitCheck is automatically called by SetInput(), SetInverse(), // and Concatenate(vtkXTransform *). Avoid using this function, // it is experimental. virtual int CircuitCheck(vtkAbstractTransform *transform); // Description: // Override GetMTime necessary because of inverse transforms. unsigned long GetMTime(); // Description: // Needs a special UnRegister() implementation to avoid // circular references. virtual void UnRegister(vtkObjectBase *O); // Description: // @deprecated This method is deprecated in the base class. It is // still valid to use it on many of the specialized classes. VTK_LEGACY(void Identity()); protected: vtkAbstractTransform(); ~vtkAbstractTransform(); // Description: // Perform any subclass-specific Update. virtual void InternalUpdate() {}; // Description: // Perform any subclass-specific DeepCopy. virtual void InternalDeepCopy(vtkAbstractTransform *) {}; float InternalFloatPoint[3]; double InternalDoublePoint[3]; private: //BTX // We need to record the time of the last update, and we also need // to do mutex locking so updates don't collide. These are private // because Update() is not virtual. // If DependsOnInverse is set, then this transform object will // check its inverse on every update, and update itself accordingly // if necessary. //ETX vtkTimeStamp UpdateTime; vtkSimpleCriticalSection *UpdateMutex; vtkSimpleCriticalSection *InverseMutex; int DependsOnInverse; //BTX // MyInverse is a transform which is the inverse of this one. //ETX vtkAbstractTransform *MyInverse; int InUnRegister; private: vtkAbstractTransform(const vtkAbstractTransform&); // Not implemented. void operator=(const vtkAbstractTransform&); // Not implemented. }; //BTX //------------------------------------------------------------------------- // A simple data structure to hold both a transform and its inverse. // One of ForwardTransform or InverseTransform might be NULL, // and must be acquired by calling GetInverse() on the other. class vtkTransformPair { public: vtkAbstractTransform *ForwardTransform; vtkAbstractTransform *InverseTransform; void SwapForwardInverse() { vtkAbstractTransform *tmp = this->ForwardTransform; this->ForwardTransform = this->InverseTransform; this->InverseTransform = tmp; }; }; // A helper class (not derived from vtkObject) to store a series of // transformations in a pipelined concatenation. class VTK_COMMON_EXPORT vtkTransformConcatenation { public: static vtkTransformConcatenation *New() { return new vtkTransformConcatenation(); }; void Delete() { delete this; }; // add a transform to the list according to Pre/PostMultiply semantics void Concatenate(vtkAbstractTransform *transform); // concatenate with a matrix according to Pre/PostMultiply semantics void Concatenate(const double elements[16]); // set the PreMultiply flag void SetPreMultiplyFlag(int flag) { this->PreMultiplyFlag = flag; }; int GetPreMultiplyFlag() { return this->PreMultiplyFlag; }; // the three basic linear transformations void Translate(double x, double y, double z); void Rotate(double angle, double x, double y, double z); void Scale(double x, double y, double z); // invert the concatenation void Inverse(); // get the inverse flag int GetInverseFlag() { return this->InverseFlag; }; // identity simply clears the transform list void Identity(); // copy the list void DeepCopy(vtkTransformConcatenation *transform); // the number of stored transforms int GetNumberOfTransforms() { return this->NumberOfTransforms; }; // the number of transforms that were pre-concatenated (note that // whenever Iverse() is called, the pre-concatenated and // post-concatenated transforms are switched) int GetNumberOfPreTransforms() { return this->NumberOfPreTransforms; }; // the number of transforms that were post-concatenated. int GetNumberOfPostTransforms() { return this->NumberOfTransforms-this->NumberOfPreTransforms; }; // get one of the transforms vtkAbstractTransform *GetTransform(int i); // get maximum MTime of all transforms unsigned long GetMaxMTime(); void PrintSelf(ostream& os, vtkIndent indent); protected: vtkTransformConcatenation(); ~vtkTransformConcatenation(); int InverseFlag; int PreMultiplyFlag; vtkMatrix4x4 *PreMatrix; vtkMatrix4x4 *PostMatrix; vtkAbstractTransform *PreMatrixTransform; vtkAbstractTransform *PostMatrixTransform; int NumberOfTransforms; int NumberOfPreTransforms; int MaxNumberOfTransforms; vtkTransformPair *TransformList; }; // A helper class (not derived from vtkObject) to store a stack of // concatenations. class VTK_COMMON_EXPORT vtkTransformConcatenationStack { public: static vtkTransformConcatenationStack *New() { return new vtkTransformConcatenationStack(); }; void Delete() { delete this; }; // pop will pop delete 'concat', then pop the // top item on the stack onto 'concat'. void Pop(vtkTransformConcatenation **concat); // push will move 'concat' onto the stack, and // make 'concat' a copy of its previous self void Push(vtkTransformConcatenation **concat); void DeepCopy(vtkTransformConcatenationStack *stack); protected: vtkTransformConcatenationStack(); ~vtkTransformConcatenationStack(); int StackSize; vtkTransformConcatenation **Stack; vtkTransformConcatenation **StackBottom; }; //ETX #endif