【VTK+有限元后处理】节点点云属性颜色映射

目的

在之前的一篇文章【VTK+有限元后处理】可视化结果云图中,我们实现了对有限元结果的云图显示,效果如下:

image-20221125173918307

这样的云图显示也有不足之处,比如想要查看内部单元的属性值分布情况,这种可视化方式显然是不能满足需求的。解决方法之一,便是对模型进行剖切显示,详见文章:【VTK+有限元后处理】实时剖切视图。剖切显示需要调整剖切平面位置和法向以满足我们对内部单元属性分布的观察,个人认为有些许的繁琐。

于是,我想如果能得到节点的点云,再将属性值映射到点云上,就能很方便的查看内部单元节点的属性分布情况。

代码及测试结果

节点点云提取

用到VTK中的vtkVertexGlyphFilter过滤器。

1
2
3
4
5
6
7
8
9
10
11
12
13
def nodes2points(self):
"""节点转点云"""
points = vtk.vtkPolyData()
points.SetPoints(self.FEModel.ugrid.GetPoints())

# vtkVertexGlyphFilter类将丢弃输入数据中的所有单元,取而代之的是在每个点上创建一个顶点
vertexGlyphFilter = vtk.vtkVertexGlyphFilter()
vertexGlyphFilter.AddInputData(points)
vertexGlyphFilter.Update()
self.pointCloud = vertexGlyphFilter.GetOutput()
# 点云绘制
self.SceneManager.drawPdSrc(self.pointCloud, (241 / 255, 135 / 255, 184 / 255), point_size = 3)
self.SceneManager.display()

![GIF 2022-11-25 17-51-25](D:\OneDrive\桌面\GIF 2022-11-25 17-51-25.gif)

属性颜色映射

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
def loadScalarField(self):
if len(self.FEModel.nodes) == 0: # 节点是否为空
self.statusbar.showMessage("laod FEModel file first!", 3000)
return
fn, _type = QtWidgets.QFileDialog.getOpenFileName(self, '打开标量场文件', self.last_path, '*.csv;;*.ntl')
if fn:
if _type == "*.ntl":
self.FEModel.read_ntl(fn)
elif _type == '*.csv':
self.FEModel.read_csv(fn)
# 属性(标量)赋值
mapper = self.SceneManager.main_actor.GetMapper()
if mapper.GetInput() == self.pointCloud:
self.pointCloud.GetPointData().SetScalars(self.FEModel.ugrid.GetPointData().GetScalars())
mapper.SetInputData(self.pointCloud)
# 可视化属性映射结果
scalarRange = self.FEModel.ugrid.GetPointData().GetScalars().GetRange()
title = self.FEModel.ugrid.GetPointData().GetScalars().GetName()
self.SceneManager.drawScalarField(mapper, scalarRange, title)
self.SceneManager.display()

关键代码self.pointCloud.GetPointData().SetScalars(self.FEModel.ugrid.GetPointData().GetScalars()),将vtkUnstructuredGrid数据(有限元模型)中存储的节点的标量值赋给vtkPolyData数据(节点点云)。上述代码中,drawScalarField函数定义如下:

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
def drawScalarField(self, scalar_mapper, scalarRange, title):
# 定义颜色映射表
lut = vtk.vtkLookupTable()
lut.SetHueRange(0.67, 0.0) # 色调范围从红色到蓝色
# lut.SetAlphaRange(1.0, 1.0) # 透明度范围
# lut.SetValueRange(1.0, 1.0)
# lut.SetSaturationRange(1.0, 1.0) # 颜色饱和度
# lut.SetNumberOfTableValues(256)
lut.SetNumberOfColors(256) # 颜色个数
# lut.SetRange(scalarRange)
lut.Build()

scalar_mapper.SetScalarRange(scalarRange)
scalar_mapper.SetLookupTable(lut)
self.renderer.RemoveActor(self.main_actor) # 移除main_actor
self.main_actor = vtk.vtkActor()
self.main_actor.SetMapper(scalar_mapper)
self.main_actor.GetProperty().SetPointSize(3)
self.main_actor.GetProperty().SetOpacity(1) # 设置透明度
self.renderer.AddActor(self.main_actor)
# 色标带
self.scalarBar_actor.SetLookupTable(scalar_mapper.GetLookupTable()) # 将颜色查找表传入窗口中的色标带
self.scalarBar_actor.SetTitle(title)
self.scalarBar_actor.SetNumberOfLabels(5)
self.renderer.AddActor2D(self.scalarBar_actor)

代码测试效果如下所示。

![GIF 2022-11-25 18-02-30](D:\OneDrive\桌面\GIF 2022-11-25 18-02-30.gif)


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!