hello, 各位小伙伴,好久不见~ 假期结束,又该回到我们日常的代码生活中去啦!
这几天呢,我遇到一个问题,那就是怎么生成某个固定方向的圆柱体并保存呢?我们都知道啊,vtk直接生成的圆柱体是固定沿y轴生成的。但是如果我们想要生成并保存一个沿着固定方向的圆柱体该怎么办呢?网上有很多小伙伴给出的结果是生成很多个直线最终构成一个沿固定方向的圆柱,但是这种方法,在保存模型或者需要生成多个圆柱体时就变得非常麻烦。
所以,今天我就教大家用vtk如何直接沿直线(固定)方向生成圆柱体,并保存模型。话不多说,我们就开始吧!
首先,我们先建立一个普通的圆柱体。
# 创建一个圆柱体
cylinder = vtk.vtkCylinderSource()
cylinder.SetCenter((0, 2, 0))
cylinder.SetRadius(1.0)
cylinder.SetHeight(2.0)
cylinder.SetResolution(100)
这里值得注意的是,在cylinder.SetCenter()的时候,这个中心点我们最好设置为我们最终希望圆柱所在的位置点上,这样就不需要我们后续再去移动了。比如说,在我的任务中,我知道圆柱体两端圆心的位置,我就可以直接根据这两个圆心的位置求得圆柱体的中心点,就不需要后续移动。
然后,设置固定方向的方向向量。
# 定义目标方向向量
target_direction = np.array([1.0, 1.0, 0.0])
接下来,需要计算旋转矩阵。这里的current_direction ,如果前期没有对圆柱体进行旋转,那么直接等于[0.0, 1.0, 0.0]即可,如果旋转了,就设定为旋转后的初始方向向量。
# 计算旋转矩阵
current_direction = np.array([0.0, 1.0, 0.0]) # 初始方向,这里假设圆柱体的初始方向是Y轴
rotation_axis = np.cross(current_direction, target_direction)
rotation_angle = np.arccos(np.dot(current_direction, target_direction) / (np.linalg.norm(current_direction) * np.linalg.norm(target_direction)))
# 创建一个Transform来旋转圆柱体
transform = vtk.vtkTransform()
transform.RotateWXYZ(np.degrees(rotation_angle), rotation_axis)
然后再进行旋转变换。
# 应用变换到圆柱体的几何数据
transform_filter = vtk.vtkTransformFilter()
transform_filter.SetInputConnection(cylinder.GetOutputPort())
transform_filter.SetTransform(transform)
transform_filter.Update()
最后,保存为PLY或者STL即可。大家根据自己的需求决定。我这里就以PLY为例进行说明。
# 创建PLY文件写入器
ply_writer = vtk.vtkPLYWriter()
ply_writer.SetFileName("tilted_cylinder.ply") # 设置保存文件名
ply_writer.SetInputData(transform_filter.GetOutput())
ply_writer.Write()
上述代码中的圆柱中心位置、圆柱半径、圆柱高、方向向量、以及文件名等,大家可以根据自己的需求进行向量的改变。
给大家看一下,保存后模型的效果图(如图1)哦~
图1 模型效果图
最后附上完整代码,希望对大家有所帮助哦~ 最后这个代码中,还有旋转后模型的显示等。
#生成指定方向的圆柱体
import vtk
# 创建一个圆柱体
cylinder = vtk.vtkCylinderSource()
cylinder.SetCenter((0, 2, 0))
cylinder.SetRadius(1.0)
cylinder.SetHeight(2.0)
cylinder.SetResolution(100)
# 创建一个渲染器和渲染窗口
renderer = vtk.vtkRenderer()
render_window = vtk.vtkRenderWindow()
render_window.AddRenderer(renderer)
# 创建一个交互器
interactor = vtk.vtkRenderWindowInteractor()
interactor.SetRenderWindow(render_window)
# 创建一个Actor并添加到渲染器
mapper = vtk.vtkPolyDataMapper()
mapper.SetInputConnection(cylinder.GetOutputPort())
actor = vtk.vtkActor()
actor.SetMapper(mapper)
#renderer.AddActor(actor)
##创建一个Transform来倾斜圆柱体
# transform = vtk.vtkTransform()
# transform.RotateY(45.0) # 绕Y轴倾斜45度
# transform.RotateX(45.0) # 绕Y轴倾斜45度
# 定义目标方向向量
target_direction = np.array([1.0, 1.0, 0.0])
# 计算旋转矩阵
current_direction = np.array([0.0, 1.0, 0.0]) # 初始方向,这里假设圆柱体的初始方向是Y轴
rotation_axis = np.cross(current_direction, target_direction)
rotation_angle = np.arccos(np.dot(current_direction, target_direction) / (np.linalg.norm(current_direction) * np.linalg.norm(target_direction)))
# 创建一个Transform来旋转圆柱体
transform = vtk.vtkTransform()
transform.RotateWXYZ(np.degrees(rotation_angle), rotation_axis)
# 应用变换到圆柱体的几何数据
transform_filter = vtk.vtkTransformFilter()
transform_filter.SetInputConnection(cylinder.GetOutputPort())
transform_filter.SetTransform(transform)
transform_filter.Update()
# 创建一个Actor来显示旋转后的模型
rotated_mapper = vtk.vtkPolyDataMapper()
rotated_mapper.SetInputConnection(transform_filter.GetOutputPort())
rotated_actor = vtk.vtkActor()
rotated_actor.SetMapper(rotated_mapper)
renderer.AddActor(rotated_actor)
# 创建PLY文件写入器
ply_writer = vtk.vtkPLYWriter()
ply_writer.SetFileName("tilted_cylinder.ply") # 设置保存文件名
ply_writer.SetInputData(transform_filter.GetOutput())
ply_writer.Write()
# 设置渲染窗口尺寸
render_window.SetSize(800, 800)
# 启动交互式渲染器
interactor.Start()
如果大家对vtk或者医学图像处理感兴趣,还可以看看我其他的博客和资源哦~