The article shows how to cut a volume by a plane and display the cut section. The left renderer contains the original volume object, and the right renderer shows the cross section in the window.
We have to initialize the module vtkRenderingVolumeOpenGL2 before start to render volume.
All implementation details are in the following code snippet.

Environment:
VTK-9.0.1
macOS Big Sur 11.1

#include <iostream>
#include <vtkSmartPointer.h>
#include <vtkSphereSource.h>
#include <vtkActor.h>
#include <vtkConeSource.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkPolyDataMapper.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkImageData.h>
#include <vtkImageStencil.h>
#include <vtkPolyDataToImageStencil.h>
#include <vtkColorTransferFunction.h>
#include <vtkPointData.h>
#include <vtkCamera.h>
#include <vtkVolumeProperty.h>
#include <vtkSmartVolumeMapper.h>
#include <vtkCutter.h>
#include <vtkPlane.h>
#include <vtkPiecewiseFunction.h>
#include <vtkPolyDataNormals.h>
#include <vtkFillHolesFilter.h>
#include <vtkImageMarchingCubes.h>
#include <vtkVolume.h>
#include <vtkRenderingVolumeOpenGL2Module.h>
#include <vtkProperty.h>

#define vtkSPtr vtkSmartPointer
#define vtkSPtrNew(Var, Type) vtkSPtr<Type> Var = vtkSPtr<Type>::New();

using namespace std;

#define vtkSPtr vtkSmartPointer
#define vtkSPtrNew(Var, Type) vtkSPtr<Type> Var = vtkSPtr<Type>::New();

unsigned char inval = 255;
unsigned char outval = 0;
double spacingVal = 0.5;

vtkSPtr<vtkImageData> ConvertPolydataToImage(vtkPolyData *polydata)
{
    double spacingVal = 0.5;
    double bounds[6];
    polydata->GetBounds(bounds);

    int dim[3];
    for (int i = 0; i < 3; i++)
    {
        dim[i] = static_cast<int>( ceil((bounds[2 * i + 1] - bounds[2 * i]) / spacingVal) );
    }
    double origin[3];
    origin[0] = bounds[0] + spacingVal / 2;
    origin[1] = bounds[2] + spacingVal / 2;
    origin[2] = bounds[4] + spacingVal / 2;

    vtkSPtrNew(imageData, vtkImageData)
    imageData->SetSpacing(spacingVal, spacingVal, spacingVal);
    imageData->SetDimensions(dim);
    imageData->SetOrigin(origin);
    imageData->AllocateScalars(VTK_UNSIGNED_CHAR, 1);
    imageData->SetExtent( 0, dim[0] - 1, 0, dim[1] - 1, 0, dim[2] - 1 );

    // fill the imageData with foreground voxels
    vtkIdType count = imageData->GetNumberOfPoints();
    for (vtkIdType i = 0; i < count; ++i)
    {
        imageData->GetPointData()->GetScalars()->SetTuple1(i, inval);
    }

    // polygonal data --> imageData stencil:
    vtkSPtrNew(pd2stenc, vtkPolyDataToImageStencil);
    pd2stenc->SetInputData(polydata);
    pd2stenc->SetOutputOrigin(origin);
    pd2stenc->SetOutputSpacing(spacingVal, spacingVal, spacingVal);
    pd2stenc->SetOutputWholeExtent(imageData->GetExtent());
    pd2stenc->Update();

    // cut the corresponding white imageData and set the background:
    vtkSPtrNew(imgstenc, vtkImageStencil);
    imgstenc->SetInputData(imageData);
    imgstenc->SetStencilConnection(pd2stenc->GetOutputPort());
    imgstenc->ReverseStencilOff();
    imgstenc->SetBackgroundValue( outval );
    imgstenc->Update();

    imageData->DeepCopy(imgstenc->GetOutput());
    return imageData;
}

#include <vtkAutoInit.h>
VTK_MODULE_INIT(vtkRenderingVolumeOpenGL2);

int main()
{
    vtkSPtrNew( cone, vtkConeSource );
    cone->Update();

    vtkSPtr<vtkImageData> data = ConvertPolydataToImage( cone->GetOutput() );

    vtkSPtrNew( volumeMapper, vtkSmartVolumeMapper );
    volumeMapper->SetInputData( data );

    vtkSPtrNew( volumeProperty, vtkVolumeProperty );
    volumeProperty->ShadeOff();
    volumeProperty->SetInterpolationType(VTK_LINEAR_INTERPOLATION);

    vtkSPtrNew( volume, vtkVolume );
    volume->SetProperty( volumeProperty );
    volume->SetMapper( volumeMapper );

    //========= start to cut =========
    vtkSPtrNew( plane, vtkPlane );
    plane->SetOrigin( 0, 0, 0 );
    plane->SetNormal( 0, 1, 0 );
    vtkSPtrNew( cutter, vtkCutter );
    cutter->SetCutFunction( plane );
    cutter->SetInputData( data );
    cutter->Update();

    vtkSPtrNew( mapper, vtkPolyDataMapper );
    mapper->SetInputConnection( cutter->GetOutputPort() );

    vtkSPtrNew( actor, vtkActor );
    actor->SetMapper( mapper );
    actor->GetProperty()->SetColor( 1, 0, 0 );
    //========= finished: cut ========

    vtkSPtrNew( camera, vtkCamera );

    // Define viewport ranges
    // (xmin, ymin, xmax, ymax) left-top and right-bottom point
    double leftViewport[4] = {0.0, 0.0, 0.5, 1.0};
    double rightViewport[4] = {0.5, 0.0, 1.0, 1.0};
    // Setup renderers
    vtkSmartPointer<vtkRenderer> leftRenderer =
        vtkSmartPointer<vtkRenderer>::New();
    leftRenderer->SetViewport( leftViewport );
    leftRenderer->AddViewProp( volume );
    leftRenderer->SetBackground( .6, .5, .4 );
    leftRenderer->SetActiveCamera( camera );

    vtkSmartPointer<vtkRenderer> rightRenderer =
        vtkSmartPointer<vtkRenderer>::New();
    rightRenderer->SetViewport( rightViewport );
    rightRenderer->AddActor( actor );
    rightRenderer->SetBackground( .4, .5, .6 );
    rightRenderer->SetActiveCamera( camera );

    vtkSPtrNew( renderWindow, vtkRenderWindow );

    vtkSPtrNew( renderWindowInteractor, vtkRenderWindowInteractor );
    renderWindowInteractor->SetRenderWindow( renderWindow );

    renderWindow->SetSize( 800, 400 );
    leftRenderer->ResetCamera();
    renderWindow->AddRenderer( leftRenderer );
    renderWindow->AddRenderer( rightRenderer );
    renderWindow->Render();
    renderWindowInteractor->Start();
    return 0;
}

Result:

Categories: VTK

0 0 vote
Article Rating
Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments
A prohibited operation
0
Would love your thoughts, please comment.x
()
x