VTK学习笔记(二)

VTK是一套可视化工具箱,可以用来完成复杂的3D可视化,其中提供了大量的高级可视化功能,有一些现成的库可以调用VTK完成可视化,不过如果需要更底层的实现对于库的了解也是必不可少的。

目录


接前文

VTK教程五:窗口交互

前面所有的案例都没有交互,仅仅是渲染。这个案例终于要讨论交互了。下面是这个案例的代码:

#!/usr/bin/env python

#
# This example introduces the concepts of user interaction with VTK.
# First, a different interaction style (than the default) is defined.
# Second, the interaction is started.
#
#

import vtk

#
# Next we create an instance of vtkConeSource and set some of its
# properties. The instance of vtkConeSource "cone" is part of a visualization
# pipeline (it is a source process object); it produces data (output type is
# vtkPolyData) which other filters may process.
# 对象还是一样的
#
cone = vtk.vtkConeSource()
cone.SetHeight( 3.0 )
cone.SetRadius( 1.0 )
cone.SetResolution( 10 )

#
# In this example we terminate the pipeline with a mapper process object.
# (Intermediate filters such as vtkShrinkPolyData could be inserted in
# between the source and the mapper.)  We create an instance of
# vtkPolyDataMapper to map the polygonal data into graphics primitives. We
# connect the output of the cone souece to the input of this mapper.
#
coneMapper = vtk.vtkPolyDataMapper()
coneMapper.SetInputConnection(cone.GetOutputPort())

#
# Create an actor to represent the cone. The actor orchestrates rendering of
# the mapper's graphics primitives. An actor also refers to properties via a
# vtkProperty instance, and includes an internal transformation matrix. We
# set this actor's mapper to be coneMapper which we created above.
#
coneActor = vtk.vtkActor()
coneActor.SetMapper(coneMapper)

#
# Create the Renderer and assign actors to it. A renderer is like a
# viewport. It is part or all of a window on the screen and it is responsible
# for drawing the actors it has.  We also set the background color here.
#
ren1 = vtk.vtkRenderer()
ren1.AddActor(coneActor)
ren1.SetBackground(0.1, 0.2, 0.4)

#
# Finally we create the render window which will show up on the screen
# We put our renderer into the render window using AddRenderer. We also
# set the size to be 300 pixels by 300.
# 前面都是一个样的
#
renWin = vtk.vtkRenderWindow()
renWin.AddRenderer(ren1)
renWin.SetSize(300, 300)

#
# The vtkRenderWindowInteractor class watches for events (e.g., keypress,
# mouse) in the vtkRenderWindow. These events are translated into
# event invocations that VTK understands (see VTK/Common/vtkCommand.h
# for all events that VTK processes). Then observers of these VTK
# events can process them as appropriate.
# 这里vtkRenderWindow没有直接Render而是交给了vtkRenderWindowInteractor来响应
# 键盘和鼠标响应
iren = vtk.vtkRenderWindowInteractor()
iren.SetRenderWindow(renWin)

#
# By default the vtkRenderWindowInteractor instantiates an instance
# of vtkInteractorStyle. vtkInteractorStyle translates a set of events
# it observes into operations on the camera, actors, and/or properties
# in the vtkRenderWindow associated with the vtkRenderWinodwInteractor.
# Here we specify a particular interactor style.
# 默认的鼠标设置比较不适合鼠标操作,这里开发者也把响应换成vtkInteractorStyleTrackballCamera了。
style = vtk.vtkInteractorStyleTrackballCamera()
iren.SetInteractorStyle(style)

#
# Unlike the previous scripts where we performed some operations and then
# exited, here we leave an event loop running. The user can use the mouse
# and keyboard to perform the operations on the scene according to the
# current interaction style.
# 交互需要一个Event loop,跟其他GUI程序是一样的
#

#
# Initialize and start the event loop. Once the render window appears, mouse
# in the window to move the camera. The Start() method executes an event
# loop which listens to user mouse and keyboard events. Note that keypress-e
# exits the event loop. (Look in vtkInteractorStyle.h for a summary of events, or
# the appropriate Doxygen documentation.)
#
iren.Initialize()
iren.Start()

关于鼠标和键盘的操作,此处将vtkInteractorStyle和vtkInteractorStyleTrackballCamera的注释拷贝如下:

@class vtkInteractorStyle

@brief provide event-driven interface to the rendering window (defines trackball mode)

vtkInteractorStyle is a base class implementing the majority of motion control routines and defines an event driven interface to support vtkRenderWindowInteractor. vtkRenderWindowInteractor implements platform dependent key/mouse routing and timer control, which forwards events in a neutral form to vtkInteractorStyle.

vtkInteractorStyle implements the “joystick” style of interaction. That is, holding down the mouse keys generates a stream of events that cause continuous actions (e.g., rotate, translate, pan, zoom). (The class vtkInteractorStyleTrackball implements a grab and move style.) The event bindings for this class include the following:

  • Keypress j / Keypress t: toggle between joystick (position sensitive) and trackball (motion sensitive) styles. In joystick style, motion occurs continuously as long as a mouse button is pressed. In trackball style, motion occurs when the mouse button is pressed and the mouse pointer moves.
  • Keypress c / Keypress a: toggle between camera and actor modes. In camera mode, mouse events affect the camera position and focal point. In actor mode, mouse events affect the actor that is under the mouse pointer.
  • Button 1: rotate the camera around its focal point (if camera mode) or rotate the actor around its origin (if actor mode). The rotation is in the direction defined from the center of the renderer’s viewport towards the mouse position. In joystick mode, the magnitude of the rotation is determined by the distance the mouse is from the center of the render window.
  • Button 2: pan the camera (if camera mode) or translate the actor (if actor mode). In joystick mode, the direction of pan or translation is from the center of the viewport towards the mouse position. In trackball mode, the direction of motion is the direction the mouse moves. (Note: with 2-button mice, pan is defined as <Shift>-Button 1.)
  • Button 3: zoom the camera (if camera mode) or scale the actor (if actor mode). Zoom in/increase scale if the mouse position is in the top half of the viewport; zoom out/decrease scale if the mouse position is in the bottom half. In joystick mode, the amount of zoom is controlled by the distance of the mouse pointer from the horizontal centerline of the window.
  • Keypress 3: toggle the render window into and out of stereo mode. By default, red-blue stereo pairs are created. Some systems support Crystal Eyes LCD stereo glasses; you have to invoke SetStereoTypeToCrystalEyes() on the rendering window.
  • Keypress e: exit the application.
  • Keypress f: fly to the picked point
  • Keypress p: perform a pick operation. The render window interactor has an internal instance of vtkCellPicker that it uses to pick.
  • Keypress r: reset the camera view along the current view direction. Centers the actors and moves the camera so that all actors are visible.
  • Keypress s: modify the representation of all actors so that they are surfaces.
  • Keypress u: invoke the user-defined function. Typically, this keypress will bring up an interactor that you can type commands in. Typing u calls UserCallBack() on the vtkRenderWindowInteractor, which invokes a vtkCommand::UserEvent. In other words, to define a user-defined callback, just add an observer to the vtkCommand::UserEvent on the vtkRenderWindowInteractor object.
  • Keypress w: modify the representation of all actors so that they are wireframe.

vtkInteractorStyle can be subclassed to provide new interaction styles and a facility to override any of the default mouse/key operations which currently handle trackball or joystick styles is provided. Note that this class will fire a variety of events that can be watched using an observer, such as LeftButtonPressEvent, LeftButtonReleaseEvent, MiddleButtonPressEvent, MiddleButtonReleaseEvent, RightButtonPressEvent, RightButtonReleaseEvent, EnterEvent, LeaveEvent, KeyPressEvent, KeyReleaseEvent, CharEvent, ExposeEvent, ConfigureEvent, TimerEvent, MouseMoveEvent,

@class vtkInteractorStyleTrackballCamera

@brief interactive manipulation of the camera

vtkInteractorStyleTrackballCamera allows the user to interactively manipulate (rotate, pan, etc.) the camera, the viewpoint of the scene. In trackball interaction, the magnitude of the mouse motion is proportional to the camera motion associated with a particular mouse binding. For example, small left-button motions cause small changes in the rotation of the camera around its focal point. For a 3-button mouse, the left button is for rotation, the right button for zooming, the middle button for panning, and ctrl + left button for spinning. (With fewer mouse buttons, ctrl + shift + left button is for zooming, and shift + left button is for panning.)

VTK教程六:3D Widgets

该教程主要演示了vtkBoxWidget,其他Widget的用法也是类似的。教程的代码如下:

#!/usr/bin/env python
#
# This example introduces 3D widgets. 3D widgets take advantage of the
# event/observer design pattern introduced previously. They typically
# have a particular representation in the scene which can be interactively
# selected and manipulated using the mouse and keyboard. As the widgets
# are manipulated, they in turn invoke events such as StartInteractionEvent,
# InteractionEvent, and EndInteractionEvent which can be used to manipulate
# the scene that the widget is embedded in. 3D widgets work in the context
# of the event loop which was set up in the previous example.

# First we import the VTK Python package that will make available all
# of the VTK commands to Python.
import vtk

# Next we create an instance of vtkConeSource and set some of its
# properties. The instance of vtkConeSource "cone" is part of a
# visualization pipeline (it is a source process object); it produces
# data (output type is vtkPolyData) which other filters may process.
cone = vtk.vtkConeSource()
cone.SetHeight(3.0)
cone.SetRadius(1.0)
cone.SetResolution(10)

# In this example we terminate the pipeline with a mapper process object.
# (Intermediate filters such as vtkShrinkPolyData could be inserted in
# between the source and the mapper.)  We create an instance of
# vtkPolyDataMapper to map the polygonal data into graphics primitives. We
# connect the output of the cone souece to the input of this mapper.
coneMapper = vtk.vtkPolyDataMapper()
coneMapper.SetInputConnection(cone.GetOutputPort())

# Create an actor to represent the cone. The actor orchestrates rendering of
# the mapper's graphics primitives. An actor also refers to properties via a
# vtkProperty instance, and includes an internal transformation matrix. We
# set this actor's mapper to be coneMapper which we created above.
coneActor = vtk.vtkActor()
coneActor.SetMapper(coneMapper)

# Create the Renderer and assign actors to it. A renderer is like a
# viewport. It is part or all of a window on the screen and it is
# responsible for drawing the actors it has.  We also set the
# background color here.
ren1 = vtk.vtkRenderer()
ren1.AddActor(coneActor)
ren1.SetBackground(0.1, 0.2, 0.4)

# Finally we create the render window which will show up on the screen
# We put our renderer into the render window using AddRenderer. We
# also set the size to be 300 pixels by 300.
renWin = vtk.vtkRenderWindow()
renWin.AddRenderer(ren1)
renWin.SetSize(300, 300)

# The vtkRenderWindowInteractor class watches for events (e.g., keypress,
# mouse) in the vtkRenderWindow. These events are translated into
# event invocations that VTK understands (see VTK/Common/vtkCommand.h
# for all events that VTK processes). Then observers of these VTK
# events can process them as appropriate.
iren = vtk.vtkRenderWindowInteractor()
iren.SetRenderWindow(renWin)

# By default the vtkRenderWindowInteractor instantiates an instance
# of vtkInteractorStyle. vtkInteractorStyle translates a set of events
# it observes into operations on the camera, actors, and/or properties
# in the vtkRenderWindow associated with the vtkRenderWinodwInteractor.
# Here we specify a particular interactor style.
# 前面和教程五是一样的
style = vtk.vtkInteractorStyleTrackballCamera()
iren.SetInteractorStyle(style)


# Here we use a vtkBoxWidget to transform the underlying coneActor (by
# manipulating its transformation matrix). Many other types of widgets
# are available for use, see the documentation for more details.
#
# The SetInteractor method is how 3D widgets are associated with the render
# window interactor. Internally, SetInteractor sets up a bunch of callbacks
# using the Command/Observer mechanism (AddObserver()). The place factor
# controls the initial size of the widget with respect to the bounding box
# of the input to the widget.
# SetPlaceFactor 的目的是:
# Set/Get a factor representing the scaling of the widget upon
# placement (via the PlaceWidget() method). Normally the widget is
# placed so that it just fits within the bounding box defined in
# PlaceWidget(bounds). The PlaceFactor will make the widget larger
# (PlaceFactor > 1) or smaller (PlaceFactor < 1). By default,
# PlaceFactor is set to 0.5.
boxWidget = vtk.vtkBoxWidget()
boxWidget.SetInteractor(iren)
boxWidget.SetPlaceFactor(1.25)

# Place the interactor initially. The input to a 3D widget is used to
# initially position and scale the widget. The EndInteractionEvent is
# observed which invokes the SelectPolygons callback.

# 下面是演示Widget的放置方法,首先需要设置SetProp3D,这是因为:
# Specify a vtkProp3D around which to place the widget. This is not
# required, but if supplied, it is used to initially position the
# widget.

boxWidget.SetProp3D(coneActor)
boxWidget.PlaceWidget()

# Similar to Step2/Python/Cone2.py, we define a callback for
# interaction.  As can be seen the callback takes two arguments.  The
# first being the object that generates the event and the second
# argument the event name (which is a string).
#
# 下面的Callback是可以随便编写的,这里是将Widget的变换矩阵更新到对象。注意到
# GetTransform的并没有返回变换矩阵,而是直接修改了参数:
# virtual void vtkBoxWidget::GetTransform (   vtkTransform *  t   )
# virtual
# Retrieve a linear transform characterizing the transformation of the box.#

# Note that the transformation is relative to where PlaceWidget was initially called. This method modifies the transform provided. The transform can be used to control the position of vtkProp3D's, as well as other transformation operations (e.g., vtkTranformPolyData).

def myCallback(widget, event_string):
    t = vtk.vtkTransform()
    boxWidget.GetTransform(t)
    boxWidget.GetProp3D().SetUserTransform(t)


# Now for every interaction event that is generated by the boxWidget,
# call our callback function.
# 建立Observer
boxWidget.AddObserver("InteractionEvent", myCallback)

# Normally the user presses the "i" key to bring a 3D widget to
# life. Here we will manually enable it so it appears with the cone.
# 将Widget默认设置为开,可以按“i”键关闭
boxWidget.On()

# Start the event loop.
iren.Initialize()
iren.Start()

关于BoxWidget,下面是它的解释:

This 3D widget defines a region of interest that is represented by an arbitrarily oriented hexahedron with interior face angles of 90 degrees (orthogonal faces). The object creates 7 handles that can be moused on and manipulated. The first six correspond to the six faces, the seventh is in the center of the hexahedron. In addition, a bounding box outline is shown, the “faces” of which can be selected for object rotation or scaling. A nice feature of the object is that the vtkBoxWidget, like any 3D widget, will work with the current interactor style. That is, if vtkBoxWidget does not handle an event, then all other registered observers (including the interactor style) have an opportunity to process the event. Otherwise, the vtkBoxWidget will terminate the processing of the event that it handles.>

大意是BoxWidget有七个手柄,六个在六个面上,另一个在中心。

To use this object, just invoke SetInteractor() with the argument of the method a vtkRenderWindowInteractor. You may also wish to invoke “PlaceWidget()” to initially position the widget. The interactor will act normally until the “i” key (for “interactor”) is pressed, at which point the vtkBoxWidget will appear. (See superclass documentation for information about changing this behavior.) By grabbing the six face handles (use the left mouse button), faces can be moved. By grabbing the center handle (with the left mouse button), the entire hexahedron can be translated. (Translation can also be employed by using the “shift-left-mouse-button” combination inside of the widget.) Scaling is achieved by using the right mouse button “up” the render window (makes the widget bigger) or “down” the render window (makes the widget smaller). To rotate vtkBoxWidget, pick a face (but not a face handle) and move the left mouse. (Note: the mouse button must be held down during manipulation.) Events that occur outside of the widget (i.e., no part of the widget is picked) are propagated to any other registered obsevers (such as the interaction style). Turn off the widget by pressing the “i” key again. (See the superclass documentation on key press activiation.)>

The vtkBoxWidget is very flexible. It can be used to select, cut, clip, or perform any other operation that depends on an implicit function (use the GetPlanes() method); or it can be used to transform objects using a linear transformation (use the GetTransform() method). Typical usage of the widget is to make use of the StartInteractionEvent, InteractionEvent, and EndInteractionEvent events. The InteractionEvent is called on mouse motion; the other two events are called on button down and button up (either left or right button).>

Some additional features of this class include the ability to control the rendered properties of the widget. You can set the properties of the selected and unselected representations of the parts of the widget. For example, you can set the property for the handles, faces, and outline in their normal and selected states.>

The box widget can be oriented by specifying a transformation matrix. This transformation is applied to the initial bounding box as defined by the PlaceWidget() method. DO NOT ASSUME that the transformation is applied to a unit box centered at the origin; this is wrong!

结语

以上就是VTK自带的六个教程,基本上涵盖VTK的基础使用。大家也能感觉到这六个案例还是比较废柴的,到最后也就只是使用了一个Widget。所以,后面我们会继续学习更深入的内容。Stay tuned!

评论