text: /*=========================================================================
  
    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.  
  // <p>Transformations can be pipelined through two mechanisms:  
  // <p>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.
  // <p>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:
    vtkTransformPair() {};
  
    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
  
  
  
  
  
  