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.
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. There also is an example in the scipy-cookbook but again - only with default orientation.
The tvtk documentation is not rich in examples and it is almost hard to believe that there is no example that involves alternate orientation. The documentation only states that classes and methods correspond to their C++ counterparts following some conventions.
- 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.
- 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.
- 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.
- 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).
Maybe someone who has extensively used VTK with C++ could find that useful but for me it is not very helpful. Nevertheless, I tried to look up the VTK C++ documentation and it did give me some clues. The vtkActor class does inherit some types from vtkProp3D and vtkProp. 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. The tvtk
library is just a wrapper on top of C++ one, which makes it impossible to just inspect
what attributes are accepted.
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. Most examples ignore orientations and use spheres so orientation seems not relevant.
Let's summarize.
tvtk
that involves multiple glyphs with different positions and orientations I will accept such answer.CylinderSource
I explicitly specify where the center is location. 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!). 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. Also, you might confuse the tvtk
's Actor
with Mayavi's Actor which does not have orientation property. 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...
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')