Skip to content

PineRootDecimation

vtk-examples/Python/VisualizationAlgorithms/PineRootDecimation

Description

Demonstrates how to apply the decimation filter to get a reduced data size and then the connectivity filter to remove noisy isosurfaces. The data is from the root system of a pine tree.

To count the number of triangles in the polydata we do the following:

C++

We use a lambda function

auto NumberofTriangles = [](auto *pd)

Python

We just implement:

def NumberOfTriangles(pd):

within the scope of the calling function.

Info

See Figure 9-52 in Chapter 9 in the VTK Textbook.

Other languages

See (Cxx)

Question

If you have a question about this example, please use the VTK Discourse Forum

Code

PineRootDecimation.py

#!/usr/bin/env python

# noinspection PyUnresolvedReferences
import vtkmodules.vtkInteractionStyle
# noinspection PyUnresolvedReferences
import vtkmodules.vtkRenderingOpenGL2
from vtkmodules.vtkCommonColor import vtkNamedColors
from vtkmodules.vtkCommonCore import vtkIdList
from vtkmodules.vtkFiltersCore import (
    vtkConnectivityFilter,
    vtkDecimatePro
)
from vtkmodules.vtkFiltersModeling import vtkOutlineFilter
from vtkmodules.vtkIOGeometry import vtkMCubesReader
from vtkmodules.vtkRenderingCore import (
    vtkActor,
    vtkDataSetMapper,
    vtkPolyDataMapper,
    vtkRenderWindow,
    vtkRenderWindowInteractor,
    vtkRenderer
)


def main():
    def NumberOfTriangles(pd):
        """
        Count the number of triangles.
        :param pd: vtkPolyData.
        :return: The number of triangles.
        """
        cells = pd.GetPolys()
        numOfTriangles = 0
        idList = vtkIdList()
        for i in range(0, cells.GetNumberOfCells()):
            cells.GetNextCell(idList)
            # If a cell has three points it is a triangle.
            if idList.GetNumberOfIds() == 3:
                numOfTriangles += 1
        return numOfTriangles

    colors = vtkNamedColors()

    fileName = get_program_parameters()

    # Create the pipeline.
    reader = vtkMCubesReader()
    reader.SetFileName(fileName)
    reader.FlipNormalsOff()
    reader.Update()
    print('Before Decimation.')
    print('There are: ', NumberOfTriangles(reader.GetOutput()), 'triangles')

    deci = vtkDecimatePro()
    deci.SetInputConnection(reader.GetOutputPort())
    deci.SetTargetReduction(0.9)
    deci.SetAbsoluteError(0.0005)
    deci.MaximumIterations = 6
    deci.SetFeatureAngle(30)
    deci.SetErrorIsAbsolute(1)
    deci.AccumulateErrorOn()
    # deci.SplittingOff()
    deci.Update()
    print('After Decimation.')
    print('There are: ', NumberOfTriangles(deci.GetOutput()), 'triangles')

    connect = vtkConnectivityFilter()
    connect.SetInputConnection(deci.GetOutputPort())
    connect.SetExtractionModeToLargestRegion()
    connect.Update()
    print('After Connectivity.')
    print('There are: ', NumberOfTriangles(connect.GetOutput()), 'triangles')

    isoMapper = vtkDataSetMapper()
    isoMapper.SetInputConnection(connect.GetOutputPort())
    isoMapper.ScalarVisibilityOff()
    isoActor = vtkActor()
    isoActor.SetMapper(isoMapper)
    isoActor.GetProperty().SetColor(colors.GetColor3d('raw_sienna'))

    #  Get an outline of the data set for context.
    outline = vtkOutlineFilter()
    outline.SetInputConnection(reader.GetOutputPort())
    outlineMapper = vtkPolyDataMapper()
    outlineMapper.SetInputConnection(outline.GetOutputPort())
    outlineActor = vtkActor()
    outlineActor.SetMapper(outlineMapper)
    outlineActor.GetProperty().SetColor(colors.GetColor3d('Black'))

    #  Create the Renderer, RenderWindow and RenderWindowInteractor.
    ren = vtkRenderer()
    renWin = vtkRenderWindow()
    renWin.AddRenderer(ren)
    iren = vtkRenderWindowInteractor()
    iren.SetRenderWindow(renWin)

    # Add the actors to the renderer, set the background and size.
    ren.AddActor(outlineActor)
    ren.AddActor(isoActor)
    ren.SetBackground(1, 1, 1)
    # renWin.SetSize(750, 750)
    renWin.SetSize(512, 512)
    renWin.SetWindowName('PineRootDecimation')

    ren.SetBackground(colors.GetColor3d('SlateGray'))

    # render the image

    cam = ren.GetActiveCamera()
    cam.SetFocalPoint(40.6018, 37.2813, 50.1953)
    cam.SetPosition(40.6018, -280.533, 47.0172)
    cam.ComputeViewPlaneNormal()
    cam.SetClippingRange(26.1073, 1305.36)
    cam.SetViewAngle(20.9219)
    cam.SetViewUp(0.0, 0.0, 1.0)

    iren.Initialize()
    renWin.Render()
    iren.Start()


def get_program_parameters():
    import argparse
    description = 'Applying connectivity and decimation filters to remove noisy isosurfaces and reduce data size.'
    epilogue = '''
        Applying connectivity and decimation filters to remove noisy isosurfaces and reduce data size..

This example demonstrates how to use the vtkConnectivityFilter and vtkDecimate.

   '''
    parser = argparse.ArgumentParser(description=description, epilog=epilogue,
                                     formatter_class=argparse.RawDescriptionHelpFormatter)
    parser.add_argument('filename', help='pine_root.tri.')
    args = parser.parse_args()
    return args.filename


if __name__ == '__main__':
    main()