Hello everyone,
I’m trying to pick an actor from an assembly, but I’m always getting the first actor in the assembly as the picked actor. My understanding is that that I should get the picked actor from the path returned by the picker (vtkPropPicker to be more precise). This path should contain 2 nodes: the assembly would be in the first node and the picked actor would be the in second node (a call to GetViewProp() is needed to get the actual actor). Did I understood it correctly?
I’ve modified HighlightWithSilhouette example to test this with no luck:
# !/usr/bin/env python
import vtk
def get_program_parameters():
import argparse
description = 'Highlighting a selected object with a silhouette.'
epilogue = '''
Click on the object to highlight it.
The selected object is highlighted with a silhouette.
'''
parser = argparse.ArgumentParser(description=description, epilog=epilogue,
formatter_class=argparse.RawTextHelpFormatter)
parser.add_argument('numberOfSpheres', nargs='?', type=int, default=10,
help='The number of spheres, default is 10.')
args = parser.parse_args()
return args.numberOfSpheres
class MouseInteractorHighLightActor(vtk.vtkInteractorStyleTrackballCamera):
def __init__(self, silhouette=None, silhouetteActor=None):
self.AddObserver("LeftButtonPressEvent", self.onLeftButtonDown)
self.LastPickedActor = None
self.Silhouette = silhouette
self.SilhouetteActor = silhouetteActor
def onLeftButtonDown(self, obj, event):
clickPos = self.GetInteractor().GetEventPosition()
# Pick from this location.
picker = vtk.vtkPropPicker()
picker.Pick(clickPos[0], clickPos[1], 0, self.GetDefaultRenderer())
print("---------- New picking ------------------")
print("Path: %s", picker.GetPath())
print("Path 1: %s", picker.GetPath().GetItemAsObject(1).GetViewProp())
print("-----------------------------------------")
self.LastPickedActor = picker.GetPath().GetItemAsObject(1).GetViewProp() #picker.GetActor()
# If we picked something before, remove the silhouette actor and
# generate a new one.
if self.LastPickedActor:
self.GetDefaultRenderer().RemoveActor(self.SilhouetteActor)
# Highlight the picked actor by generating a silhouette
self.Silhouette.SetInputData(self.LastPickedActor.GetMapper().GetInput())
self.GetDefaultRenderer().AddActor(self.SilhouetteActor)
# Forward events
self.OnLeftButtonDown()
return
def SetSilhouette(self, silhouette):
self.Silhouette = silhouette
def SetSilhouetteActor(self, silhouetteActor):
self.SilhouetteActor = silhouetteActor
def main():
numberOfSpheres = get_program_parameters()
colors = vtk.vtkNamedColors()
# A renderer and render window
renderer = vtk.vtkRenderer()
renderer.SetBackground(colors.GetColor3d('SteelBlue'))
renderWindow = vtk.vtkRenderWindow()
renderWindow.SetSize(640, 480)
renderWindow.AddRenderer(renderer)
# An interactor
interactor = vtk.vtkRenderWindowInteractor()
interactor.SetRenderWindow(renderWindow)
# Assembly
assembly = vtk.vtkPropAssembly()
# Add spheres to play with
for i in range(numberOfSpheres):
source = vtk.vtkSphereSource()
# random position and radius
x = vtk.vtkMath.Random(-5, 5)
y = vtk.vtkMath.Random(-5, 5)
z = vtk.vtkMath.Random(-5, 5)
radius = vtk.vtkMath.Random(.5, 1.0)
source.SetRadius(radius)
source.SetCenter(x, y, z)
source.SetPhiResolution(11)
source.SetThetaResolution(21)
mapper = vtk.vtkPolyDataMapper()
mapper.SetInputConnection(source.GetOutputPort())
actor = vtk.vtkActor()
actor.SetMapper(mapper)
r = vtk.vtkMath.Random(.4, 1.0)
g = vtk.vtkMath.Random(.4, 1.0)
b = vtk.vtkMath.Random(.4, 1.0)
actor.GetProperty().SetDiffuseColor(r, g, b)
actor.GetProperty().SetDiffuse(.8)
actor.GetProperty().SetSpecular(.5)
actor.GetProperty().SetSpecularColor(colors.GetColor3d('White'))
actor.GetProperty().SetSpecularPower(30.0)
assembly.AddPart(actor)
# Add assembly to renderer
renderer.AddActor(assembly)
# Render and interact
renderWindow.Render()
# Create the silhouette pipeline, the input data will be set in the
# interactor
silhouette = vtk.vtkPolyDataSilhouette()
silhouette.SetCamera(renderer.GetActiveCamera())
# Create mapper and actor for silhouette
silhouetteMapper = vtk.vtkPolyDataMapper()
silhouetteMapper.SetInputConnection(silhouette.GetOutputPort())
silhouetteActor = vtk.vtkActor()
silhouetteActor.SetMapper(silhouetteMapper)
silhouetteActor.GetProperty().SetColor(colors.GetColor3d("Tomato"))
silhouetteActor.GetProperty().SetLineWidth(5)
# Set the custom type to use for interaction.
style = MouseInteractorHighLightActor(silhouette, silhouetteActor)
style.SetDefaultRenderer(renderer)
# Start
interactor.Initialize()
interactor.SetInteractorStyle(style)
renderWindow.SetWindowName('HighlightWithSilhouette')
renderWindow.Render()
interactor.Start()
if __name__ == "__main__":
main()
As you can see in the above code, I add the actors to the assembly. And then add the assembly to the renderer. In the picking part, I assign the actor in last node of the path to LastPickedActor (to highligh it). I also print the path and the actor of the last element of the path, so I can see that the path has 2 elements and the memory position of the picked actor (I always get the same actor with the same memory position).
Any help will be apreciated
Thanks!
T,