Cloned library of VTK-5.0.0 with extra build files for internal package management.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

516 lines
14 KiB

2 years ago
package require vtk
package require vtkinteraction
# This example demonstrates how to use the vtkImagePlaneWidget
# and a vtkSplineWidger to do profile probing of a 3D image
# dataset. The use of vtkAnnotatedCubeActor, vtkAxesActor and
# vtkOrientationMarkerWidget is also demostrated.
#
# GUI controls are provided as follows:
# a) x,y,z buttons set the widgets to orthonormal
# positioning, set the horizontal slider to move the
# widgets along their common plane normal, and set the
# camera to face the widgets
# b) right clicking on x,y,z buttons pops up a menu to set
# the widget's reslice interpolation mode
# c) when in axes aligned, orthogonal orientation, the slider
# will move the widget by slice index within the appropriate range
#
# Start by loading some data.
#
vtkVolume16Reader v16
v16 SetDataDimensions 64 64
v16 SetDataByteOrderToLittleEndian
v16 SetImageRange 1 93
v16 SetDataSpacing 3.2 3.2 1.5
v16 SetFilePrefix "$VTK_DATA_ROOT/Data/headsq/quarter"
v16 Update
scan [[v16 GetOutput] GetWholeExtent] "%d %d %d %d %d %d" \
xMin xMax yMin yMax zMin zMax
set spacing [[v16 GetOutput] GetSpacing]
set sx [lindex $spacing 0]
set sy [lindex $spacing 1]
set sz [lindex $spacing 2]
set origin [[v16 GetOutput] GetOrigin]
set ox [lindex $origin 0]
set oy [lindex $origin 1]
set oz [lindex $origin 2]
# Create an outline of the 3D image data bounds.
#
vtkOutlineFilter outline
outline SetInput [ v16 GetOutput ]
vtkPolyDataMapper outlineMapper
outlineMapper SetInput [ outline GetOutput ]
vtkActor outlineActor
outlineActor SetMapper outlineMapper
# Set up two renderers in one render window: one for the
# vtkImagePlaneWidget, vtkSplineWidget, and outline, and
# one for the profile plot.
#
vtkRenderer ren1
ren1 SetBackground 0.4 0.4 0.5
vtkRenderer ren2
ren2 SetBackground 0.8 0.8 0.8
vtkRenderWindow renWin
renWin AddRenderer ren1
renWin AddRenderer ren2
renWin SetSize 800 400
ren1 SetViewport 0 0 0.5 1
ren2 SetViewport 0.5 0 1 1
# Create a vtkImagePlaneWidget to slice through the data.
#
vtkImagePlaneWidget ipw
ipw DisplayTextOn
ipw TextureInterpolateOff
ipw UserControlledLookupTableOff
ipw SetInput [ v16 GetOutput ]
ipw SetResliceInterpolateToNearestNeighbour
ipw KeyPressActivationOff
[ ipw GetPlaneProperty ] SetColor 1 0 0
set xmode [ ipw GetResliceInterpolate ]
set ymode [ ipw GetResliceInterpolate ]
set zmode [ ipw GetResliceInterpolate ]
ipw SetPlaneOrientationToXAxes
ipw SetSliceIndex 32
ipw AddObserver InteractionEvent UpdateIPW
# Create a vtkSplineWidget to interactively probe the data.
#
vtkSplineWidget spline
spline SetInput [ v16 GetOutput ]
spline PlaceWidget
spline SetPriority 1.0
spline KeyPressActivationOff
spline ProjectToPlaneOn
spline SetProjectionNormal 0
spline SetProjectionPosition 102.4
spline SetNumberOfHandles 5
spline SetResolution 500
spline AddObserver InteractionEvent UpdateSW
# A vtkPolyData will be continuously updated from the spline
# during interaction.
#
vtkPolyData poly
spline GetPolyData poly
# The filter to probe the image data.
#
vtkProbeFilter probe
probe SetInput poly
probe SetSource [ v16 GetOutput ]
# The plot of the profile data.
#
vtkXYPlotActor profile
profile AddInput [ probe GetOutput ]
[ profile GetPositionCoordinate ] SetValue 0.05 0.05 0
[ profile GetPosition2Coordinate ] SetValue 0.95 0.95 0
profile SetXValuesToNormalizedArcLength
profile SetNumberOfXLabels 6
profile SetTitle "Profile Data "
profile SetXTitle "s"
profile SetYTitle "I(s)"
profile SetXRange 0 1
set range [[v16 GetOutput] GetScalarRange]
profile SetYRange [lindex $range 0] [lindex $range 1]
[ profile GetProperty ] SetColor 0 0 0
[ profile GetProperty ] SetLineWidth 2
profile SetLabelFormat "%g"
[ profile GetTitleTextProperty ] SetColor 0.02 0.06 0.62
[ profile GetTitleTextProperty ] SetFontFamilyToArial
profile SetAxisTitleTextProperty [ profile GetTitleTextProperty ]
profile SetAxisLabelTextProperty [ profile GetTitleTextProperty ]
profile SetTitleTextProperty [ profile GetTitleTextProperty ]
# Create a composite orientation marker using
# vtkAnnotatedCubeActor and vtkAxesActor.
#
vtkAnnotatedCubeActor cube
cube SetXPlusFaceText "R"
cube SetXMinusFaceText "L"
cube SetYPlusFaceText "A"
cube SetYMinusFaceText "P"
cube SetZPlusFaceText "I"
cube SetZMinusFaceText "S"
cube SetXFaceTextRotation 180
cube SetYFaceTextRotation 180
cube SetZFaceTextRotation -90
cube SetFaceTextScale 0.65
set property [ cube GetCubeProperty ]
$property SetColor 0.5 1 1
set property [ cube GetTextEdgesProperty ]
$property SetLineWidth 1
$property SetDiffuse 0
$property SetAmbient 1
$property SetColor 0.18 0.28 0.23
cube TextEdgesOn
cube CubeOn
cube FaceTextOn
set property [ cube GetXPlusFaceProperty ]
$property SetColor 0 0 1
$property SetInterpolationToFlat
set property [ cube GetXMinusFaceProperty ]
$property SetColor 0 0 1
$property SetInterpolationToFlat
set property [ cube GetYPlusFaceProperty ]
$property SetColor 0 1 0
$property SetInterpolationToFlat
set property [ cube GetYMinusFaceProperty ]
$property SetColor 0 1 0
$property SetInterpolationToFlat
set property [ cube GetZPlusFaceProperty ]
$property SetColor 1 0 0
$property SetInterpolationToFlat
set property [ cube GetZMinusFaceProperty ]
$property SetColor 1 0 0
$property SetInterpolationToFlat
vtkAxesActor axes
axes SetShaftTypeToCylinder
axes SetXAxisLabelText "x"
axes SetYAxisLabelText "y"
axes SetZAxisLabelText "z"
axes SetTotalLength 1.5 1.5 1.5
vtkTextProperty tprop
tprop ItalicOn
tprop ShadowOn
tprop SetFontFamilyToTimes
[ axes GetXAxisCaptionActor2D ] SetCaptionTextProperty tprop
vtkTextProperty tprop2
tprop2 ShallowCopy tprop
[ axes GetYAxisCaptionActor2D ] SetCaptionTextProperty tprop2
vtkTextProperty tprop3
tprop3 ShallowCopy tprop
[ axes GetZAxisCaptionActor2D ] SetCaptionTextProperty tprop3
# Combine the two actors into one with vtkPropAssembly ...
#
vtkPropAssembly assembly
assembly AddPart axes
assembly AddPart cube
# Add the composite marker to the widget. The widget
# should be kept in non-interactive mode and the aspect
# ratio of the render window taken into account explicitly,
# since the widget currently does not take this into
# account in a multi-renderer environment.
#
vtkOrientationMarkerWidget marker
marker SetOutlineColor 0.93 0.57 0.13
marker SetOrientationMarker assembly
marker SetViewport 0.0 0.0 0.15 0.3
# Add the actors.
#
ren1 AddActor outlineActor
ren2 AddActor2D profile
# Prevent the tk window from showing up then start the event loop.
wm withdraw .
# Build a tcl GUI.
#
toplevel .top
wm title .top "Probe With vtkSplineWidget Example"
wm protocol .top WM_DELETE_WINDOW ::vtk::cb_exit
set popm [menu .top.mm -tearoff 0]
set interpmode 0
$popm add radiobutton -label "nearest" -variable interpmode -value 0 \
-command SetInterpolation
$popm add radiobutton -label "linear" -variable interpmode -value 1 \
-command SetInterpolation
$popm add radiobutton -label "cubic" -variable interpmode -value 2 \
-command SetInterpolation
set display_frame [frame .top.f1]
set ctrl_buttons [frame .top.btns]
pack $display_frame $ctrl_buttons \
-side top -anchor n \
-fill both -expand f
set quit_button [button $ctrl_buttons.btn1 \
-text "Quit" \
-command ::vtk::cb_exit]
set x_button [button $ctrl_buttons.btn2 \
-text "x" \
-command AlignXaxis]
set y_button [button $ctrl_buttons.btn3 \
-text "y" \
-command AlignYaxis]
set z_button [button $ctrl_buttons.btn4 \
-text "z" \
-command AlignZaxis]
set last_btn -1
bind $x_button <Button-3> "set last_btn 0; ConfigMenu; $popm post %X %Y"
bind $y_button <Button-3> "set last_btn 1; ConfigMenu; $popm post %X %Y"
bind $z_button <Button-3> "set last_btn 2; ConfigMenu; $popm post %X %Y"
# Share the popup menu among buttons, keeping
# track of associated plane's interpolation mode
#
proc ConfigMenu { } {
global last_btn popm interpmode xmode ymode zmode
if { $last_btn == 0 } {
set interpmode $xmode
} elseif { $last_btn == 1 } {
set interpmode $ymode
} else {
set interpmode $zmode
}
$popm entryconfigure $last_btn -variable interpmode
}
pack $quit_button $x_button $y_button $z_button \
-side left \
-expand t -fill both
# Create the render widget
#
set renderer_frame [frame $display_frame.rFm]
pack $renderer_frame \
-padx 3 -pady 3 \
-side left -anchor n \
-fill both -expand f
set render_widget [vtkTkRenderWidget $renderer_frame.r \
-width 800 \
-height 400 \
-rw renWin]
pack $render_widget $display_frame \
-side top -anchor n \
-fill both -expand f
# Add a slice scale to browse the current slice stack
#
set slice_number [ipw GetSliceIndex]
scale .top.slice \
-from $xMin \
-to $xMax \
-orient horizontal \
-command SetSlice \
-variable slice_number \
-label "Slice"
pack .top.slice \
-fill x -expand f
proc SetSlice {slice} {
ipw SetSliceIndex $slice
UpdateIPW
renWin Render
}
::vtk::bind_tk_render_widget $render_widget
# Set the interactor for the widgets
#
set iact [[$render_widget GetRenderWindow] GetInteractor]
vtkInteractorStyleTrackballCamera style
$iact SetInteractorStyle style
ipw SetInteractor $iact
ipw On
spline SetInteractor $iact
spline SetPlaneSource [ ipw GetPolyDataAlgorithm ]
spline SetProjectionNormal 3
spline On
marker SetInteractor $iact
marker SetEnabled 1
marker InteractiveOff
# Create an initial interesting view
#
set cam1 [ren1 GetActiveCamera]
$cam1 Elevation 110
$cam1 SetViewUp 0 0 -1
$cam1 Azimuth 45
ren1 ResetCamera
# Render it
#
$render_widget Render
# Supporting procedures
#
# Align the camera so that it faces the desired widget
#
proc AlignCamera { } {
global ox oy oz sx sy sz xMax xMin yMax yMin zMax zMin slice_number
set cx [expr $ox + (0.5*($xMax - $xMin))*$sx]
set cy [expr $oy + (0.5*($yMax - $yMin))*$sy]
set cz [expr $oy + (0.5*($zMax - $zMin))*$sz]
set vx 0
set vy 0
set vz 0
set nx 0
set ny 0
set nz 0
set iaxis [ipw GetPlaneOrientation]
if { $iaxis == 0 } {
set vz -1
set nx [expr $ox + $xMax*$sx]
set cx [expr $ox + $slice_number*$sx]
} elseif { $iaxis == 1 } {
set vz -1
set ny [expr $oy + $yMax*$sy]
set cy [expr $oy + $slice_number*$sy]
} else {
set vy 1
set nz [expr $oz + $zMax*$sz]
set cz [expr $oz + $slice_number*$sz]
}
set px [expr $cx + $nx*2]
set py [expr $cy + $ny*2]
set pz [expr $cz + $nz*3]
set camera [ ren1 GetActiveCamera ]
$camera SetViewUp $vx $vy $vz
$camera SetFocalPoint $cx $cy $cz
$camera SetPosition $px $py $pz
$camera OrthogonalizeViewUp
ren1 ResetCamera
renWin Render
}
# Align the widget back into orthonormal position,
# set the slider to reflect the widget's position,
# call AlignCamera to set the camera facing the widget
#
proc AlignXaxis { } {
global xMax xMin slice_number interpmode xmode
set ori [ ipw GetPlaneOrientation ]
if { $ori != 0 } {
ipw SetPlaneOrientationToXAxes
set slice_number [expr ($xMax - $xMin)/2]
ipw SetSliceIndex $slice_number
} else {
set slice_number [ipw GetSliceIndex]
}
.top.slice config -from $xMin -to $xMax
.top.slice set $slice_number
UpdateSplinePosition
AlignCamera
set interpmode $xmode
SetInterpolation
}
proc AlignYaxis { } {
global yMin yMax slice_number interpmode ymode
set po [ ipw GetPlaneOrientation ]
set ori [ ipw GetPlaneOrientation ]
if { $ori != 1 } {
ipw SetPlaneOrientationToYAxes
set slice_number [expr ($yMax - $yMin)/2]
ipw SetSliceIndex $slice_number
} else {
set slice_number [ipw GetSliceIndex]
}
.top.slice config -from $yMin -to $yMax
.top.slice set $slice_number
UpdateSplinePosition
AlignCamera
set interpmode $ymode
SetInterpolation
}
proc AlignZaxis { } {
global zMin zMax slice_number interpmode zmode
set ori [ ipw GetPlaneOrientation ]
if { $ori != 2 } {
ipw SetPlaneOrientationToZAxes
set slice_number [expr ($zMax - $zMin)/2]
ipw SetSliceIndex $slice_number
} else {
set slice_number [ipw GetSliceIndex]
}
.top.slice config -from $zMin -to $zMax
.top.slice set $slice_number
UpdateSplinePosition
AlignCamera
set interpmode $zmode
SetInterpolation
}
proc UpdateSplinePosition { } {
set ori [ ipw GetPlaneOrientation ]
spline ProjectToPlaneOff
spline PlaceWidget
spline ProjectToPlaneOn
spline SetProjectionNormal $ori
spline SetProjectionNormal 3
UpdateIPW
}
# Set the vtkImagePlaneWidget's reslice interpolation mode
# to the corresponding popup menu choice and store
# it for subsequent orientation changes.
#
proc SetInterpolation { } {
global interpmode xmode ymode zmode
if { $interpmode == 0 } {
ipw TextureInterpolateOff
} else {
ipw TextureInterpolateOn
}
ipw SetResliceInterpolate $interpmode
set ori [ipw GetPlaneOrientation]
if { $ori == 0 } {
set xmode $interpmode
} elseif { $ori == 1 } {
set ymode $interpmode
} else {
set zmode $interpmode
}
renWin Render
}
# Procedure to update the placement of the vtkSplineWidget on the
# plane defined by the vtkImagePlaneWidget.
#
proc UpdateIPW { } {
set ori [ ipw GetPlaneOrientation ]
if { $ori == 3 } {
spline SetProjectionPosition 0
} else {
set pos [ ipw GetSlicePosition ]
spline SetProjectionPosition $pos
}
UpdateSW
}
# Procedure to update the spline geometry fed into the probe filter.
#
proc UpdateSW { } {
spline GetPolyData poly
}