/[escript]/trunk/pyvisi/py_src/velocity.py
ViewVC logotype

Annotation of /trunk/pyvisi/py_src/velocity.py

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1189 - (hide annotations)
Thu Jun 7 05:31:25 2007 UTC (13 years, 2 months ago) by jongui
File MIME type: text/x-python
File size: 19727 byte(s)
A Scalar Bar can now be displayed by creating an instance of a 'Legend'. The Scalar Bar can either show the scalar data range or vector data range. Corresponding examples and tests have also been added.
1 ksteube 1147 """
2     @author: John NGUI
3     """
4    
5     import vtk
6     from mapper import DataSetMapper
7     from lookuptable import LookupTable
8     from actor import Actor3D
9 jongui 1148 from constant import Viewport, Color, Arrow, ColorMode, Lut
10 ksteube 1147 from arrow import Arrow2D, Arrow3D
11     from glyph import Glyph3D
12     from outline import Outline
13     from point import MaskPoints
14     from average import CellDataToPointData
15    
16     # NOTE: DataSetMapper, Actor3D, Arrow2D, Arrow3D, Glyph3D and
17     # MaskPoints were inherited to allow access to their public
18     # methods from the driver.
19     class Velocity(DataSetMapper, Actor3D, Arrow2D, Arrow3D, Glyph3D, MaskPoints):
20     """
21     Class that shows a vector field using arrows. The arrows can either be
22     colored or grey-scaled, depending on the lookup table used. If the arrows
23     are colored, there are two possible coloring modes, either using vector data
24     or scalar data. Similarly, there are two possible types of
25     arrows, either using two-dimensional or three-dimensional.
26     """
27    
28     # The SOUTH_WEST default viewport is used when there is only one viewport.
29     # This saves the user from specifying the viewport when there is only one.
30     # If no lut is specified, the color scheme will be used.
31 jongui 1148 def __init__(self, scene, data_collector, arrow = Arrow.TWO_D,
32     color_mode = ColorMode.VECTOR, viewport = Viewport.SOUTH_WEST,
33 ksteube 1147 lut = Lut.COLOR, cell_to_point = False, outline = True):
34     """
35     Initialise the Velocity.
36    
37     @attention: The source can either be point or cell data. If the
38     source is cell data, a conversion to point data may or may not be
39     required, in order for the object to be rendered correctly.
40     If a conversion is needed, the 'cell_to_point' flag must be set to
41     'True', otherwise 'False' (which is the default).
42    
43     @type scene: L{Scene <scene.Scene>} object
44     @param scene: Scene in which objects are to be rendered on
45     @type data_collector: L{DataCollector <datacollector.DataCollector>}
46     object
47     @param data_collector: Deal with source of data for visualisation
48 jongui 1148 @type arrow: L{Arrow <constant.Arrow>} constant
49     @param arrow: Type of arrow (two dimensional or three dimensional)
50     @type color_mode: L{ColorMode <constant.ColorMode>} constant
51     @param color_mode: Type of color mode
52 ksteube 1147 @type viewport: L{Viewport <constant.Viewport>} constant
53     @param viewport: Viewport in which objects are to be rendered on
54     @type lut : L{Lut <constant.Lut>} constant
55     @param lut: Lookup table color scheme
56     @type cell_to_point: Boolean
57     @param cell_to_point: Converts cell data to point data (by averaging)
58     @type outline: Boolean
59     @param outline: Places an outline around the domain surface
60     """
61    
62 jongui 1148 self.__data_collector = data_collector
63     self.__arrow = arrow
64     self.__color_mode = color_mode
65     self.__viewport = viewport
66     self.__lut = lut
67     self.__cell_to_point = cell_to_point
68     self.__outline = outline
69    
70     self.__modified = True # Keeps track whether Velocity has been modified.
71     MaskPoints.__init__(self)
72     Glyph3D.__init__(self)
73     DataSetMapper.__init__(self)
74     Actor3D.__init__(self)
75     scene._addVisualizationModules(self)
76 ksteube 1147
77 jongui 1148 # ----- Outline -----
78 ksteube 1147
79 jongui 1148 # NOTE: Changes cannot be made to the Outline's properties from the
80     # driver.
81     if(self.__outline == True):
82     outline = Outline(self.__data_collector._getDataCollectorOutput())
83     mapper = DataSetMapper()
84     mapper._setupDataSetMapper(outline._getOutlineOutput())
85 ksteube 1147
86 jongui 1148 actor3D = Actor3D()
87     actor3D._setupActor3D(mapper._getDataSetMapper())
88 ksteube 1147 # Default outline color is black.
89 jongui 1148 actor3D.setColor(Color.BLACK)
90 ksteube 1147
91     # Default line width is 1.
92 jongui 1148 actor3D._setLineWidth(1)
93 jongui 1158 scene._addActor3D(self.__viewport, actor3D._getActor3D())
94 ksteube 1147
95     # ----- Velocity -----
96    
97     # NOTE: Lookup table color mapping (color or grey scale) MUST be set
98     # before DataSetMapper. If it is done after DataSetMapper, no effect
99     # will take place.
100 jongui 1148 if(self.__lut == Lut.COLOR): # Colored lookup table.
101 ksteube 1147 lookup_table = LookupTable()
102     lookup_table._setTableValue()
103 jongui 1148 elif(self.__lut == Lut.GREY_SCALE): # Grey scaled lookup table.
104 ksteube 1147 lookup_table = LookupTable()
105     lookup_table._setLookupTableToGreyScale()
106    
107 jongui 1148 if(self.__cell_to_point == True): # Converts cell data to point data.
108     c2p = CellDataToPointData(
109     self.__data_collector._getDataCollectorOutput())
110     self._setupMaskPoints(c2p._getCellToPointOutput())
111     elif(self.__cell_to_point == False): # No conversion happens.
112     self._setupMaskPoints(data_collector._getDataCollectorOutput())
113 ksteube 1147
114 jongui 1148 if(self.__arrow == Arrow.TWO_D): # Use 2D arrows.
115 ksteube 1147 Arrow2D.__init__(self)
116 jongui 1148 self._setupGlyph3D(self._getMaskPointsOutput(),
117     self._getArrow2DOutput())
118 ksteube 1147 elif(arrow == Arrow.THREE_D): # Use 3D arrows.
119     Arrow3D.__init__(self)
120 jongui 1148 self._setupGlyph3D(self._getMaskPointsOutput(),
121     self._getArrow3DOutput())
122 ksteube 1147
123 jongui 1148 self._setupDataSetMapper(self._getGlyph3DOutput(),
124 ksteube 1147 lookup_table._getLookupTable())
125    
126 jongui 1148 self._setupActor3D(self._getDataSetMapper())
127 jongui 1158 scene._addActor3D(self.__viewport, self._getActor3D())
128 ksteube 1147
129 jongui 1148 def _isModified(self):
130     """
131     Return whether the Velocity or DataCollector has been modified.
132 ksteube 1147
133 jongui 1148 @rtype: Boolean
134     @return: True or False
135     """
136 ksteube 1147
137 jongui 1148 return self.__modified or self.__data_collector._isModified()
138 ksteube 1147
139 jongui 1158 def _render(self, scene):
140 jongui 1148 """
141     Render the velocity.
142 jongui 1158
143     @type scene: L{Scene <scene.Scene>} object
144     @param scene: Scene in which objects are to be rendered on
145 jongui 1148 """
146    
147     if (self._isModified() == True):
148     if(self.__data_collector._isScalarSet() == True):
149     self.__data_collector._setActiveScalar()
150     if(self.__data_collector._isVectorSet() == True):
151     self.__data_collector._setActiveVector()
152    
153     # Color velocity by vector.
154     if(self.__color_mode == ColorMode.VECTOR):
155     self._setColorModeByVector()
156 jongui 1189
157     # self._isScalarRangeSet checks whether the scalar range has
158     # been specified by the user. If it has, then the scalar range
159     # read from the source will be ignored.
160     if(not(self._isScalarRangeSet())):
161     self._setRange(self.__data_collector._getVectorRange())
162     self._setScalarRange(\
163     self.__data_collector._getVectorRange())
164     else:
165     self._setRange(self._getDataSetMapperRange())
166    
167 jongui 1148 # Color velocity by scalar.
168     elif(self.__color_mode == ColorMode.SCALAR):
169     self._setColorModeByScalar()
170    
171 jongui 1189 # self._isScalarRangeSet checks whether the scalar range has
172     # been specified by the user. If it has, then the scalar range
173     # read from the source will be ignored.
174     if(not(self._isScalarRangeSet())):
175     self._setRange(self.__data_collector._getScalarRange())
176     self._setScalarRange(\
177     self.__data_collector._getScalarRange())
178     else:
179     self._setRange(self._getDataSetMapperRange())
180    
181 jongui 1148 self.__modified = False
182    
183    
184 ksteube 1147 ###############################################################################
185    
186    
187     from transform import Transform
188     from plane import Plane
189     from cutter import Cutter
190    
191     # NOTE: DataSetMapper, Actor3D, Arrow2D, Arrow3D, Glyph3D, Transform, Plane,
192     # Cutter and MaskPoints were inherited to allow access to
193     # their public methods from the driver.
194     class VelocityOnPlaneCut(DataSetMapper, Actor3D, Arrow2D, Arrow3D,
195     Glyph3D, Transform, Plane, Cutter, MaskPoints):
196     """
197     This class works in a similar way to L{MapOnPlaneCut <map.MapOnPlaneCut>},
198 jongui 1148 except that it shows a vector field using arrows cut using a plane.
199 ksteube 1147 """
200    
201     # The SOUTH_WEST default viewport is used when there is only one viewport.
202     # This saves the user from specifying the viewport when there is only one.
203     # If no lut is specified, the color scheme willbe used.
204     def __init__(self, scene, data_collector, arrow = Arrow.TWO_D,
205     color_mode = ColorMode.VECTOR, viewport = Viewport.SOUTH_WEST,
206     lut = Lut.COLOR, cell_to_point = False, outline = True):
207     """
208     Initialise the VelocityOnPlaneCut.
209    
210     @attention: The source can either be point or cell data. If the
211     source is cell data, a conversion to point data may or may not be
212     required, in order for the object to be rendered correctly.
213     If a conversion is needed, the 'cell_to_point' flag must be set to
214     'True', otherwise 'False' (which is the default).
215    
216     @type scene: L{Scene <scene.Scene>} object
217     @param scene: Scene in which objects are to be rendered on
218     @type data_collector: L{DataCollector <datacollector.DataCollector>}
219     object
220     @param data_collector: Deal with source of data for visualisation
221     @type arrow: L{Arrow <constant.Arrow>} constant
222     @param arrow: Type of arrow (two dimensional or three dimensional)
223     @type color_mode: L{ColorMode <constant.ColorMode>} constant
224     @param color_mode: Type of color mode
225     @type viewport: L{Viewport <constant.Viewport>} constant
226     @param viewport: Viewport in which objects are to be rendered on
227     @type lut : L{Lut <constant.Lut>} constant
228     @param lut: Lookup table color scheme
229     @type cell_to_point: Boolean
230     @param cell_to_point: Converts cell data to point data (by averaging)
231     @type outline: Boolean
232     @param outline: Places an outline around the domain surface
233     """
234    
235 jongui 1148 self.__data_collector = data_collector
236     self.__arrow = arrow
237     self.__color_mode = color_mode
238     self.__viewport = viewport
239     self.__lut = lut
240     self.__cell_to_point = cell_to_point
241     self.__outline = outline
242    
243     # Keeps track whether VelocityOnPlaneCut has been modified.
244     self.__modified = True
245     Transform.__init__(self)
246     Plane.__init__(self)
247     Cutter.__init__(self)
248     MaskPoints.__init__(self)
249     Glyph3D.__init__(self)
250     DataSetMapper.__init__(self)
251     Actor3D.__init__(self)
252     scene._addVisualizationModules(self)
253 ksteube 1147
254 jongui 1148 # ----- Outline -----
255 ksteube 1147
256 jongui 1148 # NOTE: Changes cannot be made to the Outline's properties from the
257     # driver.
258     if(self.__outline == True):
259     outline = Outline(self.__data_collector._getDataCollectorOutput())
260     mapper = DataSetMapper()
261     mapper._setupDataSetMapper(outline._getOutlineOutput())
262 ksteube 1147
263 jongui 1148 actor3D = Actor3D()
264     actor3D._setupActor3D(mapper._getDataSetMapper())
265 ksteube 1147 # Default outline color is black.
266 jongui 1148 actor3D.setColor(Color.BLACK)
267 ksteube 1147
268     # Default line width is 1.
269 jongui 1148 actor3D._setLineWidth(1)
270 jongui 1158 scene._addActor3D(self.__viewport, actor3D._getActor3D())
271 ksteube 1147
272     # ----- Velocity on a cut plane -----
273    
274     # NOTE: Lookup table color mapping (color or grey scale) MUST be set
275     # before DataSetMapper. If it is done after DataSetMapper, no effect
276     # will take place.
277     if(lut == Lut.COLOR): # Colored lookup table.
278     lookup_table = LookupTable()
279     lookup_table._setTableValue()
280     elif(lut == Lut.GREY_SCALE): # Grey scaled lookup table.
281     lookup_table = LookupTable()
282     lookup_table._setLookupTableToGreyScale()
283    
284 jongui 1148 self._setupPlane(self._getTransform())
285 ksteube 1147
286 jongui 1148 if(self.__cell_to_point == True): # Converts cell data to point data.
287     c2p = CellDataToPointData(
288     self.__data_collector._getDataCollectorOutput())
289     self._setupCutter(c2p._getCellToPointOutput(), self._getPlane())
290     elif(self.__cell_to_point == False): # No conversion happens.
291     self._setupCutter(self.__data_collector._getDataCollectorOutput(),
292     self._getPlane())
293 ksteube 1147
294 jongui 1148 self._setupMaskPoints(self._getCutterOutput())
295 ksteube 1147
296 jongui 1148 if(self.__arrow == Arrow.TWO_D): # Use 2D arrows.
297 ksteube 1147 Arrow2D.__init__(self)
298 jongui 1148 self._setupGlyph3D(self._getMaskPointsOutput(),
299     self._getActor2DOutput())
300     elif(self.__arrow == Arrow.THREE_D): # Use 3D arrows.
301 ksteube 1147 Arrow3D.__init__(self)
302 jongui 1148 self._setupGlyph3D(self._getMaskPointsOutput(),
303     self._getArrow3DOutput())
304 ksteube 1147
305 jongui 1148 self._setupDataSetMapper(self._getGlyph3DOutput(),
306 ksteube 1147 lookup_table._getLookupTable())
307    
308 jongui 1148 self._setupActor3D(self._getDataSetMapper())
309 jongui 1158 scene._addActor3D(self.__viewport, self._getActor3D())
310 jongui 1148
311     def _isModified(self):
312     """
313     Return whether the VelocityOnPlaneCut or DataCollector has been
314     modified.
315 ksteube 1147
316 jongui 1148 @rtype: Boolean
317     @return: True or False
318     """
319 ksteube 1147
320 jongui 1148 return self.__modified or self.__data_collector._isModified()
321 ksteube 1147
322 jongui 1158 def _render(self, scene):
323 jongui 1148 """
324 jongui 1158 Render the velocity cut using a plane.
325    
326     @type scene: L{Scene <scene.Scene>} object
327     @param scene: Scene in which objects are to be rendered on
328 jongui 1148 """
329 ksteube 1147
330 jongui 1148 if (self._isModified() == True):
331     if(self.__data_collector._isVectorSet() == True):
332     self.__data_collector._setActiveVector()
333     # Color velocity by vector.
334     if(self.__color_mode == ColorMode.VECTOR):
335     self._setColorModeByVector()
336 jongui 1189
337     # self._isScalarRangeSet checks whether the scalar range has
338     # been specified by the user. If it has, then the scalar range
339     # read from the source will be ignored.
340     if(not(self._isScalarRangeSet())):
341     self._setRange(self.__data_collector._getVectorRange())
342     self._setScalarRange(\
343     self.__data_collector._getVectorRange())
344     else:
345     self._setRange(self._getDataSetMapperRange())
346    
347 jongui 1148 # Color velocity by scalar.
348     elif(self.__color_mode == ColorMode.SCALAR):
349     self._setColorModeByScalar()
350    
351 jongui 1189 # self._isScalarRangeSet checks whether the scalar range has
352     # been specified by the user. If it has, then the scalar range
353     # read from the source will be ignored.
354     if(not(self._isScalarRangeSet())):
355     self._setRange(self.__data_collector._getScalarRange())
356     self._setScalarRange(\
357     self.__data_collector._getScalarRange())
358     else:
359     self._setRange(self._getDataSetMapperRange())
360    
361 jongui 1148 self.__modified = False
362    
363    
364 ksteube 1147 ###############################################################################
365    
366    
367     from clipper import Clipper
368    
369     # NOTE: DataSetMapper, Actor3D, Arrow2D, Arrow3D, Glyph3D, Transform, Plane,
370     # Clipper and MaskPoints were inherited to allow access to
371     # their public methods from the driver.
372     class VelocityOnPlaneClip(DataSetMapper, Actor3D, Arrow2D, Arrow3D,
373     Glyph3D, Transform, Plane, Clipper, MaskPoints):
374     """
375     This class works in a similar way to L{MapOnPlaneClip <map.MapOnPlaneClip>}
376     , except that it shows a vector field using arrows clipped using a plane.
377     """
378    
379     # The SOUTH_WEST default viewport is used when there is only one viewport.
380     # This saves the user from specifying the viewport when there is only one.
381     # If no lut is specified, the color scheme will be used.
382     def __init__(self, scene, data_collector, arrow = Arrow.TWO_D,
383     color_mode = ColorMode.VECTOR, viewport = Viewport.SOUTH_WEST,
384     lut = Lut.COLOR, cell_to_point = False, outline = True):
385     """
386     Initialise the VelocityOnPlaneClip.
387    
388     @attention: The source can either be point or cell data. If the
389     source is cell data, a conversion to point data may or may not be
390     required, in order for the object to be rendered correctly.
391     If a conversion is needed, the 'cell_to_point' flag must be set to
392     'True', otherwise 'False' (which is the default).
393    
394     @type scene: L{Scene <scene.Scene>} object
395     @param scene: Scene in which objects are to be rendered on
396     @type data_collector: L{DataCollector <datacollector.DataCollector>}
397     object
398     @param data_collector: Deal with source of data for visualisation
399     @type arrow: L{Arrow <constant.Arrow>} constant
400     @param arrow: Type of arrow (two dimensional or three dimensional)
401     @type color_mode: L{ColorMode <constant.ColorMode>} constant
402     @param color_mode: Type of color mode
403     @type viewport: L{Viewport <constant.Viewport>} constant
404     @param viewport: Viewport in which objects are to be rendered on
405     @type lut : L{Lut <constant.Lut>} constant
406     @param lut: Lookup table color scheme
407     @type cell_to_point: Boolean
408     @param cell_to_point: Converts cell data to point data (by averaging)
409     @type outline: Boolean
410     @param outline: Places an outline around the domain surface
411     """
412    
413 jongui 1148 self.__data_collector = data_collector
414     self.__arrow = arrow
415     self.__color_mode = color_mode
416     self.__viewport = viewport
417     self.__lut = lut
418     self.__cell_to_point = cell_to_point
419     self.__outline = outline
420    
421     # Keeps track whether VelocityOnPlaneCut has been modified.
422     self.__modified = True
423     Transform.__init__(self)
424     Plane.__init__(self)
425     Clipper.__init__(self)
426     MaskPoints.__init__(self)
427     Glyph3D.__init__(self)
428     DataSetMapper.__init__(self)
429     Actor3D.__init__(self)
430     scene._addVisualizationModules(self)
431 ksteube 1147
432 jongui 1148 # ----- Outline -----
433 ksteube 1147
434 jongui 1148 # NOTE: Changes cannot be made to the Outline's properties from the
435     # driver.
436     if(self.__outline == True):
437     outline = Outline(self.__data_collector._getDataCollectorOutput())
438     mapper = DataSetMapper()
439     mapper._setupDataSetMapper(outline._getOutlineOutput())
440 ksteube 1147
441 jongui 1148 actor3D = Actor3D()
442     actor3D._setupActor3D(mapper._getDataSetMapper())
443 ksteube 1147 # Default outline color is black.
444 jongui 1148 actor3D.setColor(Color.BLACK)
445 ksteube 1147
446     # Default line width is 1.
447 jongui 1148 actor3D._setLineWidth(1)
448 jongui 1158 scene._addActor3D(self.__viewport, actor3D._getActor3D())
449 ksteube 1147
450     # ----- Velocity on a clipped plane -----
451    
452     # NOTE: Lookup table color mapping (color or grey scale) MUST be set
453     # before DataSetMapper. If it is done after DataSetMapper, no effect
454     # will take place.
455 jongui 1148 if(self.__lut == Lut.COLOR): # Colored lookup table.
456 ksteube 1147 lookup_table = LookupTable()
457     lookup_table._setTableValue()
458 jongui 1148 elif(self.__lut == Lut.GREY_SCALE): # Grey scaled lookup table.
459 ksteube 1147 lookup_table = LookupTable()
460     lookup_table._setLookupTableToGreyScale()
461    
462 jongui 1148 self._setupPlane(self._getTransform())
463 ksteube 1147
464 jongui 1148 if(self.__cell_to_point == True): # Converts cell data to point data.
465     c2p = CellDataToPointData(
466     self.__data_collector._getDataCollectorOutput())
467     self._setupMaskPoints(c2p._getCellToPointOutput())
468     elif(self.__cell_to_point == False): # No conversion happens.
469     self._setupMaskPoints(
470     self.__data_collector._getDataCollectorOutput())
471 ksteube 1147
472     # NOTE: Glyph3D must come before Clipper. Otherwise clipping may not
473     # work correctly.
474 jongui 1148 if(self.__arrow == Arrow.TWO_D): # Use 2D arrows.
475 ksteube 1147 Arrow2D.__init__(self)
476 jongui 1148 self._setupGlyph3D(self._getMaskPointsOutput(),
477     self._getArrow2DOutput())
478     elif(self.__arrow == Arrow.THREE_D): # Use 3D arrows.
479 ksteube 1147 Arrow3D.__init__(self)
480 jongui 1148 self._setupGlyph3D(self._getMaskPointsOutput(),
481     self._getArrow3DOutput())
482 ksteube 1147
483 jongui 1148 self._setupClipper(self._getGlyph3DOutput(), self._getPlane())
484     self._setClipFunction()
485 ksteube 1147
486     # NOTE: Clipper must come after Glyph. Otherwise clipping
487     # may not work correctly.
488 jongui 1148 self._setupDataSetMapper(self._getClipperOutput(),
489 ksteube 1147 lookup_table._getLookupTable())
490    
491 jongui 1148 self._setupActor3D(self._getDataSetMapper())
492 jongui 1158 scene._addActor3D(self.__viewport, self._getActor3D())
493 jongui 1148
494     def _isModified(self):
495     """
496     Return whether the VelocityOnPlaneClip or DataCollector has been
497     modified.
498 ksteube 1147
499 jongui 1148 @rtype: Boolean
500     @return: True or False
501     """
502 ksteube 1147
503 jongui 1148 return self.__modified or self.__data_collector._isModified()
504    
505 jongui 1158 def _render(self, scene):
506 jongui 1148 """
507     Render the velocity clip using a plane..
508 jongui 1158
509     @type scene: L{Scene <scene.Scene>} object
510     @param scene: Scene in which objects are to be rendered on
511 jongui 1148 """
512    
513     if (self._isModified() == True):
514     if(self.__data_collector._isVectorSet() == True):
515     self.__data_collector._setActiveVector()
516     # Color velocity by vector.
517     if(self.__color_mode == ColorMode.VECTOR):
518     self._setColorModeByVector()
519 jongui 1189
520     # self._isScalarRangeSet checks whether the scalar range has
521     # been specified by the user. If it has, then the scalar range
522     # read from the source will be ignored.
523     if(not(self._isScalarRangeSet())):
524     self._setRange(self.__data_collector._getVectorRange())
525     self._setScalarRange(\
526     self.__data_collector._getVectorRange())
527     else:
528     self._setRange(self._getDataSetMapperRange())
529    
530 jongui 1148 # Color velocity by scalar.
531     elif(self.__color_mode == ColorMode.SCALAR):
532     self._setColorModeByScalar()
533    
534 jongui 1189 # self._isScalarRangeSet checks whether the scalar range has
535     # been specified by the user. If it has, then the scalar range
536     # read from the source will be ignored.
537     if(not(self._isScalarRangeSet())):
538     self._setRange(self.__data_collector._getScalarRange())
539     self._setScalarRange(\
540     self.__data_collector._getScalarRange())
541     else:
542     self._setRange(self._getDataSetMapperRange())
543    
544 jongui 1148 self.__modified = False
545    
546    

  ViewVC Help
Powered by ViewVC 1.1.26