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
vtkImageData) instance. Is there a way to extract the cells of the
vtkStructuredGrid to use them in the
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.
I can set transparency in my
But this is not rendered as an actual volume (
vtkImageData), that is, only the outside-facing cells are rendered. If this helps, I can post the code.
unfortunately, I have to render the
vtkStructuredGrid as an actual volume to look “into” the volume.
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
image->SetDimensions(nI, nJ, nK);
double dX = x_extent / nI;
double dY = y_extent / nJ;
double dZ = z_extent / nK;
image->SetSpacing( dX, dY, dZ);
In the code above,
*_extent are the extents of your
vtkUnstructuredGrid along the main axes (compute the bounding box of your
vtkUnstructuredGrid with the
GetBounds method: https://vtk.org/doc/nightly/html/classvtkDataSet.html#a9e3d8ff1ca5cafdc8433772d09b5a70f).
n* are the resolutions (number of voxels) of your output
- Scan the output
vtkImageData, querying the value of the input
vtkUnstructuredGrid that exists in the x,y,z location of a given
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,
get_value_at() function that does the following:
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.