vtkImplicitFunctionToImageStencil.cxx 4.49 KB
Newer Older
1 2 3 4 5
/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkImplicitFunctionToImageStencil.cxx

6
  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
7 8
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
9

10 11
     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12
     PURPOSE.  See the above copyright notice for more information.
13 14 15

=========================================================================*/
#include "vtkImplicitFunctionToImageStencil.h"
16 17 18

#include "vtkImageStencilData.h"
#include "vtkImplicitFunction.h"
19
#include "vtkImageData.h"
20 21
#include "vtkInformation.h"
#include "vtkInformationVector.h"
22
#include "vtkObjectFactory.h"
23
#include "vtkStreamingDemandDrivenPipeline.h"
24

Brad King's avatar
Brad King committed
25
#include <math.h>
26

Brad King's avatar
Brad King committed
27
vtkStandardNewMacro(vtkImplicitFunctionToImageStencil);
28 29
vtkCxxSetObjectMacro(vtkImplicitFunctionToImageStencil, Input,
                     vtkImplicitFunction);
30 31 32 33

//----------------------------------------------------------------------------
vtkImplicitFunctionToImageStencil::vtkImplicitFunctionToImageStencil()
{
34
  this->SetNumberOfInputPorts(0);
35
  this->Threshold = 0;
36

37 38 39 40 41 42 43 44 45 46 47
  this->Input = NULL;
}

//----------------------------------------------------------------------------
vtkImplicitFunctionToImageStencil::~vtkImplicitFunctionToImageStencil()
{
  this->SetInput(NULL);
}

//----------------------------------------------------------------------------
void vtkImplicitFunctionToImageStencil::PrintSelf(ostream& os,
48
                                                  vtkIndent indent)
49
{
Brad King's avatar
Brad King committed
50
  this->Superclass::PrintSelf(os,indent);
51 52 53 54 55

  os << indent << "Input: " << this->Input << "\n";
  os << indent << "Threshold: " << this->Threshold << "\n";
}

56 57 58 59 60 61 62 63 64 65 66 67 68 69
//----------------------------------------------------------------------------
unsigned long vtkImplicitFunctionToImageStencil::GetMTime()
{
  unsigned long mTime = this->Superclass::GetMTime();

  if ( this->Input != NULL )
    {
    unsigned long nTime = this->Input->GetMTime();
    mTime = ( nTime > mTime ? nTime : mTime );
    }

  return mTime;
}

70 71 72
//----------------------------------------------------------------------------
// set up the clipping extents from an implicit function by brute force
// (i.e. by evaluating the function at each and every voxel)
73 74 75 76
int vtkImplicitFunctionToImageStencil::RequestData(
  vtkInformation *request,
  vtkInformationVector **inputVector,
  vtkInformationVector *outputVector)
77
{
78 79 80 81 82
  this->Superclass::RequestData(request, inputVector, outputVector);

  vtkInformation *outInfo = outputVector->GetInformationObject(0);
  vtkImageStencilData *data = vtkImageStencilData::SafeDownCast(
    outInfo->Get(vtkDataObject::DATA_OBJECT()));
83
  vtkImplicitFunction *function = this->Input;
Ken Martin's avatar
Ken Martin committed
84 85 86
  double *spacing = data->GetSpacing();
  double *origin = data->GetOrigin();
  double threshold = this->Threshold;
87

Ken Martin's avatar
Ken Martin committed
88 89 90
  // if the input is not set then punt
  if (!function)
    {
91
    return 1;
Ken Martin's avatar
Ken Martin committed
92 93
    }

94
  // for conversion of (idX,idY,idZ) into (x,y,z)
Ken Martin's avatar
Ken Martin committed
95
  double point[3];
96

97 98
  // for keeping track of progress
  unsigned long count = 0;
99 100
  int extent[6];
  data->GetExtent(extent);
101 102
  unsigned long target = static_cast<unsigned long>(
    (extent[5] - extent[4] + 1)*(extent[3] - extent[2] + 1)/50.0);
103 104
  target++;

105 106 107 108 109 110 111 112 113 114 115 116
  // loop through all voxels
  for (int idZ = extent[4]; idZ <= extent[5]; idZ++)
    {
    point[2] = idZ*spacing[2] + origin[2];

    for (int idY = extent[2]; idY <= extent[3]; idY++)
      {
      point[1] = idY*spacing[1] + origin[1];
      int state = 1; // inside or outside, start outside
      int r1 = extent[0];
      int r2 = extent[1];

117
      if (count%target == 0)
118 119
        {
        this->UpdateProgress(count/(50.0*target));
120
        }
121
      count++;
122

123
      for (int idX = extent[0]; idX <= extent[1]; idX++)
124
        {
125
        point[0] = idX*spacing[0] + origin[0];
126 127 128
        int newstate = 1;
        if (function->FunctionValue(point) < threshold)
          {
129
          newstate = -1;
130 131 132 133 134 135 136 137 138 139 140 141
          if (newstate != state)
            { // sub extent starts
            r1 = idX;
            }
          }
        else if (newstate != state)
          { // sub extent ends
          r2 = idX - 1;
          data->InsertNextExtent(r1, r2, idY, idZ);
          }
        state = newstate;
        } // for idX
142
      if (state == -1)
143 144 145
        { // if inside at end, cap off the sub extent
        data->InsertNextExtent(r1, extent[1], idY, idZ);
        }
146
      } // for idY
147
    } // for idZ
148 149

  return 1;
150
}