/*========================================================================= Program: Visualization Toolkit Module: vtkAbstractTransform.h 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. =========================================================================*/ /** * @class vtkAbstractTransform * @brief superclass for all geometric transformations * * 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. * @sa * vtkGeneralTransform vtkWarpTransform vtkHomogeneousTransform * vtkLinearTransform vtkIdentityTransform * vtkTransformPolyDataFilter vtkTransformFilter vtkImageReslice * vtkImplicitFunction */ #ifndef vtkAbstractTransform_h #define vtkAbstractTransform_h #include "vtkCommonTransformsModule.h" // For export macro #include "vtkObject.h" class vtkDataArray; class vtkMatrix4x4; class vtkPoints; class vtkSimpleCriticalSection; class VTKCOMMONTRANSFORMS_EXPORT vtkAbstractTransform : public vtkObject { public: vtkTypeMacro(vtkAbstractTransform, vtkObject); void PrintSelf(ostream& os, vtkIndent indent) override; /** * 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); } /** * 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); } /** * Apply the transformation to a double-precision coordinate. * Use this if you are programming in Python or Java. */ double* TransformPoint(double x, double y, double z) VTK_SIZEHINT(3) { return this->TransformDoublePoint(x, y, z); } double* TransformPoint(const double point[3]) VTK_SIZEHINT(3) { return this->TransformPoint(point[0], point[1], point[2]); } //@{ /** * Apply the transformation to an (x,y,z) coordinate. * Use this if you are programming in Python or Java. */ float* TransformFloatPoint(float x, float y, float z) VTK_SIZEHINT(3) { 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]) VTK_SIZEHINT(3) { return this->TransformFloatPoint(point[0], point[1], point[2]); } //@} //@{ /** * Apply the transformation to a double-precision (x,y,z) coordinate. * Use this if you are programming in Python or Java. */ double* TransformDoublePoint(double x, double y, double z) VTK_SIZEHINT(3) { 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]) VTK_SIZEHINT(3) { return this->TransformDoublePoint(point[0], point[1], point[2]); } //@} //@{ /** * 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]) VTK_SIZEHINT(3) { this->TransformNormalAtPoint(point, normal, this->InternalDoublePoint); return this->InternalDoublePoint; } //@{ /** * 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]) VTK_SIZEHINT(3) { this->TransformNormalAtPoint(point, normal, this->InternalDoublePoint); return this->InternalDoublePoint; } //@} //@{ /** * 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]) VTK_SIZEHINT(3) { this->TransformNormalAtPoint(point, normal, this->InternalFloatPoint); return this->InternalFloatPoint; } //@} //@{ /** * 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]) VTK_SIZEHINT(3) { this->TransformVectorAtPoint(point, vector, this->InternalDoublePoint); return this->InternalDoublePoint; } //@{ /** * 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]) VTK_SIZEHINT(3) { this->TransformVectorAtPoint(point, vector, this->InternalDoublePoint); return this->InternalDoublePoint; } //@} //@{ /** * 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]) VTK_SIZEHINT(3) { this->TransformVectorAtPoint(point, vector, this->InternalFloatPoint); return this->InternalFloatPoint; } //@} /** * Apply the transformation to a series of points, and append the * results to outPts. */ virtual void TransformPoints(vtkPoints* inPts, vtkPoints* outPts); /** * 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, int nOptionalVectors = 0, vtkDataArray** inVrsArr = nullptr, vtkDataArray** outVrsArr = nullptr); /** * 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(); /** * 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); /** * Invert the transformation. */ virtual void Inverse() = 0; /** * Copy this transform from another of the same type. */ void DeepCopy(vtkAbstractTransform*); /** * 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(); //@{ /** * 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; //@} //@{ /** * 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; //@} /** * Make another transform of the same type. */ virtual VTK_NEWINSTANCE vtkAbstractTransform* MakeTransform() = 0; /** * 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); /** * Override GetMTime necessary because of inverse transforms. */ vtkMTimeType GetMTime() override; /** * Needs a special UnRegister() implementation to avoid * circular references. */ void UnRegister(vtkObjectBase* O) override; protected: vtkAbstractTransform(); ~vtkAbstractTransform() override; /** * Perform any subclass-specific Update. */ virtual void InternalUpdate() {} /** * Perform any subclass-specific DeepCopy. */ virtual void InternalDeepCopy(vtkAbstractTransform*) {} float InternalFloatPoint[3]; double InternalDoublePoint[3]; private: // 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. vtkTimeStamp UpdateTime; vtkSimpleCriticalSection* UpdateMutex; vtkSimpleCriticalSection* InverseMutex; int DependsOnInverse; // MyInverse is a transform which is the inverse of this one. vtkAbstractTransform* MyInverse; int InUnRegister; private: vtkAbstractTransform(const vtkAbstractTransform&) = delete; void operator=(const vtkAbstractTransform&) = delete; }; //------------------------------------------------------------------------- // A simple data structure to hold both a transform and its inverse. // One of ForwardTransform or InverseTransform might be nullptr, // and must be acquired by calling GetInverse() on the other. class vtkTransformPair { public: vtkTransformPair() {} vtkAbstractTransform* ForwardTransform; vtkAbstractTransform* InverseTransform; void SwapForwardInverse() { vtkAbstractTransform* tmp = this->ForwardTransform; this->ForwardTransform = this->InverseTransform; this->InverseTransform = tmp; } }; // .NAME vtkTransformConcatenation - store a series of transformations. // .SECTION Description // A helper class (not derived from vtkObject) to store a series of // transformations in a pipelined concatenation. class VTKCOMMONTRANSFORMS_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/get 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 Inverse() 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 */ vtkMTimeType 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; private: vtkTransformConcatenation(const vtkTransformConcatenation&) = delete; void operator=(const vtkTransformConcatenation&) = delete; }; // .NAME vtkTransformConcatenationStack - Store a stack of concatenations. // .SECTION Description // A helper class (not derived from vtkObject) to store a stack of // concatenations. class VTKCOMMONTRANSFORMS_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; private: vtkTransformConcatenationStack(const vtkTransformConcatenationStack&) = delete; void operator=(const vtkTransformConcatenationStack&) = delete; }; #endif