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.
2125 lines
58 KiB
2125 lines
58 KiB
/*=========================================================================
|
|
|
|
Program: Visualization Toolkit
|
|
Module: $RCSfile: vtkImageData.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 "vtkImageData.h"
|
|
|
|
#include "vtkCellData.h"
|
|
#include "vtkDataArray.h"
|
|
#include "vtkExtentTranslator.h"
|
|
#include "vtkGenericCell.h"
|
|
#include "vtkInformation.h"
|
|
#include "vtkInformationIntegerKey.h"
|
|
#include "vtkInformationVector.h"
|
|
#include "vtkLargeInteger.h"
|
|
#include "vtkLine.h"
|
|
#include "vtkMath.h"
|
|
#include "vtkObjectFactory.h"
|
|
#include "vtkPixel.h"
|
|
#include "vtkPointData.h"
|
|
#include "vtkPoints.h"
|
|
#include "vtkStreamingDemandDrivenPipeline.h"
|
|
#include "vtkVertex.h"
|
|
#include "vtkVoxel.h"
|
|
|
|
vtkCxxRevisionMacro(vtkImageData, "$Revision: 1.15.4.2 $");
|
|
vtkStandardNewMacro(vtkImageData);
|
|
|
|
//----------------------------------------------------------------------------
|
|
vtkImageData::vtkImageData()
|
|
{
|
|
int idx;
|
|
|
|
this->Vertex = vtkVertex::New();
|
|
this->Line = vtkLine::New();
|
|
this->Pixel = vtkPixel::New();
|
|
this->Voxel = vtkVoxel::New();
|
|
|
|
this->DataDescription = VTK_EMPTY;
|
|
|
|
for (idx = 0; idx < 3; ++idx)
|
|
{
|
|
this->Dimensions[idx] = 0;
|
|
this->Increments[idx] = 0;
|
|
this->Origin[idx] = 0.0;
|
|
this->Spacing[idx] = 1.0;
|
|
}
|
|
this->Information->Set(vtkDataObject::DATA_EXTENT_TYPE(), VTK_3D_EXTENT);
|
|
this->Information->Set(vtkDataObject::DATA_EXTENT(), this->Extent, 6);
|
|
|
|
int extent[6] = {0, -1, 0, -1, 0, -1};
|
|
memcpy(this->Extent, extent, 6*sizeof(int));
|
|
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
vtkImageData::~vtkImageData()
|
|
{
|
|
this->Vertex->Delete();
|
|
this->Line->Delete();
|
|
this->Pixel->Delete();
|
|
this->Voxel->Delete();
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
// Copy the geometric and topological structure of an input structured points
|
|
// object.
|
|
void vtkImageData::CopyStructure(vtkDataSet *ds)
|
|
{
|
|
vtkImageData *sPts=(vtkImageData *)ds;
|
|
this->Initialize();
|
|
|
|
int i;
|
|
for (i=0; i<3; i++)
|
|
{
|
|
this->Dimensions[i] = sPts->Dimensions[i];
|
|
this->Spacing[i] = sPts->Spacing[i];
|
|
this->Origin[i] = sPts->Origin[i];
|
|
}
|
|
this->SetExtent(sPts->GetExtent());
|
|
|
|
vtkInformation* thisPInfo = this->GetPipelineInformation();
|
|
vtkInformation* thatPInfo = ds->GetPipelineInformation();
|
|
if(thisPInfo && thatPInfo)
|
|
{
|
|
// copy point data.
|
|
if (thatPInfo->Has(POINT_DATA_VECTOR()))
|
|
{
|
|
thisPInfo->CopyEntry(thatPInfo, POINT_DATA_VECTOR());
|
|
}
|
|
// copy cell data.
|
|
if (thatPInfo->Has(CELL_DATA_VECTOR()))
|
|
{
|
|
thisPInfo->CopyEntry(thatPInfo, CELL_DATA_VECTOR());
|
|
}
|
|
}
|
|
this->DataDescription = sPts->DataDescription;
|
|
this->CopyInformation(sPts);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkImageData::Initialize()
|
|
{
|
|
this->Superclass::Initialize();
|
|
if(this->Information)
|
|
{
|
|
this->SetDimensions(0,0,0);
|
|
}
|
|
}
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkImageData::CopyInformationToPipeline(vtkInformation* request,
|
|
vtkInformation* input)
|
|
{
|
|
// Let the superclass copy whatever it wants.
|
|
this->Superclass::CopyInformationToPipeline(request, input);
|
|
|
|
// Set default pipeline information during a request for information.
|
|
if(request->Has(vtkDemandDrivenPipeline::REQUEST_INFORMATION()))
|
|
{
|
|
// Copy settings from the input if available. Otherwise use our
|
|
// current settings.
|
|
vtkInformation* output = this->PipelineInformation;
|
|
|
|
if(input && input->Has(ORIGIN()))
|
|
{
|
|
output->CopyEntry(input, ORIGIN());
|
|
}
|
|
else if (!output->Has(ORIGIN()))
|
|
{
|
|
// Set origin (only if it is not set).
|
|
output->Set(ORIGIN(), this->GetOrigin(), 3);
|
|
}
|
|
|
|
if(input && input->Has(SPACING()))
|
|
{
|
|
output->CopyEntry(input, SPACING());
|
|
}
|
|
else if (!output->Has(SPACING()))
|
|
{
|
|
// Set spacing (only if it is not set).
|
|
output->Set(SPACING(), this->GetSpacing(), 3);
|
|
}
|
|
|
|
// copy of input to output (if input exists) occurs in vtkDataObject, so
|
|
// only to to check need to check if the scalar info exists in the field
|
|
// data info of the output. If it exists, then we assume the type and
|
|
// number of components are set; if not, set type and number of components
|
|
// to default values
|
|
vtkInformation *scalarInfo = vtkDataObject::GetActiveFieldInformation(output,
|
|
FIELD_ASSOCIATION_POINTS, vtkDataSetAttributes::SCALARS);
|
|
if (!scalarInfo)
|
|
{
|
|
vtkDataObject::SetPointDataActiveScalarInfo(output, VTK_DOUBLE, 1);
|
|
}
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkImageData::CopyInformationFromPipeline(vtkInformation* request)
|
|
{
|
|
// Let the superclass copy whatever it wants.
|
|
this->Superclass::CopyInformationFromPipeline(request);
|
|
|
|
// Copy pipeline information to data information before the producer
|
|
// executes.
|
|
if(request->Has(vtkDemandDrivenPipeline::REQUEST_DATA()))
|
|
{
|
|
this->CopyOriginAndSpacingFromPipeline();
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
// Graphics filters reallocate every execute. Image filters try to reuse
|
|
// the scalars.
|
|
void vtkImageData::PrepareForNewData()
|
|
{
|
|
// free everything but the scalars
|
|
vtkDataArray *scalars = this->GetPointData()->GetScalars();
|
|
if (scalars)
|
|
{
|
|
scalars->Register(this);
|
|
}
|
|
this->Initialize();
|
|
if (scalars)
|
|
{
|
|
this->GetPointData()->SetScalars(scalars);
|
|
scalars->UnRegister(this);
|
|
}
|
|
}
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
// The input data object must be of type vtkImageData or a subclass!
|
|
void vtkImageData::CopyTypeSpecificInformation( vtkDataObject *data )
|
|
{
|
|
vtkImageData *image = (vtkImageData *)data;
|
|
|
|
// Copy the generic stuff
|
|
this->CopyInformation( data );
|
|
|
|
// Now do the specific stuff
|
|
this->SetOrigin( image->GetOrigin() );
|
|
this->SetSpacing( image->GetSpacing() );
|
|
this->SetScalarType( image->GetScalarType() );
|
|
this->SetNumberOfScalarComponents(
|
|
image->GetNumberOfScalarComponents() );
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
template <class T>
|
|
unsigned long vtkImageDataGetTypeSize(T*)
|
|
{
|
|
return sizeof(T);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
unsigned long vtkImageData::GetEstimatedMemorySize()
|
|
{
|
|
vtkLargeInteger size;
|
|
int idx;
|
|
int *uExt;
|
|
unsigned long lsize;
|
|
|
|
// Start with the number of scalar components
|
|
size = (unsigned long)(this->GetNumberOfScalarComponents());
|
|
|
|
// Multiply by the number of bytes per scalar
|
|
switch (this->GetScalarType())
|
|
{
|
|
vtkTemplateMacro(
|
|
size *= vtkImageDataGetTypeSize(static_cast<VTK_TT*>(0))
|
|
);
|
|
case VTK_BIT:
|
|
size = size / 8;
|
|
break;
|
|
default:
|
|
vtkWarningMacro(<< "GetExtentMemorySize: "
|
|
<< "Cannot determine input scalar type");
|
|
}
|
|
|
|
// Multiply by the number of scalars.
|
|
uExt = this->GetUpdateExtent();
|
|
for (idx = 0; idx < 3; ++idx)
|
|
{
|
|
size = size*(uExt[idx*2+1] - uExt[idx*2] + 1);
|
|
}
|
|
|
|
// In case the extent is set improperly, set the size to 0
|
|
if (size < 0)
|
|
{
|
|
vtkWarningMacro("Oops, size should not be negative.");
|
|
size = 0;
|
|
}
|
|
|
|
// Convert from double bytes to unsigned long kilobytes
|
|
size = size >> 10;
|
|
lsize = size.CastToUnsignedLong();
|
|
return lsize;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
vtkCell *vtkImageData::GetCell(vtkIdType cellId)
|
|
{
|
|
vtkCell *cell = NULL;
|
|
int loc[3];
|
|
vtkIdType idx, npts;
|
|
int iMin, iMax, jMin, jMax, kMin, kMax;
|
|
double x[3];
|
|
double *origin = this->GetOrigin();
|
|
double *spacing = this->GetSpacing();
|
|
const int* extent = this->Extent;
|
|
|
|
int dims[3];
|
|
dims[0] = extent[1] - extent[0] + 1;
|
|
dims[1] = extent[3] - extent[2] + 1;
|
|
dims[2] = extent[5] - extent[4] + 1;
|
|
|
|
int d01 = dims[0]*dims[1];
|
|
|
|
iMin = iMax = jMin = jMax = kMin = kMax = 0;
|
|
|
|
if (dims[0] == 0 || dims[1] == 0 || dims[2] == 0)
|
|
{
|
|
vtkErrorMacro("Requesting a cell from an empty image.");
|
|
return NULL;
|
|
}
|
|
|
|
switch (this->DataDescription)
|
|
{
|
|
case VTK_EMPTY:
|
|
//cell = this->EmptyCell;
|
|
return NULL;
|
|
|
|
case VTK_SINGLE_POINT: // cellId can only be = 0
|
|
cell = this->Vertex;
|
|
break;
|
|
|
|
case VTK_X_LINE:
|
|
iMin = cellId;
|
|
iMax = cellId + 1;
|
|
cell = this->Line;
|
|
break;
|
|
|
|
case VTK_Y_LINE:
|
|
jMin = cellId;
|
|
jMax = cellId + 1;
|
|
cell = this->Line;
|
|
break;
|
|
|
|
case VTK_Z_LINE:
|
|
kMin = cellId;
|
|
kMax = cellId + 1;
|
|
cell = this->Line;
|
|
break;
|
|
|
|
case VTK_XY_PLANE:
|
|
iMin = cellId % (dims[0]-1);
|
|
iMax = iMin + 1;
|
|
jMin = cellId / (dims[0]-1);
|
|
jMax = jMin + 1;
|
|
cell = this->Pixel;
|
|
break;
|
|
|
|
case VTK_YZ_PLANE:
|
|
jMin = cellId % (dims[1]-1);
|
|
jMax = jMin + 1;
|
|
kMin = cellId / (dims[1]-1);
|
|
kMax = kMin + 1;
|
|
cell = this->Pixel;
|
|
break;
|
|
|
|
case VTK_XZ_PLANE:
|
|
iMin = cellId % (dims[0]-1);
|
|
iMax = iMin + 1;
|
|
kMin = cellId / (dims[0]-1);
|
|
kMax = kMin + 1;
|
|
cell = this->Pixel;
|
|
break;
|
|
|
|
case VTK_XYZ_GRID:
|
|
iMin = cellId % (dims[0] - 1);
|
|
iMax = iMin + 1;
|
|
jMin = (cellId / (dims[0] - 1)) % (dims[1] - 1);
|
|
jMax = jMin + 1;
|
|
kMin = cellId / ((dims[0] - 1) * (dims[1] - 1));
|
|
kMax = kMin + 1;
|
|
cell = this->Voxel;
|
|
break;
|
|
}
|
|
|
|
// Extract point coordinates and point ids
|
|
// Ids are relative to extent min.
|
|
npts = 0;
|
|
for (loc[2]=kMin; loc[2]<=kMax; loc[2]++)
|
|
{
|
|
x[2] = origin[2] + (loc[2]+extent[4]) * spacing[2];
|
|
for (loc[1]=jMin; loc[1]<=jMax; loc[1]++)
|
|
{
|
|
x[1] = origin[1] + (loc[1]+extent[2]) * spacing[1];
|
|
for (loc[0]=iMin; loc[0]<=iMax; loc[0]++)
|
|
{
|
|
x[0] = origin[0] + (loc[0]+extent[0]) * spacing[0];
|
|
|
|
idx = loc[0] + loc[1]*dims[0] + loc[2]*d01;
|
|
cell->PointIds->SetId(npts,idx);
|
|
cell->Points->SetPoint(npts++,x);
|
|
}
|
|
}
|
|
}
|
|
|
|
return cell;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkImageData::GetCell(vtkIdType cellId, vtkGenericCell *cell)
|
|
{
|
|
vtkIdType npts, idx;
|
|
int loc[3];
|
|
int iMin, iMax, jMin, jMax, kMin, kMax;
|
|
double *origin = this->GetOrigin();
|
|
double *spacing = this->GetSpacing();
|
|
double x[3];
|
|
const int* extent = this->Extent;
|
|
|
|
int dims[3];
|
|
dims[0] = extent[1] - extent[0] + 1;
|
|
dims[1] = extent[3] - extent[2] + 1;
|
|
dims[2] = extent[5] - extent[4] + 1;
|
|
int d01 = dims[0]*dims[1];
|
|
|
|
iMin = iMax = jMin = jMax = kMin = kMax = 0;
|
|
|
|
if (dims[0] == 0 || dims[1] == 0 || dims[2] == 0)
|
|
{
|
|
vtkErrorMacro("Requesting a cell from an empty image.");
|
|
cell->SetCellTypeToEmptyCell();
|
|
return;
|
|
}
|
|
|
|
switch (this->DataDescription)
|
|
{
|
|
case VTK_EMPTY:
|
|
cell->SetCellTypeToEmptyCell();
|
|
return;
|
|
|
|
case VTK_SINGLE_POINT: // cellId can only be = 0
|
|
cell->SetCellTypeToVertex();
|
|
break;
|
|
|
|
case VTK_X_LINE:
|
|
iMin = cellId;
|
|
iMax = cellId + 1;
|
|
cell->SetCellTypeToLine();
|
|
break;
|
|
|
|
case VTK_Y_LINE:
|
|
jMin = cellId;
|
|
jMax = cellId + 1;
|
|
cell->SetCellTypeToLine();
|
|
break;
|
|
|
|
case VTK_Z_LINE:
|
|
kMin = cellId;
|
|
kMax = cellId + 1;
|
|
cell->SetCellTypeToLine();
|
|
break;
|
|
|
|
case VTK_XY_PLANE:
|
|
iMin = cellId % (dims[0]-1);
|
|
iMax = iMin + 1;
|
|
jMin = cellId / (dims[0]-1);
|
|
jMax = jMin + 1;
|
|
cell->SetCellTypeToPixel();
|
|
break;
|
|
|
|
case VTK_YZ_PLANE:
|
|
jMin = cellId % (dims[1]-1);
|
|
jMax = jMin + 1;
|
|
kMin = cellId / (dims[1]-1);
|
|
kMax = kMin + 1;
|
|
cell->SetCellTypeToPixel();
|
|
break;
|
|
|
|
case VTK_XZ_PLANE:
|
|
iMin = cellId % (dims[0]-1);
|
|
iMax = iMin + 1;
|
|
kMin = cellId / (dims[0]-1);
|
|
kMax = kMin + 1;
|
|
cell->SetCellTypeToPixel();
|
|
break;
|
|
|
|
case VTK_XYZ_GRID:
|
|
iMin = cellId % (dims[0] - 1);
|
|
iMax = iMin + 1;
|
|
jMin = (cellId / (dims[0] - 1)) % (dims[1] - 1);
|
|
jMax = jMin + 1;
|
|
kMin = cellId / ((dims[0] - 1) * (dims[1] - 1));
|
|
kMax = kMin + 1;
|
|
cell->SetCellTypeToVoxel();
|
|
break;
|
|
}
|
|
|
|
// Extract point coordinates and point ids
|
|
for (npts=0,loc[2]=kMin; loc[2]<=kMax; loc[2]++)
|
|
{
|
|
x[2] = origin[2] + (loc[2]+extent[4]) * spacing[2];
|
|
for (loc[1]=jMin; loc[1]<=jMax; loc[1]++)
|
|
{
|
|
x[1] = origin[1] + (loc[1]+extent[2]) * spacing[1];
|
|
for (loc[0]=iMin; loc[0]<=iMax; loc[0]++)
|
|
{
|
|
x[0] = origin[0] + (loc[0]+extent[0]) * spacing[0];
|
|
|
|
idx = loc[0] + loc[1]*dims[0] + loc[2]*d01;
|
|
cell->PointIds->SetId(npts,idx);
|
|
cell->Points->SetPoint(npts++,x);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
// Fast implementation of GetCellBounds(). Bounds are calculated without
|
|
// constructing a cell.
|
|
void vtkImageData::GetCellBounds(vtkIdType cellId, double bounds[6])
|
|
{
|
|
int loc[3], iMin, iMax, jMin, jMax, kMin, kMax;
|
|
double x[3];
|
|
double *origin = this->GetOrigin();
|
|
double *spacing = this->GetSpacing();
|
|
const int* extent = this->Extent;
|
|
|
|
int dims[3];
|
|
dims[0] = extent[1] - extent[0] + 1;
|
|
dims[1] = extent[3] - extent[2] + 1;
|
|
dims[2] = extent[5] - extent[4] + 1;
|
|
|
|
iMin = iMax = jMin = jMax = kMin = kMax = 0;
|
|
|
|
if (dims[0] == 0 || dims[1] == 0 || dims[2] == 0)
|
|
{
|
|
vtkErrorMacro("Requesting cell bounds from an empty image.");
|
|
bounds[0] = bounds[1] = bounds[2] = bounds[3]
|
|
= bounds[4] = bounds[5] = 0.0;
|
|
return;
|
|
}
|
|
|
|
switch (this->DataDescription)
|
|
{
|
|
case VTK_EMPTY:
|
|
return;
|
|
|
|
case VTK_SINGLE_POINT: // cellId can only be = 0
|
|
break;
|
|
|
|
case VTK_X_LINE:
|
|
iMin = cellId;
|
|
iMax = cellId + 1;
|
|
break;
|
|
|
|
case VTK_Y_LINE:
|
|
jMin = cellId;
|
|
jMax = cellId + 1;
|
|
break;
|
|
|
|
case VTK_Z_LINE:
|
|
kMin = cellId;
|
|
kMax = cellId + 1;
|
|
break;
|
|
|
|
case VTK_XY_PLANE:
|
|
iMin = cellId % (dims[0]-1);
|
|
iMax = iMin + 1;
|
|
jMin = cellId / (dims[0]-1);
|
|
jMax = jMin + 1;
|
|
break;
|
|
|
|
case VTK_YZ_PLANE:
|
|
jMin = cellId % (dims[1]-1);
|
|
jMax = jMin + 1;
|
|
kMin = cellId / (dims[1]-1);
|
|
kMax = kMin + 1;
|
|
break;
|
|
|
|
case VTK_XZ_PLANE:
|
|
iMin = cellId % (dims[0]-1);
|
|
iMax = iMin + 1;
|
|
kMin = cellId / (dims[0]-1);
|
|
kMax = kMin + 1;
|
|
break;
|
|
|
|
case VTK_XYZ_GRID:
|
|
iMin = cellId % (dims[0] - 1);
|
|
iMax = iMin + 1;
|
|
jMin = (cellId / (dims[0] - 1)) % (dims[1] - 1);
|
|
jMax = jMin + 1;
|
|
kMin = cellId / ((dims[0] - 1) * (dims[1] - 1));
|
|
kMax = kMin + 1;
|
|
break;
|
|
}
|
|
|
|
|
|
// carefully compute the bounds
|
|
if (kMax >= kMin && jMax >= jMin && iMax >= iMin)
|
|
{
|
|
bounds[0] = bounds[2] = bounds[4] = VTK_DOUBLE_MAX;
|
|
bounds[1] = bounds[3] = bounds[5] = -VTK_DOUBLE_MAX;
|
|
|
|
// Extract point coordinates
|
|
for (loc[2]=kMin; loc[2]<=kMax; loc[2]++)
|
|
{
|
|
x[2] = origin[2] + (loc[2]+extent[4]) * spacing[2];
|
|
bounds[4] = (x[2] < bounds[4] ? x[2] : bounds[4]);
|
|
bounds[5] = (x[2] > bounds[5] ? x[2] : bounds[5]);
|
|
}
|
|
for (loc[1]=jMin; loc[1]<=jMax; loc[1]++)
|
|
{
|
|
x[1] = origin[1] + (loc[1]+extent[2]) * spacing[1];
|
|
bounds[2] = (x[1] < bounds[2] ? x[1] : bounds[2]);
|
|
bounds[3] = (x[1] > bounds[3] ? x[1] : bounds[3]);
|
|
}
|
|
for (loc[0]=iMin; loc[0]<=iMax; loc[0]++)
|
|
{
|
|
x[0] = origin[0] + (loc[0]+extent[0]) * spacing[0];
|
|
bounds[0] = (x[0] < bounds[0] ? x[0] : bounds[0]);
|
|
bounds[1] = (x[0] > bounds[1] ? x[0] : bounds[1]);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
vtkMath::UninitializeBounds(bounds);
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
double *vtkImageData::GetPoint(vtkIdType ptId)
|
|
{
|
|
static double x[3];
|
|
int i, loc[3];
|
|
double *origin = this->GetOrigin();
|
|
double *spacing = this->GetSpacing();
|
|
const int* extent = this->Extent;
|
|
|
|
int dims[3];
|
|
dims[0] = extent[1] - extent[0] + 1;
|
|
dims[1] = extent[3] - extent[2] + 1;
|
|
dims[2] = extent[5] - extent[4] + 1;
|
|
|
|
x[0] = x[1] = x[2] = 0.0;
|
|
if (dims[0] == 0 || dims[1] == 0 || dims[2] == 0)
|
|
{
|
|
vtkErrorMacro("Requesting a point from an empty image.");
|
|
return x;
|
|
}
|
|
|
|
switch (this->DataDescription)
|
|
{
|
|
case VTK_EMPTY:
|
|
return x;
|
|
|
|
case VTK_SINGLE_POINT:
|
|
loc[0] = loc[1] = loc[2] = 0;
|
|
break;
|
|
|
|
case VTK_X_LINE:
|
|
loc[1] = loc[2] = 0;
|
|
loc[0] = ptId;
|
|
break;
|
|
|
|
case VTK_Y_LINE:
|
|
loc[0] = loc[2] = 0;
|
|
loc[1] = ptId;
|
|
break;
|
|
|
|
case VTK_Z_LINE:
|
|
loc[0] = loc[1] = 0;
|
|
loc[2] = ptId;
|
|
break;
|
|
|
|
case VTK_XY_PLANE:
|
|
loc[2] = 0;
|
|
loc[0] = ptId % dims[0];
|
|
loc[1] = ptId / dims[0];
|
|
break;
|
|
|
|
case VTK_YZ_PLANE:
|
|
loc[0] = 0;
|
|
loc[1] = ptId % dims[1];
|
|
loc[2] = ptId / dims[1];
|
|
break;
|
|
|
|
case VTK_XZ_PLANE:
|
|
loc[1] = 0;
|
|
loc[0] = ptId % dims[0];
|
|
loc[2] = ptId / dims[0];
|
|
break;
|
|
|
|
case VTK_XYZ_GRID:
|
|
loc[0] = ptId % dims[0];
|
|
loc[1] = (ptId / dims[0]) % dims[1];
|
|
loc[2] = ptId / (dims[0]*dims[1]);
|
|
break;
|
|
}
|
|
|
|
for (i=0; i<3; i++)
|
|
{
|
|
x[i] = origin[i] + (loc[i]+extent[i*2]) * spacing[i];
|
|
}
|
|
|
|
return x;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
vtkIdType vtkImageData::FindPoint(double x[3])
|
|
{
|
|
int i, loc[3];
|
|
double d;
|
|
double *origin = this->GetOrigin();
|
|
double *spacing = this->GetSpacing();
|
|
const int* extent = this->Extent;
|
|
|
|
int dims[3];
|
|
dims[0] = extent[1] - extent[0] + 1;
|
|
dims[1] = extent[3] - extent[2] + 1;
|
|
dims[2] = extent[5] - extent[4] + 1;
|
|
|
|
//
|
|
// Compute the ijk location
|
|
//
|
|
for (i=0; i<3; i++)
|
|
{
|
|
d = x[i] - origin[i];
|
|
loc[i] = (int) ((d / spacing[i]) + 0.5);
|
|
if ( loc[i] < extent[i*2] || loc[i] > extent[i*2+1] )
|
|
{
|
|
return -1;
|
|
}
|
|
// since point id is relative to the first point actually stored
|
|
loc[i] -= extent[i*2];
|
|
}
|
|
//
|
|
// From this location get the point id
|
|
//
|
|
return loc[2]*dims[0]*dims[1] + loc[1]*dims[0] + loc[0];
|
|
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
vtkIdType vtkImageData::FindCell(double x[3], vtkCell *vtkNotUsed(cell),
|
|
vtkGenericCell *vtkNotUsed(gencell),
|
|
vtkIdType vtkNotUsed(cellId),
|
|
double vtkNotUsed(tol2),
|
|
int& subId, double pcoords[3],
|
|
double *weights)
|
|
{
|
|
return
|
|
this->FindCell( x, (vtkCell *)NULL, 0, 0.0, subId, pcoords, weights );
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
vtkIdType vtkImageData::FindCell(double x[3], vtkCell *vtkNotUsed(cell),
|
|
vtkIdType vtkNotUsed(cellId),
|
|
double vtkNotUsed(tol2),
|
|
int& subId, double pcoords[3], double *weights)
|
|
{
|
|
int loc[3];
|
|
int *dims = this->GetDimensions();
|
|
|
|
if ( this->ComputeStructuredCoordinates(x, loc, pcoords) == 0 )
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
vtkVoxel::InterpolationFunctions(pcoords,weights);
|
|
|
|
//
|
|
// From this location get the cell id
|
|
//
|
|
subId = 0;
|
|
return loc[2] * (dims[0]-1)*(dims[1]-1) +
|
|
loc[1] * (dims[0]-1) + loc[0];
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
vtkCell *vtkImageData::FindAndGetCell(double x[3],
|
|
vtkCell *vtkNotUsed(cell),
|
|
vtkIdType vtkNotUsed(cellId),
|
|
double vtkNotUsed(tol2), int& subId,
|
|
double pcoords[3], double *weights)
|
|
{
|
|
int i, j, k, loc[3];
|
|
vtkIdType npts, idx;
|
|
double xOut[3];
|
|
int iMax = 0;
|
|
int jMax = 0;
|
|
int kMax = 0;;
|
|
vtkCell *cell = NULL;
|
|
double *origin = this->GetOrigin();
|
|
double *spacing = this->GetSpacing();
|
|
const int* extent = this->Extent;
|
|
|
|
int dims[3];
|
|
dims[0] = extent[1] - extent[0] + 1;
|
|
dims[1] = extent[3] - extent[2] + 1;
|
|
dims[2] = extent[5] - extent[4] + 1;
|
|
vtkIdType d01 = dims[0]*dims[1];
|
|
|
|
if ( this->ComputeStructuredCoordinates(x, loc, pcoords) == 0 )
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
//
|
|
// Get the parametric coordinates and weights for interpolation
|
|
//
|
|
switch (this->DataDescription)
|
|
{
|
|
case VTK_EMPTY:
|
|
return NULL;
|
|
|
|
case VTK_SINGLE_POINT: // cellId can only be = 0
|
|
vtkVertex::InterpolationFunctions(pcoords,weights);
|
|
iMax = loc[0];
|
|
jMax = loc[1];
|
|
kMax = loc[2];
|
|
cell = this->Vertex;
|
|
break;
|
|
|
|
case VTK_X_LINE:
|
|
vtkLine::InterpolationFunctions(pcoords,weights);
|
|
iMax = loc[0] + 1;
|
|
jMax = loc[1];
|
|
kMax = loc[2];
|
|
cell = this->Line;
|
|
break;
|
|
|
|
case VTK_Y_LINE:
|
|
vtkLine::InterpolationFunctions(pcoords,weights);
|
|
iMax = loc[0];
|
|
jMax = loc[1] + 1;
|
|
kMax = loc[2];
|
|
cell = this->Line;
|
|
break;
|
|
|
|
case VTK_Z_LINE:
|
|
vtkLine::InterpolationFunctions(pcoords,weights);
|
|
iMax = loc[0];
|
|
jMax = loc[1];
|
|
kMax = loc[2] + 1;
|
|
cell = this->Line;
|
|
break;
|
|
|
|
case VTK_XY_PLANE:
|
|
vtkPixel::InterpolationFunctions(pcoords,weights);
|
|
iMax = loc[0] + 1;
|
|
jMax = loc[1] + 1;
|
|
kMax = loc[2];
|
|
cell = this->Pixel;
|
|
break;
|
|
|
|
case VTK_YZ_PLANE:
|
|
vtkPixel::InterpolationFunctions(pcoords,weights);
|
|
iMax = loc[0];
|
|
jMax = loc[1] + 1;
|
|
kMax = loc[2] + 1;
|
|
cell = this->Pixel;
|
|
break;
|
|
|
|
case VTK_XZ_PLANE:
|
|
vtkPixel::InterpolationFunctions(pcoords,weights);
|
|
iMax = loc[0] + 1;
|
|
jMax = loc[1];
|
|
kMax = loc[2] + 1;
|
|
cell = this->Pixel;
|
|
break;
|
|
|
|
case VTK_XYZ_GRID:
|
|
vtkVoxel::InterpolationFunctions(pcoords,weights);
|
|
iMax = loc[0] + 1;
|
|
jMax = loc[1] + 1;
|
|
kMax = loc[2] + 1;
|
|
cell = this->Voxel;
|
|
break;
|
|
}
|
|
|
|
npts = 0;
|
|
for (k = loc[2]; k <= kMax; k++)
|
|
{
|
|
xOut[2] = origin[2] + k * spacing[2];
|
|
for (j = loc[1]; j <= jMax; j++)
|
|
{
|
|
xOut[1] = origin[1] + j * spacing[1];
|
|
// make idx relative to the extent not the whole extent
|
|
idx = loc[0]-extent[0] + (j-extent[2])*dims[0]
|
|
+ (k-extent[4])*d01;
|
|
for (i = loc[0]; i <= iMax; i++, idx++)
|
|
{
|
|
xOut[0] = origin[0] + i * spacing[0];
|
|
|
|
cell->PointIds->SetId(npts,idx);
|
|
cell->Points->SetPoint(npts++,xOut);
|
|
}
|
|
}
|
|
}
|
|
subId = 0;
|
|
|
|
return cell;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
int vtkImageData::GetCellType(vtkIdType vtkNotUsed(cellId))
|
|
{
|
|
switch (this->DataDescription)
|
|
{
|
|
case VTK_EMPTY:
|
|
return VTK_EMPTY_CELL;
|
|
|
|
case VTK_SINGLE_POINT:
|
|
return VTK_VERTEX;
|
|
|
|
case VTK_X_LINE: case VTK_Y_LINE: case VTK_Z_LINE:
|
|
return VTK_LINE;
|
|
|
|
case VTK_XY_PLANE: case VTK_YZ_PLANE: case VTK_XZ_PLANE:
|
|
return VTK_PIXEL;
|
|
|
|
case VTK_XYZ_GRID:
|
|
return VTK_VOXEL;
|
|
|
|
default:
|
|
vtkErrorMacro(<<"Bad data description!");
|
|
return VTK_EMPTY_CELL;
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkImageData::ComputeBounds()
|
|
{
|
|
double *origin = this->GetOrigin();
|
|
double *spacing = this->GetSpacing();
|
|
const int* extent = this->Extent;
|
|
|
|
if ( extent[0] > extent[1] ||
|
|
extent[2] > extent[3] ||
|
|
extent[4] > extent[5] )
|
|
{
|
|
vtkMath::UninitializeBounds(this->Bounds);
|
|
return;
|
|
}
|
|
|
|
int swapXBounds = (spacing[0] < 0); // 1 if true, 0 if false
|
|
int swapYBounds = (spacing[1] < 0); // 1 if true, 0 if false
|
|
int swapZBounds = (spacing[2] < 0); // 1 if true, 0 if false
|
|
|
|
this->Bounds[0] = origin[0] + (extent[0+swapXBounds] * spacing[0]);
|
|
this->Bounds[2] = origin[1] + (extent[2+swapYBounds] * spacing[1]);
|
|
this->Bounds[4] = origin[2] + (extent[4+swapZBounds] * spacing[2]);
|
|
|
|
this->Bounds[1] = origin[0] + (extent[1-swapXBounds] * spacing[0]);
|
|
this->Bounds[3] = origin[1] + (extent[3-swapYBounds] * spacing[1]);
|
|
this->Bounds[5] = origin[2] + (extent[5-swapZBounds] * spacing[2]);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
// Given structured coordinates (i,j,k) for a voxel cell, compute the eight
|
|
// gradient values for the voxel corners. The order in which the gradient
|
|
// vectors are arranged corresponds to the ordering of the voxel points.
|
|
// Gradient vector is computed by central differences (except on edges of
|
|
// volume where forward difference is used). The scalars s are the scalars
|
|
// from which the gradient is to be computed. This method will treat
|
|
// only 3D structured point datasets (i.e., volumes).
|
|
void vtkImageData::GetVoxelGradient(int i, int j, int k, vtkDataArray *s,
|
|
vtkDataArray *g)
|
|
{
|
|
double gv[3];
|
|
int ii, jj, kk, idx=0;
|
|
|
|
for ( kk=0; kk < 2; kk++)
|
|
{
|
|
for ( jj=0; jj < 2; jj++)
|
|
{
|
|
for ( ii=0; ii < 2; ii++)
|
|
{
|
|
this->GetPointGradient(i+ii, j+jj, k+kk, s, gv);
|
|
g->SetTuple(idx++, gv);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
// Given structured coordinates (i,j,k) for a point in a structured point
|
|
// dataset, compute the gradient vector from the scalar data at that point.
|
|
// The scalars s are the scalars from which the gradient is to be computed.
|
|
// This method will treat structured point datasets of any dimension.
|
|
void vtkImageData::GetPointGradient(int i,int j,int k, vtkDataArray *s,
|
|
double g[3])
|
|
{
|
|
int *dims=this->GetDimensions();
|
|
double *ar=this->GetSpacing();
|
|
vtkIdType ijsize=dims[0]*dims[1];
|
|
double sp, sm;
|
|
|
|
// x-direction
|
|
if ( dims[0] == 1 )
|
|
{
|
|
g[0] = 0.0;
|
|
}
|
|
else if ( i == 0 )
|
|
{
|
|
sp = s->GetComponent(i+1 + j*dims[0] + k*ijsize, 0);
|
|
sm = s->GetComponent(i + j*dims[0] + k*ijsize, 0);
|
|
g[0] = (sm - sp) / ar[0];
|
|
}
|
|
else if ( i == (dims[0]-1) )
|
|
{
|
|
sp = s->GetComponent(i + j*dims[0] + k*ijsize,0);
|
|
sm = s->GetComponent(i-1 + j*dims[0] + k*ijsize,0);
|
|
g[0] = (sm - sp) / ar[0];
|
|
}
|
|
else
|
|
{
|
|
sp = s->GetComponent(i+1 + j*dims[0] + k*ijsize,0);
|
|
sm = s->GetComponent(i-1 + j*dims[0] + k*ijsize,0);
|
|
g[0] = 0.5 * (sm - sp) / ar[0];
|
|
}
|
|
|
|
// y-direction
|
|
if ( dims[1] == 1 )
|
|
{
|
|
g[1] = 0.0;
|
|
}
|
|
else if ( j == 0 )
|
|
{
|
|
sp = s->GetComponent(i + (j+1)*dims[0] + k*ijsize,0);
|
|
sm = s->GetComponent(i + j*dims[0] + k*ijsize,0);
|
|
g[1] = (sm - sp) / ar[1];
|
|
}
|
|
else if ( j == (dims[1]-1) )
|
|
{
|
|
sp = s->GetComponent(i + j*dims[0] + k*ijsize,0);
|
|
sm = s->GetComponent(i + (j-1)*dims[0] + k*ijsize,0);
|
|
g[1] = (sm - sp) / ar[1];
|
|
}
|
|
else
|
|
{
|
|
sp = s->GetComponent(i + (j+1)*dims[0] + k*ijsize,0);
|
|
sm = s->GetComponent(i + (j-1)*dims[0] + k*ijsize,0);
|
|
g[1] = 0.5 * (sm - sp) / ar[1];
|
|
}
|
|
|
|
// z-direction
|
|
if ( dims[2] == 1 )
|
|
{
|
|
g[2] = 0.0;
|
|
}
|
|
else if ( k == 0 )
|
|
{
|
|
sp = s->GetComponent(i + j*dims[0] + (k+1)*ijsize,0);
|
|
sm = s->GetComponent(i + j*dims[0] + k*ijsize,0);
|
|
g[2] = (sm - sp) / ar[2];
|
|
}
|
|
else if ( k == (dims[2]-1) )
|
|
{
|
|
sp = s->GetComponent(i + j*dims[0] + k*ijsize,0);
|
|
sm = s->GetComponent(i + j*dims[0] + (k-1)*ijsize,0);
|
|
g[2] = (sm - sp) / ar[2];
|
|
}
|
|
else
|
|
{
|
|
sp = s->GetComponent(i + j*dims[0] + (k+1)*ijsize,0);
|
|
sm = s->GetComponent(i + j*dims[0] + (k-1)*ijsize,0);
|
|
g[2] = 0.5 * (sm - sp) / ar[2];
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
// Set dimensions of structured points dataset.
|
|
void vtkImageData::SetDimensions(int i, int j, int k)
|
|
{
|
|
this->SetExtent(0, i-1, 0, j-1, 0, k-1);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
// Set dimensions of structured points dataset.
|
|
void vtkImageData::SetDimensions(int dim[3])
|
|
{
|
|
this->SetExtent(0, dim[0]-1, 0, dim[1]-1, 0, dim[2]-1);
|
|
}
|
|
|
|
|
|
// streaming change: ijk is in extent coordinate system.
|
|
//----------------------------------------------------------------------------
|
|
// Convenience function computes the structured coordinates for a point x[3].
|
|
// The voxel is specified by the array ijk[3], and the parametric coordinates
|
|
// in the cell are specified with pcoords[3]. The function returns a 0 if the
|
|
// point x is outside of the volume, and a 1 if inside the volume.
|
|
int vtkImageData::ComputeStructuredCoordinates(double x[3], int ijk[3],
|
|
double pcoords[3])
|
|
{
|
|
int i;
|
|
double d, doubleLoc;
|
|
double *origin = this->GetOrigin();
|
|
double *spacing = this->GetSpacing();
|
|
const int* extent = this->Extent;
|
|
|
|
int dims[3];
|
|
dims[0] = extent[1] - extent[0] + 1;
|
|
dims[1] = extent[3] - extent[2] + 1;
|
|
dims[2] = extent[5] - extent[4] + 1;
|
|
|
|
//
|
|
// Compute the ijk location
|
|
//
|
|
for (i=0; i<3; i++)
|
|
{
|
|
d = x[i] - origin[i];
|
|
doubleLoc = d / spacing[i];
|
|
// Floor for negtive indexes.
|
|
ijk[i] = (int) (floor(doubleLoc));
|
|
if ( ijk[i] >= extent[i*2] && ijk[i] < extent[i*2 + 1] )
|
|
{
|
|
pcoords[i] = doubleLoc - (double)ijk[i];
|
|
}
|
|
|
|
else if ( ijk[i] < extent[i*2] || ijk[i] > extent[i*2+1] )
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
else //if ( ijk[i] == extent[i*2+1] )
|
|
{
|
|
if (dims[i] == 1)
|
|
{
|
|
pcoords[i] = 0.0;
|
|
}
|
|
else
|
|
{
|
|
ijk[i] -= 1;
|
|
pcoords[i] = 1.0;
|
|
}
|
|
}
|
|
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkImageData::PrintSelf(ostream& os, vtkIndent indent)
|
|
{
|
|
this->Superclass::PrintSelf(os,indent);
|
|
|
|
int idx;
|
|
int *dims = this->GetDimensions();
|
|
const int* extent = this->Extent;
|
|
|
|
os << indent << "ScalarType: " << this->GetScalarType() << endl;
|
|
os << indent << "NumberOfScalarComponents: " <<
|
|
this->GetNumberOfScalarComponents() << endl;
|
|
os << indent << "Spacing: (" << this->Spacing[0] << ", "
|
|
<< this->Spacing[1] << ", "
|
|
<< this->Spacing[2] << ")\n";
|
|
os << indent << "Origin: (" << this->Origin[0] << ", "
|
|
<< this->Origin[1] << ", "
|
|
<< this->Origin[2] << ")\n";
|
|
os << indent << "Dimensions: (" << dims[0] << ", "
|
|
<< dims[1] << ", "
|
|
<< dims[2] << ")\n";
|
|
os << indent << "Increments: (" << this->Increments[0] << ", "
|
|
<< this->Increments[1] << ", "
|
|
<< this->Increments[2] << ")\n";
|
|
os << indent << "Extent: (" << extent[0];
|
|
for (idx = 1; idx < 6; ++idx)
|
|
{
|
|
os << ", " << extent[idx];
|
|
}
|
|
os << ")\n";
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkImageData::UpdateInformation()
|
|
{
|
|
// Use the compatibility method in the superclass to update the
|
|
// information.
|
|
this->Superclass::UpdateInformation();
|
|
|
|
// Now copy the information the caller is probably expecting to get
|
|
// from this data object instead of the pipeline information. This
|
|
// preserves compatibility.
|
|
this->CopyOriginAndSpacingFromPipeline();
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkImageData::SetNumberOfScalarComponents(int num)
|
|
{
|
|
this->GetProducerPort();
|
|
if(vtkInformation* info = this->GetPipelineInformation())
|
|
{
|
|
vtkDataObject::SetPointDataActiveScalarInfo(info, -1, num);
|
|
}
|
|
else
|
|
{
|
|
vtkErrorMacro("SetNumberOfScalarComponents called with no "
|
|
"executive producing this image data object.");
|
|
}
|
|
this->ComputeIncrements();
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
int vtkImageData::GetNumberOfScalarComponents()
|
|
{
|
|
this->GetProducerPort();
|
|
if(vtkInformation* info = this->GetPipelineInformation())
|
|
{
|
|
vtkInformation *scalarInfo = vtkDataObject::GetActiveFieldInformation(info,
|
|
FIELD_ASSOCIATION_POINTS, vtkDataSetAttributes::SCALARS);
|
|
if (scalarInfo && scalarInfo->Has(FIELD_NUMBER_OF_COMPONENTS()))
|
|
{
|
|
return scalarInfo->Get( FIELD_NUMBER_OF_COMPONENTS() );
|
|
}
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
vtkIdType *vtkImageData::GetIncrements()
|
|
{
|
|
// Make sure the increments are up to date. The filter bypass and update
|
|
// mechanism make it tricky to update the increments anywhere other than here
|
|
this->ComputeIncrements();
|
|
|
|
return this->Increments;
|
|
}
|
|
|
|
void vtkImageData::GetIncrements(vtkIdType &incX, vtkIdType &incY, vtkIdType &incZ)
|
|
{
|
|
// Make sure the increments are up to date. The filter bypass and update
|
|
// mechanism make it tricky to update the increments anywhere other than here
|
|
this->ComputeIncrements();
|
|
|
|
incX = this->Increments[0];
|
|
incY = this->Increments[1];
|
|
incZ = this->Increments[2];
|
|
}
|
|
|
|
void vtkImageData::GetIncrements(vtkIdType inc[3])
|
|
{
|
|
// Make sure the increments are up to date. The filter bypass and update
|
|
// mechanism make it tricky to update the increments anywhere other than here
|
|
this->ComputeIncrements();
|
|
|
|
inc[0] = this->Increments[0];
|
|
inc[1] = this->Increments[1];
|
|
inc[2] = this->Increments[2];
|
|
}
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkImageData::GetContinuousIncrements(int extent[6], vtkIdType &incX,
|
|
vtkIdType &incY, vtkIdType &incZ)
|
|
{
|
|
int e0, e1, e2, e3;
|
|
|
|
incX = 0;
|
|
const int* selfExtent = this->Extent;
|
|
|
|
e0 = extent[0];
|
|
if (e0 < selfExtent[0])
|
|
{
|
|
e0 = selfExtent[0];
|
|
}
|
|
e1 = extent[1];
|
|
if (e1 > selfExtent[1])
|
|
{
|
|
e1 = selfExtent[1];
|
|
}
|
|
e2 = extent[2];
|
|
if (e2 < selfExtent[2])
|
|
{
|
|
e2 = selfExtent[2];
|
|
}
|
|
e3 = extent[3];
|
|
if (e3 > selfExtent[3])
|
|
{
|
|
e3 = selfExtent[3];
|
|
}
|
|
|
|
// Make sure the increments are up to date
|
|
this->ComputeIncrements();
|
|
|
|
incY = this->Increments[1] - (e1 - e0 + 1)*this->Increments[0];
|
|
incZ = this->Increments[2] - (e3 - e2 + 1)*this->Increments[1];
|
|
}
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
// This method computes the increments from the MemoryOrder and the extent.
|
|
void vtkImageData::ComputeIncrements()
|
|
{
|
|
int idx;
|
|
// make sure we have data before computing incrments to traverse it
|
|
if (!this->GetPointData()->GetScalars())
|
|
{
|
|
return;
|
|
}
|
|
vtkIdType inc = this->GetPointData()->GetScalars()->GetNumberOfComponents();
|
|
const int* extent = this->Extent;
|
|
|
|
for (idx = 0; idx < 3; ++idx)
|
|
{
|
|
this->Increments[idx] = inc;
|
|
inc *= (extent[idx*2+1] - extent[idx*2] + 1);
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkImageData::CopyOriginAndSpacingFromPipeline()
|
|
{
|
|
// Copy origin and spacing from pipeline information to the internal
|
|
// copies.
|
|
vtkInformation* info = this->PipelineInformation;
|
|
if(info->Has(SPACING()))
|
|
{
|
|
this->SetSpacing(info->Get(SPACING()));
|
|
}
|
|
if(info->Has(ORIGIN()))
|
|
{
|
|
this->SetOrigin(info->Get(ORIGIN()));
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
template <class TIn, class TOut>
|
|
void vtkImageDataConvertScalar(TIn* in, TOut* out)
|
|
{
|
|
*out = static_cast<TOut>(*in);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
double vtkImageData::GetScalarComponentAsDouble(int x, int y, int z, int comp)
|
|
{
|
|
// Check the component index.
|
|
if(comp < 0 || comp >= this->GetNumberOfScalarComponents())
|
|
{
|
|
vtkErrorMacro("Bad component index " << comp);
|
|
return 0.0;
|
|
}
|
|
|
|
// Get a pointer to the scalar tuple.
|
|
void* ptr = this->GetScalarPointer(x, y, z);
|
|
if(!ptr)
|
|
{
|
|
// An error message was already generated by GetScalarPointer.
|
|
return 0.0;
|
|
}
|
|
double result = 0.0;
|
|
|
|
// Convert the scalar type.
|
|
switch (this->GetScalarType())
|
|
{
|
|
vtkTemplateMacro(vtkImageDataConvertScalar(static_cast<VTK_TT*>(ptr)+comp,
|
|
&result));
|
|
default:
|
|
{
|
|
vtkErrorMacro("Unknown Scalar type " << this->GetScalarType());
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkImageData::SetScalarComponentFromDouble(int x, int y, int z, int comp,
|
|
double value)
|
|
{
|
|
// Check the component index.
|
|
if(comp < 0 || comp >= this->GetNumberOfScalarComponents())
|
|
{
|
|
vtkErrorMacro("Bad component index " << comp);
|
|
return;
|
|
}
|
|
|
|
// Get a pointer to the scalar tuple.
|
|
void* ptr = this->GetScalarPointer(x, y, z);
|
|
if(!ptr)
|
|
{
|
|
// An error message was already generated by GetScalarPointer.
|
|
return;
|
|
}
|
|
|
|
// Convert the scalar type.
|
|
switch (this->GetScalarType())
|
|
{
|
|
vtkTemplateMacro(vtkImageDataConvertScalar(
|
|
&value, static_cast<VTK_TT*>(ptr)+comp));
|
|
default:
|
|
{
|
|
vtkErrorMacro("Unknown Scalar type " << this->GetScalarType());
|
|
}
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
float vtkImageData::GetScalarComponentAsFloat(int x, int y, int z, int comp)
|
|
{
|
|
return this->GetScalarComponentAsDouble(x, y, z, comp);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkImageData::SetScalarComponentFromFloat(int x, int y, int z, int comp,
|
|
float value)
|
|
{
|
|
this->SetScalarComponentFromDouble(x, y, z, comp, value);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
// This Method returns a pointer to a location in the vtkImageData.
|
|
// Coordinates are in pixel units and are relative to the whole
|
|
// image origin.
|
|
void *vtkImageData::GetScalarPointer(int x, int y, int z)
|
|
{
|
|
int tmp[3];
|
|
tmp[0] = x;
|
|
tmp[1] = y;
|
|
tmp[2] = z;
|
|
return this->GetScalarPointer(tmp);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
// This Method returns a pointer to a location in the vtkImageData.
|
|
// Coordinates are in pixel units and are relative to the whole
|
|
// image origin.
|
|
void *vtkImageData::GetScalarPointerForExtent(int extent[6])
|
|
{
|
|
int tmp[3];
|
|
tmp[0] = extent[0];
|
|
tmp[1] = extent[2];
|
|
tmp[2] = extent[4];
|
|
return this->GetScalarPointer(tmp);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void *vtkImageData::GetScalarPointer(int coordinate[3])
|
|
{
|
|
vtkDataArray *scalars = this->GetPointData()->GetScalars();
|
|
|
|
// Make sure the array has been allocated.
|
|
if (scalars == NULL)
|
|
{
|
|
vtkDebugMacro("Allocating scalars in ImageData");
|
|
this->AllocateScalars();
|
|
scalars = this->PointData->GetScalars();
|
|
}
|
|
|
|
if (scalars == NULL)
|
|
{
|
|
vtkErrorMacro("Could not allocate scalars.");
|
|
return NULL;
|
|
}
|
|
|
|
const int* extent = this->Extent;
|
|
// error checking: since most access will be from pointer arithmetic.
|
|
// this should not waste much time.
|
|
for (int idx = 0; idx < 3; ++idx)
|
|
{
|
|
if (coordinate[idx] < extent[idx*2] ||
|
|
coordinate[idx] > extent[idx*2+1])
|
|
{
|
|
vtkErrorMacro(<< "GetScalarPointer: Pixel (" << coordinate[0] << ", "
|
|
<< coordinate[1] << ", "
|
|
<< coordinate[2] << ") not in memory.\n Current extent= ("
|
|
<< extent[0] << ", " << extent[1] << ", "
|
|
<< extent[2] << ", " << extent[3] << ", "
|
|
<< extent[4] << ", " << extent[5] << ")");
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
return this->GetArrayPointer(scalars, coordinate);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
// This method returns a pointer to the origin of the vtkImageData.
|
|
void *vtkImageData::GetScalarPointer()
|
|
{
|
|
if (this->PointData->GetScalars() == NULL)
|
|
{
|
|
vtkDebugMacro("Allocating scalars in ImageData");
|
|
this->AllocateScalars();
|
|
}
|
|
return this->PointData->GetScalars()->GetVoidPointer(0);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkImageData::SetScalarType(int type)
|
|
{
|
|
this->GetProducerPort();
|
|
if(vtkInformation* info = this->GetPipelineInformation())
|
|
{
|
|
vtkDataObject::SetPointDataActiveScalarInfo(info, type, -1);
|
|
}
|
|
else
|
|
{
|
|
vtkErrorMacro("SetScalarType called with no "
|
|
"executive producing this image data object.");
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
int vtkImageData::GetScalarType()
|
|
{
|
|
this->GetProducerPort();
|
|
if(vtkInformation* info = this->GetPipelineInformation())
|
|
{
|
|
vtkInformation *scalarInfo = vtkDataObject::GetActiveFieldInformation(info,
|
|
FIELD_ASSOCIATION_POINTS, vtkDataSetAttributes::SCALARS);
|
|
if (scalarInfo)
|
|
{
|
|
return scalarInfo->Get( FIELD_ARRAY_TYPE() );
|
|
}
|
|
}
|
|
return VTK_DOUBLE;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkImageData::AllocateScalars()
|
|
{
|
|
int newType = VTK_DOUBLE;
|
|
int newNumComp = 1;
|
|
|
|
// basically allocate the scalars based om the
|
|
this->GetProducerPort();
|
|
if(vtkInformation* info = this->GetPipelineInformation())
|
|
{
|
|
vtkInformation *scalarInfo = vtkDataObject::GetActiveFieldInformation(info,
|
|
FIELD_ASSOCIATION_POINTS, vtkDataSetAttributes::SCALARS);
|
|
if (scalarInfo)
|
|
{
|
|
newType = scalarInfo->Get( FIELD_ARRAY_TYPE() );
|
|
if ( scalarInfo->Has(FIELD_NUMBER_OF_COMPONENTS()) )
|
|
{
|
|
newNumComp = scalarInfo->Get( FIELD_NUMBER_OF_COMPONENTS() );
|
|
}
|
|
}
|
|
}
|
|
|
|
vtkDataArray *scalars;
|
|
|
|
// if the scalar type has not been set then we have a problem
|
|
if (newType == VTK_VOID)
|
|
{
|
|
vtkErrorMacro("Attempt to allocate scalars before scalar type was set!.");
|
|
return;
|
|
}
|
|
|
|
const int* extent = this->Extent;
|
|
|
|
// if we currently have scalars then just adjust the size
|
|
scalars = this->PointData->GetScalars();
|
|
if (scalars && scalars->GetDataType() == newType
|
|
&& scalars->GetReferenceCount() == 1)
|
|
{
|
|
scalars->SetNumberOfComponents(newNumComp);
|
|
scalars->SetNumberOfTuples((extent[1] - extent[0] + 1)*
|
|
(extent[3] - extent[2] + 1)*
|
|
(extent[5] - extent[4] + 1));
|
|
// Since the execute method will be modifying the scalars
|
|
// directly.
|
|
scalars->Modified();
|
|
return;
|
|
}
|
|
|
|
// allocate the new scalars
|
|
scalars = vtkDataArray::CreateDataArray(newType);
|
|
scalars->SetNumberOfComponents(newNumComp);
|
|
|
|
// allocate enough memory
|
|
scalars->
|
|
SetNumberOfTuples((extent[1] - extent[0] + 1)*
|
|
(extent[3] - extent[2] + 1)*
|
|
(extent[5] - extent[4] + 1));
|
|
|
|
this->PointData->SetScalars(scalars);
|
|
scalars->Delete();
|
|
}
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
int vtkImageData::GetScalarSize()
|
|
{
|
|
return vtkDataArray::GetDataTypeSize(this->GetScalarType());
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
// This templated function executes the filter for any type of data.
|
|
template <class IT, class OT>
|
|
void vtkImageDataCastExecute(vtkImageData *inData, IT *inPtr,
|
|
vtkImageData *outData, OT *outPtr,
|
|
int outExt[6])
|
|
{
|
|
int idxR, idxY, idxZ;
|
|
int maxY, maxZ;
|
|
vtkIdType inIncX, inIncY, inIncZ;
|
|
vtkIdType outIncX, outIncY, outIncZ;
|
|
int rowLength;
|
|
|
|
// find the region to loop over
|
|
rowLength = (outExt[1] - outExt[0]+1)*inData->GetNumberOfScalarComponents();
|
|
maxY = outExt[3] - outExt[2];
|
|
maxZ = outExt[5] - outExt[4];
|
|
|
|
// Get increments to march through data
|
|
inData->GetContinuousIncrements(outExt, inIncX, inIncY, inIncZ);
|
|
outData->GetContinuousIncrements(outExt, outIncX, outIncY, outIncZ);
|
|
|
|
// Loop through ouput pixels
|
|
for (idxZ = 0; idxZ <= maxZ; idxZ++)
|
|
{
|
|
for (idxY = 0; idxY <= maxY; idxY++)
|
|
{
|
|
for (idxR = 0; idxR < rowLength; idxR++)
|
|
{
|
|
// Pixel operation
|
|
*outPtr = (OT)(*inPtr);
|
|
outPtr++;
|
|
inPtr++;
|
|
}
|
|
outPtr += outIncY;
|
|
inPtr += inIncY;
|
|
}
|
|
outPtr += outIncZ;
|
|
inPtr += inIncZ;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
template <class T>
|
|
void vtkImageDataCastExecute(vtkImageData *inData, T *inPtr,
|
|
vtkImageData *outData, int outExt[6])
|
|
{
|
|
void *outPtr = outData->GetScalarPointerForExtent(outExt);
|
|
|
|
if (outPtr == NULL)
|
|
{
|
|
vtkGenericWarningMacro("Scalars not allocated.");
|
|
return;
|
|
}
|
|
|
|
switch (outData->GetScalarType())
|
|
{
|
|
vtkTemplateMacro(
|
|
vtkImageDataCastExecute(inData,
|
|
(T *)(inPtr),
|
|
outData,
|
|
(VTK_TT *)(outPtr),
|
|
outExt) );
|
|
default:
|
|
vtkGenericWarningMacro("Execute: Unknown output ScalarType");
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
// This method is passed a input and output region, and executes the filter
|
|
// algorithm to fill the output from the input.
|
|
// It just executes a switch statement to call the correct function for
|
|
// the regions data types.
|
|
void vtkImageData::CopyAndCastFrom(vtkImageData *inData, int extent[6])
|
|
{
|
|
void *inPtr = inData->GetScalarPointerForExtent(extent);
|
|
|
|
if (inPtr == NULL)
|
|
{
|
|
vtkErrorMacro("Scalars not allocated.");
|
|
return;
|
|
}
|
|
|
|
switch (inData->GetScalarType())
|
|
{
|
|
vtkTemplateMacro(vtkImageDataCastExecute(inData, (VTK_TT *)(inPtr),
|
|
this, extent) );
|
|
default:
|
|
vtkErrorMacro(<< "Execute: Unknown input ScalarType");
|
|
return;
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkImageData::Crop()
|
|
{
|
|
int nExt[6];
|
|
int idxX, idxY, idxZ;
|
|
int maxX, maxY, maxZ;
|
|
vtkIdType outId, inId, inIdY, inIdZ, incZ, incY;
|
|
vtkImageData *newImage;
|
|
int numPts, numCells, tmp;
|
|
const int* extent = this->Extent;
|
|
|
|
int updateExtent[6] = {0,-1,0,-1,0,-1};
|
|
this->GetUpdateExtent(updateExtent);
|
|
|
|
// If extents already match, then we need to do nothing.
|
|
if (extent[0] == updateExtent[0]
|
|
&& extent[1] == updateExtent[1]
|
|
&& extent[2] == updateExtent[2]
|
|
&& extent[3] == updateExtent[3]
|
|
&& extent[4] == updateExtent[4]
|
|
&& extent[5] == updateExtent[5])
|
|
{
|
|
return;
|
|
}
|
|
|
|
// Take the intersection of the two extent so that
|
|
// we are not asking for more than the extent.
|
|
this->GetUpdateExtent(nExt);
|
|
if (nExt[0] < extent[0]) { nExt[0] = extent[0];}
|
|
if (nExt[1] > extent[1]) { nExt[1] = extent[1];}
|
|
if (nExt[2] < extent[2]) { nExt[2] = extent[2];}
|
|
if (nExt[3] > extent[3]) { nExt[3] = extent[3];}
|
|
if (nExt[4] < extent[4]) { nExt[4] = extent[4];}
|
|
if (nExt[5] > extent[5]) { nExt[5] = extent[5];}
|
|
|
|
// If the extents are the same just return.
|
|
if (extent[0] == nExt[0] && extent[1] == nExt[1]
|
|
&& extent[2] == nExt[2] && extent[3] == nExt[3]
|
|
&& extent[4] == nExt[4] && extent[5] == nExt[5])
|
|
{
|
|
vtkDebugMacro("Extents already match.");
|
|
return;
|
|
}
|
|
|
|
// How many point/cells.
|
|
numPts = (nExt[1]-nExt[0]+1)*(nExt[3]-nExt[2]+1)*(nExt[5]-nExt[4]+1);
|
|
// Conditional are to handle 3d, 2d, and even 1d images.
|
|
tmp = nExt[1] - nExt[0];
|
|
if (tmp <= 0)
|
|
{
|
|
tmp = 1;
|
|
}
|
|
numCells = tmp;
|
|
tmp = nExt[3] - nExt[2];
|
|
if (tmp <= 0)
|
|
{
|
|
tmp = 1;
|
|
}
|
|
numCells *= tmp;
|
|
tmp = nExt[5] - nExt[4];
|
|
if (tmp <= 0)
|
|
{
|
|
tmp = 1;
|
|
}
|
|
numCells *= tmp;
|
|
|
|
// Create a new temporary image.
|
|
newImage = vtkImageData::New();
|
|
newImage->SetScalarType(this->GetScalarType());
|
|
newImage->SetNumberOfScalarComponents(this->GetNumberOfScalarComponents());
|
|
newImage->SetExtent(nExt);
|
|
vtkPointData *npd = newImage->GetPointData();
|
|
vtkCellData *ncd = newImage->GetCellData();
|
|
npd->CopyAllocate(this->PointData, numPts);
|
|
ncd->CopyAllocate(this->CellData, numCells);
|
|
|
|
// Loop through outData points
|
|
incY = extent[1]-extent[0]+1;
|
|
incZ = (extent[3]-extent[2]+1)*incY;
|
|
outId = 0;
|
|
inIdZ = incZ * (nExt[4]-extent[4])
|
|
+ incY * (nExt[2]-extent[2])
|
|
+ (nExt[0]-extent[0]);
|
|
|
|
for (idxZ = nExt[4]; idxZ <= nExt[5]; idxZ++)
|
|
{
|
|
inIdY = inIdZ;
|
|
for (idxY = nExt[2]; idxY <= nExt[3]; idxY++)
|
|
{
|
|
inId = inIdY;
|
|
for (idxX = nExt[0]; idxX <= nExt[1]; idxX++)
|
|
{
|
|
npd->CopyData( this->PointData, inId, outId);
|
|
++inId;
|
|
++outId;
|
|
}
|
|
inIdY += incY;
|
|
}
|
|
inIdZ += incZ;
|
|
}
|
|
|
|
// Loop through outData cells
|
|
// Have to handle the 2d and 1d cases.
|
|
maxX = nExt[1];
|
|
maxY = nExt[3];
|
|
maxZ = nExt[5];
|
|
if (maxX == nExt[0])
|
|
{
|
|
++maxX;
|
|
}
|
|
if (maxY == nExt[2])
|
|
{
|
|
++maxY;
|
|
}
|
|
if (maxZ == nExt[4])
|
|
{
|
|
++maxZ;
|
|
}
|
|
incY = extent[1]-extent[0];
|
|
incZ = (extent[3]-extent[2])*incY;
|
|
outId = 0;
|
|
inIdZ = incZ * (nExt[4]-extent[4])
|
|
+ incY * (nExt[2]-extent[2])
|
|
+ (nExt[0]-extent[0]);
|
|
for (idxZ = nExt[4]; idxZ < maxZ; idxZ++)
|
|
{
|
|
inIdY = inIdZ;
|
|
for (idxY = nExt[2]; idxY < maxY; idxY++)
|
|
{
|
|
inId = inIdY;
|
|
for (idxX = nExt[0]; idxX < maxX; idxX++)
|
|
{
|
|
ncd->CopyData(this->CellData, inId, outId);
|
|
++inId;
|
|
++outId;
|
|
}
|
|
inIdY += incY;
|
|
}
|
|
inIdZ += incZ;
|
|
}
|
|
|
|
this->PointData->ShallowCopy(npd);
|
|
this->CellData->ShallowCopy(ncd);
|
|
this->SetExtent(nExt);
|
|
newImage->Delete();
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
double vtkImageData::GetScalarTypeMin()
|
|
{
|
|
return vtkDataArray::GetDataTypeMin(this->GetScalarType());
|
|
}
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
double vtkImageData::GetScalarTypeMax()
|
|
{
|
|
return vtkDataArray::GetDataTypeMax(this->GetScalarType());
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkImageData::SetExtent(int x1, int x2, int y1, int y2, int z1, int z2)
|
|
{
|
|
int ext[6];
|
|
ext[0] = x1;
|
|
ext[1] = x2;
|
|
ext[2] = y1;
|
|
ext[3] = y2;
|
|
ext[4] = z1;
|
|
ext[5] = z2;
|
|
this->SetExtent(ext);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkImageData::SetExtent(int *extent)
|
|
{
|
|
int description;
|
|
|
|
description = vtkStructuredData::SetExtent(extent, this->Extent);
|
|
if ( description < 0 ) //improperly specified
|
|
{
|
|
vtkErrorMacro (<< "Bad Extent, retaining previous values");
|
|
}
|
|
|
|
if (description == VTK_UNCHANGED)
|
|
{
|
|
return;
|
|
}
|
|
|
|
this->DataDescription = description;
|
|
|
|
this->Modified();
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
int *vtkImageData::GetDimensions()
|
|
{
|
|
const int* extent = this->Extent;
|
|
this->Dimensions[0] = extent[1] - extent[0] + 1;
|
|
this->Dimensions[1] = extent[3] - extent[2] + 1;
|
|
this->Dimensions[2] = extent[5] - extent[4] + 1;
|
|
|
|
return this->Dimensions;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkImageData::GetDimensions(int *dOut)
|
|
{
|
|
int *dims = this->GetDimensions();
|
|
dOut[0] = dims[0];
|
|
dOut[1] = dims[1];
|
|
dOut[2] = dims[2];
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkImageData::SetAxisUpdateExtent(int idx, int min, int max)
|
|
{
|
|
int modified = 0;
|
|
|
|
if (idx > 2)
|
|
{
|
|
vtkWarningMacro("illegal axis!");
|
|
return;
|
|
}
|
|
|
|
int updateExtent[6] = {0,-1,0,-1,0,-1};
|
|
this->GetUpdateExtent(updateExtent);
|
|
|
|
if (updateExtent[idx*2] != min)
|
|
{
|
|
modified = 1;
|
|
updateExtent[idx*2] = min;
|
|
}
|
|
if (updateExtent[idx*2+1] != max)
|
|
{
|
|
modified = 1;
|
|
updateExtent[idx*2+1] = max;
|
|
}
|
|
|
|
this->SetUpdateExtent(updateExtent);
|
|
if (modified)
|
|
{
|
|
this->Modified();
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkImageData::GetAxisUpdateExtent(int idx, int &min, int &max)
|
|
{
|
|
if (idx > 2)
|
|
{
|
|
vtkWarningMacro("illegal axis!");
|
|
return;
|
|
}
|
|
|
|
int updateExtent[6] = {0,-1,0,-1,0,-1};
|
|
this->GetUpdateExtent(updateExtent);
|
|
min = updateExtent[idx*2];
|
|
max = updateExtent[idx*2+1];
|
|
}
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
unsigned long vtkImageData::GetActualMemorySize()
|
|
{
|
|
return this->vtkDataSet::GetActualMemorySize();
|
|
}
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkImageData::ShallowCopy(vtkDataObject *dataObject)
|
|
{
|
|
vtkImageData *imageData = vtkImageData::SafeDownCast(dataObject);
|
|
|
|
if ( imageData != NULL )
|
|
{
|
|
this->InternalImageDataCopy(imageData);
|
|
}
|
|
|
|
// Do superclass
|
|
this->vtkDataSet::ShallowCopy(dataObject);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkImageData::DeepCopy(vtkDataObject *dataObject)
|
|
{
|
|
vtkImageData *imageData = vtkImageData::SafeDownCast(dataObject);
|
|
|
|
if ( imageData != NULL )
|
|
{
|
|
this->InternalImageDataCopy(imageData);
|
|
}
|
|
|
|
// Do superclass
|
|
this->vtkDataSet::DeepCopy(dataObject);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
// This copies all the local variables (but not objects).
|
|
void vtkImageData::InternalImageDataCopy(vtkImageData *src)
|
|
{
|
|
int idx;
|
|
|
|
this->DataDescription = src->DataDescription;
|
|
this->SetScalarType(src->GetScalarType());
|
|
this->SetNumberOfScalarComponents(src->GetNumberOfScalarComponents());
|
|
for (idx = 0; idx < 3; ++idx)
|
|
{
|
|
this->Dimensions[idx] = src->Dimensions[idx];
|
|
this->Increments[idx] = src->Increments[idx];
|
|
this->Origin[idx] = src->Origin[idx];
|
|
this->Spacing[idx] = src->Spacing[idx];
|
|
}
|
|
memcpy(this->Extent, src->GetExtent(), 6*sizeof(int));
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
vtkIdType vtkImageData::GetNumberOfCells()
|
|
{
|
|
vtkIdType nCells=1;
|
|
int i;
|
|
int *dims = this->GetDimensions();
|
|
|
|
for (i=0; i<3; i++)
|
|
{
|
|
if (dims[i] == 0)
|
|
{
|
|
return 0;
|
|
}
|
|
if (dims[i] > 1)
|
|
{
|
|
nCells *= (dims[i]-1);
|
|
}
|
|
}
|
|
|
|
return nCells;
|
|
}
|
|
|
|
//============================================================================
|
|
// Starting to make some more general methods that deal with any array
|
|
// (not just scalars).
|
|
//============================================================================
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
// This Method returns a pointer to a location in the vtkImageData.
|
|
// Coordinates are in pixel units and are relative to the whole
|
|
// image origin.
|
|
void vtkImageData::GetArrayIncrements(vtkDataArray* array, vtkIdType increments[3])
|
|
{
|
|
const int* extent = this->Extent;
|
|
// We could store tupple increments and just
|
|
// multiply by the number of componenets...
|
|
increments[0] = array->GetNumberOfComponents();
|
|
increments[1] = increments[0] * (extent[1]-extent[0]+1);
|
|
increments[2] = increments[1] * (extent[3]-extent[2]+1);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void *vtkImageData::GetArrayPointerForExtent(vtkDataArray* array,
|
|
int extent[6])
|
|
{
|
|
int tmp[3];
|
|
tmp[0] = extent[0];
|
|
tmp[1] = extent[2];
|
|
tmp[2] = extent[4];
|
|
return this->GetArrayPointer(array, tmp);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
// This Method returns a pointer to a location in the vtkImageData.
|
|
// Coordinates are in pixel units and are relative to the whole
|
|
// image origin.
|
|
void *vtkImageData::GetArrayPointer(vtkDataArray* array, int coordinate[3])
|
|
{
|
|
vtkIdType incs[3];
|
|
int idx;
|
|
|
|
if (array == NULL)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
const int* extent = this->Extent;
|
|
// error checking: since most acceses will be from pointer arithmetic.
|
|
// this should not waste much time.
|
|
for (idx = 0; idx < 3; ++idx)
|
|
{
|
|
if (coordinate[idx] < extent[idx*2] ||
|
|
coordinate[idx] > extent[idx*2+1])
|
|
{
|
|
vtkErrorMacro(<< "GetPointer: Pixel (" << coordinate[0] << ", "
|
|
<< coordinate[1] << ", "
|
|
<< coordinate[2] << ") not in current extent: ("
|
|
<< extent[0] << ", " << extent[1] << ", "
|
|
<< extent[2] << ", " << extent[3] << ", "
|
|
<< extent[4] << ", " << extent[5] << ")");
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
// compute the index of the vector.
|
|
this->GetArrayIncrements(array, incs);
|
|
idx = ((coordinate[0] - extent[0]) * incs[0]
|
|
+ (coordinate[1] - extent[2]) * incs[1]
|
|
+ (coordinate[2] - extent[4]) * incs[2]);
|
|
// I could check to see if the array has the correct number
|
|
// of tupples for the extent, but that would be an extra multiply.
|
|
if (idx < 0 || idx > array->GetMaxId())
|
|
{
|
|
vtkErrorMacro("Coordinate (" << coordinate[0] << ", " << coordinate[1]
|
|
<< ", " << coordinate[2] << ") out side of array (max = "
|
|
<< array->GetMaxId());
|
|
return NULL;
|
|
}
|
|
|
|
return array->GetVoidPointer(idx);
|
|
}
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkImageData::ComputeInternalExtent(int *intExt, int *tgtExt, int *bnds)
|
|
{
|
|
int i;
|
|
const int* extent = this->Extent;
|
|
for (i = 0; i < 3; ++i)
|
|
{
|
|
intExt[i*2] = tgtExt[i*2];
|
|
if (intExt[i*2] - bnds[i*2] < extent[i*2])
|
|
{
|
|
intExt[i*2] = extent[i*2] + bnds[i*2];
|
|
}
|
|
intExt[i*2+1] = tgtExt[i*2+1];
|
|
if (intExt[i*2+1] + bnds[i*2+1] > extent[i*2+1])
|
|
{
|
|
intExt[i*2+1] = extent[i*2+1] - bnds[i*2+1];
|
|
}
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
vtkImageData* vtkImageData::GetData(vtkInformation* info)
|
|
{
|
|
return info? vtkImageData::SafeDownCast(info->Get(DATA_OBJECT())) : 0;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
vtkImageData* vtkImageData::GetData(vtkInformationVector* v, int i)
|
|
{
|
|
return vtkImageData::GetData(v->GetInformationObject(i));
|
|
}
|
|
|