I have a vtkStructuredGrid whose points are not distributed on a uniform rectangular grid. I want to use the volume rendering capabilities like opacity transfer functions.
To achieve that, I have to convert the vtkStructuredGrid instance to a vtkUnstructuredGrid (or vtkImageData) instance. Is there a way to extract the cells of the vtkStructuredGrid to use them in the vtkUnstructuredGrid?
Alternatively, is it possible to apply opacity transfer functions when using vtkStructuredGrid instances? Since I want to animate the volume, I guess a vtkStructuredGrid would be beneficial regarding the performance.
Ok… given that your original vtkStructuredGrid is not regular, you will have to “raster” it into a regularly spaced grid. This is much like rastering a vector drawing into pixels. Searching the internet, I couldn’t find a VTK filter that could do this. Hence, you are left for implementing this operation yourself like I did. Unfortunately my code does this as domain objects in my program (gammaray/valuestransferer.cpp at master · PauloCarvalhoRJ/gammaray · GitHub), not as VTK objects, as VTK is only used for visualization.
The basic steps to do this with VTK objects (untested code based on my code for my domain classes):
Create a vtkImageData large enough to contain the volume of your original vtkUnstructuredGrid:
Scan the output vtkImageData, querying the value of the input vtkUnstructuredGrid that exists in the x,y,z location of a given vtkImageData voxel:
for (int k = 0; k < nK; k++)
{
double cellCenterZ = originZ + k * dZ + dZ/2;
for (int j = 0; j < nJ; j++)
{
double cellCenterY = originY + j * dY + dY/2;
for (int i = 0; i < nI; i++)
{
double cellCenterX = originX + i * dX + dX/2;
unsigned char* ptr = (unsigned char*)image->GetScalarPointer(i, j, k);
*ptr = get_value_at( unstructuredGrid,
cellCenterX,
cellCenterY,
cellCenterZ );
}
}
}
Write a get_value_at() function that does the following:
3.1) Call unstructuredGrid()->FindCell(cellCenterX, cellCenterY, cellCenterZ, ... ) to retrieve the cell index of the vtkUnstructuredGrid containing or near the center of a cell of the output vtkImageData. Refer do its documentation regarding the other parameters: https://vtk.org/doc/nightly/html/classvtkDataSet.html#a2221c10d3c4cca44e82c5ef70e4e1cbd .
3.2) Using the index returned by FindCell(), get the scalar value contained in it:
vtkCellData *cellData = unstructuredGrid->GetCellData();
vtkDataArray* data = cellData->GetArray( id_returned_by_FindIndex );
return data->GetTuple1( 0 ); //this assumes you have one scalar in each cell.
//Query data->GetNumberOfTuples() to get the number of values per cell in
//multi-valued grids. You may even have no data in a given cell (defensive programming alert!)
Of course there will be much more code than posted here, but I hope this helps to get you started and understand the center tasks to perform a data transfer between grids with different geometries and topologies.