I did a little more research:
As per the documentation, extract_selection accepts only 2 InputData slots, 0 → the data and 1 → the selection. So my second approach above is expected to fail.
The following working example is a merge of the linked CellPicking and vtkQuad examples and basically shows what I want to do - with 1 quad. As described above, I need it working with 6 selectable quads.
I tried grouping the quads polydata in a vtkMultiBlockDataSet, and provide this as the InputData at index 0, but then nothing is selected, no matter where I click in the viewport.
from vtkmodules.vtkCommonColor import vtkNamedColors
from vtkmodules.vtkCommonCore import vtkIdTypeArray
from vtkmodules.vtkCommonDataModel import (
vtkSelection,
vtkSelectionNode,
vtkUnstructuredGrid
)
from vtkmodules.vtkFiltersExtraction import vtkExtractSelection
from vtkmodules.vtkRenderingCore import (
vtkActor,
vtkCellPicker,
vtkDataSetMapper,
vtkPolyDataMapper,
vtkRenderWindow,
vtkRenderWindowInteractor,
vtkRenderer
)
from vtk import *
# Catch mouse events
class MouseInteractorStyle(vtkInteractorStyleTrackballCamera):
def __init__(self, data):
self.AddObserver('LeftButtonPressEvent', self.left_button_press_event)
self.data = data
self.selected_mapper = vtkDataSetMapper()
self.selected_actor = vtkActor()
def left_button_press_event(self, obj, event):
colors = vtkNamedColors()
# Get the location of the click (in window coordinates)
pos = self.GetInteractor().GetEventPosition()
picker = vtkCellPicker()
picker.SetTolerance(0.0005)
# Pick from this location.
picker.Pick(pos[0], pos[1], 0, self.GetDefaultRenderer())
world_position = picker.GetPickPosition()
print(f'Cell id is: {picker.GetCellId()}')
if picker.GetCellId() != -1:
print(f'Pick position is: ({world_position[0]:.6g}, {world_position[1]:.6g}, {world_position[2]:.6g})')
ids = vtkIdTypeArray()
ids.SetNumberOfComponents(1)
ids.InsertNextValue(picker.GetCellId())
selection_node = vtkSelectionNode()
selection_node.SetFieldType(vtkSelectionNode.CELL)
selection_node.SetContentType(vtkSelectionNode.INDICES)
selection_node.SetSelectionList(ids)
selection = vtkSelection()
selection.AddNode(selection_node)
extract_selection = vtkExtractSelection()
extract_selection.SetInputData(0, self.data)
extract_selection.SetInputData(1, selection)
extract_selection.Update()
# In selection
selected = vtkUnstructuredGrid()
selected.ShallowCopy(extract_selection.GetOutput())
print(f'Number of points in the selection: {selected.GetNumberOfPoints()}')
print(f'Number of cells in the selection : {selected.GetNumberOfCells()}')
self.selected_mapper.SetInputData(selected)
self.selected_actor.SetMapper(self.selected_mapper)
self.selected_actor.GetProperty().EdgeVisibilityOn()
self.selected_actor.GetProperty().SetColor(colors.GetColor3d('Tomato'))
self.selected_actor.GetProperty().SetLineWidth(3)
self.GetInteractor().GetRenderWindow().GetRenderers().GetFirstRenderer().AddActor(self.selected_actor)
self.selected_actor.VisibilityOn()
else:
if hasattr(self, 'selected_actor'):
self.selected_actor.VisibilityOff()
# Forward events
self.OnLeftButtonDown()
def main(argv):
colors = vtkNamedColors()
# Annotate the points
# https: // examples.vtk.org / site / Cxx / Annotation / TextOrigin /
# Create four points (must be in counter clockwise order)
p0 = [0.0, 0.0, 0.0]
p1 = [1.0, 0.0, 0.0]
p2 = [1.0, 1.0, 0.0]
p3 = [0.0, 1.0, 0.0]
# Add the points to a vtkPoints object
points = vtkPoints()
points.InsertNextPoint(p0)
points.InsertNextPoint(p1)
points.InsertNextPoint(p2)
points.InsertNextPoint(p3)
# Create a quad on the four points
quad = vtkQuad()
quad.GetPointIds().SetId(0, 0)
quad.GetPointIds().SetId(1, 1)
quad.GetPointIds().SetId(2, 2)
quad.GetPointIds().SetId(3, 3)
# Create a cell array to store the quad in
quads = vtkCellArray()
quads.InsertNextCell(quad)
# Create a polydata to store everything in
polydata = vtkPolyData()
# Add the points and quads to the dataset
polydata.SetPoints(points)
polydata.SetPolys(quads)
mapper = vtkPolyDataMapper()
mapper.SetInputData(polydata)
actor = vtkActor()
actor.GetProperty().SetColor(colors.GetColor3d('SeaGreen'))
actor.GetProperty().SetOpacity(0.1)
actor.SetMapper(mapper)
renderer = vtkRenderer()
ren_win = vtkRenderWindow()
ren_win.AddRenderer(renderer)
ren_win.SetWindowName('CellPicking')
iren = vtkRenderWindowInteractor()
iren.SetRenderWindow(ren_win)
renderer.AddActor(actor)
# renderer.ResetCamera()
renderer.SetBackground(colors.GetColor3d('White'))
# Add the custom style.
style = MouseInteractorStyle(polydata)
style.SetDefaultRenderer(renderer)
iren.SetInteractorStyle(style)
ren_win.Render()
iren.Initialize()
iren.Start()
if __name__ == '__main__':
import sys
main(sys.argv)