Firstly, I’m still fairly new at VTK, I’m doing the best I can
I have a scene illustrating points as glyphs. I want to be able to pick and highlight each glyph individually.
I have implemented the interactor style highlighting actors, which works perfectly. However, this will select all glyphs at once.
I’m showing the points as glyphs since I normally have more than 10,000 points. And creating an individual actor for each point makes interaction impossible (simple operates to slow).
I looked into a vtkCellPicker, and I’m getting something, but it is definitely not correct, and I was hoping someone could assist me.
What I have:
import vtk
import numpy as np
class InteractorStyle(vtk.vtkInteractorStyleTrackballCamera):
def __init__(self, glyphs, renderer):
self.glyphs = glyphs
self.renderer = renderer
self.AddObserver("LeftButtonPressEvent", self._left_button_press_event)
def _left_button_press_event(self, obj, event):
click_pos = self.GetInteractor().GetEventPosition()
cell_picker = vtk.vtkCellPicker()
cell_picker.Pick(click_pos[0], click_pos[1], 0, self.GetDefaultRenderer())
input_ids = self.glyphs.GetOutput().GetPointData().GetArray("InputPointIds")
if input_ids:
cell = self.glyphs.GetOutput().GetCell(cell_picker.GetCellId())
if cell and cell.GetNumberOfPoints() > 0:
input_id = cell.GetPointId(0)
selected_id = input_ids.GetTuple1(input_id)
if selected_id >= 0:
highlight_sphere = vtk.vtkSphereSource()
highlight_sphere.SetRadius(2)
highlight_sphere.SetThetaResolution(8)
highlight_sphere.SetPhiResolution(8)
highlight_sphere.SetCenter(self.glyphs.GetOutput().GetPoint(int(selected_id)))
mapper = vtk.vtkPolyDataMapper()
mapper.SetInputConnection(highlight_sphere.GetOutputPort())
highlight_actor = vtk.vtkActor()
highlight_actor.SetMapper(mapper)
self.renderer.AddActor(highlight_actor)
print("Pick!")
self.OnLeftButtonDown()
return
renderer = vtk.vtkRenderer()
render_window = vtk.vtkRenderWindow()
render_window.AddRenderer(renderer)
interactor = vtk.vtkRenderWindowInteractor()
interactor.SetRenderWindow(render_window)
sphere = vtk.vtkSphereSource()
sphere.SetRadius(1)
sphere.SetThetaResolution(8)
sphere.SetPhiResolution(8)
points = vtk.vtkPoints()
p_data = vtk.vtkPolyData()
for i in range(20):
points.InsertNextPoint(20 * np.random.random(3))
p_data.SetPoints(points)
glyph = vtk.vtkGlyph3D()
glyph.GeneratePointIdsOn()
glyph.SetInputData(p_data)
glyph.SetSourceConnection(sphere.GetOutputPort())
glyph.Update()
mapper = vtk.vtkPolyDataMapper()
mapper.SetInputConnection(glyph.GetOutputPort())
actor = vtk.vtkActor()
actor.SetMapper(mapper)
renderer.AddActor(actor)
style = InteractorStyle(glyph, renderer)
style.SetDefaultRenderer(renderer)
interactor.SetInteractorStyle(style)
render_window.Render()
interactor.Start()
I add a sphere when something is clicked, at the found coordinates. This shows that the returned coordinates are not those I expected.
So, is this the wrong way to go about this issue?
If the CellPicker is the correct way, how can I extract the glyph and recolor it?