【问题标题】:How to export a 3D vtk rendered scene to paraview using python?如何使用 python 将 3D vtk 渲染场景导出到 paraview?
【发布时间】:2019-02-04 10:15:14
【问题描述】:

我已经编写了一个代码来使用 python 中的 vtk 生成圆柱体对象。此代码在生成 3D 场景时运行良好,我可以在其中缩放或转动我制作的圆柱体。问题是我想将此渲染的场景导出到 paraview 以查看并保存以供以后工作。我怎样才能做到这一点? 以下是生成带有圆柱体的 Y 形的代码:

import vtk
import numpy as np

'''
Adding multiple Actors to one renderer scene using VTK package with python api.
Each cylinder is an Actor with three input specifications: Startpoint, Endpoint and radius.
After creating all the Actors, the preferred Actors will be added to a list and that list will be our input to the 
renderer scene.
A list or numpy array with appropriate 3*1 shape could be used to specify starting and ending points.

There are two alternative ways to apply the transform.
 1) Use vtkTransformPolyDataFilter to create a new transformed polydata.
    This method is useful if the transformed polydata is needed
      later in the pipeline
    To do this, set USER_MATRIX = True
 2) Apply the transform directly to the actor using vtkProp3D's SetUserMatrix.
    No new data is produced.
    To do this, set USER_MATRIX = False
'''
USER_MATRIX = True


def cylinder_object(startPoint, endPoint, radius, my_color="DarkRed"):
    colors = vtk.vtkNamedColors()

    # Create a cylinder.
    # Cylinder height vector is (0,1,0).
    # Cylinder center is in the middle of the cylinder
    cylinderSource = vtk.vtkCylinderSource()
    cylinderSource.SetRadius(radius)
    cylinderSource.SetResolution(50)

    # Generate a random start and end point
    # startPoint = [0] * 3
    # endPoint = [0] * 3

    rng = vtk.vtkMinimalStandardRandomSequence()
    rng.SetSeed(8775070)  # For testing.8775070

    # Compute a basis
    normalizedX = [0] * 3
    normalizedY = [0] * 3
    normalizedZ = [0] * 3

    # The X axis is a vector from start to end
    vtk.vtkMath.Subtract(endPoint, startPoint, normalizedX)
    length = vtk.vtkMath.Norm(normalizedX)
    vtk.vtkMath.Normalize(normalizedX)

    # The Z axis is an arbitrary vector cross X
    arbitrary = [0] * 3
    for i in range(0, 3):
        rng.Next()
        arbitrary[i] = rng.GetRangeValue(-10, 10)
    vtk.vtkMath.Cross(normalizedX, arbitrary, normalizedZ)
    vtk.vtkMath.Normalize(normalizedZ)

    # The Y axis is Z cross X
    vtk.vtkMath.Cross(normalizedZ, normalizedX, normalizedY)
    matrix = vtk.vtkMatrix4x4()
    # Create the direction cosine matrix
    matrix.Identity()
    for i in range(0, 3):
        matrix.SetElement(i, 0, normalizedX[i])
        matrix.SetElement(i, 1, normalizedY[i])
        matrix.SetElement(i, 2, normalizedZ[i])
    # Apply the transforms
    transform = vtk.vtkTransform()
    transform.Translate(startPoint)  # translate to starting point
    transform.Concatenate(matrix)  # apply direction cosines
    transform.RotateZ(-90.0)  # align cylinder to x axis
    transform.Scale(1.0, length, 1.0)  # scale along the height vector
    transform.Translate(0, .5, 0)  # translate to start of cylinder

    # Transform the polydata
    transformPD = vtk.vtkTransformPolyDataFilter()
    transformPD.SetTransform(transform)
    transformPD.SetInputConnection(cylinderSource.GetOutputPort())

    # Create a mapper and actor for the arrow
    mapper = vtk.vtkPolyDataMapper()
    actor = vtk.vtkActor()
    if USER_MATRIX:
        mapper.SetInputConnection(cylinderSource.GetOutputPort())
        actor.SetUserMatrix(transform.GetMatrix())
    else:
        mapper.SetInputConnection(transformPD.GetOutputPort())
    actor.SetMapper(mapper)
    actor.GetProperty().SetColor(colors.GetColor3d(my_color))
    return actor


def render_scene(my_actor_list):
    renderer = vtk.vtkRenderer()
    for arg in my_actor_list:
        renderer.AddActor(arg)
    namedColors = vtk.vtkNamedColors()
    renderer.SetBackground(namedColors.GetColor3d("SlateGray"))

    window = vtk.vtkRenderWindow()
    window.SetWindowName("Oriented Cylinder")
    window.AddRenderer(renderer)

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

    # Visualize
    window.Render()
    interactor.Start()


if __name__ == '__main__':

    my_list = []
    p0 = np.array([0, 0, 0])
    p1 = np.array([0, 10, 0])
    p2 = np.array([7, 17, 0])
    p3 = np.array([-5, 15, 0])
    my_list.append(cylinder_object(p0, p1, 1, "Red"))
    my_list.append(cylinder_object(p1, p2, 0.8, "Green"))
    my_list.append(cylinder_object(p1, p3, 0.75, "Navy"))
    render_scene(my_list)

我有多个演员,所有演员在一个渲染场景中一起渲染,我可以将每个演员传递给vtk.vtkSTLWriter吗?这似乎不起作用!

【问题讨论】:

    标签: python rendering vtk paraview


    【解决方案1】:

    您正在寻找的是 vtkExporter class 的子类,根据链接的文档:

    vtkExporter 是一个将场景导出到文件的抽象类。它与 vtkWriter 非常相似,只是 writer 只写出对象的几何和拓扑数据,其中 exporter 可以写出材质属性、光照、相机参数等。

    从类的继承图中可以看出,大约有 15 个类支持将这样的场景导出到可以在适当的阅读器中查看的文件中。

    恕我直言,您最幸运的是vtkVRMLExporter class,因为它是一种相当常见的格式。话虽如此,我不相信 Paraview 支持 VRML 文件(至少基于我发现的一些非常古老的帖子),但我很确定 MayaVi 支持。

    或者,正如您所提到的,您可以将对象导出到 STL 文件中,但 STL 文件只包含三角形坐标和有关它们如何连接的信息。此类文件不可能描述场景信息,例如相机或照明信息。最后我检查了一个 STL 文件只能包含一个对象,所以你的三个圆柱体最终会成为一个合并的对象,所以它可能不是你想要的。

    【讨论】:

    • 谢谢。我添加了一些代码,但它不适用于 paraview,但适用于 windows 10 上的 print 3D。
    【解决方案2】:

    我添加了这些代码,它从我渲染的场景中创建了一个VRML 文件。

    exporter = vtk.vtkVRMLExporter()
    exporter.SetRenderWindow(window)
    exporter.SetFileName("cylinders.wrl")
    exporter.Write()
    exporter.Update()
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-30
      • 2014-08-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多