Mouse Interaction with ModelNode: Hover and Click Functions

Hello,

I want to create a feature that interacts with a modelNode through the mouse. Specifically, when the mouse hovers over a model, I want its color to change, and when clicked, I want the camera to center on that model.

I have come across several similar questions, but I couldn’t find a solution, and some of the example links were invalid.

I thought knowing the mouse (cursor) position would be the starting point, so I found the following code that allows me to get the mouse coordinates:

crosshairNode=slicer.util.getNode(“Crosshair”)

def onMouseMoved(ViewName):
ras=[0,0,0]
crosshairNode.GetCursorPositionRAS(ras)
print(ras)

for viewName in [“View1”]:
threeDView = slicer.app.layoutManager().threeDWidget(viewName).threeDView()
tag = threeDView.interactor().AddObserver(vtk.vtkCommand.MouseMoveEvent , lambda caller, event, viewName=viewName: onMouseMoved(viewName))

However, I am having difficulty determining if the mouse is over a specific model with these coordinates (do I need to write code to compare the coordinates with all points of the model? This seems to take too long).

I believe that the features I mentioned are already implemented in the markups module. Therefore, I would appreciate it if you could provide a code snippet or some tips.

Check out focus implementation @Sunderlandkyl. It seems to be what you would like to achieve. You can find more information here.

I solved this using vtk.vtkCellPicker().
This is the code snippet of my implementation.

def setThreeDViewInteraction(self):
    self.picker = vtk.vtkCellPicker()
    self.picker.SetTolerance(0.005)    

    modelDisplayableManager = slicer.app.layoutManager().threeDWidget('View1').threeDView().displayableManagerByClassName("vtkMRMLModelDisplayableManager")
    self.actorModels = []
    for modelNode in self.modelNodes:
        self.actorModels.append(modelDisplayableManager.GetActorByID(modelNode.GetDisplayNode().GetID()))

    self.interactor3D = slicer.app.layoutManager().threeDWidget('View1').threeDView().interactor()
    self.threeDViewMouseHoverTag = self.interactor3D.AddObserver(vtk.vtkCommand.MouseMoveEvent, self.threeDViewMouseHover)
    self.threeDViewMouseClickTag = self.interactor3D.AddObserver(vtk.vtkCommand.LeftButtonDoubleClickEvent, self.threeDViewMouseClick)
    
def threeDViewMouseHover(self, caller, event):
    x, y = caller.GetEventPosition()
    self.picker.Pick(x, y, 0, caller.GetRenderWindow().GetRenderers().GetFirstRenderer())
    actorMouse = self.picker.GetActor()

    if actorMouse in self.actorModels:
        for modelNode in self.modelNodes:
            modelNode.GetDisplayNode().SetAmbient(0.95)
    else:
        for modelNode in self.modelNodes:
            modelNode.GetDisplayNode().SetAmbient(0.5)