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

目的

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

代码实现

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
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从原模型上提取选中的单元进行显示。

主干代码如下:

1
2
3
4
5
6
7
8
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的透明度调高,以便于观察单元。

测试结果

![GIF 2022-11-23 12-22-38](D:\OneDrive\桌面\GIF 2022-11-23 12-22-38.gif)

参考

[1] VTK:交互与拾取——单位拾取

[2] vtk拾取单元

[3] VTK: vtkCellPicker Class Reference