Statistiques
| Révision :

root / ase / visualize / vtk / pipeline.py @ 3

Historique | Voir | Annoter | Télécharger (6,74 ko)

1

    
2
import numpy as np
3

    
4
from vtk import vtkPolyDataMapper, vtkPolyDataNormals, \
5
                vtkLinearSubdivisionFilter, vtkSmoothPolyDataFilter, \
6
                vtkDepthSortPolyData, vtkAlgorithm, vtkAlgorithmOutput
7
from ase.visualize.vtk.grid import vtkVolumeGrid
8

    
9
# -------------------------------------------------------------------
10

    
11
class vtkPipeline:
12
    _branchable = False
13

    
14
    def __init__(self, vtkish_data=None):
15

    
16
        self.vtkish_data = None
17
        self.closed = False
18
        self.pending = False
19
        self.filters = tuple()
20

    
21
        if vtkish_data is not None:
22
            self.set_data(vtkish_data)
23

    
24
    def hasdata(self):
25
        return (self.vtkish_data is not None)
26

    
27
    def hasfilters(self):
28
        return len(self.filters)>0
29

    
30
    def set_data(self, vtkish_data):
31

    
32
        assert vtkish_data is not None
33

    
34
        if self.hasdata():
35
            raise RuntimeError('Pipeline already has input.')
36
        elif vtkish_data in self:
37
            raise ValueError('Pipeline loop detected.')
38

    
39
        if isinstance(vtkish_data, vtkPipeline):
40
            # The embedded pipeline takes over
41
            vtkish_data.signal_close()
42

    
43
        self.vtkish_data = vtkish_data
44

    
45
        if not self.hasfilters():
46
            return
47

    
48
        vtkish_inner = self.filters[0]
49
        
50
        if isinstance(vtkish_inner, vtkPipeline):
51
            vtkish_inner.set_data(vtkish_data) #TODO does this work?
52
        else:
53
            assert isinstance(vtkish_inner, vtkAlgorithm)
54

    
55
            if isinstance(vtkish_data, vtkPipeline):
56
                # The embedded pipeline takes over
57
                vtkish_data.connect(vtkish_inner)
58
            else:
59
                assert isinstance(vtkish_data, vtkAlgorithm)
60
                vtkish_inner.SetInputConnection(vtkish_data.GetOutputPort())
61

    
62
    def isempty(self):
63
        return not self.hasdata() and not self.hasfilters()
64

    
65
    def isclosed(self):
66
        if self.pending:
67
            raise RuntimeError('Pipeline output port state is pending.')
68
        return self.closed
69

    
70
    def signal_close(self):
71
        if self.closed:
72
            raise RuntimeError('Pipeline output port is already closed.')
73
        elif not self._branchable:
74
            self.pending = True
75

    
76
    def get_output_port(self):
77
        if self.closed:
78
            raise RuntimeError('Pipeline output port is closed.')
79
        elif self.pending:
80
            self.closed = True
81
            self.pending = False
82

    
83
        if self.hasfilters():
84
            vtkish_outer = self.filters[-1]
85
        elif self.hasdata():
86
            vtkish_outer = self.vtkish_data
87
        else:
88
            raise RuntimeError('Pipeline output port unavailable.')
89

    
90
        if isinstance(vtkish_outer, vtkPipeline):
91
            return vtkish_outer.get_output_port()
92
        else:
93
            assert isinstance(vtkish_outer, vtkAlgorithm)
94
            return vtkish_outer.GetOutputPort()
95

    
96
    def set_input_connection(self, vtk_port):
97
        assert isinstance(vtk_port, vtkAlgorithmOutput)
98

    
99
        vtkish_inner = self.filters[0]
100

    
101
        if isinstance(vtkish_inner, vtkPipeline):
102
            # Connect must be passed down
103
            vtkish_inner.set_input_connection(vtk_port)
104
        else:
105
            vtkish_inner.SetInputConnection(vtk_port)
106

    
107
    def connect(self, vtkish_filter):
108
        if vtkish_filter in self:
109
            raise ValueError('Pipeline loop detected.')
110

    
111
        if isinstance(vtkish_filter, vtkPipeline):
112
            # Connection must be passed down
113
            if not self.isempty():
114
                vtkish_filter.set_input_connection(self.get_output_port())
115

    
116
            # The containing pipeline takes over
117
            vtkish_filter.signal_close()
118

    
119
        elif not self.isempty():
120
            assert isinstance(vtkish_filter, vtkAlgorithm)
121
            vtkish_filter.SetInputConnection(self.get_output_port())
122

    
123
    def append(self, vtkish_filter):
124
        self.connect(vtkish_filter)
125
        self.filters += (vtkish_filter,)
126

    
127
    def extend(self, vtkish_filters):
128
        map(self.append, vtkish_filters)
129

    
130
    def __contains__(self, vtkish_candidate):
131
        if vtkish_candidate == self:
132
            return True
133

    
134
        if self.hasdata():
135
            if isinstance(self.vtkish_data, vtkPipeline):
136
                if vtkish_candidate in self.vtkish_data:
137
                    return True
138
            else:
139
                if vtkish_candidate == self.vtkish_data:
140
                    return True
141

    
142
        if vtkish_candidate in self.filters:
143
            return True
144

    
145
        for vtkish_filter in self.filters:
146
            if isinstance(vtkish_filter, vtkPipeline) \
147
                and vtkish_candidate in vtkish_filter:
148
                return True
149

    
150
        return False
151

    
152
    def __getitem__(self, i): #TODO XXX this is a hack
153
        return self.filters[i]
154

    
155
# -------------------------------------------------------------------
156

    
157
class vtkPolyDataPipeline(vtkPipeline):
158
    def __init__(self, vtkish_polydata=None):
159
        vtkPipeline.__init__(self, vtkish_polydata)
160

    
161
    def connect(self, vtkish_filter):
162
        if isinstance(vtkish_filter, vtkPolyDataMapper):
163
            self.signal_close()
164
        vtkPipeline.connect(self, vtkish_filter)
165

    
166
class vtkSurfaceSmootherPipeline(vtkPolyDataPipeline):
167
    def __init__(self, grid, vtkish_polydata=None, angle=15):
168

    
169
        vtkPolyDataPipeline.__init__(self, vtkish_polydata)
170

    
171
        # Make sure grid argument is correct type
172
        assert isinstance(grid, vtkVolumeGrid)
173
        self.grid = grid
174

    
175
        # Split polys with intersection angles greater than angle
176
        vtk_dnorm = vtkPolyDataNormals()
177
        vtk_dnorm.SetFeatureAngle(angle)
178
        vtk_dnorm.SplittingOn()
179
        vtk_dnorm.ComputeCellNormalsOff()
180
        vtk_dnorm.ComputePointNormalsOff()
181
        self.append(vtk_dnorm)
182

    
183
        relax = self.grid.get_relaxation_factor()
184

    
185
        if relax is not None:
186
            print 'relax=',relax
187
            #vtk_subdiv = vtkButterflySubdivisionFilter()
188
            vtk_subdiv = vtkLinearSubdivisionFilter()
189
            self.append(vtk_subdiv)
190
    
191
            # Smooth out some of the sharp points.
192
            vtk_smooth = vtkSmoothPolyDataFilter()
193
            vtk_smooth.SetRelaxationFactor(relax)
194
            self.append(vtk_smooth)
195

    
196
class vtkDepthSortPipeline(vtkPolyDataPipeline):
197
    def __init__(self, vtk_renderer, vtkish_polydata=None):
198

    
199
        vtkPolyDataPipeline.__init__(self, vtkish_polydata)
200

    
201
        # The depht sort object is set up to generate scalars representing
202
        # the sort depth. A camera is assigned for the sorting. The camera
203
        # defines the sort vector (position and focal point).
204
        vtk_ds = vtkDepthSortPolyData()
205
        vtk_ds.SetCamera(vtk_renderer.GetActiveCamera())
206
        vtk_ds.SetDirectionToBackToFront()
207
        #vtk_ds.SetVector(1, 1, 1)
208
        #vtk_ds.SortScalarsOn()
209
        #vtk_ds.Update()
210
        self.append(vtk_ds)
211

    
212
        vtk_renderer.ResetCamera()
213