How to limit extent of planes in ResliceCursorWidget

I am working with a vtkResliceCusorWidget in a FourPlaneViewer-like application.

I would like to know how I can limit the size of the plane widgets that are generated by vtkResliceCursorLineRepresentation.

If, for instance, I use GetRepresentation().GetResliceCursorActor() on my vtkResliceCursorWidget then the resulting actor is many times larger than the image data it is acting on.

If I check the bounds on my vtkResliceCursorLineRepresentation however, then they match the bounds of my underlying image data. Working with SetPlaceFactor method does not seem to have any effect, but default value should be appropriate.

The resulting issue is:
A) displaying the widget polydata in a 3D view is oversized.
B) the widget extends too far beyond its renderwidow viewport - interfering with picking (i.e. interaction in the 3D viewport may activate the reslice widget in one of the other 3 viewports).

The later I can partially correct by setting priorities on the widget that update based upon the viewport that the mouse is in, but this seems overkill.

A working example (without the priority adjustment) is included below. VTK version 9.0.0

import vtk

def readData():
    myVTIDataFile = 'heart.vtk'
    # reader = vtk.vtkXMLImageDataReader()
    reader = vtk.vtkGenericDataObjectReader()
    reader.SetFileName(myVTIDataFile)
    reader.Update()
    return reader.GetOutput()


def ResliceCursorCallback(obj,event):
    thisLineRepresentation = obj.GetResliceCursorRepresentation()
    interactionState = thisLineRepresentation.GetInteractionState()
    if interactionState > 4:
        # These lines keep planes orthogonal (if rotating)
        x, y = obj.GetInteractor().GetEventPosition()
        obj.GetResliceCursorRepresentation().ComputeInteractionState(x, y, 1)


# Read data
data = readData()
imageDims = data.GetDimensions()

# Make a contour of image to display in 3D panel
contourFilter = vtk.vtkContourFilter()
contourFilter.SetInputData(data)
contourFilter.SetValue(0, 125.0)
contourFilter.Update()
surfMapper = vtk.vtkPolyDataMapper()
surfMapper.ScalarVisibilityOff()
surfMapper.SetInputConnection(contourFilter.GetOutputPort())
surfActor = vtk.vtkActor()
surfActor.SetMapper(surfMapper)
surfActor.GetProperty().SetColor(1,0.75,0)

# Renderers
renWin = vtk.vtkRenderWindow()
RendererArray = [None]*4
for i in range(0,4):
    RendererArray[i] = vtk.vtkRenderer()
    renWin.AddRenderer(RendererArray[i])
renWin.SetMultiSamples(0)

# Render window interactor
iren = vtk.vtkRenderWindowInteractor()
renWin.SetInteractor(iren)

# Picker
picker = vtk.vtkPointPicker()
picker.SetTolerance(0.5)

# Properties
ipwProp = vtk.vtkProperty()

# ResliceCursor
resliceCursor = vtk.vtkResliceCursor()
center = data.GetCenter()
resliceCursor.SetCenter(center[0], center[1], center[2])
resliceCursor.SetThickMode(0)
resliceCursor.SetThickness(0.01, 0.01, 0.01)
resliceCursor.SetHole(2)
resliceCursor.SetImage(data)


# 2D Reslice cursor widgets
resliceCursorWidgetArray = [None]*3
viewUp = [[0, 0, 1],[0, 0, 1],[0, -1, 0]]
print('Data bounds:', data.GetBounds())
for i in range(0,3):
    range_color = data.GetScalarRange()
    resliceCursorWidgetArray[i] = vtk.vtkResliceCursorWidget()
    rscRep = vtk.vtkResliceCursorLineRepresentation()
    rscRep.GetResliceCursorActor().GetCursorAlgorithm().SetResliceCursor(resliceCursor)
    rscRep.GetResliceCursorActor().GetCursorAlgorithm().SetReslicePlaneNormal(i)
    rscRep.SetWindowLevel(range_color[1] - range_color[0], (range_color[0] + range_color[1]) / 2.0, 0)
    if i > 0:
        rscRep.SetLookupTable(resliceCursorWidgetArray[0].GetRepresentation().GetLookupTable())
    ##
    print('    vtkResliceCursorLineRepresentation %d bounds:'%(i), rscRep.GetBounds())
    ##
    resliceCursorWidgetArray[i].SetInteractor(iren)
    resliceCursorWidgetArray[i].SetRepresentation(rscRep)
    resliceCursorWidgetArray[i].SetDefaultRenderer(RendererArray[i])
    resliceCursorWidgetArray[i].SetEnabled(1)
    RendererArray[i].GetActiveCamera().SetFocalPoint(0, 0, 0)
    camPos = [0, 0, 0]
    camPos[i] = 1
    RendererArray[i].GetActiveCamera().SetPosition(camPos[0], camPos[1], camPos[2])
    RendererArray[i].GetActiveCamera().ParallelProjectionOn()
    RendererArray[i].GetActiveCamera().SetViewUp(viewUp[i][0], viewUp[i][1], viewUp[i][2])
    RendererArray[i].ResetCamera()
    resliceCursorWidgetArray[i].AddObserver('InteractionEvent',ResliceCursorCallback)


# Add 3D actors
RendererArray[3].AddActor(surfActor)
pd = resliceCursor.GetCenterlineAxisPolyData(1)

pdMapper = vtk.vtkPolyDataMapper()
pdMapper.ScalarVisibilityOff()
pdMapper.SetInputData(pd)
pdActor = vtk.vtkActor()
pdActor.SetMapper(pdMapper)
pdActor.GetProperty().SetColor(0,1,0)
RendererArray[3].AddActor(pdActor)
# for i in range(3):
#     iActor = resliceCursorWidgetArray[i].GetRepresentation().GetResliceCursorActor()
#     RendererArray[3].AddActor(iActor)

# Background
RendererArray[0].SetBackground(0.3, 0.1, 0.1)
RendererArray[1].SetBackground(0.1, 0.3, 0.1)
RendererArray[2].SetBackground(0.1, 0.1, 0.3)
RendererArray[3].SetBackground(0.1, 0.1, 0.1)
renWin.SetSize(600, 600)

# Render
RendererArray[0].SetViewport(0, 0, 0.5, 0.5)
RendererArray[1].SetViewport(0.5, 0, 1, 0.5)
RendererArray[2].SetViewport(0, 0.5, 0.5, 1)
RendererArray[3].SetViewport(0.5, 0.5, 1, 1)
renWin.Render()

# Camera in 3D view
RendererArray[3].GetActiveCamera().Elevation(110)
RendererArray[3].GetActiveCamera().SetViewUp(0, 0, -1)
RendererArray[3].GetActiveCamera().Azimuth(45)
RendererArray[3].GetActiveCamera().Dolly(1.15)
RendererArray[3].ResetCameraClippingRange()

iren.Initialize()
iren.Start()

Appreciate any help.
Thanks,
Fraser

1 Like