1 """ The Axes class and some helper functions.
2 """
3
4
5 from numpy import *
6
7
8 import vtk
9
10 from Figure import *
11
12
14 """ The Axes is the region of the figure window where the plot is displayed.
15 """
16
17 num = 0
18 current = None
19
20
21 standardDirection = array([0.894,0.358,0.268])
22 standardViewUp = array([0,0,1.])
23 frontDirection = array([0,1.,0])
24 frontViewUp = array([0,0,1.])
25 backDirection = array([0,-1.,0])
26 backViewUp = array([0,0,1.])
27 rightDirection = array([1.,0,0])
28 rightViewUp = array([0,0,1.])
29 leftDirection = array([-1.,0,0])
30 leftViewUp = array([0,0,1.])
31 topDirection = array([0,0,1.])
32 topViewUp = array([1.,0,0])
33 bottomDirection = array([0,0,-1.])
34 bottomViewUp = array([1.,0,0])
35 perspectiveDistance = 6.5
36 parallelDistance = 15
37
39 """ Create a new instance of Axes.
40 """
41
42
43 self.ren = vtk.vtkRenderer()
44
45 renWin.AddRenderer(self.ren)
46
47
48
49
50
51
52 self.distance = Axes.perspectiveDistance
53 self.camera = vtk.vtkCamera();
54 self.camera.SetClippingRange(0.1, 10)
55 self.camera.SetFocalPoint(0, 0, -0.3)
56
57 self.camera.SetPosition(-5, -2, -1.5)
58 self.camera.SetViewUp(0, 0, 1)
59 self.ren.SetActiveCamera(self.camera)
60
61
62 self.ax = vtk.vtkCubeAxesActor2D()
63 self.ax.SetCamera(self.camera)
64 self.ax.SetFlyModeToClosestTriad()
65 self.ax.SetInertia(1000000)
66 self.ax.UseRangesOn()
67 self.ren.AddViewProp(self.ax)
68 self.SetNumTicks(6)
69
70
71
72 self.bounds = array([-1., 1.,-1.,1.,-1.,1.])
73 self.ranges = array([2, 2, 2])
74 self.centers = array([0, 0, 0])
75 self.aspect = array([1,1,1])
76 self.autoAspect = 0
77 self.userLims = [0,0,0]
78
79
80
81
82
83
84
85 Axes.current = self
86 Axes.num+=1
87
88
89 self.children = []
90 self.numChildren = 0
91
92
94 """ Set the direction of the camera.
95
96 The direction is defined as a 3 element vector.
97 """
98 self.camera.SetFocalPoint([0,0,0])
99 self.camera.SetPosition( direction*self.distance )
100
102 """ Set the view up direction of the camera.
103
104 The direction is defined as a 3 element vector.
105 """
106 self.camera.SetViewUp( direction )
107
109 """ Set the normalized distance of the camera from
110 the center of the Axes.
111 """
112 self.distance = distance
113
114
116 """ Add a child (Plottable) to the Axes.
117
118 All Plottable's should do this on initialization.
119 """
120 self.children.append(child)
121 self.numChildren+=1
122
123
125 """ Update the bounds of the Axes.
126
127 Although the actual bounds of the Axes will always
128 be between -1 and 1, the children are scaled according
129 to what their combined spatial bounds are.
130 """
131
132 cc = 0
133 for c in self.children:
134 cc += 1
135
136 bounds = c.GetBounds()
137
138 if cc == 1:
139
140 if self.userLims[0]<1:
141 self.bounds[0:2] = bounds[0:2]
142 if self.userLims[1]<1:
143 self.bounds[2:4] = bounds[2:4]
144 if self.userLims[2]<1:
145 self.bounds[4:6] = bounds[4:6]
146
147 else:
148
149 self.bounds = KeepLargestBounds(bounds, self.bounds, self.userLims)
150
151 self.SetRanges()
152
153
155 """ Automatically adjust the ranges of all three axes
156 based on the bounds of the children.
157 """
158 self.ax.SetRanges(self.bounds)
159 self.ranges = array([self.bounds[1]-self.bounds[0], self.bounds[3]-self.bounds[2], self.bounds[5]-self.bounds[4]])
160 self.centers = array([(self.bounds[1]+self.bounds[0])/2, (self.bounds[3]+self.bounds[2])/2, (self.bounds[5]+self.bounds[4])/2])
161
162
164 """ Scales the children so that they'll fit inside the
165 normalized axes ranges.
166 """
167 if self.autoAspect>0:
168 maxRange = self.ranges.max()
169
170 self.ranges = maxRange * self.aspect
171 self.bounds[::2] = self.centers - self.ranges/2
172 self.bounds[1::2] = self.centers + self.ranges/2
173 self.ax.SetRanges(self.bounds)
174
175 frac = 2.0*(1-self.ax.GetCornerOffset())
176 scale = frac/self.ranges
177 for c in self.children:
178 c.SetScale( scale )
179 c.UpdatePos(self.ranges, self.centers)
180
181
183 """ Set the x axis limits.
184 """
185 if lim[1]>lim[0]:
186 self.bounds[0:2] = lim
187 self.userLims[0] = 1
188 self.SetRanges()
189
190
192 """ Set the y axis limits.
193 """
194 if lim[1]>lim[0]:
195 self.bounds[2:4] = lim
196 self.userLims[1] = 1
197 self.SetRanges()
198
199
201 """ Set the z axis limits.
202 """
203 if lim[1]>lim[0]:
204 self.bounds[4:6] = lim
205 self.userLims[2] = 1
206 self.SetRanges()
207
208
210 """ Get the x axis limits.
211 """
212 return self.bounds[0:2]
213
214
216 """ Get the y axis limits.
217 """
218 return self.bounds[2:4]
219
220
222 """ Get the z axis limits.
223 """
224 return self.bounds[4:6]
225
226
228 """ Set the number of ticks on all axes.
229 """
230 self.ax.SetNumberOfLabels(n)
231 self.nTicks = n
232 self.UpdateGrid()
233
234
236 """ Update the grid based on the axis ticks.
237 """
238
239 dGrid = arange(float(self.nTicks))/(float(self.nTicks)-1) * 2*(1-self.ax.GetCornerOffset()) - 1*(1-self.ax.GetCornerOffset())
240 xArray = vtk.vtkFloatArray()
241 xArray.SetNumberOfValues(len(dGrid))
242 yArray = vtk.vtkFloatArray()
243 yArray.SetNumberOfValues(len(dGrid))
244 zArray = vtk.vtkFloatArray()
245 zArray.SetNumberOfValues(len(dGrid))
246 for g in arange(len(dGrid)):
247 xArray.SetValue(g, dGrid[g])
248 yArray.SetValue(g, dGrid[g])
249 zArray.SetValue(g, dGrid[g])
250
251
252 gridProps = vtk.vtkProperty()
253 gridProps.SetRepresentationToWireframe()
254 gridProps.BackfaceCullingOff()
255 gridProps.FrontfaceCullingOff()
256
257
258 self.grid = vtk.vtkRectilinearGrid()
259 self.grid.SetDimensions(len(dGrid), len(dGrid), len(dGrid))
260 self.grid.SetXCoordinates(xArray)
261 self.grid.SetYCoordinates(yArray)
262 self.grid.SetZCoordinates(zArray)
263 self.gridFilter = ( vtk.vtkRectilinearGridGeometryFilter(), vtk.vtkRectilinearGridGeometryFilter(), vtk.vtkRectilinearGridGeometryFilter())
264 self.gridMapper = ( vtk.vtkPolyDataMapper(), vtk.vtkPolyDataMapper(), vtk.vtkPolyDataMapper())
265 self.gridActor = (vtk.vtkActor(), vtk.vtkActor(), vtk.vtkActor())
266 extent = [ 0, self.nTicks-1, 0, self.nTicks-1, 0, self.nTicks-1]
267 for i in range(len(self.gridFilter)):
268 self.gridFilter[i].SetInput(self.grid)
269 extent_ = extent[:]
270 extent_[2*i] = extent_[2*i+1] = self.nTicks-1
271 self.gridFilter[i].SetExtent(extent_)
272 self.gridMapper[i].SetInput(self.gridFilter[i].GetOutput())
273 self.gridActor[i].SetMapper(self.gridMapper[i])
274 self.gridActor[i].SetProperty(gridProps)
275
276 self.ren.AddActor(self.gridActor[i])
277 self.SetGridInvisible();
278
280 """ Makes the grid visible (still experimental).
281 """
282 for a in self.gridActor:
283 props = a.GetProperty()
284 props.SetOpacity(1)
285 a.SetProperty(props)
286
287
289 """ Makes the grid invisible (still experimental).
290 """
291 for a in self.gridActor:
292 props = a.GetProperty()
293 props.SetOpacity(0)
294 a.SetProperty(props)
295
296
298 """ Set the x axis label.
299 """
300 self.ax.SetXLabel(label)
301
302
304 """ Set the y axis label.
305 """
306 self.ax.SetYLabel(label)
307
308
310 """ Set the z axis label.
311 """
312 self.ax.SetZLabel(label)
313
314
316 """ Get the x axis label.
317 """
318 return self.ax.GetXLabel(label)
319
320
322 """ Get the y axis label.
323 """
324 return self.ax.GetYLabel(label)
325
326
328 """ Get the z axis label.
329 """
330 return self.ax.GetZLabel(label)
331
332
333
334
335
337 """ Set up a check for aborting rendering.
338
339 obj will be the object generating the event.
340 In this case it is renWin.
341 """
342 if obj.GetEventPending() != 0:
343 obj.SetAbortRender(1)
344
345
347 """ Keep the largest of the two bounding boxes.
348 """
349 bounds = bounds1.copy()
350 if bounds2[0] < bounds1[0] and userLims[0]==0:
351 bounds[0] = bounds2[0]
352 if bounds2[1] > bounds1[1] and userLims[0]==0:
353 bounds[1] = bounds2[1]
354 if bounds2[2] < bounds1[2] and userLims[1]==0:
355 bounds[2] = bounds2[2]
356 if bounds2[3] > bounds1[3] and userLims[1]==0:
357 bounds[3] = bounds2[3]
358 if bounds2[4] < bounds1[4] and userLims[2]==0:
359 bounds[4] = bounds2[4]
360 if bounds2[5] > bounds1[5] and userLims[2]==0:
361 bounds[5] = bounds2[5]
362 return bounds
363