1
""" A module that integrates through a tensor field to generate a
2
hyperstreamline. The integration is along the maximum
3
eigenvector and the cross section of the hyperstreamline is
4
defined by the two other eigenvectors. Thus the shape of the
5
hyperstreamline is "tube-like", with the cross section being
6
elliptical. Hyperstreamlines are used to visualize tensor fields.
8
# Authors: KK Rai (kk.rai [at] iitb.ac.in)
9
# R. Ambareesha (ambareesha [at] iitb.ac.in)
10
# Prabhu Ramachandran <prabhu_r@users.sf.net>
12
# Enthought library imports.
13
from enthought.traits.api import Instance, Delegate
14
from enthought.traits.ui.api import View, Group, Item
15
from enthought.tvtk.api import tvtk
18
from enthought.mayavi.core.module import Module
19
from enthought.mayavi.components.actor import Actor
21
######################################################################
22
# `HyperStreamline` class.
23
######################################################################
24
class HyperStreamline(Module):
25
# The version of this class. Used for persistence.
28
# The hyper streamline object.
29
streamline = Instance(tvtk.HyperStreamline, allow_none=False)
31
# The actor for the streamlines.
32
actor = Instance(Actor, allow_none=False)
35
widget = Instance(tvtk.PointWidget, args=(),
36
kw={'outline': False, 'x_shadows': False,
37
'y_shadows': False, 'z_shadows': False},
40
# Create the UI for the traits.
41
view = View(Group(Item(name='actor', style='custom'),
44
Group(Item(name='widget', style='custom', resizable=True),
47
Group(Item(name='streamline', style='custom',
54
######################################################################
56
######################################################################
57
def setup_pipeline(self):
58
"""Override this method so that it *creates* the tvtk
61
This method is invoked when the object is initialized via
62
`__init__`. Note that at the time this method is called, the
63
tvtk data pipeline will *not* yet be setup. So upstream data
64
will not be available. The idea is that you simply create the
65
basic objects and setup those parts of the pipeline not
66
dependent on upstream sources and filters. You should also
67
set the `actors` attribute up at this point.
69
self.widget.on_trait_change(self._start_position_changed)
71
self.streamline = tvtk.HyperStreamline()
72
self.streamline.start_position = self.widget.position
73
self.streamline.integrate_minor_eigenvector()
74
self.streamline.maximum_propagation_distance = 10.0
75
self.streamline.integration_step_length =0.1
76
self.streamline.step_length = 0.01
77
self.streamline.radius = 0.25
78
self.streamline.number_of_sides = 18
79
self.streamline.integration_direction = 2 #integrate both direction
81
self.streamline.on_trait_change(self.render)
83
self.widgets.append(self.widget)
85
def update_pipeline(self):
86
"""Override this method so that it *updates* the tvtk pipeline
87
when data upstream is known to have changed.
89
This method is invoked (automatically) when any of the inputs
90
sends a `pipeline_changed` event.
92
mm = self.module_manager
95
src = mm.source.outputs[0]
96
self.streamline.input = src
100
if old_inp is None or src != old_inp:
102
self.streamline.update()
103
self.outputs = [self.streamline.output]
104
self.pipeline_changed = True
106
def update_data(self):
107
"""Override this method so that it flushes the vtk pipeline if
110
This method is invoked (automatically) when any of the inputs
111
sends a `data_changed` event.
113
# Just set data_changed, the component should do the rest.
114
self.data_changed = True
116
######################################################################
117
# Non-public methods.
118
######################################################################
119
def _streamline_changed(self, old, new):
121
old.on_trait_change(self.render, remove=True)
122
new.on_trait_change(self.render)
123
mm = self.module_manager
125
new.input = mm.source.outputs[0]
127
# A default output so there are no pipeline errors. The
128
# update_pipeline call corrects this if needed.
129
self.outputs = [new.output]
130
self.update_pipeline()
132
def _start_position_changed(self, value):
133
self.streamline.start_position = self.widget.position
135
def _actor_changed(self, old, new):
136
new.scene = self.scene
138
self._change_components(old, new)