简体   繁体   English

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

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

I played a bit with Mayavi and particularly with tvtk but I struggle finding examples in which glyphs are placed on the scene at different orientation than default.我玩了一点Mayavi ,尤其是tvtk但我很难找到将字形以与默认方向不同的方向放置在场景中的示例。

Based on this example I prepared the following scene with two cyllinders, one red and one blue,基于这个例子,我用两个圆柱体准备了以下场景,一个红色一个蓝色,

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')

and what I am trying to achieve here is change the orientation of one of them.我在这里试图实现的是改变其中之一的方向。 Either by providing rotation matrix, either by calling a method, doesn't matter as long as I can somehow rotate the glyph independently (and not just rotate entire scene).无论是通过提供旋转矩阵,还是通过调用方法,只要我能以某种方式独立旋转字形(而不仅仅是旋转整个场景),这都无关紧要。

The above example renders上面的例子呈现

代码示例的渲染输出

Regarding other questions on that have been previously asked, this one seems useful, yet instead of rotating the actor it rotates entire scene about Y-axis.关于之前已经提出的其他问题,这个问题似乎很有用,但它不是旋转演员,而是围绕 Y 轴旋转整个场景。 There also is an example in the scipy-cookbook but again - only with default orientation.scipy-cookbook 中还有一个示例,但同样 - 仅使用默认方向。

The tvtk documentation is not rich in examples and it is almost hard to believe that there is no example that involves alternate orientation. tvtk 文档中的例子并不丰富,几乎很难相信没有涉及交替方向的例子。 The documentation only states that classes and methods correspond to their C++ counterparts following some conventions.该文档仅说明类和方法对应于遵循某些约定的 C++ 对应项。

  1. tvtk class names are essentially similar to VTK classes except there is no annoying 'vtk' at the front. tvtk 类名本质上类似于 VTK 类,只是前面没有烦人的“vtk”。 The only difficulty is with classes that start with a digit.唯一的困难在于以数字开头的类。 For example 'vtk3DSImporter' becomes '3DSImporter'.例如,“vtk3DSImporter”变为“3DSImporter”。 This is illegal in Python and therefore the class name used is 'ThreeDSImporter'.这在 Python 中是非法的,因此使用的类名是“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. tvtk 方法名称是经过深思熟虑的样式名称,而不是 CamelCase。 That is, if a VTK method is called AddItem, the equivalent tvtk name is add_item.也就是说,如果一个 VTK 方法被称为 AddItem,则等效的 tvtk 名称是 add_item。 This is done for the sake of consistency with names used in the enthought package.这样做是为了与 enthought 包中使用的名称保持一致。
  3. Many VTK methods are replaced by handy properties.许多 VTK 方法被方便的属性取代。 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.在上面的例子中,我们使用了 m.input = cs.output 和 p.representation = 'w' 而不是 m.SetInput(cs.GetOutput()) 和 p.SetRepresentationToWireframe() 等。其中一些属性真的是特质。
  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.与 VTK 对象不同,可以在对象初始化时通过在类实例化时将对象的属性(特征)作为关键字参数传递来设置 tvtk 对象的属性。 For example cs = tvtk.ConeSource(radius=0.1, height=0.5).例如 cs = tvtk.ConeSource(radius=0.1, height=0.5)。

Maybe someone who has extensively used VTK with C++ could find that useful but for me it is not very helpful.也许在 C++ 中广泛使用 VTK 的人会发现它很有用,但对我来说它不是很有帮助。 Nevertheless, I tried to look up the VTK C++ documentation and it did give me some clues.尽管如此,我还是尝试查找 VTK C++ 文档,它确实给了我一些线索。 The vtkActor class does inherit some types from vtkProp3D and vtkProp . vtkActor 类确实从vtkProp3DvtkProp继承了一些类型。 The vtkProp3D does seem to admit methods and attributes related to object orientation on the scene but it is unclear to me how to set them. vtkProp3D似乎承认与场景中的对象方向相关的方法和属性,但我不清楚如何设置它们。 The tvtk library is just a wrapper on top of C++ one, which makes it impossible to just inspect what attributes are accepted. tvtk库只是 C++ 库之上的一个包装器,这使得仅inspect哪些属性被接受是不可能的。

I think for the sake of the internet, maybe we should prepare a proper example of rendering a scene with Mayavi and tvtk that admits both positions of actors and their orientations.我想为了互联网,也许我们应该准备一个适当的例子,用Mayavitvtk渲染一个场景,同时承认演员的位置和方向。 Most examples ignore orientations and use spheres so orientation seems not relevant.大多数示例忽略方向并使用球体,因此方向似乎不相关。

Let's summarize.让我们总结一下。

  1. If someone provides a link to a proper example of rendering a scene with Mayavi and tvtk that involves multiple glyphs with different positions and orientations I will accept such answer.如果有人提供了一个使用 Mayavi 和tvtk渲染场景的正确示例的链接,该场景涉及具有不同位置和方向的多个字形,我将接受这样的答案。
  2. Making a custom example for (1) will also meet acceptance.为 (1) 制作自定义示例也将被接受。
  3. Maybe someone could also comment a bit on the difference between positions of the glyph and the actor that maps this glyph on the scene.也许有人也可以评论一下字形的位置和在场景中映射这个字形的演员之间的区别。 As you can see in the examples when I create CylinderSource I explicitly specify where the center is location.正如您在示例中看到的,当我创建CylinderSource我明确指定了中心所在的位置。 This is confusing because is should be the actors center that determines the glyphs position on the scene.这令人困惑,因为它应该是决定场景中字形位置的演员中心。

Thanks a lot!非常感谢!

Ok, it turned out Actor accepts orientation argument which is in degrees (not in radians!).好吧,事实证明Actor接受以度为单位的orientation参数(而不是以弧度为单位!)。 Also, the position of the actor has to be specified when actor is created and not when glyph is created!此外,角色的位置必须在创建角色时指定,而不是在创建字形时指定!

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

renders渲染

渲染输出

I found it by trial and error... The tvtk code in Mayavi package is generated so it is pointless to try to find what attributes are accepted by studying the GitHub repository.我是通过反复试验找到的...... Mayavi包中的tvtk代码是生成的,所以尝试通过研究GitHub存储库来查找哪些属性是没有意义的。 Also, you might confuse the tvtk 's Actor with Mayavi's Actor which does not have orientation property.此外,您可能会将tvtkActor与没有方向属性的Mayavi 的 Actor混淆。 Oh and there is actually a property names "property" so try to search for that and get thousands of results as the word property is extensively used everywhere...哦,实际上有一个属性名称“属性”,所以尝试搜索它并获得数千个结果,因为property一词在任何地方都被广泛使用......

Edit:编辑:

I noticed I have been specifying positions of actors in the glyph center which was wrong!我注意到我一直在字形中心指定演员的位置,这是错误的! Here entire source updated:这里更新了整个源:

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')

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM