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:

cut volume
Categories: VTK

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Inline Feedbacks
View all comments

Content Summary
: Input your strings, the tool can get a brief summary of the content for you.

X
0
Would love your thoughts, please comment.x
()
x