一、
通过已知点集、单元集可以在vtk生成想要的几何体,这里首先做几点说明:
点集:
1.点集可以自由定义xyz的坐标点
2.可以循环生成一系列散点
3.可以从其他可导出点的坐标的软件导出点集做数据提取转换到vtk里面引用
单元集:
1.自由定义单元集连接方式,用line的指令连接
2.可以从其他可导出单元集的坐标的软件导出点集做数据提取转换到vtk里面引用
3.用符合vtk规则的输入方式生成六面体单元的坐标,在本文中就是分别给出两个面,且这两个面的坐标是六面体的8个顶点组成(4个点一个面)不重复,注意数组的顺序为逆时针或者顺时针的转动
二、
代码解析:
首先是笔者用到的8320个点集、3283的单元集,其中8320个点里面不是全都是生成模型的点,是从abaqus(前文中单元集的第三个创建方式)导出时包含一个圆环体和一个长方体,在本文仅将长方体的单元体绘制给读者展示。(下图是abaqus中的原图)
首先创建点集:笔者将点集通过代码提取到一个txt文件,并对该文件进行提取到数组中。如有疑问可以看笔者的前几篇文章
以下是提取代码并加入到vtk的points中:
points = vtk.vtkPoints()
with open('vtkNodeoutput.txt', 'r') as vf:
content = vf.readlines()
nodeendless = []
for nodei in range(len(content)):
nodezerooutput = content[nodei]
node_without_spaces_and_newlines = nodezerooutput.replace(" ", "") ####去掉空格和换行符
nodearray = node_without_spaces_and_newlines.splitlines()
nodelens = len(nodearray)
for i in range(nodelens): #####'''以数组形式保存每一个节点信息'''
new_arr = nodearray[i].split(',')
nodeendless.append(new_arr)
for nodei in range(len(nodeendless)):
zuobiao = nodeendless[nodei]
zuobiaonumpy = (float(zuobiao[0]), float(zuobiao[1]), float(zuobiao[2]))
points.InsertNextPoint(zuobiaonumpy)
print(points)有:
下面是重头戏绘制六面体单元集:先上代码(从abaqus的inp提取单元集的代码已省略)
cellstype = vtk.vtkTypeUInt8Array()
cellstype.SetNumberOfComponents(1)
cellstype.SetName("CellTypes")
cellstype.InsertNextTuple1(vtk.VTK_HEXAHEDRON)
################################################
cells = vtkCellArray()
for icell in tqdm(range(len(endlessfirst))):
celli = endlessfirst[icell]
issss = [int(celli[0])-1, int(celli[1])-1, int(celli[2])-1, int(celli[3])-1, int(celli[4])-1, int(celli[5])-1, int(celli[6])-1, int(celli[7])-1]
cells.InsertNextCell(8, issss)
cellstype.InsertNextTuple1(vtk.VTK_HEXAHEDRON)//这个代码虽然和上面重复但是需要给每个插入的新的cells赋予,不然会报错
#################################################
ugrid = vtk.vtkUnstructuredGrid()
ugrid.SetPoints(points)
ugrid.SetCells(cellstype, cells)
#######################################
# 创建一个 mapper
mapper = vtk.vtkDataSetMapper()
mapper.SetInputData(ugrid)
本段代码有四个部分:
一、添加单元格类型为每个单元格包含一个组件
二、创建每个单元的节点集,在此是将下图的每个单元的节点坐标循环到cells里
三、建立网格的空间,将这些单元加入到网格空间中
ugrid.SetPoints(points)(加入刚才的节点集) ugrid.SetCells(cellstype, cells)(加入刚才创建的单元类型,加入刚才循环输出到cells的单元集)
这样就可以把单元集合节点集对应起来,注意单元集对应的序号所以是节点集里面的,而节点集是从0开始的,所以单元集的第0个单元的1节点对应的是节点集的第0个节点信息
四、按照vtk的代码习惯将创建的带有节点和单元信息的网格加入到mapper里。
下面是完整代码示例:
import vtk
import numpy as np
import vtkmodules.vtkRenderingOpenGL2
from vtkmodules.vtkCommonColor import vtkNamedColors
from vtkmodules.vtkCommonCore import vtkPoints
from vtkmodules.vtkCommonDataModel import vtkCellArray, vtkExplicitStructuredGrid
from vtkmodules.vtkInteractionStyle import vtkInteractorStyleRubberBandPick
from vtkmodules.vtkRenderingCore import vtkActor, vtkRenderWindowInteractor
from tqdm import tqdm
# 创建六面体的顶点坐标
points = vtk.vtkPoints()
with open('vtkNodeoutput.txt', 'r') as vf:
content = vf.readlines()
nodeendless = []
for nodei in range(len(content)):
nodezerooutput = content[nodei]
node_without_spaces_and_newlines = nodezerooutput.replace(" ", "") ####去掉空格和换行符
nodearray = node_without_spaces_and_newlines.splitlines()
nodelens = len(nodearray)
for i in range(nodelens): #####'''以数组形式保存每一个节点信息'''
new_arr = nodearray[i].split(',')
nodeendless.append(new_arr)
for nodei in range(len(nodeendless)):
zuobiao = nodeendless[nodei]
zuobiaonumpy = (float(zuobiao[0]), float(zuobiao[1]), float(zuobiao[2]))
points.InsertNextPoint(zuobiaonumpy)
print(points)
with open('datatext\\elementoutput.txt', 'r') as vf:
elementvtk = vf.readlines()
elementvtk.pop(0)
elendless = []
for elei in range(len(elementvtk)):
element = elementvtk[elei]
node_without_spaces_and_newlines = element.replace(" ", "") ####去掉空格和换行符
emelentarry = node_without_spaces_and_newlines.splitlines()
elelens = len(emelentarry)
for i in range(elelens): #####
new_arr = emelentarry[i].split(',')
elendless.append(new_arr)
endlessfirst =[]
for i in range(len(elendless)):
deletefirst = elendless[i]
deletefirst.pop(0)
endlessfirst.append(deletefirst)
print(endlessfirst)
#########################################
cellstype = vtk.vtkTypeUInt8Array()
cellstype.SetNumberOfComponents(1)
cellstype.SetName("CellTypes")
cellstype.InsertNextTuple1(vtk.VTK_HEXAHEDRON)
################################################
# 创建六面体的八个顶点的连接关系
cells = vtkCellArray()
for icell in tqdm(range(len(endlessfirst))):
celli = endlessfirst[icell]
issss = [int(celli[0])-1, int(celli[1])-1, int(celli[2])-1, int(celli[3])-1, int(celli[4])-1, int(celli[5])-1, int(celli[6])-1, int(celli[7])-1]
cells.InsertNextCell(8, issss)
cellstype.InsertNextTuple1(vtk.VTK_HEXAHEDRON)
#################################################
# 创建无结构网格
ugrid = vtk.vtkUnstructuredGrid()
ugrid.SetPoints(points)
ugrid.SetCells(cellstype, cells)
# 创建一个 mapper
mapper = vtk.vtkDataSetMapper()
mapper.SetInputData(ugrid)
# 创建一个 actor
actor = vtk.vtkActor()
actor.SetMapper(mapper)
# 创建渲染器、渲染窗口和交互器
renderer = vtk.vtkRenderer()
renderWindow = vtk.vtkRenderWindow()
renderWindow.AddRenderer(renderer)
renderWindowInteractor = vtk.vtkRenderWindowInteractor()
renderWindowInteractor.SetRenderWindow(renderWindow)
# 将 actor 添加到渲染器中
renderer.AddActor(actor)
# 设置背景颜色为白色
renderer.SetBackground(0, 0, 0)
# 渲染并启动交互器
camera = renderer.GetActiveCamera()
interactor = vtkRenderWindowInteractor()
interactor.SetRenderWindow(renderWindow)
interactor.SetInteractorStyle(vtkInteractorStyleRubberBandPick())
renderWindow.Render()
interactor.Start()
运行效果: