Converting VTK PolyData to VTK ImageData with vtkResampleToImage and Rendering ImageData

Hi everyone,

I’m working on converting a vtkPolyData object into vtkImageData using vtkResampleToImage. My vtkPolyData consists of multiple nested mesh surfaces, each with distinct cell/point scalar values to differentiate between them.

After converting to vtkImageData, I wrote a script to render the resulting image data. While the rendering displays the correct spatial positioning, it doesn’t seem to include any of the scalar data from the original vtkPolyData.

Here’s what I’ve tried so far:

  1. Used vtkResampleToImage to convert the vtkPolyData to vtkImageData.
  2. Wrote a rendering script to visualize the vtkImageData.

The issue is that the rendered output only shows the correct position but lacks the scalar data (e.g., no color or values from the original meshes).

Has anyone encountered this issue before? Am I missing a step in the conversion or rendering process? Any advice or suggestions would be greatly appreciated!

Thanks in advance!
The function to make voxelgrid from vtkpolydata:

    vtkSmartPointer<vtkStructuredGrid> SegmentationIO::MakeVoxelGrid2(vtkSmartPointer<vtkPolyData>& polydata)
    {
    vtkNew<vtkCellDataToPointData> cellToPoint;
    cellToPoint->SetInputData(polydata);
    cellToPoint->PassCellDataOn(); // Optionally discard the original cell data.
    cellToPoint->Update();
//    vtkSmartPointer<vtkPolyData> polyWithPointScalars = cellToPoint->GetOutput();
    vtkSmartPointer<vtkPolyData> polyWithPointScalars = vtkPolyData::SafeDownCast(cellToPoint->GetOutput());

    // Check that IBODY is present in the point data.
    vtkDataArray* ibodyArray = polyWithPointScalars->GetPointData()->GetArray("IBODY");
    if (!ibodyArray){std::cerr << "Error: IBODY array not found in point data!" << std::endl;return nullptr;}

//    vtkSmartPointer<vtkDataSet> dataset = polydata; // polyData is a vtkPolyData


    // Resample the polydata to an image.
    vtkNew<vtkResampleToImage> resample;
    resample->SetInputConnection(cellToPoint->GetOutputPort());
    
    // Use the polydata's bounds as the sampling bounds.
    double bounds[6];
    polyWithPointScalars->GetBounds(bounds);
    resample->SetSamplingBounds(bounds);
    
    int dimX = static_cast<int>((bounds[1] - bounds[0]) ) + 1;
    int dimY = static_cast<int>((bounds[3] - bounds[2]) ) + 1;
    int dimZ = static_cast<int>((bounds[5] - bounds[4]) ) + 1;
    resample->SetSamplingDimensions(dimX, dimY, dimZ);

    
    
    // Set the desired sampling dimensions.
//    resample->SetSamplingDimensions(NXVOXEL, NYVOXEL, NZVOXEL);
    resample->Update();
    
    vtkSmartPointer<vtkImageData> imageData = resample->GetOutput();
    
    double position[3] = {dimX/2,-10,dimZ/2};
    RenderImageData(imageData,position,10, 0.5);
    
    using VTKImageToImageType = itk::VTKImageToImageFilter<ImageTypeTiff>;

    auto vtkImageToImageFilter = VTKImageToImageType::New();
    vtkImageToImageFilter->SetInput(imageData);
    vtkImageToImageFilter->Update();

    auto image = ImageTypeTiff::New();
    image->Graft(vtkImageToImageFilter->GetOutput()); // Need to do this because QuickView can't accept const

    // Example: Write the ITK image to a file
    typedef itk::ImageFileWriter<ImageTypeTiff> WriterType;
    WriterType::Pointer writer = WriterType::New();
    writer->SetFileName("labelImage.tiff"); 
    writer->SetInput(image);
    try {writer->Update();} catch (itk::ExceptionObject& err) {std::cerr << "ITK Exception: " << err << std::endl;}

    
    vtkNew<vtkMetaImageWriter> imageWriter;
    imageWriter->SetFileName("labelImage.mhd");
    imageWriter->SetInputData(imageData);
    imageWriter->Write();
    
    
    // Convert the vtkImageData to a vtkStructuredGrid.
    vtkSmartPointer<vtkStructuredGrid> structuredGrid = ConvertImageDataToStructuredGrid(imageData);
    return structuredGrid; }	

The function to render vtkImageData:

    void RenderImageData(vtkSmartPointer<vtkImageData>& imageData, double position[], double distance, double transparency)
    {
        std::cout << "There are " << imageData->GetNumberOfPoints() << " points." << std::endl;
        std::cout << "There are " << imageData->GetNumberOfCells() << " cells." << std::endl;

        imageData->GetPointData()->SetActiveScalars("IBODY");
        
        int dimensions[3]; imageData->GetDimensions(dimensions);
        
        auto dataSize = dimensions[0]*dimensions[1]*dimensions[2];
        
        
        vtkNew<vtkLookupTable> lut;
        lut->SetNumberOfTableValues(dataSize);
        lut->Build();


        vtkNew<vtkDataSetMapper> mapper;
        mapper->SetInputData(imageData);
        mapper->SetScalarModeToUsePointData();
        mapper->SetLookupTable(lut);
        mapper->SetScalarRange(0, dataSize - 1);
        mapper->ScalarVisibilityOn();

        vtkNew<vtkActor> actor;
        actor->SetMapper(mapper);
        actor->GetProperty()->SetOpacity(transparency);

        vtkNew<vtkNamedColors> colors;

        vtkNew<vtkRenderer> renderer;
        renderer->SetBackground(colors->GetColor3d("LightSteelBlue").GetData());

        vtkNew<vtkOpenGLRenderWindow> renderWindow;
        renderWindow->OffScreenRenderingOn();
        renderWindow->SetShowWindow(false);
        renderWindow->SetSize(640, 480);
        renderWindow->SetWindowName("Voxel Grid Render Window");
        renderWindow->AddRenderer(renderer);

        vtkNew<vtkRenderWindowInteractor> interactor;
        interactor->SetRenderWindow(renderWindow);

        std::string legend = "Image Data No of Cells : " + std::to_string(NXVOXEL) + " " + std::to_string(NYVOXEL) + " " + std::to_string(NZVOXEL);

        vtkNew<vtkTextActor> txt;
        txt->SetInput(legend.c_str());
        vtkTextProperty* txtprop = txt->GetTextProperty();
        txtprop->SetFontFamilyToArial();
        txtprop->SetFontSize(12);
        txtprop->SetColor(colors->GetColor3d("Blue").GetData());
        txt->SetDisplayPosition(20, 12);

        double bounds[6];
        imageData->GetBounds(bounds);

        vtkNew<vtkCubeAxesActor> cubeAxesActor;
        cubeAxesActor->GetProperty()->SetColor(colors->GetColor3d("Gold").GetData());
        cubeAxesActor->SetBounds(bounds);
        cubeAxesActor->SetCamera(renderer->GetActiveCamera());
        cubeAxesActor->SetXUnits("cm");
        cubeAxesActor->SetYUnits("cm");
        cubeAxesActor->SetZUnits("cm");

        renderer->AddActor(actor);
        renderer->AddActor(txt);
        renderer->AddActor(cubeAxesActor);

        renderer->GetActiveCamera()->Elevation(-90);
        renderer->ResetCamera();
        renderWindow->Render();

        vtkNew<vtkWindowToImageFilter> windowToImageFilter;
        windowToImageFilter->SetInput(renderWindow);
        windowToImageFilter->Update();

        std::string body = "image_data_render.png";

        vtkNew<vtkPNGWriter> writer;
        writer->SetFileName(body.c_str());
        writer->SetInputConnection(windowToImageFilter->GetOutputPort());
        writer->Write();
        std::cerr << "Image Data Visualization Ok." << std::endl;

        auto camera = renderer->GetActiveCamera();
        camera->SetPosition(position[0], position[1], position[2]);
        camera->SetFocalPoint(1, 1.5, 2);
        camera->SetViewUp(0, 0, 1);
        camera->SetDistance(distance);

        std::cout << "Camera Ok" << std::endl;

        interactor->Start();}