Cloned library of VTK-5.0.0 with extra build files for internal package management.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

478 lines
13 KiB

2 years ago
/*=========================================================================
Program: Visualization Toolkit
Module: $RCSfile: vtkTransformToGrid.cxx,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.
=========================================================================*/
#include "vtkTransformToGrid.h"
#include "vtkAbstractTransform.h"
#include "vtkIdentityTransform.h"
#include "vtkImageData.h"
#include "vtkInformation.h"
#include "vtkInformationVector.h"
#include "vtkObjectFactory.h"
#include "vtkStreamingDemandDrivenPipeline.h"
vtkCxxRevisionMacro(vtkTransformToGrid, "$Revision: 1.21 $");
vtkStandardNewMacro(vtkTransformToGrid);
vtkCxxSetObjectMacro(vtkTransformToGrid,Input,vtkAbstractTransform);
//----------------------------------------------------------------------------
vtkTransformToGrid::vtkTransformToGrid()
{
this->Input = NULL;
this->GridScalarType = VTK_DOUBLE;
for (int i = 0; i < 3; i++)
{
this->GridExtent[2*i] = this->GridExtent[2*i+1] = 0;
this->GridOrigin[i] = 0.0;
this->GridSpacing[i] = 1.0;
}
this->DisplacementScale = 1.0;
this->DisplacementShift = 0.0;
this->SetNumberOfInputPorts(0);
this->SetNumberOfOutputPorts(1);
}
//----------------------------------------------------------------------------
vtkTransformToGrid::~vtkTransformToGrid()
{
this->SetInput(static_cast<vtkAbstractTransform*>(0));
}
//----------------------------------------------------------------------------
void vtkTransformToGrid::PrintSelf(ostream& os, vtkIndent indent)
{
int i;
this->Superclass::PrintSelf(os,indent);
os << indent << "Input: (" << this->Input << ")\n";
os << indent << "GridSpacing: (" << this->GridSpacing[0];
for (i = 1; i < 3; ++i)
{
os << ", " << this->GridSpacing[i];
}
os << ")\n";
os << indent << "GridOrigin: (" << this->GridOrigin[0];
for (i = 1; i < 3; ++i)
{
os << ", " << this->GridOrigin[i];
}
os << ")\n";
os << indent << "GridExtent: (" << this->GridExtent[0];
for (i = 1; i < 6; ++i)
{
os << ", " << this->GridExtent[i];
}
os << ")\n";
os << indent << "GridScalarType: " <<
vtkImageScalarTypeNameMacro(this->GridScalarType) << "\n";
this->UpdateShiftScale();
os << indent << "DisplacementScale: " << this->DisplacementScale << "\n";
os << indent << "DisplacementShift: " << this->DisplacementShift << "\n";
}
//----------------------------------------------------------------------------
// This method returns the largest data that can be generated.
void vtkTransformToGrid::RequestInformation (
vtkInformation * vtkNotUsed(request),
vtkInformationVector ** vtkNotUsed( inputVector ),
vtkInformationVector *outputVector)
{
// get the info objects
vtkInformation* outInfo = outputVector->GetInformationObject(0);
if (this->GetInput() == NULL)
{
vtkErrorMacro("Missing input");
return;
}
// update the transform, maybe in the future make transforms part of the
// pipeline
this->Input->Update();
outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(),
this->GridExtent,6);
outInfo->Set(vtkDataObject::SPACING(),this->GridSpacing,3);
outInfo->Set(vtkDataObject::ORIGIN(),this->GridOrigin,3);
vtkDataObject::SetPointDataActiveScalarInfo(outInfo, this->GridScalarType, 3);
}
//----------------------------------------------------------------------------
// Return the maximum absolute displacement of the transform over
// the entire grid extent -- this is extremely robust and extremely
// inefficient, it should be possible to do much better than this.
void vtkTransformToGridMinMax(vtkTransformToGrid *self, int extent[6],
double &minDisplacement, double &maxDisplacement)
{
vtkAbstractTransform *transform = self->GetInput();
transform->Update();
if (!transform)
{
minDisplacement = -1.0;
maxDisplacement = +1.0;
return;
}
double *spacing = self->GetGridSpacing();
double *origin = self->GetGridOrigin();
maxDisplacement = -1e37;
minDisplacement = +1e37;
double point[3],newPoint[3],displacement;
for (int k = extent[4]; k <= extent[5]; k++)
{
point[2] = k*spacing[2] + origin[2];
for (int j = extent[2]; j <= extent[3]; j++)
{
point[1] = j*spacing[1] + origin[1];
for (int i = extent[0]; i <= extent[1]; i++)
{
point[0] = i*spacing[0] + origin[0];
transform->InternalTransformPoint(point,newPoint);
for (int l = 0; l < 3; l++)
{
displacement = newPoint[l] - point[l];
if (displacement > maxDisplacement)
{
maxDisplacement = displacement;
}
if (displacement < minDisplacement)
{
minDisplacement = displacement;
}
}
}
}
}
}
//----------------------------------------------------------------------------
void vtkTransformToGrid::UpdateShiftScale()
{
int gridType = this->GridScalarType;
// nothing to do for double or double
if (gridType == VTK_DOUBLE || gridType == VTK_DOUBLE)
{
this->DisplacementShift = 0.0;
this->DisplacementScale = 1.0;
vtkDebugMacro(<< "displacement (scale, shift) = (" <<
this->DisplacementScale << ", " <<
this->DisplacementShift << ")");
return;
}
// check mtime
if (this->ShiftScaleTime.GetMTime() > this->GetMTime())
{
return;
}
// get the maximum displacement
double minDisplacement, maxDisplacement;
vtkTransformToGridMinMax(this,this->GridExtent,
minDisplacement,
maxDisplacement);
vtkDebugMacro(<< "displacement (min, max) = (" <<
minDisplacement << ", " << maxDisplacement << ")");
double typeMin,typeMax;
switch (gridType)
{
case VTK_SHORT:
typeMin = VTK_SHORT_MIN;
typeMax = VTK_SHORT_MAX;
break;
case VTK_UNSIGNED_SHORT:
typeMin = VTK_UNSIGNED_SHORT_MIN;
typeMax = VTK_UNSIGNED_SHORT_MAX;
break;
case VTK_CHAR:
typeMin = VTK_CHAR_MIN;
typeMax = VTK_CHAR_MAX;
break;
case VTK_UNSIGNED_CHAR:
typeMin = VTK_UNSIGNED_CHAR_MIN;
typeMax = VTK_UNSIGNED_CHAR_MAX;
break;
default:
vtkErrorMacro(<< "UpdateShiftScale: Unknown input ScalarType");
return;
}
this->DisplacementScale = ((maxDisplacement - minDisplacement)/
(typeMax - typeMin));
this->DisplacementShift = ((typeMax*minDisplacement-typeMin*maxDisplacement)/
(typeMax - typeMin));
if (this->DisplacementScale == 0.0)
{
this->DisplacementScale = 1.0;
}
vtkDebugMacro(<< "displacement (scale, shift) = (" <<
this->DisplacementScale << ", " <<
this->DisplacementShift << ")");
this->ShiftScaleTime.Modified();
}
//----------------------------------------------------------------------------
// macros to ensure proper round-to-nearest behaviour
inline void vtkGridRound(double val, unsigned char& rnd)
{
rnd = (unsigned char)(val+0.5f);
}
inline void vtkGridRound(double val, char& rnd)
{
rnd = (char)((val+128.5f)-128);
}
inline void vtkGridRound(double val, short& rnd)
{
rnd = (short)((int)(val+32768.5f)-32768);
}
inline void vtkGridRound(double val, unsigned short& rnd)
{
rnd = (unsigned short)(val+0.5f);
}
inline void vtkGridRound(double val, double& rnd)
{
rnd = (double)(val);
}
//----------------------------------------------------------------------------
template<class T>
void vtkTransformToGridExecute(vtkTransformToGrid *self,
vtkImageData *grid, T *gridPtr, int extent[6],
double shift, double scale, int id)
{
vtkAbstractTransform *transform = self->GetInput();
int isIdentity = 0;
if (transform == 0)
{
transform = vtkIdentityTransform::New();
isIdentity = 1;
}
double *spacing = grid->GetSpacing();
double *origin = grid->GetOrigin();
vtkIdType *increments = grid->GetIncrements();
double invScale = 1.0/scale;
double point[3];
double newPoint[3];
T *gridPtr0 = gridPtr;
unsigned long count = 0;
unsigned long target = (unsigned long)
((extent[5]-extent[4]+1)*(extent[3]-extent[2]+1)/50.0);
target++;
for (int k = extent[4]; k <= extent[5]; k++)
{
point[2] = k*spacing[2] + origin[2];
T *gridPtr1 = gridPtr0;
for (int j = extent[2]; j <= extent[3]; j++)
{
if (id == 0)
{
if (count % target == 0)
{
self->UpdateProgress(count/(50.0*target));
}
count++;
}
point[1] = j*spacing[1] + origin[1];
gridPtr = gridPtr1;
for (int i = extent[0]; i <= extent[1]; i++)
{
point[0] = i*spacing[0] + origin[0];
transform->InternalTransformPoint(point,newPoint);
vtkGridRound((newPoint[0] - point[0] - shift)*invScale,*gridPtr++);
vtkGridRound((newPoint[1] - point[1] - shift)*invScale,*gridPtr++);
vtkGridRound((newPoint[2] - point[2] - shift)*invScale,*gridPtr++);
}
gridPtr1 += increments[1];
}
gridPtr0 += increments[2];
}
if (isIdentity)
{
transform->Delete();
}
}
//----------------------------------------------------------------------------
void vtkTransformToGrid::RequestData(
vtkInformation* vtkNotUsed( request ),
vtkInformationVector** vtkNotUsed( inputVector ),
vtkInformationVector* outputVector)
{
// get the data object
vtkInformation *outInfo = outputVector->GetInformationObject(0);
vtkImageData *grid = vtkImageData::SafeDownCast(
outInfo->Get(vtkDataObject::DATA_OBJECT()));
grid->SetExtent(
outInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT()));
grid->AllocateScalars();
int *extent = grid->GetExtent();
double *gridPtr = (double *)grid->GetScalarPointerForExtent(extent);
int gridType = grid->GetScalarType();
this->UpdateShiftScale();
double scale = this->DisplacementScale;
double shift = this->DisplacementShift;
int id = 0;
switch (gridType)
{
case VTK_DOUBLE:
vtkTransformToGridExecute(this, grid, (double *)(gridPtr), extent,
shift,scale,id);
break;
case VTK_SHORT:
vtkTransformToGridExecute(this, grid, (short *)(gridPtr), extent,
shift,scale,id);
break;
case VTK_UNSIGNED_SHORT:
vtkTransformToGridExecute(this, grid, (unsigned short *)(gridPtr),extent,
shift,scale,id);
break;
case VTK_CHAR:
vtkTransformToGridExecute(this, grid, (char *)(gridPtr), extent,
shift,scale,id);
break;
case VTK_UNSIGNED_CHAR:
vtkTransformToGridExecute(this, grid, (unsigned char *)(gridPtr), extent,
shift,scale,id);
break;
default:
vtkErrorMacro(<< "Execute: Unknown input ScalarType");
}
}
//----------------------------------------------------------------------------
unsigned long vtkTransformToGrid::GetMTime()
{
unsigned long mtime = this->Superclass::GetMTime();
if (this->Input)
{
unsigned long mtime2 = this->Input->GetMTime();
if (mtime2 > mtime)
{
mtime = mtime2;
}
}
return mtime;
}
//----------------------------------------------------------------------------
int vtkTransformToGrid::ProcessRequest(vtkInformation* request,
vtkInformationVector** inputVector,
vtkInformationVector* outputVector)
{
// generate the data
if(request->Has(vtkDemandDrivenPipeline::REQUEST_DATA()))
{
this->RequestData(request, inputVector, outputVector);
return 1;
}
// execute information
if(request->Has(vtkDemandDrivenPipeline::REQUEST_INFORMATION()))
{
this->RequestInformation(request, inputVector, outputVector);
// after executing set the origin and spacing from the
// info
int i;
for (i = 0; i < this->GetNumberOfOutputPorts(); ++i)
{
vtkInformation* info = outputVector->GetInformationObject(i);
vtkImageData *output =
vtkImageData::SafeDownCast(info->Get(vtkDataObject::DATA_OBJECT()));
// if execute info didn't set origin and spacing then we set them
if (!info->Has(vtkDataObject::ORIGIN()))
{
info->Set(vtkDataObject::ORIGIN(),0,0,0);
info->Set(vtkDataObject::SPACING(),1,1,1);
}
if (output)
{
output->SetOrigin(info->Get(vtkDataObject::ORIGIN()));
output->SetSpacing(info->Get(vtkDataObject::SPACING()));
}
}
return 1;
}
return this->Superclass::ProcessRequest(request, inputVector, outputVector);
}
//----------------------------------------------------------------------------
vtkImageData* vtkTransformToGrid::GetOutput()
{
return vtkImageData::SafeDownCast(this->GetOutputDataObject(0));
}
int vtkTransformToGrid::FillOutputPortInformation(
int vtkNotUsed(port), vtkInformation* info)
{
// now add our info
info->Set(vtkDataObject::DATA_TYPE_NAME(), "vtkImageData");
return 1;
}