Commit 3dae091d authored by David Gobbi's avatar David Gobbi
Browse files

Simplify vtkImageStencilIterator.

This class is now derived from vtkImagePointDataIterator, which is a
non-templated base class that provides most of the functionality. By
removing most of the code from the template, the amount of code bloat
caused by the template is reduced.
parent f7fb4c66
set(Module_SRCS
vtkImageStencilIterator.cxx
vtkExtractVOI.cxx
vtkImageAppendComponents.cxx
vtkImageBlend.cxx
......@@ -27,6 +26,7 @@ set(Module_SRCS
vtkImageResliceToColors.cxx
vtkImageShiftScale.cxx
vtkImageShrink3D.cxx
vtkImageStencilIterator.h
vtkImageThreshold.cxx
vtkImageTranslateExtent.cxx
vtkImageWrapPad.cxx
......
/*=========================================================================
Program: Visualization Toolkit
Module: vtkImageStencilIterator.cxx
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.
=========================================================================*/
#include "vtkImageStencilIterator.txx"
template class VTKIMAGINGCORE_EXPORT vtkImageStencilIterator<signed char>;
template class VTKIMAGINGCORE_EXPORT vtkImageStencilIterator<char>;
template class VTKIMAGINGCORE_EXPORT vtkImageStencilIterator<int>;
template class VTKIMAGINGCORE_EXPORT vtkImageStencilIterator<long>;
template class VTKIMAGINGCORE_EXPORT vtkImageStencilIterator<short>;
template class VTKIMAGINGCORE_EXPORT vtkImageStencilIterator<float>;
template class VTKIMAGINGCORE_EXPORT vtkImageStencilIterator<double>;
template class VTKIMAGINGCORE_EXPORT vtkImageStencilIterator<unsigned long>;
template class VTKIMAGINGCORE_EXPORT vtkImageStencilIterator<unsigned short>;
template class VTKIMAGINGCORE_EXPORT vtkImageStencilIterator<unsigned char>;
template class VTKIMAGINGCORE_EXPORT vtkImageStencilIterator<unsigned int>;
template class VTKIMAGINGCORE_EXPORT vtkImageStencilIterator<long long>;
template class VTKIMAGINGCORE_EXPORT vtkImageStencilIterator<unsigned long long>;
......@@ -23,54 +23,73 @@
#ifndef vtkImageStencilIterator_h
#define vtkImageStencilIterator_h
#include "vtkSystemIncludes.h"
#include "vtkImagingCoreModule.h"
class vtkImageData;
class vtkImageStencilData;
class vtkAlgorithm;
#include "vtkImagePointDataIterator.h"
template<class DType>
class VTKIMAGINGCORE_EXPORT vtkImageStencilIterator
class VTKIMAGINGCORE_EXPORT vtkImageStencilIterator :
public vtkImagePointDataIterator
{
public:
// Description:
// Default empty constructor, useful only when creating an array of
// iterators. Call Initialize() on each iterator before using.
vtkImageStencilIterator();
// Description:
// Create an iterator for an extent of an image. If a stencil is
// provided, it must have an extent at least as large as the desired
// extent.
vtkImageStencilIterator(
vtkImageData *image, vtkImageStencilData *stencil, int extent[6],
vtkAlgorithm *algorithm=0, int threadId=0);
// Default constructor, its use must be followed by Initialize().
vtkImageStencilIterator()
{
this->Increment = 0;
this->BasePointer = 0;
this->Pointer = 0;
this->SpanEndPointer = 0;
}
// Description:
// Initialize an iterator for an extent of the image. If a stencil is
// provided, it must have an extent at least as large as the desired
// extent.
void Initialize(
vtkImageData *image, vtkImageStencilData *stencil, int extent[6]);
// Create an iterator for the given image, with several options.
// If a stencil is provided, then the iterator's IsInStencil() method
// reports whether each span is inside the stencil. If an extent is
// provided, it iterates over the extent and ignores the rest of the
// image (the provided extent must be within the image extent). If
// a pointer to the algorithm is provided and threadId is set to zero,
// then progress events will provided for the algorithm.
vtkImageStencilIterator(vtkImageData *image,
vtkImageStencilData *stencil=0,
const int extent[6] = 0,
vtkAlgorithm *algorithm=0,
int threadId=0)
: vtkImagePointDataIterator(image, extent, stencil, algorithm, threadId)
{
this->BasePointer = static_cast<DType *>(
vtkImagePointDataIterator::GetVoidPointer(image, 0, &this->Increment));
this->UpdatePointer();
}
// Description:
// Check if the iterator is within the stencilled region. This
// is updated when NextSpan() is called.
bool IsInStencil()
// Initialize an iterator. See constructor for more details.
void Initialize(vtkImageData *image,
vtkImageStencilData *stencil=0,
const int extent[6] = 0,
vtkAlgorithm *algorithm=0,
int threadId=0)
{
return this->InStencil;
this->vtkImagePointDataIterator::Initialize(
image, extent, stencil, algorithm, threadId);
this->BasePointer = static_cast<DType *>(
vtkImagePointDataIterator::GetVoidPointer(image, 0, &this->Increment));
this->UpdatePointer();
}
// Description:
// Move the iterator to the start of the next span. A span is a
// contiguous region over which nothing but the X index changes.
void NextSpan();
// Move the iterator to the beginning of the next span.
// A span is a contiguous region of the image over which nothing but
// the point Id and the X index changes.
void NextSpan()
{
this->vtkImagePointDataIterator::NextSpan();
this->UpdatePointer();
}
// Description:
// Test if the end of the extent has been reached
// Test if the iterator has completed iterating over the entire extent.
bool IsAtEnd()
{
return (this->Pointer == this->EndPointer);
return this->vtkImagePointDataIterator::IsAtEnd();
}
// Description:
......@@ -89,51 +108,21 @@ public:
protected:
// Description
// Set all the state variables for the stencil span that includes idX.
void SetSpanState(int idX);
// Description:
// Update the pointer (called automatically when a new span begins).
void UpdatePointer()
{
this->Pointer = this->BasePointer + this->Id*this->Increment;
this->SpanEndPointer = this->BasePointer + this->SpanEnd*this->Increment;
}
// Description
// Report the progress and do an abort check. This must be called
// every time that one row of the image is completed. Only called if
// Algorithm is not null.
void ReportProgress();
// The pointer must be incremented by this amount for each pixel.
int Increment;
// Pointers
DType *Pointer; // current iterator position within data
DType *SpanEndPointer; // end of current span
DType *RowEndPointer; // end of current row
DType *SliceEndPointer; // end of current slice
DType *EndPointer; // end of data
// Increments
vtkIdType PixelIncrement; // to next pixel
vtkIdType RowIncrement; // to same position in next row
vtkIdType SliceIncrement; // to same position in next slice
vtkIdType RowEndIncrement; // from end of row to start of next row
vtkIdType SliceEndIncrement; // from end of slice to start of next slice
// Stencil-related items
bool HasStencil;
bool InStencil;
int SpanSliceEndIncrement;
int SpanSliceIncrement;
int SpanMinX;
int SpanMaxX;
int SpanMinY;
int SpanMaxY;
int SpanMinZ;
int SpanMaxZ;
int SpanIndexX;
int SpanIndexY;
int SpanIndexZ;
int *SpanCountPointer;
int **SpanListPointer;
// Progress-related items
vtkAlgorithm *Algorithm;
vtkIdType Count;
vtkIdType Target;
DType *BasePointer; // pointer to the first voxel
DType *Pointer; // current iterator position within data
DType *SpanEndPointer; // end of current span
};
#endif
......
/*=========================================================================
Program: Visualization Toolkit
Module: vtkImageStencilIterator.txx
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.
=========================================================================*/
#ifndef vtkImageStencilIterator_txx
#define vtkImageStencilIterator_txx
#include "vtkImageStencilIterator.h"
#include "vtkImageData.h"
#include "vtkImageStencilData.h"
#include "vtkAlgorithm.h"
//----------------------------------------------------------------------------
class vtkImageStencilIteratorFriendship
{
public:
static int *GetExtentListLengths(vtkImageStencilData *stencil)
{
return stencil->ExtentListLengths;
}
static int **GetExtentLists(vtkImageStencilData *stencil)
{
return stencil->ExtentLists;
}
};
//----------------------------------------------------------------------------
template <class DType>
vtkImageStencilIterator<DType>::vtkImageStencilIterator()
{
this->Pointer = 0;
this->SpanEndPointer = 0;
this->RowEndPointer = 0;
this->SliceEndPointer = 0;
this->EndPointer = 0;
this->PixelIncrement = 0;
this->RowEndIncrement = 0;
this->RowIncrement = 0;
this->SliceEndIncrement = 0;
this->SliceIncrement = 0;
this->HasStencil = false;
this->InStencil = false;
this->SpanSliceEndIncrement = 0;
this->SpanSliceIncrement = 0;
this->SpanMinX = 0;
this->SpanMaxX = 0;
this->SpanMinY = 0;
this->SpanMaxY = 0;
this->SpanMinZ = 0;
this->SpanMaxZ = 0;
this->SpanIndexX = 0;
this->SpanIndexY = 0;
this->SpanIndexZ = 0;
this->SpanCountPointer = 0;
this->SpanListPointer = 0;
this->Algorithm = 0;
this->Count = 0;
this->Target = 0;
}
//----------------------------------------------------------------------------
template <class DType>
void vtkImageStencilIterator<DType>::Initialize(
vtkImageData *image, vtkImageStencilData *stencil, int extent[6])
{
image->GetIncrements(
this->PixelIncrement, this->RowIncrement, this->SliceIncrement);
vtkIdType tmp;
image->GetContinuousIncrements(
extent, tmp, this->RowEndIncrement, this->SliceEndIncrement);
this->SliceEndIncrement = this->SliceEndIncrement + this->RowEndIncrement;
this->Pointer = static_cast<DType *>(
image->GetScalarPointerForExtent(extent));
this->SpanEndPointer = this->Pointer;
this->RowEndPointer = this->Pointer;
this->SliceEndPointer = this->Pointer;
this->EndPointer = this->Pointer;
if (extent[1] >= extent[0] &&
extent[3] >= extent[2] &&
extent[5] >= extent[4])
{
this->SpanEndPointer = this->Pointer +
this->PixelIncrement*(extent[1] - extent[0] + 1);
this->RowEndPointer = this->SpanEndPointer;
this->SliceEndPointer = this->RowEndPointer +
this->RowIncrement*(extent[3] - extent[2]);
this->EndPointer = this->SliceEndPointer +
this->SliceIncrement*(extent[5] - extent[4]);
}
// Code for when a stencil is provided
if (stencil)
{
this->HasStencil = true;
this->InStencil = true;
this->SpanIndexX = 0;
this->SpanIndexY = 0;
this->SpanIndexZ = 0;
int stencilExtent[6];
stencil->GetExtent(stencilExtent);
// The stencil has a YZ array of span lists, we need increments
// to get to the next Z position in the YZ array.
this->SpanSliceIncrement = 0;
this->SpanSliceEndIncrement = 0;
if (stencilExtent[3] >= stencilExtent[2] &&
stencilExtent[5] >= stencilExtent[4])
{
this->SpanSliceIncrement = stencilExtent[3] - stencilExtent[2] + 1;
int botOffset = extent[2] - stencilExtent[2];
if (botOffset >= 0)
{
this->SpanSliceEndIncrement += botOffset;
}
int topOffset = stencilExtent[3] - extent[3];
if (topOffset >= 0)
{
this->SpanSliceEndIncrement += topOffset;
}
}
// The X extent for the spans we want to iterate through
this->SpanMinX = extent[0];
this->SpanMaxX = extent[1];
// Find the offset to the start position within the YZ array.
vtkIdType startOffset = 0;
int yOffset = extent[2] - stencilExtent[2];
if (yOffset >= 0)
{
this->SpanMinY = 0;
startOffset += yOffset;
}
else
{
this->SpanMinY = -yOffset;
}
if (stencilExtent[3] > extent[3])
{
this->SpanMaxY = extent[3] - extent[2];
}
else
{
this->SpanMaxY = stencilExtent[3] - extent[2];
}
int zOffset = extent[4] - stencilExtent[4];
if (zOffset >= 0)
{
this->SpanMinZ = 0;
startOffset += zOffset*this->SpanSliceIncrement;
}
else
{
this->SpanMinZ = -zOffset;
}
if (stencilExtent[5] > extent[5])
{
this->SpanMaxZ = extent[5] - extent[4];
}
else
{
this->SpanMaxZ = stencilExtent[5] - extent[4];
}
if (this->SpanMinY <= this->SpanMaxY &&
this->SpanMinZ <= this->SpanMaxZ)
{
this->SpanCountPointer =
vtkImageStencilIteratorFriendship::GetExtentListLengths(stencil) +
startOffset;
this->SpanListPointer =
vtkImageStencilIteratorFriendship::GetExtentLists(stencil) +
startOffset;
// Holds the current position within the span list for the current row
this->SetSpanState(this->SpanMinX);
}
else
{
this->SpanCountPointer = 0;
this->SpanListPointer = 0;
this->InStencil = false;
}
}
else
{
this->HasStencil = false;
this->InStencil = true;
this->SpanSliceEndIncrement = 0;
this->SpanSliceIncrement = 0;
this->SpanMinX = 0;
this->SpanMaxX = 0;
this->SpanMinY = 0;
this->SpanMaxY = 0;
this->SpanMinZ = 0;
this->SpanMaxZ = 0;
this->SpanIndexX = 0;
this->SpanIndexY = 0;
this->SpanIndexZ = 0;
this->SpanCountPointer = 0;
this->SpanListPointer = 0;
}
}
//----------------------------------------------------------------------------
template <class DType>
vtkImageStencilIterator<DType>::vtkImageStencilIterator(
vtkImageData *image, vtkImageStencilData *stencil, int extent[6],
vtkAlgorithm *algorithm, int threadId)
{
this->Initialize(image, stencil, extent);
if (algorithm && threadId == 0)
{
this->Algorithm = algorithm;
vtkIdType maxCount = extent[3] - extent[2] + 1;
maxCount *= extent[5] - extent[4] + 1;
this->Target = maxCount/50 + 1;
this->Count = this->Target*50 - (maxCount/this->Target)*this->Target + 1;
}
else
{
this->Algorithm = 0;
this->Target = 0;
this->Count = 0;
}
}
//----------------------------------------------------------------------------
template <class DType>
void vtkImageStencilIterator<DType>::SetSpanState(int idX)
{
// Find the span that includes idX
bool inStencil = false;
int *spans = *this->SpanListPointer;
int n = *this->SpanCountPointer;
int i;
for (i = 0; i < n; i++)
{
if (spans[i] > idX)
{
break;
}
inStencil = !inStencil;
}
// Set the primary span state variables
this->SpanIndexX = i;
this->InStencil = inStencil;
// Clamp the span end to SpanMaxX+1
int endIdX = this->SpanMaxX + 1;
if (i < n && spans[i] <= this->SpanMaxX)
{
endIdX = spans[i];
}
// Compute the pointers for idX and endIdX
DType *rowStartPointer =
this->RowEndPointer - (this->RowIncrement - this->RowEndIncrement);
this->Pointer =
rowStartPointer + (idX - this->SpanMinX)*this->PixelIncrement;
this->SpanEndPointer =
rowStartPointer + (endIdX - this->SpanMinX)*this->PixelIncrement;
}
//----------------------------------------------------------------------------
template <class DType>
void vtkImageStencilIterator<DType>::NextSpan()
{
if (this->SpanEndPointer == this->RowEndPointer)
{
int spanIncr = 1;
if (this->SpanEndPointer != this->SliceEndPointer)
{
// Move to the next row
this->Pointer = this->RowEndPointer + this->RowEndIncrement;
this->RowEndPointer += this->RowIncrement;
this->SpanEndPointer = this->RowEndPointer;
this->SpanIndexY++;
}
else if (this->SpanEndPointer != this->EndPointer)
{
// Move to the next slice
this->Pointer = this->SliceEndPointer + this->SliceEndIncrement;
this->SliceEndPointer += this->SliceIncrement;
this->RowEndPointer = this->Pointer +
(this->RowIncrement - this->RowEndIncrement);
this->SpanEndPointer = this->RowEndPointer;
this->SpanIndexY = 0;
this->SpanIndexZ++;
spanIncr += this->SpanSliceEndIncrement;
}
else
{
// reached EndPointer
this->Pointer = this->EndPointer;
return;
}
if (this->HasStencil)
{
if ((this->SpanIndexY >= this->SpanMinY) &&
(this->SpanIndexY <= this->SpanMaxY) &&
(this->SpanIndexZ >= this->SpanMinZ) &&
(this->SpanIndexZ <= this->SpanMaxZ))
{
this->SpanCountPointer += spanIncr;
this->SpanListPointer += spanIncr;
this->SetSpanState(this->SpanMinX);
}
else
{
this->InStencil = false;
}
}
if (this->Algorithm)
{
this->ReportProgress();
}
}
else
{
// Move to the next span in the current row
this->Pointer = this->SpanEndPointer;
// Clamp the span end to SpanMaxX+1
int endIdX = this->SpanMaxX + 1;
this->SpanIndexX++;
if (this->SpanIndexX < *this->SpanCountPointer)
{
int tmpIdX = (*this->SpanListPointer)[this->SpanIndexX];
if (tmpIdX < endIdX)
{
endIdX = tmpIdX;
}
}
// Compute the pointer for endIdX
this->SpanEndPointer = this->RowEndPointer -
(this->RowIncrement - this->RowEndIncrement) +
(endIdX - this->SpanMinX)*this->PixelIncrement;
// Flip the state
this->InStencil = !this->InStencil;
}
}
//----------------------------------------------------------------------------
template <class DType>
void vtkImageStencilIterator<DType>::ReportProgress()
{
if (this->Count % this->Target == 0)
{
if (this->Algorithm->GetAbortExecute())
{
this->Pointer = this->EndPointer;
this->SpanEndPointer = this->EndPointer;
this->RowEndPointer = this->EndPointer;
this->SliceEndPointer = this->EndPointer;
}
else
{
this->Algorithm->UpdateProgress(0.02*(this->Count/this->Target));
}
}
this->Count++;
}
#endif
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment