#!/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()