text: /*=========================================================================
  
    Program:   Visualization Toolkit
    Module:    vtkImageReslice.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.
  
  =========================================================================*/
  // .NAME vtkImageReslice - Reslices a volume along a new set of axes.
  // .SECTION Description
  // vtkImageReslice is the swiss-army-knife of image geometry filters:  
  // It can permute, rotate, flip, scale, resample, deform, and pad image
  // data in any combination with reasonably high efficiency.  Simple
  // operations such as permutation, resampling and padding are done
  // with similar efficiently to the specialized vtkImagePermute,
  // vtkImageResample, and vtkImagePad filters.  There are a number of
  // tasks that vtkImageReslice is well suited for:
  // <p>1) Application of simple rotations, scales, and translations to
  // an image. It is often a good idea to use vtkImageChangeInformation
  // to center the image first, so that scales and rotations occur around
  // the center rather than around the lower-left corner of the image.
  // <p>2) Resampling of one data set to match the voxel sampling of 
  // a second data set via the SetInformationInput() method, e.g. for
  // the purpose of comparing two images or combining two images.
  // A transformation, either linear or nonlinear, can be applied 
  // at the same time via the SetResliceTransform method if the two
  // images are not in the same coordinate space.
  // <p>3) Extraction of slices from an image volume.  The most convenient
  // way to do this is to use SetResliceAxesDirectionCosines() to
  // specify the orientation of the slice.  The direction cosines give
  // the x, y, and z axes for the output volume.  The method 
  // SetOutputDimensionality(2) is used to specify that want to output a
  // slice rather than a volume.  The SetResliceAxesOrigin() command is
  // used to provide an (x,y,z) point that the slice will pass through.
  // You can use both the ResliceAxes and the ResliceTransform at the
  // same time, in order to extract slices from a volume that you have
  // applied a transformation to.
  // .SECTION Caveats
  // This filter is very inefficient if the output X dimension is 1.
  // .SECTION see also
  // vtkAbstractTransform vtkMatrix4x4
  
  
  #ifndef __vtkImageReslice_h
  #define __vtkImageReslice_h
  
  
  #include "vtkThreadedImageAlgorithm.h"
  
  // interpolation mode constants
  #define VTK_RESLICE_NEAREST 0
  #define VTK_RESLICE_LINEAR 1
  #define VTK_RESLICE_RESERVED_2 2
  #define VTK_RESLICE_CUBIC 3
  
  class vtkImageData;
  class vtkAbstractTransform;
  class vtkMatrix4x4;
  class vtkImageStencilData;
  
  class VTK_IMAGING_EXPORT vtkImageReslice : public vtkThreadedImageAlgorithm
  {
  public:
    static vtkImageReslice *New();
    vtkTypeMacro(vtkImageReslice, vtkThreadedImageAlgorithm);
  
    virtual void PrintSelf(ostream& os, vtkIndent indent);
  
    // Description:
    // This method is used to set up the axes for the output voxels.
    // The output Spacing, Origin, and Extent specify the locations
    // of the voxels within the coordinate system defined by the axes.
    // The ResliceAxes are used most often to permute the data, e.g.
    // to extract ZY or XZ slices of a volume as 2D XY images.
    // <p>The first column of the matrix specifies the x-axis 
    // vector (the fourth element must be set to zero), the second
    // column specifies the y-axis, and the third column the
    // z-axis.  The fourth column is the origin of the
    // axes (the fourth element must be set to one).  
    // <p>An alternative to SetResliceAxes() is to use 
    // SetResliceAxesDirectionCosines() to set the directions of the
    // axes and SetResliceAxesOrigin() to set the origin of the axes.
    virtual void SetResliceAxes(vtkMatrix4x4*);
    vtkGetObjectMacro(ResliceAxes, vtkMatrix4x4);
  
    // Description:
    // Specify the direction cosines for the ResliceAxes (i.e. the
    // first three elements of each of the first three columns of 
    // the ResliceAxes matrix).  This will modify the current
    // ResliceAxes matrix, or create a new matrix if none exists.
    void SetResliceAxesDirectionCosines(double x0, double x1, double x2,
                                        double y0, double y1, double y2,
                                        double z0, double z1, double z2);
    void SetResliceAxesDirectionCosines(const double x[3],
                                        const double y[3],
                                        const double z[3]) {
      this->SetResliceAxesDirectionCosines(x[0], x[1], x[2],
                                           y[0], y[1], y[2],
                                           z[0], z[1], z[2]); };
    void SetResliceAxesDirectionCosines(const double xyz[9]) {
      this->SetResliceAxesDirectionCosines(xyz[0], xyz[1], xyz[2],
                                           xyz[3], xyz[4], xyz[5],
                                           xyz[6], xyz[7], xyz[8]); };
    void GetResliceAxesDirectionCosines(double x[3], double y[3], double z[3]);
    void GetResliceAxesDirectionCosines(double xyz[9]) {
      this->GetResliceAxesDirectionCosines(&xyz[0], &xyz[3], &xyz[6]); };
    double *GetResliceAxesDirectionCosines() {
      this->GetResliceAxesDirectionCosines(this->ResliceAxesDirectionCosines);
      return this->ResliceAxesDirectionCosines; };
  
    // Description:
    // Specify the origin for the ResliceAxes (i.e. the first three
    // elements of the final column of the ResliceAxes matrix).
    // This will modify the current ResliceAxes matrix, or create
    // new matrix if none exists.
    void SetResliceAxesOrigin(double x, double y, double z);
    void SetResliceAxesOrigin(const double xyz[3]) {
      this->SetResliceAxesOrigin(xyz[0], xyz[1], xyz[2]); };
    void GetResliceAxesOrigin(double xyz[3]);
    double *GetResliceAxesOrigin() {
      this->GetResliceAxesOrigin(this->ResliceAxesOrigin);
      return this->ResliceAxesOrigin; };
  
    // Description:
    // Set a transform to be applied to the resampling grid that has
    // been defined via the ResliceAxes and the output Origin, Spacing
    // and Extent.  Note that applying a transform to the resampling
    // grid (which lies in the output coordinate system) is
    // equivalent to applying the inverse of that transform to
    // the input volume.  Nonlinear transforms such as vtkGridTransform
    // and vtkThinPlateSplineTransform can be used here.
    virtual void SetResliceTransform(vtkAbstractTransform*);
    vtkGetObjectMacro(ResliceTransform, vtkAbstractTransform);
  
    // Description:
    // Set a vtkImageData from which the default Spacing, Origin,
    // and WholeExtent of the output will be copied.  The spacing,
    // origin, and extent will be permuted according to the 
    // ResliceAxes.  Any values set via SetOutputSpacing, 
    // SetOutputOrigin, and SetOutputExtent will override these
    // values.  By default, the Spacing, Origin, and WholeExtent
    // of the Input are used.
    virtual void SetInformationInput(vtkImageData*);
    vtkGetObjectMacro(InformationInput, vtkImageData);
  
    // Description:
    // Specify whether to transform the spacing, origin and extent
    // of the Input (or the InformationInput) according to the
    // direction cosines and origin of the ResliceAxes before applying
    // them as the default output spacing, origin and extent 
    // (default: On).
    vtkSetMacro(TransformInputSampling, int);
    vtkBooleanMacro(TransformInputSampling, int);
    vtkGetMacro(TransformInputSampling, int);
  
    // Description:
    // Turn this on if you want to guarantee that the extent of the
    // output will be large enough to ensure that none of the 
    // data will be cropped (default: Off).
    vtkSetMacro(AutoCropOutput, int);
    vtkBooleanMacro(AutoCropOutput, int);
    vtkGetMacro(AutoCropOutput, int);
  
    // Description:
    // Turn on wrap-pad feature (default: Off).
    vtkSetMacro(Wrap, int);
    vtkGetMacro(Wrap, int);
    vtkBooleanMacro(Wrap, int);
  
    // Description:
    // Turn on mirror-pad feature (default: Off).
    // This will override the wrap-pad. 
    vtkSetMacro(Mirror, int);
    vtkGetMacro(Mirror, int);
    vtkBooleanMacro(Mirror, int);
  
    // Description:
    // Extend the apparent input border by a half voxel (default: On).
    // This changes how interpolation is handled at the borders of the
    // input image: if the center of an output voxel is beyond the edge
    // of the input image, but is within a half voxel width of the edge
    // (using the input voxel width), then the value of the output voxel
    // is calculated as if the input's edge voxels were duplicated past
    // the edges of the input.
    // This has no effect if Mirror or Wrap are on.
    vtkSetMacro(Border, int);
    vtkGetMacro(Border, int);
    vtkBooleanMacro(Border, int);
  
    // Description:
    // Set interpolation mode (default: nearest neighbor). 
    vtkSetClampMacro(InterpolationMode, int,
                     VTK_RESLICE_NEAREST, VTK_RESLICE_CUBIC);
    vtkGetMacro(InterpolationMode, int);
    void SetInterpolationModeToNearestNeighbor() {
      this->SetInterpolationMode(VTK_RESLICE_NEAREST); };
    void SetInterpolationModeToLinear() {
      this->SetInterpolationMode(VTK_RESLICE_LINEAR); };
    void SetInterpolationModeToCubic() {
      this->SetInterpolationMode(VTK_RESLICE_CUBIC); };
    const char *GetInterpolationModeAsString();
  
    // Description:
    // Turn on and off optimizations (default on, they should only be
    // turned off for testing purposes). 
    vtkSetMacro(Optimization, int);
    vtkGetMacro(Optimization, int);
    vtkBooleanMacro(Optimization, int);
  
    // Description:
    // Set the background color (for multi-component images).
    vtkSetVector4Macro(BackgroundColor, double);
    vtkGetVector4Macro(BackgroundColor, double);
  
    // Description:
    // Set background grey level (for single-component images).
    void SetBackgroundLevel(double v) { this->SetBackgroundColor(v,v,v,v); };
    double GetBackgroundLevel() { return this->GetBackgroundColor()[0]; };
  
    // Description:
    // Set the voxel spacing for the output data.  The default output
    // spacing is the input spacing permuted through the ResliceAxes.
    vtkSetVector3Macro(OutputSpacing, double);
    vtkGetVector3Macro(OutputSpacing, double);
    void SetOutputSpacingToDefault() {
      this->SetOutputSpacing(VTK_DOUBLE_MAX, VTK_DOUBLE_MAX, VTK_DOUBLE_MAX); };
  
    // Description:
    // Set the origin for the output data.  The default output origin
    // is the input origin permuted through the ResliceAxes.
    vtkSetVector3Macro(OutputOrigin, double);
    vtkGetVector3Macro(OutputOrigin, double);
    void SetOutputOriginToDefault() {
      this->SetOutputOrigin(VTK_DOUBLE_MAX, VTK_DOUBLE_MAX, VTK_DOUBLE_MAX); };
  
    // Description:
    // Set the extent for the output data.  The default output extent
    // is the input extent permuted through the ResliceAxes.
    vtkSetVector6Macro(OutputExtent, int);
    vtkGetVector6Macro(OutputExtent, int);
    void SetOutputExtentToDefault() {
      this->SetOutputExtent(VTK_INT_MIN, VTK_INT_MAX,
                            VTK_INT_MIN, VTK_INT_MAX,
                            VTK_INT_MIN, VTK_INT_MAX); };
  
    // Description:
    // Force the dimensionality of the output to either 1, 2,
    // 3 or 0 (default: 3).  If the dimensionality is 2D, then
    // the Z extent of the output is forced to (0,0) and the Z
    // origin of the output is forced to 0.0 (i.e. the output
    // extent is confined to the xy plane).  If the dimensionality
    // is 1D, the output extent is confined to the x axis.  
    // For 0D, the output extent consists of a single voxel at 
    // (0,0,0).
    vtkSetMacro(OutputDimensionality, int);
    vtkGetMacro(OutputDimensionality, int);
  
    // Description:
    // When determining the modified time of the filter, 
    // this check the modified time of the transform and matrix.
    unsigned long int GetMTime();
  
    // Description:
    // Report object referenced by instances of this class.
    virtual void ReportReferences(vtkGarbageCollector*);
  
    // Description:
    // Convenient methods for switching between nearest-neighbor and linear
    // interpolation.  
    // InterpolateOn() is equivalent to SetInterpolationModeToLinear() and
    // InterpolateOff() is equivalent to SetInterpolationModeToNearestNeighbor().
    // You should not use these methods if you use the SetInterpolationMode
    // methods.
    void SetInterpolate(int t) {
      if (t && !this->GetInterpolate()) {
        this->SetInterpolationModeToLinear(); }
      else if (!t && this->GetInterpolate()) {
        this->SetInterpolationModeToNearestNeighbor(); } };
    void InterpolateOn() {
      this->SetInterpolate(1); };
    void InterpolateOff() {
      this->SetInterpolate(0); };
    int GetInterpolate() {
      return (this->GetInterpolationMode() != VTK_RESLICE_NEAREST); };
  
    // Description:
    // Use a stencil to limit the calculations to a specific region of
    // the output.  Portions of the output that are 'outside' the stencil
    // will be cleared to the background color.  
    void SetStencil(vtkImageStencilData *stencil);
    vtkImageStencilData *GetStencil();
  
  protected:
    vtkImageReslice();
    ~vtkImageReslice();
  
    vtkMatrix4x4 *ResliceAxes;
    double ResliceAxesDirectionCosines[9];
    double ResliceAxesOrigin[3];
    vtkAbstractTransform *ResliceTransform;
    vtkImageData *InformationInput;
    int Wrap;
    int Mirror;
    int Border;
    int InterpolationMode;
    int Optimization;
    double BackgroundColor[4];
    double OutputOrigin[3];
    double OutputSpacing[3];
    int OutputExtent[6];
    int OutputDimensionality;
    int TransformInputSampling;
    int AutoCropOutput;
    int HitInputExtent;
  
    vtkMatrix4x4 *IndexMatrix;
    vtkAbstractTransform *OptimizedTransform;
  
    void GetAutoCroppedOutputBounds(vtkInformation *inInfo, double bounds[6]);
    virtual int RequestInformation(vtkInformation *, vtkInformationVector **,
                                   vtkInformationVector *);
    virtual int RequestUpdateExtent(vtkInformation *, vtkInformationVector **,
                                    vtkInformationVector *);
    virtual void ThreadedRequestData(vtkInformation *request,
                                     vtkInformationVector **inputVector,
                                     vtkInformationVector *outputVector,
                                     vtkImageData ***inData,
                                     vtkImageData **outData, int ext[6], int id);
    virtual int FillInputPortInformation(int port, vtkInformation *info);
  
    vtkMatrix4x4 *GetIndexMatrix(vtkInformation *inInfo,
                                 vtkInformation *outInfo);
    vtkAbstractTransform *GetOptimizedTransform() { 
      return this->OptimizedTransform; };
  
  private:
    vtkImageReslice(const vtkImageReslice&);  // Not implemented.
    void operator=(const vtkImageReslice&);  // Not implemented.
  };
  
  //----------------------------------------------------------------------------
  inline const char *vtkImageReslice::GetInterpolationModeAsString()
  {
    switch (this->InterpolationMode)
      {
      case VTK_RESLICE_NEAREST:
        return "NearestNeighbor";
      case VTK_RESLICE_LINEAR:
        return "Linear";
      case VTK_RESLICE_RESERVED_2:
        return "ReservedValue";
      case VTK_RESLICE_CUBIC:
        return "Cubic";
      default:
        return "";
      }
  }  
  
  #endif
  
  
  
  
  
  