【VTK+有限元后处理】单元信息查询

目的

通过可视化界面交互,实现对有限元模型上单元的选择和查询。

代码实现

大体思路和【VTK+有限元后处理】节点属性值查询的代码是差不多的。不同的地方在于标记(高亮)显示的方法。单元拾取交互的类型定义如下:

class CellPickerInteractorStyle(vtk.vtkInteractorStyleTrackballCamera):
    def __init__(self, parent = None):
        self.AddObserver("LeftButtonPressEvent", self.leftButtonPressEvent)
        self.selectedMapper = vtk.vtkDataSetMapper()
        self.selectedActor = vtk.vtkActor()
        self.dataset = None
        # Setup the text and add it to the renderer
        self.textActor = vtk.vtkTextActor()
        self.textActor.SetPosition(10, 10)
        self.textActor.GetTextProperty().SetFontSize(24)
        self.textActor.GetTextProperty().SetColor(241 / 255, 135 / 255, 184 / 255)

    def leftButtonPressEvent(self, obj, event):
        clickPos = self.GetInteractor().GetEventPosition()
        # 打印鼠标左键像素位置
        # print(f"Picking pixel: {clickPos[0]} {clickPos[1]}")
        # 注册拾取单元函数
        cellPicker = self.GetInteractor().GetPicker()
        cellPicker.SetTolerance(0.0005)
        cellPicker.Pick(clickPos[0], clickPos[1], 0, self.GetDefaultRenderer())

        if cellPicker.GetCellId() != -1:
            # print("Pick position is: ", cellPicker.GetPickPosition())
            # print("Cell id is:", cellPicker.GetCellId())
            # print("Point id is:", cellPicker.GetPointId())
            if self.dataset is None:
                print("Source data not found! ")
                return

            cell = self.dataset.GetCell(cellPicker.GetCellId())  # 通过拾取的CellId获取vtkCell
            # 打印单元信息
            self.textActor.SetInput(f"Picked Cell Type: {cell.GetClassName()}\nCell Id: {cellPicker.GetCellId()}")
            ## 高亮选择的单元方法1
            # selectedCells = vtk.vtkUnstructuredGrid()
            # cellArray = vtk.vtkCellArray()
            # pointList = vtk.vtkPoints()
            # idList = vtk.vtkIdList()
            # points = cell.GetPoints()
            # num = points.GetNumberOfPoints()
            # p = [0.0, 0.0, 0.0]
            # for i in range(num):
            #     p = points.GetPoint(i)
            #     print(f"Point{i} :\tx = {p[0]}\ty = {p[1]}\tz ={p[2]}")
            #     idList.InsertNextId(pointList.InsertNextPoint(p))
            # selectedCells.SetPoints(pointList)
            # selectedCells.InsertNextCell(cell.GetCellType(), idList)
            # print(f"Number of points in the selection: {selectedCells.GetNumberOfPoints()}")
            # print(f"Number of cells in the selection : {selectedCells.GetNumberOfCells()}")
            # mapper = vtk.vtkDataSetMapper()
            # mapper.SetInputData(selectedCells)
            # self.GetDefaultRenderer().RemoveActor(self.selectedActor)
            # self.selectedActor.SetMapper(mapper)
            # self.selectedActor.GetProperty().EdgeVisibilityOn()
            # self.selectedActor.GetProperty().SetColor(1.0, 0.0, 0.0)
            # self.selectedActor.GetProperty().SetPointSize(5.0)
            # self.GetDefaultRenderer().AddActor(self.selectedActor)

            ## 高亮选择的单元方法2
            ids = vtk.vtkIdTypeArray()
            ids.SetNumberOfComponents(1)
            ids.InsertNextValue(cellPicker.GetCellId())

            selectionNode = vtk.vtkSelectionNode()
            selectionNode.SetFieldType(vtk.vtkSelectionNode.CELL)
            selectionNode.SetContentType(vtk.vtkSelectionNode.INDICES)
            selectionNode.SetSelectionList(ids)

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

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

            self.selectedMapper.SetInputData(extractSelection.GetOutput())
            self.GetDefaultRenderer().RemoveActor(self.selectedActor)
            self.selectedActor.SetMapper(self.selectedMapper)
            self.selectedActor.GetProperty().EdgeVisibilityOn()
            self.selectedActor.GetProperty().SetEdgeColor(1, 0, 0)
            self.selectedActor.GetProperty().SetLineWidth(3)
            self.GetDefaultRenderer().AddActor2D(self.textActor)
            self.GetDefaultRenderer().AddActor(self.selectedActor)

        self.OnLeftButtonDown()

在上面代码中,高亮选中单元的方法有两个。一是通过选中的单元信息构建vtkUnstructuredGrid进行显示,另一是通过vtkExtractSelection从原模型上提取选中的单元进行显示。

主干代码如下:

def cellPick(self):
    self.ToggleOpacity(True)  # 透明显示,以便单元观察
    cellPicker = vtk.vtkCellPicker()
    self.interactor.SetPicker(cellPicker)  # 设置cellPicker
    style = CellPickerInteractorStyle()  # 设置自定义的单元拾取交互类型
    style.dataset = self.main_actor.GetMapper().GetInput()
    style.SetDefaultRenderer(self.renderer)
    self.interactor.SetInteractorStyle(style)

其中加入ToggleOpacity把actor的透明度调高,以便于观察单元。

测试结果

参考

[1] VTK:交互与拾取——单位拾取
[2] vtk拾取单元
[3] VTK: vtkCellPicker Class Reference

你可能感兴趣的:(VTK,CASTING,有限元后处理,VTK,单元拾取)