~ubuntu-branches/ubuntu/precise/mayavi2/precise

« back to all changes in this revision

Viewing changes to enthought/mayavi/components/grid_plane.py

  • Committer: Bazaar Package Importer
  • Author(s): Varun Hiremath
  • Date: 2011-07-09 01:18:36 UTC
  • mfrom: (1.1.10 upstream) (2.2.3 sid)
  • Revision ID: james.westby@ubuntu.com-20110709011836-fha21zirlgkqh92s
Tags: 4.0.0-1
* New upstream release
* debian/control:
  - Bump Standards-Version to 3.9.2
  - Set X-Python-Version: 2.6, fixes FTBFS (Closes: #625148)
  - Update Depends
* Update debian/watch file
* Cleanup debian/rules file

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
"""A grid plane component.
2
 
 
3
 
"""
4
 
# Author: Prabhu Ramachandran <prabhu_r@users.sf.net>
5
 
# Copyright (c) 2005-2006, Enthought, Inc.
6
 
# License: BSD Style.
7
 
 
8
 
# Enthought library imports.
9
 
from enthought.traits.api import Instance, Enum, Int, Range
10
 
from enthought.traits.ui.api import View, Group, Item
11
 
from enthought.tvtk.api import tvtk
12
 
from enthought.persistence import state_pickler
13
 
 
14
 
# Local imports.
15
 
from enthought.mayavi.core.component import Component
16
 
from enthought.mayavi.core.common import error
17
 
 
18
 
 
19
 
def _get_extent(inp):
20
 
    """Get the extents from the given input.
21
 
    """
22
 
    d = inp.dimensions
23
 
    return [0, d[0]-1, 0, d[1]-1, 0, d[2]-1]
24
 
 
25
 
 
26
 
######################################################################
27
 
# `GridPlane` class.
28
 
######################################################################
29
 
class GridPlane(Component):
30
 
    # The version of this class.  Used for persistence.
31
 
    __version__ = 0
32
 
 
33
 
    # The TVTK object that extracts the grid plane.  This is created
34
 
    # dynamically based on the input data type.
35
 
    plane = Instance(tvtk.Object)
36
 
 
37
 
    # The axis which is normal to the plane chosen.
38
 
    axis = Enum('x', 'y', 'z',
39
 
                desc='specifies the axis normal to the grid plane')
40
 
 
41
 
    # The position of the grid plane.
42
 
    position = Range(value=0, low='_low', high='_high',
43
 
                     enter_set=True, auto_set=False)
44
 
    
45
 
    ########################################
46
 
    # Private traits.
47
 
 
48
 
    # Determines the lower limit of the position trait and is always 0.
49
 
    _low = Int(0)
50
 
    
51
 
    # Determines the upper limit of the position trait.  The value is
52
 
    # dynamically set depending on the input data and state of the
53
 
    # axis trait.  The default is some large value to avoid errors in
54
 
    # cases where the user may set the position before adding the
55
 
    # object to the mayavi tree.
56
 
    _high = Int(10000)
57
 
 
58
 
    ########################################
59
 
    # View related traits.
60
 
    
61
 
    # The View for this object.
62
 
    view = View(Group(Item(name='axis'),
63
 
                      Item(name='position', enabled_when='_high > 0'))
64
 
                )
65
 
 
66
 
    ######################################################################
67
 
    # `object` interface
68
 
    ######################################################################
69
 
    def __get_pure_state__(self):
70
 
        d = super(GridPlane, self).__get_pure_state__()
71
 
        # These traits are dynamically created.
72
 
        for name in ('plane', '_low', '_high'):
73
 
            d.pop(name, None)
74
 
        
75
 
        return d
76
 
 
77
 
    def __set_pure_state__(self, state):
78
 
        state_pickler.set_state(self, state)
79
 
        self._position_changed(self.position)
80
 
        
81
 
    ######################################################################
82
 
    # `Component` interface
83
 
    ######################################################################
84
 
    def setup_pipeline(self):
85
 
        """Override this method so that it *creates* its tvtk
86
 
        pipeline.
87
 
 
88
 
        This method is invoked when the object is initialized via
89
 
        `__init__`.  Note that at the time this method is called, the
90
 
        tvtk data pipeline will *not* yet be setup.  So upstream data
91
 
        will not be available.  The idea is that you simply create the
92
 
        basic objects and setup those parts of the pipeline not
93
 
        dependent on upstream sources and filters.
94
 
        """
95
 
        pass
96
 
    
97
 
    def update_pipeline(self):
98
 
        """Override this method so that it *updates* the tvtk pipeline
99
 
        when data upstream is known to have changed.
100
 
 
101
 
        This method is invoked (automatically) when the input fires a
102
 
        `pipeline_changed` event.
103
 
        """
104
 
        if len(self.inputs) == 0:
105
 
            return
106
 
        input = self.inputs[0].outputs[0]
107
 
        plane = None
108
 
        if input.is_a('vtkStructuredGrid'):
109
 
            plane = tvtk.StructuredGridGeometryFilter()
110
 
        elif input.is_a('vtkStructuredPoints') or input.is_a('vtkImageData'):
111
 
            plane = tvtk.ImageDataGeometryFilter ()
112
 
        elif input.is_a('vtkRectilinearGrid'):
113
 
            plane = tvtk.RectilinearGridGeometryFilter ()
114
 
        else:
115
 
            msg = "The GridPlane component does not support the %s dataset."\
116
 
                  %(input.class_name)
117
 
            error(msg)
118
 
            raise TypeError, msg
119
 
 
120
 
        plane.input = input
121
 
        self.plane = plane
122
 
        self.outputs = [plane.output]
123
 
        self._update_limits()
124
 
        self._update_extents()
125
 
        # If the data is 2D make sure that we default to the
126
 
        # appropriate axis.
127
 
        extents = list(_get_extent(input))
128
 
        diff = [y-x for x, y in zip(extents[::2], extents[1::2])]
129
 
        if diff.count(0) > 0:
130
 
            self.axis = ['x', 'y', 'z'][diff.index(0)]
131
 
        
132
 
 
133
 
    def update_data(self):
134
 
        """Override this method to do what is necessary when upstream
135
 
        data changes.
136
 
 
137
 
        This method is invoked (automatically) when any of the inputs
138
 
        sends a `data_changed` event.
139
 
        """
140
 
        self._update_limits()
141
 
        self._update_extents()
142
 
        # Propagate the data_changed event.
143
 
        self.data_changed = True
144
 
 
145
 
    ######################################################################
146
 
    # Non-public methods.
147
 
    ######################################################################
148
 
    def _get_axis_index(self):
149
 
        return {'x':0, 'y':1, 'z':2}[self.axis]
150
 
    
151
 
    def _update_extents(self):
152
 
        inp = self.plane.input
153
 
        extents = list(_get_extent(inp))
154
 
        pos = self.position
155
 
        axis = self._get_axis_index()
156
 
        extents[2*axis] = pos
157
 
        extents[2*axis+1] = pos
158
 
        try:
159
 
            self.plane.set_extent(extents)
160
 
        except AttributeError:
161
 
            self.plane.extent = extents
162
 
 
163
 
    def _update_limits(self):
164
 
        extents = _get_extent(self.plane.input)
165
 
        axis = self._get_axis_index()
166
 
        pos = min(self.position, extents[2*axis+1])
167
 
        self._high = extents[2*axis+1]
168
 
        return pos
169
 
        
170
 
    def _axis_changed(self, val):
171
 
        if len(self.inputs) == 0:
172
 
            return
173
 
        pos = self._update_limits()
174
 
        if self.position == pos:
175
 
            self._update_extents()
176
 
            self.data_changed = True
177
 
        else:
178
 
            self.position = pos
179
 
 
180
 
    def _position_changed(self, val):
181
 
        if len(self.inputs) == 0:
182
 
            return
183
 
        self._update_extents()
184
 
        self.data_changed = True