How do I set frustum data on a vtkSelectionNode?

I’m experimenting with various strategies to support rubber band picking and I’ve been successful when using vtkExtractGeometry to do the picking, but I see some advantages if I can switch to using vtkExtractSelection, vtkSelection and vtkSelectionNode.

Unfortunately, when I follow the most relevant examples I can find, I’m getting a hard crash. (VTK 8.2, Python on WIndows 10)

The relevant code fragment is below, and I suspect that the problem is how I’m populating the vtkSelectionNode SelectionList with the frustum data…

self.Mesh is a vtkUnstructuredGrid

        frustum = self.GetInteractor().GetPicker().GetFrustum()

        selectionNode = vtk.vtkSelectionNode()
        selectionNode.SetFieldType(1)  # Points
        #  CELL_DATA = 0
        #  POINT_DATA = 1
        #  FIELD_DATA = 2
        #  VERTEX_DATA = 3
        #  EDGE_DATA = 4

        selectionNode.SetContentType(5)  # FRUSTUM
        # SELECTIONS = 0
        # GLOBALIDS = 1
        # PEDIGREEIDS = 2
        # VALUES = 3
        # INDICES = 4
        # FRUSTUM = 5
        # LOCATIONS = 6
        # THRESHOLDS = 7
        # BLOCKS = 8

        # This is where I think think things are wrong....
        selectionNode.SetSelectionList(frustum.GetPoints().GetData())

        selection = vtk.vtkSelection()
        selection.AddNode(selectionNode)

        extractSelection = vtk.vtkExtractSelection()

        extractSelection.SetInputData(0, self.Mesh)

        extractSelection.SetInputData(1, selection)
        extractSelection.Update()

Any help will be gratefully received…

Doug

Still dead in the water!!!

I made some progress, but I still can’t figure out the correct code to select using vtkExtractSelection, vtkSelectionNode and vtkSelection using a frustum

I now confirm that I had an error where I originally suspected the problem

    # This is where I think think things are wrong....
    selectionNode.SetSelectionList(frustum.GetPoints().GetData())

frustum.GetPoints returns six points on the planes of the frustum (vtkPlanes) and not the corners of the frustum. To get the corners of the frustum seems unduly difficult - here’s how I got them

        frustum = self.GetInteractor().GetPicker().GetFrustum()
        frustum_source = vtk.vtkFrustumSource()
        frustum_source.SetPlanes(frustum)
        frustum_source.Update()
        frustum_poly = frustum_source.GetOutput()
        frustum_point_coords = frustum_poly.GetPoints().GetData()
        numpy_data = numpy_support.vtk_to_numpy(frustum_point_coords)

The VTK user guide tells me the frustum corners need to be provided as 8 four component tuples, which I get as follows,

        numpy_data = np.insert(numpy_data[0:8], 3, 1.0, axis=1)
        frustum_coords_vtk = numpy_support.numpy_to_vtk(numpy_data,
                                                                                             deep=False,
										          array_type=vtk.VTK_DOUBLE)

Then I complete the rest of the code,

        selectionNode = vtk.vtkSelectionNode()
        selectionNode.SetFieldType(1)  # Points
        selectionNode.SetContentType(vtk.vtkSelectionNode.FRUSTUM)
        # Pass in my frustum corner coordinates
        selectionNode.SetSelectionList(frustum_coords_vtk)

        selection = vtk.vtkSelection()
        selection.AddNode(selectionNode)

        extractSelection = vtk.vtkExtractSelection()
        extractSelection.SetInputData(0, self.mesh)
        extractSelection.SetInputData(1, selection)
        extractSelection.Update()
        extracted = extractSelection.GetOutput()

At this point the code runs, it seem like some work is done because the filter update tales some time to execute, but the output is empty…

So I’m pretty sure this code is close… but I can’t quite get it over the line…

As always, any help will be gratefully received.

Doug

OK - Finally figured it out…

Using the FustrumSource was a red herring. The trick was to get the frustum clip points form the picker and not the frustum. The clip points are easily modified to suit the SelectionNode and everything else works as expected form there.

I still don’t understand why the SelectionNode needs the frustum clip points as four component tuples - but it clearly does.

Final working code looks like this

def OnLeftButtonUpEvent(self,obj,event):
    self.OnLeftButtonUp()
    if self.pickingEnabled:
        clip_points = self.GetInteractor().GetPicker().GetClipPoints()
        clip_points_numpy = numpy_support.vtk_to_numpy(clip_points.GetData())
        clip_points_numpy = np.insert(clip_points_numpy, 3, 1.0, axis=1)
        clip_points_coords = numpy_support.numpy_to_vtk(clip_points_numpy,
                                                        deep=False,
                                                        array_type=vtk.VTK_DOUBLE)

        selectionNode = vtk.vtkSelectionNode()
        selectionNode.SetFieldType(1)  # Points
        selectionNode.SetContentType(vtk.vtkSelectionNode.FRUSTUM)
        selectionNode.SetSelectionList(clip_points_coords)

        selection = vtk.vtkSelection()
        selection.AddNode(selectionNode)

        extractSelection = vtk.vtkExtractSelection()
        extractSelection.SetInputData(0, self.mbds)
        extractSelection.SetInputData(1, selection)

        glyph_filter = vtk.vtkVertexGlyphFilter()
        glyph_filter.SetInputConnection(extractSelection.GetOutputPort())

        self.SelectedMapper.SetInputConnection(glyph_filter.GetOutputPort())
        self.SelectedMapper.ScalarVisibilityOff()

        self.SelectedActor.GetProperty().SetColor(1.0, 0.0, 0.0)  # (R,G,B)
        self.SelectedActor.GetProperty().SetPointSize(10)

        self.GetCurrentRenderer().AddActor(self.SelectedActor)
        self.GetInteractor().GetRenderWindow().Render()

Doug