VTK Mouse Picking

From KitwarePublic
Revision as of 21:37, 12 August 2004 by Goodwin (talk | contribs) (Link to the submitted bug (idea))
Jump to navigationJump to search

The default way pick a cell/point/actor under the cursor in a render window is to press the "p" key. You may prefer to pick by pressing a mouse button. The problem is most interactor styles have already assigned functions to the mouse buttons such as rotating the camera or actor. This method of picking with a mouse button uses the fact that in vtkInteractorStyleTrackballCamera you must move the mouse in addition to pressing a mouse button to interact with the scene. Below is a tcl example of how to change vtkInteractorStyleTrackballCamera so that when you press the left mouse button and release it without moving the mouse you will perform a pick under the cursor.

The annotatePick.tcl example is modifed below to illustrate a working example but here is the pertinent code:

vtkInteractorStyleTrackballCamera style
    style AddObserver LeftButtonPressEvent {set MouseMotion 0; style OnLeftButtonDown}
    style AddObserver MouseMoveEvent {set MouseMotion 1; style OnMouseMove}
    style AddObserver LeftButtonReleaseEvent cbLBR

proc cbLBR {} {
  global MouseMotion
  
  if {$MouseMotion == 0} {
    eval picker Pick [iren GetEventPosition] 0 ren1
  }
  # Do the default things for the trackball style
  style OnLeftButtonUp 
}

A "MouseMotion" flag is set to "0" when the left button is pressed. This flag is changed to "1" when you move the mouse. When you release the left button, the callback "cbLBR" checks "MouseMotion" to see if you have moved the mouse and performs a pick if you haven't.

I have a c++ implimentation of this that also allows you to turn mouse picking on/off and to get which mouse button was pressed. I'll post it as an idea to the bug tracker with a patch to vtkInteractorStyleTrackballCamera... here's the link Bug submission. (You could use this with vtkInteractorStyleTrackballActor too)

--Goodwin 15:11, 12 Aug 2004 (EDT)

Here's the full example (modified annotatePick.tcl):

To perform a pick in the example below: move the cursor to the position in the render window you want to pick, then press and release the left mouse button without moving the mouse in between. This may seem tricky at first but you'll get used to it!

# This example demonstrates cell picking using vtkCellPicker.  It displays
# the results of picking using a vtkTextMapper.

#
# First we include the VTK Tcl packages which will make available
# all of the vtk commands to Tcl
#
package require vtk
package require vtkinteraction

# create a sphere source, mapper, and actor
#
vtkSphereSource sphere

vtkPolyDataMapper sphereMapper
    sphereMapper SetInput [sphere GetOutput]
    sphereMapper GlobalImmediateModeRenderingOn
vtkLODActor sphereActor
    sphereActor SetMapper sphereMapper

# create the spikes by glyphing the sphere with a cone.  Create the mapper
# and actor for the glyphs.
vtkConeSource cone
vtkGlyph3D glyph
    glyph SetInput [sphere GetOutput]
    glyph SetSource [cone GetOutput]
    glyph SetVectorModeToUseNormal
    glyph SetScaleModeToScaleByVector
    glyph SetScaleFactor 0.25
vtkPolyDataMapper spikeMapper
    spikeMapper SetInput [glyph GetOutput]
vtkLODActor spikeActor
    spikeActor SetMapper spikeMapper

# Create a cell picker.
vtkCellPicker picker
    picker AddObserver EndPickEvent annotatePick

# Create a text mapper and actor to display the results of picking.
vtkTextMapper textMapper
set tprop [textMapper GetTextProperty]
    $tprop SetFontFamilyToArial
    $tprop SetFontSize 10
    $tprop BoldOn
    $tprop ShadowOn
    $tprop SetColor 1 0 0
vtkActor2D textActor
    textActor VisibilityOff
    textActor SetMapper textMapper

# Create the Renderer, RenderWindow, and RenderWindowInteractor
#

vtkInteractorStyleTrackballCamera style
    style AddObserver LeftButtonPressEvent {set MouseMotion 0; style OnLeftButtonDown}
    style AddObserver MouseMoveEvent {set MouseMotion 1; style OnMouseMove}
    style AddObserver LeftButtonReleaseEvent cbLBR
vtkRenderer ren1
vtkRenderWindow renWin
    renWin AddRenderer ren1
vtkRenderWindowInteractor iren
    iren SetRenderWindow renWin
    iren SetInteractorStyle style
    iren SetPicker picker

# Add the actors to the renderer, set the background and size
#
ren1 AddActor2D textActor
ren1 AddActor sphereActor
ren1 AddActor spikeActor
ren1 SetBackground 1 1 1
renWin SetSize 300 300

# Get the camera and zoom in closer to the image.
set cam1 [ren1 GetActiveCamera]
$cam1 Zoom 1.4

# Set the user method (bound to key 'u')
iren AddObserver UserEvent {wm deiconify .vtkInteract}
iren Initialize

# Withdraw the default tk window
wm withdraw .

# Create a Tcl procedure to create the text for the text mapper used to
# display the results of picking.
proc annotatePick {} {
    if { [picker GetCellId] < 0 } {
	textActor VisibilityOff

    } else {
	set selPt [picker GetSelectionPoint]
	set x [lindex $selPt 0] 
	set y [lindex $selPt 1]
	set pickPos [picker GetPickPosition]
	set xp [lindex $pickPos 0] 
	set yp [lindex $pickPos 1]
	set zp [lindex $pickPos 2]

	textMapper SetInput "($xp, $yp, $zp)"
	textActor SetPosition $x $y
	textActor VisibilityOn
    }

    renWin Render
}

proc cbLBR {} {
  global MouseMotion
  
  if {$MouseMotion == 0} {
    eval picker Pick [iren GetEventPosition] 0 ren1
  }
  # Do the default things for the trackball style
  style OnLeftButtonUp 
}

# Pick the cell at this location.
picker Pick 85 126 0 ren1