Here is relevant introduction about vtkImageData from VTKUsersGuide.
A vtkImageData dataset is defined by data dimensions, interpoint spacing, and the origin (i.e., lower-left corner) of the dataset. If the dimension of the dataset is two, then we call the vtkImageData dataset an image, and it is composed of vtkPixel cell types. If the dimension of the dataset is three, then we call the vtkImageData dataset a volume, and it is composed of vtkVoxel cells.
I’m curious about how to create a vtkImageData instance and show it in renderer window. The following section contains my demo code, it create image data object and calculate all cell center position, then the project shows all points. The white points are vertices of image data, the red points represent all center of cells.
The algorithm class vtkImageDataGeometryFilter can help us to display vtkImageData object with small white points.
#include <vtkSmartPointer.h>
#include <vtkCell.h>
#include <vtkImageData.h>
#include <vtkImageMapper3D.h>
#include <vtkImageActor.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkImageDataGeometryFilter.h>
#include <vtkPolyDataMapper.h>
#include <vtkImageMarchingCubes.h>
#include <vtkPointData.h>
#include <vtkPointSource.h>
#include <vtkSphereSource.h>
#include <vtkProperty.h>
#include <vector>
using namespace std;
static void GetCellCenter(vtkImageData* imageData, const unsigned int cellId,
double center[3]);
int main(int, char *[])
{
vtkSmartPointer<vtkImageData> imageData =
vtkSmartPointer<vtkImageData>::New();
imageData->SetDimensions(3,3,2); // This will cause 18 points and 4 cells
imageData->SetSpacing(1.0, 1.0, 1.0);
imageData->SetOrigin(0.0, 0.0, 0.0);
std::cout << "Number of points: " << imageData->GetNumberOfPoints() << std::endl;
std::cout << "Number of cells: " << imageData->GetNumberOfCells() << std::endl;
double center[3] = {0,0,0};
vector<vtkSmartPointer<vtkSphereSource>> centerPoints;
for(vtkIdType cellId = 0; cellId < imageData->GetNumberOfCells(); ++cellId)
{
GetCellCenter(imageData, cellId, center);
vtkSmartPointer<vtkSphereSource> tmpPoint =
vtkSmartPointer<vtkSphereSource>::New();
tmpPoint->SetCenter( center );
centerPoints.push_back( tmpPoint );
std::cout << "Cell " << cellId << " center: " << center[0] << " "
<< center[1] << " " << center[2] << std::endl;
}
vtkSmartPointer<vtkImageDataGeometryFilter> geometryFilter =
vtkSmartPointer<vtkImageDataGeometryFilter>::New();
geometryFilter->SetInputData( imageData );
geometryFilter->Update();
vtkSmartPointer<vtkPolyDataMapper> mapper =
vtkSmartPointer<vtkPolyDataMapper>::New();
mapper->SetInputData( geometryFilter->GetOutput() ); //cubes->GetOutput() );
vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
actor->SetMapper( mapper );
vtkSmartPointer<vtkRenderer> renderer =
vtkSmartPointer<vtkRenderer>::New();
renderer->AddActor( actor );
renderer->SetBackground( 0, 0, 0 );
vtkSmartPointer<vtkRenderWindow> renderWindow =
vtkSmartPointer<vtkRenderWindow>::New();
renderWindow->AddRenderer( renderer );
vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor =
vtkSmartPointer<vtkRenderWindowInteractor>::New();
renderWindowInteractor->SetRenderWindow( renderWindow );
for( int i = 0; i < centerPoints.size(); ++i )
{
centerPoints[i]->SetRadius( 0.05 );
centerPoints[i]->Update();
vtkSmartPointer<vtkPolyDataMapper> pointMapper =
vtkSmartPointer<vtkPolyDataMapper>::New();
pointMapper->SetInputData( centerPoints[i]->GetOutput() );
vtkSmartPointer<vtkActor> pointActor =
vtkSmartPointer<vtkActor>::New();
pointActor->SetMapper( pointMapper );
pointActor->GetProperty()->SetColor( 1, 0, 0 );
renderer->AddActor( pointActor );
}
renderer->ResetCamera();
renderWindow->Render();
renderWindowInteractor->Start();
return EXIT_SUCCESS;
}
void GetCellCenter(vtkImageData* imageData, const unsigned int cellId, double center[3])
{
double pcoords[3] = {0,0,0};
double *weights = new double [imageData->GetMaxCellSize()];
vtkCell* cell = imageData->GetCell(cellId);
int subId = cell->GetParametricCenter(pcoords);
cell->EvaluateLocation(subId, pcoords, center, weights);
delete[] weights;
}
output:
Number of points: 18
Number of cells: 4
Cell 0 center: 0.5 0.5 0.5
Cell 1 center: 1.5 0.5 0.5
Cell 2 center: 0.5 1.5 0.5
Cell 3 center: 1.5 1.5 0.5
But I wondered how to display the image data just as normal polydata? After all, we want to see the surface of the model rather than points in most situations.
It’s not difficult for us to finish the task, we just need to replace vtkPolydataMapper
with vtkDataSetMapper
.
vtkSmartPointer<vtkDataSetMapper> mapper =
vtkSmartPointer<vtkDataSetMapper>::New();
mapper->SetInputData( imageData );