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.
294 lines
7.5 KiB
294 lines
7.5 KiB
2 years ago
|
#!/usr/bin/env python
|
||
|
|
||
|
# initial translation from the tcl by VTK/Utilities/tcl2py.py
|
||
|
# further cleanup and fixes to the translation by Charl P. Botha
|
||
|
|
||
|
import vtk
|
||
|
from vtk.util.misc import vtkGetDataRoot
|
||
|
VTK_DATA_ROOT = vtkGetDataRoot()
|
||
|
|
||
|
# This example demonstrates how to use the vtkImageTracerWidget
|
||
|
# to trace on a slice of a 3D image dataset on one of its orthogonal planes.
|
||
|
# The button actions and key modifiers are as follows for controlling the
|
||
|
# widget:
|
||
|
# 1) left button click over the image, hold and drag draws a free hand line.
|
||
|
# 2) left button click and release erases the widget line, if it exists, and
|
||
|
# repositions the handle.
|
||
|
# 3) middle button click starts a snap line. The snap line can be
|
||
|
# terminated by clicking the middle button while depressing the ctrl key.
|
||
|
# 4) when tracing or snap drawing a line, if the last cursor position is
|
||
|
# within specified tolerance to the first handle, the widget line will form
|
||
|
# a closed loop with only one handle.
|
||
|
# 5) right button clicking and holding on any handle that is part of a snap
|
||
|
# line allows handle dragging. Any existing line segments are updated
|
||
|
# accordingly.
|
||
|
# 6) ctrl key + right button down on any handle will erase it. Any existing
|
||
|
# snap line segments are updated accordingly. If the line was formed by
|
||
|
# continous tracing, the line is deleted leaving one handle.
|
||
|
# 7) shift key + right button down on any snap line segment will insert a
|
||
|
# handle at the cursor position. The snap line segment is split accordingly.
|
||
|
#
|
||
|
#
|
||
|
|
||
|
def AdjustSpline(evt, obj):
|
||
|
itw.GetPath(poly)
|
||
|
npts = itw.GetNumberOfHandles()
|
||
|
|
||
|
if npts < 2:
|
||
|
imageActor2.SetInputConnection(extract.GetOutputPort())
|
||
|
return
|
||
|
|
||
|
closed = itw.GetIsClosed()
|
||
|
|
||
|
if closed:
|
||
|
isw.ClosedOn()
|
||
|
else:
|
||
|
isw.ClosedOff()
|
||
|
imageActor2.SetInputConnection(extract.GetOutputPort())
|
||
|
|
||
|
isw.SetNumberOfHandles(npts)
|
||
|
|
||
|
for i in range(0, npts):
|
||
|
pt = poly.GetPoints().GetPoint(i)
|
||
|
isw.SetHandlePosition(i, pt[0], pt[1], pt[2])
|
||
|
|
||
|
if closed:
|
||
|
isw.GetPolyData(spoly)
|
||
|
imageActor2.SetInputConnection(stencil.GetOutputPort())
|
||
|
stencil.Update()
|
||
|
|
||
|
def AdjustTracer(evt, obj):
|
||
|
npts = isw.GetNumberOfHandles()
|
||
|
points.SetNumberOfPoints(npts)
|
||
|
|
||
|
for i in range(0, npts):
|
||
|
pt = isw.GetHandlePosition(i)
|
||
|
points.SetPoint(i, pt[0], pt[1], pt[2])
|
||
|
|
||
|
closed = isw.GetClosed()
|
||
|
|
||
|
if closed:
|
||
|
isw.GetPolyData(spoly)
|
||
|
imageActor2.SetInputConnection(stencil.GetOutputPort())
|
||
|
stencil.Update()
|
||
|
|
||
|
itw.InitializeHandles(points)
|
||
|
|
||
|
|
||
|
# Start by loading some data.
|
||
|
v16 = vtk.vtkVolume16Reader()
|
||
|
v16.SetDataDimensions(64, 64)
|
||
|
v16.SetDataByteOrderToLittleEndian()
|
||
|
v16.SetImageRange(1, 93)
|
||
|
v16.SetDataSpacing(3.2, 3.2, 1.5)
|
||
|
v16.SetFilePrefix("%s/Data/headsq/quarter" % (VTK_DATA_ROOT,))
|
||
|
v16.Update()
|
||
|
#
|
||
|
|
||
|
srange = v16.GetOutput().GetScalarRange()
|
||
|
min = srange[0]
|
||
|
max = srange[1]
|
||
|
|
||
|
diff = max-min
|
||
|
slope = 255.0/diff
|
||
|
inter = -slope*min
|
||
|
shift = inter/slope
|
||
|
|
||
|
shifter = vtk.vtkImageShiftScale()
|
||
|
shifter.SetShift(shift)
|
||
|
shifter.SetScale(slope)
|
||
|
shifter.SetOutputScalarTypeToUnsignedChar()
|
||
|
shifter.SetInputConnection(v16.GetOutputPort())
|
||
|
shifter.ReleaseDataFlagOff()
|
||
|
shifter.Update()
|
||
|
|
||
|
# Display a y-z plane.
|
||
|
#
|
||
|
imageActor = vtk.vtkImageActor()
|
||
|
imageActor.SetInput(shifter.GetOutput())
|
||
|
imageActor.VisibilityOn()
|
||
|
imageActor.SetDisplayExtent(31, 31, 0, 63, 0, 92)
|
||
|
imageActor.InterpolateOff()
|
||
|
#
|
||
|
|
||
|
spc = shifter.GetOutput().GetSpacing()
|
||
|
orig = shifter.GetOutput().GetOrigin()
|
||
|
x0 = orig[0]
|
||
|
xspc = spc[0]
|
||
|
pos = x0+xspc*31.0
|
||
|
|
||
|
# An alternative would be to formulate position in this case by:
|
||
|
# set bounds [imageActor GetBounds]
|
||
|
# set pos [lindex $bounds 0]
|
||
|
#
|
||
|
#
|
||
|
|
||
|
ren = vtk.vtkRenderer()
|
||
|
ren.SetBackground(0.4, 0.4, 0.5)
|
||
|
ren2 = vtk.vtkRenderer()
|
||
|
ren2.SetBackground(0.5, 0.4, 0.4)
|
||
|
#
|
||
|
|
||
|
renWin = vtk.vtkRenderWindow()
|
||
|
renWin.AddRenderer(ren)
|
||
|
renWin.AddRenderer(ren2)
|
||
|
renWin.SetSize(600, 300)
|
||
|
#
|
||
|
|
||
|
ren.SetViewport(0, 0, 0.5, 1)
|
||
|
ren2.SetViewport(0.5, 0, 1, 1)
|
||
|
#
|
||
|
|
||
|
interactor = vtk.vtkInteractorStyleImage()
|
||
|
#
|
||
|
|
||
|
iren = vtk.vtkRenderWindowInteractor()
|
||
|
iren.SetInteractorStyle(interactor)
|
||
|
iren.SetRenderWindow(renWin)
|
||
|
#
|
||
|
|
||
|
extract = vtk.vtkExtractVOI()
|
||
|
extract.SetVOI(31, 31, 0, 63, 0, 92)
|
||
|
extract.SetSampleRate(1, 1, 1)
|
||
|
extract.SetInputConnection(shifter.GetOutputPort())
|
||
|
extract.ReleaseDataFlagOff()
|
||
|
#
|
||
|
|
||
|
imageActor2 = vtk.vtkImageActor()
|
||
|
imageActor2.SetInput(extract.GetOutput())
|
||
|
imageActor2.VisibilityOn()
|
||
|
imageActor2.SetDisplayExtent(31, 31, 0, 63, 0, 92)
|
||
|
imageActor2.InterpolateOff()
|
||
|
#
|
||
|
|
||
|
# Set up the image tracer widget
|
||
|
#
|
||
|
itw = vtk.vtkImageTracerWidget()
|
||
|
#
|
||
|
# Set the tolerance for capturing last handle when near first handle
|
||
|
# to form closed paths.
|
||
|
#
|
||
|
itw.SetCaptureRadius(1.5)
|
||
|
itw.GetGlyphSource().SetColor(1, 0, 0)
|
||
|
#
|
||
|
# Set the size of the glyph handle
|
||
|
#
|
||
|
itw.GetGlyphSource().SetScale(3.0)
|
||
|
#
|
||
|
# Set the initial rotation of the glyph if desired. The default glyph
|
||
|
# set internally by the widget is a '+' so rotating 45 deg. gives a 'x'
|
||
|
#
|
||
|
itw.GetGlyphSource().SetRotationAngle(45.0)
|
||
|
itw.GetGlyphSource().Modified()
|
||
|
itw.ProjectToPlaneOn()
|
||
|
itw.SetProjectionNormalToXAxes()
|
||
|
itw.SetProjectionPosition(pos)
|
||
|
itw.SetViewProp(imageActor)
|
||
|
itw.SetInput(shifter.GetOutput())
|
||
|
itw.SetInteractor(iren)
|
||
|
itw.PlaceWidget()
|
||
|
|
||
|
#
|
||
|
# When the underlying vtkDataSet is a vtkImageData, the widget can be
|
||
|
# forced to snap to either nearest pixel points, or pixel centers. Here
|
||
|
# it is turned off.
|
||
|
#
|
||
|
itw.SnapToImageOff()
|
||
|
|
||
|
#
|
||
|
# Automatically form closed paths.
|
||
|
#
|
||
|
#itw AutoCloseOn
|
||
|
itw.AutoCloseOn()
|
||
|
#
|
||
|
|
||
|
# Set up a vtkSplineWidget in the second renderer and have
|
||
|
# its handles set by the tracer widget.
|
||
|
#
|
||
|
isw = vtk.vtkSplineWidget()
|
||
|
isw.SetCurrentRenderer(ren2)
|
||
|
isw.SetDefaultRenderer(ren2)
|
||
|
isw.SetInput(extract.GetOutput())
|
||
|
isw.SetInteractor(iren)
|
||
|
bnds = imageActor2.GetBounds()
|
||
|
isw.PlaceWidget(bnds[0], bnds[1], bnds[2], bnds[3], bnds[4], bnds[5])
|
||
|
isw.ProjectToPlaneOn()
|
||
|
isw.SetProjectionNormalToXAxes()
|
||
|
isw.SetProjectionPosition(pos)
|
||
|
#
|
||
|
|
||
|
# Have the widgets control each others handle positions.
|
||
|
#
|
||
|
itw.AddObserver('EndInteractionEvent',AdjustSpline)
|
||
|
isw.AddObserver('EndInteractionEvent',AdjustTracer)
|
||
|
#
|
||
|
|
||
|
itw.On()
|
||
|
isw.On()
|
||
|
#
|
||
|
|
||
|
poly = vtk.vtkPolyData()
|
||
|
points = vtk.vtkPoints()
|
||
|
spoly = vtk.vtkPolyData()
|
||
|
#
|
||
|
|
||
|
# Set up a pipleline to demonstrate extraction of a 2D
|
||
|
# region of interest. Defining a closed clockwise path using the
|
||
|
# tracer widget will extract all pixels within the loop. A counter
|
||
|
# clockwise path provides the dual region of interest.
|
||
|
#
|
||
|
extrude = vtk.vtkLinearExtrusionFilter()
|
||
|
extrude.SetInput(spoly)
|
||
|
extrude.SetScaleFactor(1)
|
||
|
extrude.SetExtrusionTypeToNormalExtrusion()
|
||
|
extrude.SetVector(1, 0, 0)
|
||
|
#
|
||
|
|
||
|
dataToStencil = vtk.vtkPolyDataToImageStencil()
|
||
|
dataToStencil.SetInputConnection(extrude.GetOutputPort())
|
||
|
#
|
||
|
|
||
|
stencil = vtk.vtkImageStencil()
|
||
|
stencil.SetInputConnection(extract.GetOutputPort())
|
||
|
stencil.SetStencil(dataToStencil.GetOutput())
|
||
|
stencil.ReverseStencilOff()
|
||
|
stencil.SetBackgroundValue(128)
|
||
|
#
|
||
|
|
||
|
# Add all the actors.
|
||
|
#
|
||
|
ren.AddViewProp(imageActor)
|
||
|
ren2.AddViewProp(imageActor2)
|
||
|
#
|
||
|
|
||
|
# Render the image.
|
||
|
#
|
||
|
renWin.Render()
|
||
|
#
|
||
|
|
||
|
ren.GetActiveCamera().SetViewUp(0, 1, 0)
|
||
|
ren.GetActiveCamera().Azimuth(270)
|
||
|
ren.GetActiveCamera().Roll(270)
|
||
|
ren.GetActiveCamera().Dolly(1.7)
|
||
|
ren.ResetCameraClippingRange()
|
||
|
#
|
||
|
|
||
|
ren2.GetActiveCamera().SetViewUp(0, 1, 0)
|
||
|
ren2.GetActiveCamera().Azimuth(270)
|
||
|
ren2.GetActiveCamera().Roll(270)
|
||
|
ren2.GetActiveCamera().Dolly(1.7)
|
||
|
ren2.ResetCameraClippingRange()
|
||
|
#
|
||
|
|
||
|
# if we don't do this, the widgets disappear behind the imageActor.
|
||
|
vtk.vtkMapper.SetResolveCoincidentTopologyToPolygonOffset()
|
||
|
vtk.vtkMapper.SetResolveCoincidentTopologyPolygonOffsetParameters(10,10)
|
||
|
|
||
|
|
||
|
renWin.Render()
|
||
|
#
|
||
|
|
||
|
iren.Initialize()
|
||
|
renWin.Render()
|
||
|
iren.Start()
|