Skip to content

ImplicitPlaneWidget2

Repository source: ImplicitPlaneWidget2

Description

This example shows how to use the second generation ImplicitPlaneWidget2 to interactively define the clipping plane for a polydata. If no arguments are specified, a vtkSphereSource generates the polydata. By specifying a .vtp file, the example can operate on arbitrary polydata.

For example, try src/Testing/Data/cow.vtp.

Other languages

See (Cxx), (Python)

Question

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

Code

ImplicitPlaneWidget2.py

#!/usr/bin/env python3

from pathlib import Path

# noinspection PyUnresolvedReferences
import vtkmodules.vtkInteractionStyle
# noinspection PyUnresolvedReferences
import vtkmodules.vtkRenderingOpenGL2
# noinspection PyUnresolvedReferences
import vtkmodules.vtkRenderingUI
from vtkmodules.vtkCommonColor import vtkNamedColors
from vtkmodules.vtkCommonCore import vtkCommand
from vtkmodules.vtkCommonDataModel import vtkPlane
from vtkmodules.vtkFiltersCore import vtkClipPolyData
from vtkmodules.vtkFiltersSources import vtkSphereSource
from vtkmodules.vtkIOXML import vtkXMLPolyDataReader
from vtkmodules.vtkInteractionWidgets import (
    vtkImplicitPlaneRepresentation,
    vtkImplicitPlaneWidget2
)
from vtkmodules.vtkRenderingCore import (
    vtkActor,
    vtkPolyDataMapper,
    vtkProperty,
    vtkRenderWindow,
    vtkRenderWindowInteractor,
    vtkRenderer
)


def get_program_parameters():
    import argparse
    description = 'How to use the second generation ImplicitPlaneWidget2 to interactively' \
                  ' define the clipping plane for a polydata.'
    epilogue = '''
    If no arguments are specified, a vtkSphereSource generates the polydata.
    By specifying a .vtp file, the example can operate on arbitrary polydata.
'''
    parser = argparse.ArgumentParser(description=description, epilog=epilogue,
                                     formatter_class=argparse.RawTextHelpFormatter)
    parser.add_argument('file_name', nargs='?', default=None, help='A VTK Poly Data file e.g. cow.vtp')

    args = parser.parse_args()
    return args.file_name


def main(fn):
    colors = vtkNamedColors()
    sphere_source = vtkSphereSource(radius=10.0)

    fn = get_program_parameters()

    # Setup a visualization pipeline.
    plane = vtkPlane()
    clipper = vtkClipPolyData(clip_function=plane, inside_out=True)
    if fn:
        fp = Path(fn)
        if not (fp.is_file() and fp.suffix == '.vtp'):
            print(f'Expected an existing file name with extension .vtp\n  got: {fp}')
            return

        reader = vtkXMLPolyDataReader(file_name=fp)
        reader >> clipper
    else:
        sphere_source >> clipper

    back_faces = vtkProperty(diffuse_color=colors.GetColor3d('Gold'))

    # Create a mapper and actor.
    mapper = vtkPolyDataMapper()
    clipper >> mapper
    actor = vtkActor(mapper=mapper, backface_property=back_faces)

    # A renderer and render window.
    renderer = vtkRenderer(background=colors.GetColor3d('SlateGray'))
    ren_win = vtkRenderWindow(window_name='ImplicitPlaneWidget2')
    ren_win.AddRenderer(renderer)

    renderer.AddActor(actor)

    # An interactor.
    iren = vtkRenderWindowInteractor()
    iren.render_window = ren_win

    # The callback will do the work.
    my_callback = IPWCallback(plane)

    rep = vtkImplicitPlaneRepresentation()
    rep.place_factor = 1.25  # This must be set prior to placing the widget.
    rep.PlaceWidget(actor.bounds)
    rep.normal = plane.normal

    plane_widget = vtkImplicitPlaneWidget2(representation=rep, interactor=iren)
    plane_widget.AddObserver(vtkCommand.InteractionEvent, my_callback)

    renderer.active_camera.Azimuth(-60)
    renderer.active_camera.Elevation(30)
    renderer.ResetCamera()
    renderer.active_camera.Zoom(0.75)

    # Render and interact.
    iren.Initialize()
    ren_win.Render()
    plane_widget.On()

    # Begin mouse interaction.
    iren.Start()


class IPWCallback:
    def __init__(self, plane):
        self.plane = plane

    def __call__(self, caller, ev):
        rep = caller.representation
        rep.GetPlane(self.plane)


if __name__ == '__main__':
    file_name = get_program_parameters()
    main(file_name)