如何在 Python 中使用 Mayavi 在 tvtk 渲染场景上旋转演员?

How to rotate actor on tvtk rendered scene with Mayavi in Python?

我玩过 Mayavi,尤其是 tvtk,但我很难找到在场景中以与默认方向不同的方向放置字形的示例。

基于此example我准备了下面的场景,一红一蓝两个圆柱体,

import mayavi.mlab as mlab

from tvtk.api import tvtk
from tvtk.common import configure_input_data

v = mlab.figure()

# Create two cyllinders
cyl1 = tvtk.CylinderSource(center=(0, 0, 0), radius=1.0, height=0.5, capping=True, resolution=24)
cyl2 = tvtk.CylinderSource(center=(3, 0, 0), radius=1.0, height=0.5, capping=True, resolution=24)


# The mapper converts them into position in 3D
cylinder_mapper1 = tvtk.PolyDataMapper()
configure_input_data(cylinder_mapper1, cyl1.output)
cyl1.update()

cylinder_mapper2 = tvtk.PolyDataMapper()
configure_input_data(cylinder_mapper2, cyl2.output)
cyl2.update()

# Assign them differrent colors
p1 = tvtk.Property(opacity=1.0, color=(1, 0, 0))
p2 = tvtk.Property(opacity=1.0, color=(0, 0, 1))

# The actor is the actually object in the scene.
cyl1_actor = tvtk.Actor(mapper=cylinder_mapper1, property=p1)
v.scene.add_actor(cyl1_actor)

cyl2_actor = tvtk.Actor(mapper=cylinder_mapper2, property=p2)
v.scene.add_actor(cyl2_actor)

# Choose a view angle, and display the figure
mlab.view(90, 45, 7.5, [1.5, 0, 0])
mlab.savefig(filename='cylinders.png')

我在这里想要实现的是改变其中一个的方向。无论是通过提供旋转矩阵,还是通过调用方法,只要我能以某种方式独立旋转字形(而不只是旋转整个场景)都没有关系。

上面的例子呈现

关于之前提出的其他问题, seems useful, yet instead of rotating the actor it rotates entire scene about Y-axis. There also is an example in the scipy-cookbook 但同样 - 仅使用默认方向。

tvtk documentation 的示例并不丰富,几乎很难相信没有涉及交替方向的示例。该文档仅说明 类 和方法对应于遵循某些约定的 C++ 对应方法。

  1. tvtk class names are essentially similar to VTK classes except there is no annoying ‘vtk’ at the front. The only difficulty is with classes that start with a digit. For example ‘vtk3DSImporter’ becomes ‘3DSImporter’. This is illegal in Python and therefore the class name used is ‘ThreeDSImporter’. So, if the first character is a digit, it is replaced by an equivalent non-digit string. There are very few classes like this so this is not a big deal.
  2. tvtk method names are enthought style names and not CamelCase. That is, if a VTK method is called AddItem, the equivalent tvtk name is add_item. This is done for the sake of consistency with names used in the enthought package.
  3. Many VTK methods are replaced by handy properties. In the above example, we used m.input = cs.output and p.representation = ‘w’ instead of what would have been m.SetInput(cs.GetOutput()) and p.SetRepresentationToWireframe() etc. Some of these properties are really traits.
  4. Unlike VTK objects, one can set the properties of a tvtk object when the object is initialized by passing the properties (traits) of the object as keyword arguments at the time of class instantiation. For example cs = tvtk.ConeSource(radius=0.1, height=0.5).

也许广泛使用 VTK 和 C++ 的人可能会发现它很有用,但对我来说不是很有帮助。尽管如此,我还是尝试查找 VTK C++ 文档,它确实给了我一些线索。 vtkActor class does inherit some types from vtkProp3D and vtkPropvtkProp3D 似乎确实承认与场景中的对象方向相关的方法和属性,但我不清楚如何设置它们。 tvtk 库只是 C++ 库之上的一个包装器,这使得它不可能只 inspect 接受哪些属性。

我想为了互联网,也许我们应该准备一个合适的例子来渲染一个场景 Mayavitvtk 承认演员的位置和他们的方向。大多数示例忽略方向并使用球体,因此方向似乎不相关。

总结一下。

  1. 如果有人提供 link 使用 Mayavi 渲染场景的正确示例,并且 tvtk 涉及具有不同位置和方向的多个字形,我会接受这样的答案。
  2. 为 (1) 制作自定义示例也会被接受。
  3. 也许有人还可以评论一下字形的位置和在场景中映射此字形的演员之间的差异。正如您在示例中看到的那样,当我创建 CylinderSource 时,我明确指定了中心所在的位置。这令人困惑,因为它应该是确定场景中字形位置的演员中心。

非常感谢!

好的,原来 Actor 接受 orientation 以度为单位的参数(不是以弧度为单位!)。另外,actor 的位置必须在创建 actor 时指定,而不是在创建 glyph 时指定!

cyl1_actor = tvtk.Actor(position=(0, 0, 0), mapper=cylinder_mapper1, property=p1, orientation=(0, 0, 90))

渲染

我通过反复试验找到它... Mayavi 包中的 tvtk 代码是 generated so it is pointless to try to find what attributes are accepted by studying the GitHub repository. Also, you might confuse the tvtk's Actor with Mayavi's Actor 没有方向 属性。哦,实际上有一个 属性 名称“属性”,所以尝试搜索它并获得数千个结果,因为 property 这个词在任何地方都被广泛使用...

编辑:

我注意到我一直在字形中心指定角色的位置是错误的!这里更新了整个源代码:

import mayavi.mlab as mlab

from tvtk.api import tvtk
from tvtk.common import configure_input_data

v = mlab.figure()

# Create two cyllinders
cyl1 = tvtk.CylinderSource(center=(0, 0, 0), radius=1.0, height=0.5, capping=True, resolution=24)
cyl2 = tvtk.CylinderSource(center=(0, 0, 0), radius=1.0, height=0.5, capping=True, resolution=24)


# The mapper converts them into position in 3D
cylinder_mapper1 = tvtk.PolyDataMapper()
configure_input_data(cylinder_mapper1, cyl1.output)
cyl1.update()

cylinder_mapper2 = tvtk.PolyDataMapper()
configure_input_data(cylinder_mapper2, cyl2.output)
cyl2.update()

# Assign them differrent colors
p1 = tvtk.Property(opacity=1.0, color=(1, 0, 0))
p2 = tvtk.Property(opacity=1.0, color=(0, 0, 1))

# The actor is the actually object in the scene.
cyl1_actor = tvtk.Actor(position=(0, 0, 0), mapper=cylinder_mapper1, property=p1)
v.scene.add_actor(cyl1_actor)

cyl2_actor = tvtk.Actor(position=(3, 0, 0), mapper=cylinder_mapper2, property=p2, orientation=(0, 0, 90))
v.scene.add_actor(cyl2_actor)

# Choose a view angle, and display the figure
mlab.view(90, 45, 7.5, [1.5, 0, 0])
mlab.savefig(filename='cylinders.png')