<div dir="ltr"><div>I almost have my code functioning how I'd like it, but it's not quite there.  I'd like to be able to take a vtkUnstructuredGrid and box pick a set of cells and points and then get their IDs.  My code gets the cells correctly, but gets all the point ids associated with the picked cells instead of just the ones inside the box.<br></div><div><br></div><div>I read that the AreaPicker is somewhat inaccurate for cells/points, but t<span style="background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline">his behavior is independent of zoom level.  I also read that using a selection is preferred, but I was unable to figure out how to implement this using a vtkSelection.</span></div><div><span style="background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline"><br></span></div><div><span style="background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline">I made an example that sets up a picker.  There are two cells.  If you box pick over a single point, I'd expect the code to print a single point ID.  I suspect the error has to do with how I'm using the <span style="text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline">vtkExtractSelectedFrustum class, but I'm not positive.  </span></span>Any ideas?</div><div><br></div><div>Thanks,</div><div><br></div><div>Steve</div><br><div><div>    from __future__ import print_function, division</div><div>    import signal</div><div>    </div><div>    import numpy as np</div><div>    import vtk</div><div>    from vtk.util.numpy_support import vtk_to_numpy, numpy_to_vtk, numpy_to_vtkIdTypeArray</div><div>    </div><div>    # kills the program when you hit Cntl+C from the command line</div><div>    # doesn't save the current state as presumably there's been an error</div><div>    signal.signal(signal.SIGINT, signal.SIG_DFL)</div><div>    </div><div>    class AreaPickStyle(vtk.vtkInteractorStyleRubberBandZoom):</div><div>        """Picks nodes & elements with a visible box widget"""</div><div>        def __init__(self, parent, callback):</div><div>            """creates the AreaPickStyle instance"""</div><div>            self.AddObserver("LeftButtonPressEvent", self._left_button_press_event)</div><div>            self.AddObserver("LeftButtonReleaseEvent", self._left_button_release_event)</div><div>            self.AddObserver("RightButtonPressEvent", self.right_button_press_event)</div><div>            self.parent = parent</div><div>            self.picker_points = []</div><div>            self.parent.area_picker.SetRenderer(self.parent.renderer)</div><div>            self.callback = callback</div><div>    </div><div>        def _left_button_press_event(self, obj, event):</div><div>            """</div><div>            gets the first point</div><div>            """</div><div>            self.OnLeftButtonDown()</div><div>            pixel_x, pixel_y = self.parent.render_window_interactor.GetEventPosition()</div><div>            self.picker_points.append((pixel_x, pixel_y))</div><div>    </div><div>        def _left_button_release_event(self, obj, event):</div><div>            """</div><div>            gets the second point and calls _pick_depth_ids</div><div>            """</div><div>            pixel_x, pixel_y = self.parent.render_window_interactor.GetEventPosition()</div><div>    </div><div>            self.picker_points.append((pixel_x, pixel_y))</div><div>    </div><div>            if len(self.picker_points) == 2:</div><div>                p1x, p1y = self.picker_points[0]</div><div>                p2x, p2y = self.picker_points[1]</div><div>                self.picker_points = []</div><div>                xmin = min(p1x, p2x)</div><div>                ymin = min(p1y, p2y)</div><div>                xmax = max(p1x, p2x)</div><div>                ymax = max(p1y, p2y)</div><div>    </div><div>                dx = abs(p1x - p2x)</div><div>                dy = abs(p1y - p2y)</div><div>                self.picker_points = []</div><div>                if dx > 0 and dy > 0:</div><div>                    self._pick_depth_ids(xmin, ymin, xmax, ymax)</div><div>                self.parent.render_window_interactor.Render()</div><div>            self.picker_points = []</div><div>    </div><div>        def _pick_depth_ids(self, xmin, ymin, xmax, ymax):</div><div>            """</div><div>            Does an area pick of all the ids inside the box, even the ones</div><div>            behind the front elements</div><div>            """</div><div>            area_picker = self.parent.area_picker</div><div>    </div><div>            area_picker.AreaPick(xmin, ymin, xmax, ymax, self.parent.renderer)</div><div>            frustum = area_picker.GetFrustum() # vtkPlanes</div><div>            grid = self.parent.grid</div><div>    </div><div>            idsname = "Ids"</div><div>            ids = vtk.vtkIdFilter()</div><div>            ids.SetInputData(grid)</div><div>    </div><div>            # default is on; just being explicit</div><div>            ids.CellIdsOn()</div><div>            ids.PointIdsOn()</div><div>            ids.SetIdsArrayName(idsname)</div><div>    </div><div>            # get the cells/points inside the frustum</div><div>            selected_frustum = vtk.vtkExtractSelectedFrustum()</div><div>            selected_frustum.SetFrustum(frustum)</div><div>    </div><div>            # we just want the ids; don't make an unstructured grid</div><div>            # return an unstructured grid anyways?</div><div>            # I think the error is in how I use vtkExtractSelectedFrustum</div><div>            selected_frustum.PreserveTopologyOn()</div><div>            selected_frustum.SetInputConnection(ids.GetOutputPort())</div><div>            selected_frustum.Update()</div><div>    </div><div>            ugrid = selected_frustum.GetOutput()</div><div>    </div><div>            cell_ids = None</div><div>            cells = ugrid.GetCellData()</div><div>            if cells is not None:</div><div>                ids = cells.GetArray('Ids')</div><div>                if ids is not None:</div><div>                    cell_ids = vtk_to_numpy(ids)</div><div>                    assert len(cell_ids) == len(np.unique(cell_ids))</div><div>    </div><div>            point_ids = None</div><div>            points = ugrid.GetPointData()</div><div>            if points is not None:</div><div>                ids = points.GetArray('Ids')</div><div>                if ids is not None:</div><div>                    point_ids = vtk_to_numpy(ids)</div><div>    </div><div>            self.callback(cell_ids, point_ids)</div><div>    </div><div>        def right_button_press_event(self, obj, event):</div><div>            """cancels the button"""</div><div>            style = vtk.vtkInteractorStyleImage()</div><div>            self.parent.render_window_interactor.SetInteractorStyle(style)</div><div>            self.parent.render_window_interactor.Render()</div><div>    </div><div>    </div><div>    def mixed_type_unstructured_grid():</div><div>        """A slightly more complex example of how to generate an</div><div>        unstructured grid with different cell types.  Returns a created</div><div>        unstructured grid.</div><div>        """</div><div>        pts = np.array([</div><div>            [0,0,0], [1,0,0], [0,1,0], [0,0,1], # tetra</div><div>            [2,0,0], [3,0,0], [3,1,0], [2,1,0],</div><div>            [2,0,1], [3,0,1], [3,1,1], [2,1,1], # Hex</div><div>            ], dtype='float32')</div><div>        # shift the points so we can show both.</div><div>        pts[:,1] += 2.0</div><div>        npoints = len(pts)</div><div>    </div><div>    </div><div>        # The cells must be int64 because numpy_to_vtkIdTypeArray requires that.</div><div>        # I think it depends on what vtkIdTypeArray() was built with.</div><div>        # nnodes_tetra, (nodes_tetra1)</div><div>        # nnodes_hexa, (nodes_hexa1)</div><div>        cells = np.array([</div><div>            4, 0, 1, 2, 3, # tetra</div><div>            8, 4, 5, 6, 7, 8, 9, 10, 11 # hex</div><div>        ], dtype='int64')</div><div>    </div><div>        # The offsets for the cells (i.e., the indices where the cells start)</div><div>        # one for each element</div><div>        cell_offsets = np.array([0, 5], dtype='int32')</div><div>    </div><div>        # add one element_type for each element</div><div>        tetra_type = vtk.vtkTetra().GetCellType() # VTK_TETRA == 10</div><div>        hex_type = vtk.vtkHexahedron().GetCellType() # VTK_HEXAHEDRON == 12</div><div>        cell_types = np.array([tetra_type, hex_type], dtype='int32')</div><div>    </div><div>        # Create the array of cells</div><div>        vtk_cells = vtk.vtkCellArray()</div><div>        vtk_cells_id_type = numpy_to_vtkIdTypeArray(cells, deep=1)</div><div>    </div><div>        # ncells = 2</div><div>        vtk_cells.SetCells(2, vtk_cells_id_type)</div><div>    </div><div>        # Now create the unstructured grid</div><div>        ugrid = vtk.vtkUnstructuredGrid()</div><div>    </div><div>        points_data = numpy_to_vtk(pts, deep=1)</div><div>    </div><div>        points = vtk.vtkPoints()</div><div>        points.SetNumberOfPoints(npoints)</div><div>        points.SetData(points_data)</div><div>        ugrid.SetPoints(points)</div><div>    </div><div>        # Now just set the cell types and reuse the ugrid locations and cells</div><div>        ugrid.SetCells(</div><div>            numpy_to_vtk(</div><div>                cell_types,</div><div>                deep=1,</div><div>                array_type=vtk.vtkUnsignedCharArray().GetDataType(),</div><div>            ),</div><div>            numpy_to_vtk(</div><div>                cell_offsets,</div><div>                deep=1,</div><div>                array_type=vtk.vtkIdTypeArray().GetDataType()</div><div>            ),</div><div>            vtk_cells,</div><div>        )</div><div>        return ugrid</div><div>    </div><div>    </div><div>    class MyGUI(object):</div><div>        def __init__(self):</div><div>            self.area_picker = vtk.vtkAreaPicker()</div><div>    </div><div>            ugrid = mixed_type_unstructured_grid()</div><div>            self.grid = ugrid</div><div>    </div><div>            # Setup render window interactor</div><div>            self.render_window_interactor = vtk.vtkRenderWindowInteractor()</div><div>    </div><div>            grid_mapper = vtk.vtkDataSetMapper()</div><div>            vtk_version = int(vtk.VTK_VERSION[0])</div><div>            if vtk_version == 5:</div><div>                grid_mapper.SetInput(ugrid)</div><div>            elif vtk_version in [6, 7, 8]:</div><div>                grid_mapper.SetInputData(ugrid)</div><div>            else:</div><div>                raise NotImplementedError(vtk.VTK_VERSION)</div><div>    </div><div>            geom_actor = vtk.vtkActor()</div><div>            geom_actor.SetMapper(grid_mapper)</div><div>    </div><div>    </div><div>            # Setup renderer</div><div>            self.renderer = vtk.vtkRenderer()</div><div>            self.renderer.AddActor(geom_actor)</div><div>            self.renderer.ResetCamera()</div><div>            self.renderer.SetBackground(0.7, 0.8, 1.0)</div><div>    </div><div>            # Setup render window</div><div>            render_window = vtk.vtkRenderWindow()</div><div>            render_window.AddRenderer(self.renderer)</div><div>    </div><div>            # Setup render window</div><div>            render_window = vtk.vtkRenderWindow()</div><div>            render_window.AddRenderer(self.renderer)</div><div>    </div><div>            def callback(cell_ids, point_ids):</div><div>                print('callback: cell_ids = %s' % cell_ids)</div><div>                print('callback: point_ids = %s' % point_ids)</div><div>    </div><div>            # Render and start interaction</div><div>            self.render_window_interactor.SetRenderWindow(render_window)</div><div>            self.render_window_interactor.Initialize()</div><div>    </div><div>            style = AreaPickStyle(self, callback)</div><div>            self.render_window_interactor.SetInteractorStyle(style)</div><div>    </div><div>        def start(self):</div><div>            self.render_window_interactor.Start()</div><div>    </div><div>    def main():</div><div>        gui = MyGUI()</div><div>        gui.start()</div><div>    </div><div>    if __name__ == '__main__':</div><div>        main()</div></div><div><br></div></div>