python VTK(二)利用散点数据集和已知单元集绘制由六面体单元组成的几何体

一、

通过已知点集、单元集可以在vtk生成想要的几何体,这里首先做几点说明:

点集:

1.点集可以自由定义xyz的坐标点

2.可以循环生成一系列散点

3.可以从其他可导出点的坐标的软件导出点集做数据提取转换到vtk里面引用

单元集:

1.自由定义单元集连接方式,用line的指令连接

2.可以从其他可导出单元集的坐标的软件导出点集做数据提取转换到vtk里面引用

3.用符合vtk规则的输入方式生成六面体单元的坐标,在本文中就是分别给出两个面,且这两个面的坐标是六面体的8个顶点组成(4个点一个面)不重复,注意数组的顺序为逆时针或者顺时针的转动

二、

代码解析:

首先是笔者用到的8320个点集、3283的单元集,其中8320个点里面不是全都是生成模型的点,是从abaqus(前文中单元集的第三个创建方式)导出时包含一个圆环体和一个长方体,在本文仅将长方体的单元体绘制给读者展示。(下图是abaqus中的原图)

703509f3a83142409e5e765d7e142768.png

 首先创建点集:笔者将点集通过代码提取到一个txt文件,并对该文件进行提取到数组中。如有疑问可以看笔者的前几篇文章

ddc5e223f9444d66a35ae37098a975b4.png

以下是提取代码并加入到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)有:

10e86e95175a4471aa333c20131743b8.png

下面是重头戏绘制六面体单元集:先上代码(从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里

68317ab4b2814625b2c650ffb82a61e1.png

三、建立网格的空间,将这些单元加入到网格空间中

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()

运行效果:

6cb0df1f817b4872bf13e96054cc5f99.png

 

  • 8
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
要使用PythonVTK实现CT医学影像DICOM文件的绘制和面绘制三维重建,你可以参考以下源码: ``` python import vtk # 创建一个渲染窗口并设置交互方式 renWin = vtk.vtkRenderWindow() iren = vtk.vtkRenderWindowInteractor() iren.SetRenderWindow(renWin) # 读取DICOM文件 reader = vtk.vtkDICOMImageReader() reader.SetDirectoryName("path/to/dicom/files") reader.Update() # 创建绘制数据集 volumeMapper = vtk.vtkFixedPointVolumeRayCastMapper() volumeMapper.SetInputConnection(reader.GetOutputPort()) # 设置绘制的颜色和透明度传输函数 volumeProperty = vtk.vtkVolumeProperty() volumeProperty.ShadeOn() volumeProperty.SetColor(vtk.vtkColorTransferFunction()) volumeProperty.SetScalarOpacity(vtk.vtkPiecewiseFunction()) # 创建绘制的可视化对象 volume = vtk.vtkVolume() volume.SetMapper(volumeMapper) volume.SetProperty(volumeProperty) # 创建面绘制的等值面数据集 contourFilter = vtk.vtkMarchingCubes() contourFilter.SetInputConnection(reader.GetOutputPort()) contourFilter.SetValue(0, thresholdValue) # 设置阈值,提取等值面 # 创建面绘制的Mapper和Actor contourMapper = vtk.vtkPolyDataMapper() contourMapper.SetInputConnection(contourFilter.GetOutputPort()) contourActor = vtk.vtkActor() contourActor.SetMapper(contourMapper) # 创建渲染器和渲染窗口 renderer = vtk.vtkRenderer() renWin.AddRenderer(renderer) renderer.AddActor(volume) renderer.AddActor(contourActor) renderer.SetBackground(0, 0, 0) # 设置背景颜色为黑色 # 设置相机视角 camera = renderer.GetActiveCamera() camera.SetPosition(0, 0, -1) # 设置相机位置 camera.SetFocalPoint(0, 0, 0) # 设置焦点 camera.SetViewUp(0, -1, 0) # 设置视角 # 激活渲染器和交互操作 renderer.ResetCamera() renWin.Render() iren.Start() ``` 请注意,上述代码只提供了一个基本的框架,实际使用时需要根据具需求进行调整。同时,你需要将代码中的"path/to/dicom/files"替换为实际的DICOM文件路径,并根据需要设置绘制和面绘制的参数。 希望以上内容对你有所帮助!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值