Package pyllar :: Module Axes
[hide private]
[frames] | no frames]

Source Code for Module pyllar.Axes

  1  """ The Axes class and some helper functions.
 
  2  """ 
  3  
 
  4  # load numeric packages
 
  5  from numpy import * 
  6  
 
  7  # load vtk.vtk extensions
 
  8  import vtk 
  9  
 
 10  from Figure import * 
 11  
 
 12  
 
13 -class Axes:
14 """ The Axes is the region of the figure window where the plot is displayed. 15 """ 16 17 num = 0 # keep track of the number of axes 18 current = None 19 20 # create standard views 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
38 - def __init__(self, renWin):
39 """ Create a new instance of Axes. 40 """ 41 42 # create a rendering window and renderer 43 self.ren = vtk.vtkRenderer() 44 # self.renWin = vtk.vtkRenderWindow() 45 renWin.AddRenderer(self.ren) 46 # self.renWin.SetSize(800,600) 47 # self.renWin.SetWindowName("Figure 1") 48 # self.renWin.AddObserver("AbortCheckEvent", CheckAbort) 49 50 51 # create the camera 52 self.distance = Axes.perspectiveDistance # default perspective view 53 self.camera = vtk.vtkCamera(); 54 self.camera.SetClippingRange(0.1, 10) 55 self.camera.SetFocalPoint(0, 0, -0.3) 56 # self.camera.SetPosition(5, 2, 1.5) 57 self.camera.SetPosition(-5, -2, -1.5) 58 self.camera.SetViewUp(0, 0, 1) 59 self.ren.SetActiveCamera(self.camera) 60 61 # create axes 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 # set up bounds 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 # by default, use the computed aspect ratios, not the user's 77 self.userLims = [0,0,0] # by default, set the axis limits automatically 78 79 # enable user interface interactor 80 # self.iren.Initialize() 81 # self.iren.Start() 82 83 84 # store in axes pool 85 Axes.current = self 86 Axes.num+=1 87 88 # create children storage 89 self.children = [] 90 self.numChildren = 0
91 92
93 - def SetViewDirection(self, direction):
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
101 - def SetViewUp(self, direction):
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
108 - def SetDistance(self, distance):
109 """ Set the normalized distance of the camera from 110 the center of the Axes. 111 """ 112 self.distance = distance
113 114
115 - def AddChild(self, child):
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
124 - def UpdateBounds(self):
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 # this is the first child, so it's bounds are the axes bounds 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 # adjust bounds to fit this child 149 self.bounds = KeepLargestBounds(bounds, self.bounds, self.userLims) 150 151 self.SetRanges()
152 153
154 - def SetRanges(self):
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
163 - def ScaleChildren(self):
164 """ Scales the children so that they'll fit inside the 165 normalized axes ranges. 166 """ 167 if self.autoAspect>0: # if the user's aspec ratio should be used 168 maxRange = self.ranges.max() 169 # self.ranges = maxRange / self.ranges * self.aspect # use the aspect ratios to scale the dimensions 170 self.ranges = maxRange * self.aspect # use the aspect ratios to scale the dimensions 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
182 - def SetXLim(self, lim=[0,0]):
183 """ Set the x axis limits. 184 """ 185 if lim[1]>lim[0]: # if there is a valid input argument 186 self.bounds[0:2] = lim 187 self.userLims[0] = 1 188 self.SetRanges()
189 190
191 - def SetYLim(self, lim=[0,0]):
192 """ Set the y axis limits. 193 """ 194 if lim[1]>lim[0]: # if there is a valid input argument 195 self.bounds[2:4] = lim 196 self.userLims[1] = 1 197 self.SetRanges()
198 199
200 - def SetZLim(self, lim=[0,0]):
201 """ Set the z axis limits. 202 """ 203 if lim[1]>lim[0]: # if there is a valid input argument 204 self.bounds[4:6] = lim 205 self.userLims[2] = 1 206 self.SetRanges()
207 208
209 - def GetXLim(self):
210 """ Get the x axis limits. 211 """ 212 return self.bounds[0:2]
213 214
215 - def GetYLim(self):
216 """ Get the y axis limits. 217 """ 218 return self.bounds[2:4]
219 220
221 - def GetZLim(self):
222 """ Get the z axis limits. 223 """ 224 return self.bounds[4:6]
225 226
227 - def SetNumTicks(self, n):
228 """ Set the number of ticks on all axes. 229 """ 230 self.ax.SetNumberOfLabels(n) 231 self.nTicks = n 232 self.UpdateGrid()
233 234
235 - def UpdateGrid(self):
236 """ Update the grid based on the axis ticks. 237 """ 238 # get the tick mark locations 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 # define grid line properties 252 gridProps = vtk.vtkProperty() 253 gridProps.SetRepresentationToWireframe() 254 gridProps.BackfaceCullingOff() 255 gridProps.FrontfaceCullingOff() 256 257 # create grid lines 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 # use the last grid element for this dimension 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 #self.gridActor[i].SetBackfaceProperty(gridProps) 276 self.ren.AddActor(self.gridActor[i]) 277 self.SetGridInvisible();
278
279 - def SetGridVisible(self):
280 """ Makes the grid visible (still experimental). 281 """ 282 for a in self.gridActor: 283 props = a.GetProperty() # get the vtk.vtkProperty object 284 props.SetOpacity(1) 285 a.SetProperty(props)
286 287
288 - def SetGridInvisible(self):
289 """ Makes the grid invisible (still experimental). 290 """ 291 for a in self.gridActor: 292 props = a.GetProperty() # get the vtk.vtkProperty object 293 props.SetOpacity(0) 294 a.SetProperty(props)
295 296
297 - def SetXLabel(self, label):
298 """ Set the x axis label. 299 """ 300 self.ax.SetXLabel(label)
301 302
303 - def SetYLabel(self, label):
304 """ Set the y axis label. 305 """ 306 self.ax.SetYLabel(label)
307 308
309 - def SetZLabel(self, label):
310 """ Set the z axis label. 311 """ 312 self.ax.SetZLabel(label)
313 314
315 - def GetXLabel(self, label):
316 """ Get the x axis label. 317 """ 318 return self.ax.GetXLabel(label)
319 320
321 - def GetYLabel(self, label):
322 """ Get the y axis label. 323 """ 324 return self.ax.GetYLabel(label)
325 326
327 - def GetZLabel(self, label):
328 """ Get the z axis label. 329 """ 330 return self.ax.GetZLabel(label)
331 332 333 ## End of the Axes class definition ## 334 335
336 -def CheckAbort(obj, event):
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
346 -def KeepLargestBounds(bounds1, bounds2, userLims=[0,0,0]):
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