【VTK+增材CAM】3D打印模型切片

目的

模型切片在3D打印喷头路径规划中是非常重要的一环。实现切片的算法有很多,主流的思想是平面与模型三角面片求交得到相交的线段,再将这些线段组织连接成折线轮廓,以便接下来进行切片层内的路径规划。下文将使用VTK简单实现模型Z轴方向的平面切片。

关键函数

vtkCutte是一个用于剪切数据的过滤器。在代码中用于得到平面和模型面片求交得到的线段。

cutter = vtk.vtkCutter()
cutter.SetInputData(polydata)
cutter.SetCutFunction(plane)
cutter.SetSortByToSortByCell()  # 按切片层数进行排序
cutter.SetValue(i, z) # 设置轮廓的值

vtkStripper是一个用于从输入线段生成折线的过滤器。在代码中用于将散乱的线段组织连接起来成为折线轮廓。

stripper = vtk.vtkStripper()
stripper.SetInputConnection(cutter.GetOutputPort())
stripper.JoinContiguousSegmentsOn()	# 将输出的折线首尾相连成封闭轮廓
stripper.Update()

完整代码

import vtk


def slice_vtk(polydata, layerThk):
    """slice model with VTK into layers

    :param polydata: vtkPolyData,输入模型
    :param layerThk: float,层高
    :return: 切片列表
    """
    # 平面相交切片
    plane = vtk.vtkPlane()
    cutter = vtk.vtkCutter()
    cutter.SetInputData(polydata)
    cutter.SetCutFunction(plane)
    cutter.SetSortByToSortByCell()  # 按切片层数进行排序
    _, _, _, _, zMin, zMax = polydata.GetBounds()
    i, z = 0, zMin + layerThk
    while z < zMax:
        cutter.SetValue(i, z)
        z += layerThk
        i += 1
    # 提取轮廓
    stripper = vtk.vtkStripper()
    stripper.SetInputConnection(cutter.GetOutputPort())
    stripper.JoinContiguousSegmentsOn()
    stripper.Update()

    # numberOfLines = stripper.GetOutput().GetNumberOfLines()
    points = stripper.GetOutput().GetPoints()
    cells = stripper.GetOutput().GetLines()
    cells.InitTraversal()
    indices = vtk.vtkIdList()
    lineCount = 0
    contours = []
    while cells.GetNextCell(indices):
        # print("Line {0}:".format(lineCount))
        contour = []
        for i in range(indices.GetNumberOfIds()):
            point = points.GetPoint(indices.GetId(i))
            contour.append((point[0], point[1], point[2]))
            # print("\t({0:0.6f} ,{1:0.6f}, {2:0.6f})".format(point[0], point[1], point[2]))
        contours.append(contour)
        lineCount += 1

    return stripper, contours2Layers(contours)


def contours2Layers(contours):
    layers = []
    for contour in contours:
        layer = next((c for c in layers if (contour[0][2] == c[0][0][2])), [])
        if not layer:
            layers.append(layer)
        layer.append(contour)
    return layers


def main():
    colors = vtk.vtkNamedColors()
    lineColor = colors.GetColor3d("black")
    modelColor = colors.GetColor3d("silver")
    backgroundColor = colors.GetColor3d("wheat")

    # 加载STL模型
    reader = vtk.vtkSTLReader()
    reader.SetFileName(modelFileName)
    reader.Update()

    stripper, layers = slice_vtk(reader.GetOutput(), 2)

    modelMapper = vtk.vtkPolyDataMapper()
    modelMapper.SetInputConnection(reader.GetOutputPort())

    model = vtk.vtkActor()
    model.SetMapper(modelMapper)
    model.GetProperty().SetDiffuseColor(modelColor)
    model.GetProperty().SetInterpolationToFlat()

    linesMapper = vtk.vtkPolyDataMapper()
    linesMapper.SetInputConnection(stripper.GetOutputPort())

    lines = vtk.vtkActor()
    lines.SetMapper(linesMapper)
    lines.GetProperty().SetDiffuseColor(lineColor)
    lines.GetProperty().SetLineWidth(3.)

    renderer = vtk.vtkRenderer()
    renderWindow = vtk.vtkRenderWindow()

    renderWindow.AddRenderer(renderer)
    renderWindow.SetSize(640, 480)

    interactor = vtk.vtkRenderWindowInteractor()
    interactor.SetRenderWindow(renderWindow)

    # Add the actors to the renderer.
    renderer.AddActor(model)
    renderer.AddActor(lines)
    renderer.SetBackground(backgroundColor)

    # This starts the event loop and as a side effect causes an
    # initial render.
    renderWindow.Render()
    interactor.Start()


if __name__ == "__main__":
    main()

在上面代码中,为了将得到的轮廓按照所属切片层进行归类管理,使用如下函数进行实现。

def contours2Layers(contours):
    layers = []
    for contour in contours:
        layer = next((c for c in layers if (contour[0][2] == c[0][0][2])), [])
        if not layer:
            layers.append(layer)
        layer.append(contour)
    return layers

测试结果

在这里插入图片描述

总结

对于平面切片计算,VTK官方文档中提到了vtkPlaneCutter。vtkPlaneCutter专门用于平面切割,相较于vtkCutter速度更快,且是多线程。为了提高切片算法效率,后期可尝试vtkPlaneCutter。

  • 4
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
VTK是Visualization Toolkit的缩写,是一个开源的图形处理工具库,用于创建、处理和渲染三维图形。它提供了丰富的功能,可以用于各种应用程序,包括科学可视化、医学图像处理、机器人学等。 Qt是一种跨平台的应用程序开发框架,具有丰富的GUI(图形用户界面)组件和工具,可以用于创建各种类型的应用程序。它提供了直观、交互式的界面设计工具,使开发人员能够轻松地创建用户友好的应用程序。 DICOM是医学图像和通信标准的缩写,它是医学领域的一种通用文件格式和协议,用于存储、传输和共享医学图像和相关信息。DICOM文件通常包含来自医学成像设备(如CT扫描、MRI、X射线等)的图像数据及其相关的患者信息、检查参数等。 VTK、Qt和DICOM常常一起使用,用于开发医学图像处理和分析的应用程序。通过使用VTK和Qt,开发人员可以轻松地创建具有丰富可视化效果的医学图像应用程序,并提供直观、智能化的界面。VTK提供了丰富的图形处理和可视化工具,可以对DICOM图像进行处理、分析和可视化。而Qt的GUI组件和界面设计工具使开发人员能够创建用户友好的应用程序界面,方便用户查看、编辑和分析DICOM图像。 总的来说,VTK、Qt和DICOM的结合为医学图像处理和分析应用程序的开发提供了强大的工具和功能。它们的使用可以加快开发过程,提高应用程序的效率和用户友好性。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值