如果是没有基础的朋友可以先看我前面三篇笔记,本章笔记我直接上代码,代码中我已经写了详细的注释
代码
import vtk
import os
def create_actor_from_stl(stl_file, color, opacity, plane_origin, plane_normal):
# 创建STL读取器并加载文件
reader = vtk.vtkSTLReader()
reader.SetFileName(stl_file)
# 创建切割平面
plane = vtk.vtkPlane()
plane.SetOrigin(plane_origin) # 设置平面原点所在位置
plane.SetNormal(plane_normal) # 设置法线,切割面垂直于法线
# 使用vtkClipPolyData根据切割平面对模型进行分割
clipper = vtk.vtkClipPolyData()
clipper.SetClipFunction(plane) # 创建切割位置,即下刀后刀刃穿过的面
clipper.SetInputConnection(reader.GetOutputPort())
clipper.InsideOutOn() # 保留切割平面的一侧(内侧)
# clipper.InsideOutOn() # 保留切割平面的一侧(外侧;法线指向的一侧)
clipper.Update() # 调用Update()方法会让裁剪器根据这些参数执行裁剪操作
# 创建映射器,并连接到clipper的输出
mapper = vtk.vtkPolyDataMapper()
mapper.SetInputConnection(clipper.GetOutputPort()) # 此处映射器接收的对象为clipper,因为我们需要的效果是切割后的模型而不是完整的模型了
# 创建actor
actor = vtk.vtkActor()
actor.SetMapper(mapper)
# 设置颜色
actor.GetProperty().SetColor(color) # 设置对象的颜色
# 设置透明度
actor.GetProperty().SetOpacity(opacity) # 设置对象的透明度
return actor
def main():
folder_path = 'Stl'
# STL文件列表
stl_files = ['Stl/Edit3D_c1f1.stl'] # 示例:添加更多STL文件路径
for filename in os.listdir(folder_path):
file_path = os.path.join(folder_path, filename)
if os.path.isfile(file_path):
stl_files.append(file_path)
# 创建渲染器
renderer = vtk.vtkRenderer()
# 扩展颜色列表到10种颜色
colors = [
(1.0, 0.0, 0.0), # 红色
(0.0, 1.0, 0.0), # 绿色
(0.0, 0.0, 1.0), # 蓝色
(1.0, 1.0, 0.0), # 黄色
(0.0, 1.0, 1.0), # 青色
(1.0, 0.0, 1.0), # 紫色
(0.5, 0.0, 0.0), # 深红色
(0.0, 0.5, 0.0), # 深绿色
(0.0, 0.0, 0.5), # 深蓝色
(0.5, 0.5, 0.5), # 灰色
]
# 定义透明度列表
opacities = [0.9, 0.8, 0.7, 0.6, 0.5, 0.4, 0.3, 0.2, 0.1, 0.2]
# 定义切割平面的原点和法线
plane_origin = [0, 0, 0]
plane_normal = [0, 0, 1]
# 对于每个STL文件,创建一个actor并添加到渲染器中
for idx, stl_file in enumerate(stl_files):
color = colors[idx % len(colors)] # 循环使用预定义的颜色
opacity = opacities[idx % len(opacities)] # 循环使用预定义的透明度
actor = create_actor_from_stl(stl_file, color, opacity, plane_origin, plane_normal)
renderer.AddActor(actor)
# 设置背景颜色、渲染窗口和交互器
renderer.SetBackground(0.1, 0.2, 0.4)
renderWindow = vtk.vtkRenderWindow()
renderWindow.AddRenderer(renderer)
renderWindowInteractor = vtk.vtkRenderWindowInteractor()
renderWindowInteractor.SetRenderWindow(renderWindow)
# 开始渲染和交互
renderWindow.Render()
renderWindowInteractor.Start()
if __name__ == "__main__":
main()
代码解释
重点是 这部分代码
# 创建切割平面
plane = vtk.vtkPlane()
plane.SetOrigin(plane_origin) # 设置平面原点所在位置
plane.SetNormal(plane_normal) # 设置法线,切割面垂直于法线
# 使用vtkClipPolyData根据切割平面对模型进行分割
clipper = vtk.vtkClipPolyData()
clipper.SetClipFunction(plane) # 创建切割位置,即下刀后刀刃穿过的面
clipper.SetInputConnection(reader.GetOutputPort())
clipper.InsideOutOn() # 保留切割平面的一侧(内侧)
# clipper.InsideOutOn() # 保留切割平面的一侧(外侧;法线指向的一侧)
clipper.Update() # 调用Update()方法会让裁剪器根据这些参数执行裁剪操作
# 创建映射器,并连接到clipper的输出
mapper = vtk.vtkPolyDataMapper()
mapper.SetInputConnection(clipper.GetOutputPort()) # 此处映射器接收的对象为clipper,因为我们需要的效果是切割后的模型而不是完整的模型了
请大家注意步骤
1.先创建切割平面:通过一个原点和通过这个原点的法线创建出垂直于这个法线的面就是切割面。
2.分割函数vtk.vtkClipPolyData()需要接收这个切割面
3.映射器此时接收的不是读取器的数据源,而是切割后的数据源clipper