Index: /anuga_core/source/anuga/examples/sww_file_visualiser_example.py
===================================================================
--- /anuga_core/source/anuga/examples/sww_file_visualiser_example.py	(revision 3957)
+++ /anuga_core/source/anuga/examples/sww_file_visualiser_example.py	(revision 3958)
@@ -11,5 +11,5 @@
 
 # The argument to OfflineVisualiser is the path to a sww file
-o = OfflineVisualiser("../../swollen_viewer/tests/cylinders.sww")
+o = OfflineVisualiser("../../anuga_viewer/tests/cylinders.sww")
 #o = OfflineVisualiser("../../../../anuga_validation/analytical solutions/circular_second_order.sww")
 
Index: /anuga_core/source/anuga/examples/visualise_rectangle.py
===================================================================
--- /anuga_core/source/anuga/examples/visualise_rectangle.py	(revision 3957)
+++ /anuga_core/source/anuga/examples/visualise_rectangle.py	(revision 3958)
@@ -33,5 +33,5 @@
         return self.h0 + self.h*((x>self.x0)&(x<self.x1)&(y>self.y0)&(y<self.y1))
 
-M = 10
+M = 20
 points, vertices, boundary = rectangular(M, M, len1 = 1.0, len2 = 1.0)
 
@@ -79,5 +79,5 @@
 R = Reflective_boundary(domain)
 domain.set_boundary( {'left': R, 'right': R, 'bottom': R, 'top': R} )
-domain.set_quantity('stage', Set_Stage(0.2, 0.4, 0.25, 0.75, 1.0, 0.00))
+domain.set_quantity('stage', Set_Stage(0.2, 0.4, 0.25, 0.75, 2.0, 0.00))
 
 #-----------------------------------------------------------------
Index: /anuga_core/source/anuga/visualiser/realtime.py
===================================================================
--- /anuga_core/source/anuga/visualiser/realtime.py	(revision 3957)
+++ /anuga_core/source/anuga/visualiser/realtime.py	(revision 3958)
@@ -45,12 +45,15 @@
     def setup_grid(self):
         self.vtk_cells = vtkCellArray()
+        triangles = self.source.triangles
+        N_tri = self.source.number_of_triangles
+        verticies = self.source.get_vertex_coordinates()
+        N_vert = len(verticies)
         # Also build vert_index - a list of the x & y values of each vertex
-        N_vert = len(self.source.vertex_coordinates)
         self.vert_index = zeros((N_vert,2), Float)
-        for n in range(N_vert):
+        for n in range(N_tri):
             self.vtk_cells.InsertNextCell(3)
             for v in range(3):
-                self.vert_index[self.source.triangles[n][v]] = self.source.vertex_coordinates[n][v*2:v*2+2]
-                self.vtk_cells.InsertCellPoint(self.source.triangles[n][v])
+                self.vert_index[triangles[n][v]] = verticies[n * 3 + v]
+                self.vtk_cells.InsertCellPoint(triangles[n][v])
 
     def update_height_quantity(self, quantityName, dynamic=True):
@@ -118,5 +121,4 @@
 
     def redraw(self):
-        print "Calling redraw"
         if self.running and self.sync_unpaused.isSet():
             self.sync_redrawReady.wait()
Index: /anuga_core/source/anuga/visualiser/visualiser-tvtk.py
===================================================================
--- /anuga_core/source/anuga/visualiser/visualiser-tvtk.py	(revision 3957)
+++ /anuga_core/source/anuga/visualiser/visualiser-tvtk.py	(revision 3958)
@@ -30,8 +30,10 @@
         self.vtk_polyData = {}
 
-        # A function queue to ensure all the visualiser configuration is done in the visualiser thread.
-        # The queue will contain zero or more functions, with the arguments to that function immediately following
-        # as a tuple.
-        self.sync_configFuncs = Queue(-1)
+        # A list of operations to be performed on the cube axes. Type: [(func, (args))]
+        self.conf_axesAlterations = []
+        # A list of all polygons to overlay. Type: [([coords], height, (colour)]
+        self.conf_overlaidPolygons = []
+        # A list of alterations to be performed on the Tk root. Type: [(func, (args))]
+        self.conf_tkAlterations = []
 
     def run(self):
@@ -40,10 +42,18 @@
         self.setup_grid()
 
-        # Normally, empty() is not reliable, however all configuration is done
-        # before the visualiser is started and nothing is added to the queue after that.
-        while not self.sync_configFuncs.empty():
-            func = self.sync_configFuncs.get(True)
-            args = self.sync_configFuncs.get(True)
-            func(*args)
+        # Handle any deferred configuration
+        # Overlaid polygons
+        for args in self.conf_overlaidPolygons:
+            self.overlay_polygon_internal(*args)
+        # Draw (and maybe alter) the axes
+        if self.vtk_drawAxes:
+            self.vtk_axes = vtkCubeAxesActor2D()
+            # Perform all of the alterations required, by applying func to the vtk_axes instance (with the given args).
+            for func, args in self.conf_axesAlterations:
+                func(*((self.vtk_axes,) + args))
+        # Alter the Tk root as necessary.
+        for func, args in self.conf_tkAlterations:
+            func(*((self.tk_root,) + args))
+        # Finished with deferred configuration.
 
         # Draw Height Quantities
@@ -51,11 +61,8 @@
             self.update_height_quantity(q, self.height_dynamic[q])
             self.draw_height_quantity(q)
-
-        if self.vtk_drawAxes is True:
-            self.tk_root.after(1, self.draw_axes)
             
         self.tk_root.mainloop()
 
-    def redraw_quantities(self, dynamic_only=False):
+    def redraw_quantities(self):
         """Redraw all dynamic quantities.
         """
@@ -73,12 +80,5 @@
         """Intstruct the visualiser to render cube axes around the render.
         """
-        self.sync_configFuncs.put(self._render_axes, True)
-        self.sync_configFuncs.put(())
-
-    def _render_axes(self):
-        """Add the axes to the visualiser.
-        """
         self.vtk_drawAxes = True
-        self.vtk_axes = vtkCubeAxesActor2D()
 
     def draw_axes(self):
@@ -90,4 +90,5 @@
             self.vtk_axes.SetCamera(self.vtk_renderer.GetActiveCamera())
             self.vtk_renderer.AddActor(self.vtk_axes)
+            self.vtk_renderer.ResetCamera(self.get_3d_bounds())
         
     def alter_axes(self, func, args):
@@ -100,12 +101,5 @@
         alter_axes(vtkCubeAxesActor2D.SetNumberOfPoints, (5,))
         """
-        self.sync_configFuncs.put(self._alter_axes, True)
-        self.sync_configFuncs.put((func,)+args, True)
-
-    def _alter_axes(self, func, *args):
-        """Apply func, with args *args to the axes actor. This function should be called from
-        within the visualiser thread after the axes have been initialised.
-        """
-        func(*((self.vtk_axes,) + args))
+        self.conf_axesAlterations.append((func, args))
             
     # --- Height Based Rendering --- #
@@ -218,8 +212,7 @@
         colour is the colour of the polygon, as a 3-tuple representing
         r, g, b values between 0 and 1."""
-        self.sync_configFuncs.put(self._overlay_polygon, True)
-        self.sync_configFuncs.put((coords, height, colour), True)
-
-    def _overlay_polygon(self, coords, height, colour):
+        self.conf_overlaidPolygons.append((coords, height, colour))
+
+    def overlay_polygon_internal(self, coords, height, colour):
         """Add a polygon to the output of the visualiser.
 
@@ -276,13 +269,5 @@
         """Apply func, with arguments tuple args to the root tk window for this visualiser.
         """
-        self.sync_configFuncs.put(self._alter_tkroot, True)
-        self.sync_configFuncs.put((func,)+args, True)
-
-    def _alter_tkroot(self, func, *args):
-        """Apply func, with arguments tuple args to the root tk window for this visualiser.
-        This function should only be called from within the visualiser after the tk root window
-        has been created.
-        """
-        func(*((self.tk_root,) + args))
+        self.conf_tkAlterations.append((func, args))
 
     # --- GUI Events --- #
Index: /anuga_core/source/anuga/visualiser/visualiser.py
===================================================================
--- /anuga_core/source/anuga/visualiser/visualiser.py	(revision 3957)
+++ /anuga_core/source/anuga/visualiser/visualiser.py	(revision 3958)
@@ -30,8 +30,10 @@
         self.vtk_polyData = {}
 
-        # A function queue to ensure all the visualiser configuration is done in the visualiser thread.
-        # The queue will contain zero or more functions, with the arguments to that function immediately following
-        # as a tuple.
-        self.sync_configFuncs = Queue(-1)
+        # A list of operations to be performed on the cube axes. Type: [(func, (args))]
+        self.conf_axesAlterations = []
+        # A list of all polygons to overlay. Type: [([coords], height, (colour)]
+        self.conf_overlaidPolygons = []
+        # A list of alterations to be performed on the Tk root. Type: [(func, (args))]
+        self.conf_tkAlterations = []
 
     def run(self):
@@ -40,10 +42,18 @@
         self.setup_grid()
 
-        # Normally, empty() is not reliable, however all configuration is done
-        # before the visualiser is started and nothing is added to the queue after that.
-        while not self.sync_configFuncs.empty():
-            func = self.sync_configFuncs.get(True)
-            args = self.sync_configFuncs.get(True)
-            func(*args)
+        # Handle any deferred configuration
+        # Overlaid polygons
+        for args in self.conf_overlaidPolygons:
+            self.overlay_polygon_internal(*args)
+        # Draw (and maybe alter) the axes
+        if self.vtk_drawAxes:
+            self.vtk_axes = vtkCubeAxesActor2D()
+            # Perform all of the alterations required, by applying func to the vtk_axes instance (with the given args).
+            for func, args in self.conf_axesAlterations:
+                func(*((self.vtk_axes,) + args))
+        # Alter the Tk root as necessary.
+        for func, args in self.conf_tkAlterations:
+            func(*((self.tk_root,) + args))
+        # Finished with deferred configuration.
 
         # Draw Height Quantities
@@ -51,11 +61,8 @@
             self.update_height_quantity(q, self.height_dynamic[q])
             self.draw_height_quantity(q)
-
-        if self.vtk_drawAxes is True:
-            self.tk_root.after(1, self.draw_axes)
             
         self.tk_root.mainloop()
 
-    def redraw_quantities(self, dynamic_only=False):
+    def redraw_quantities(self):
         """Redraw all dynamic quantities.
         """
@@ -73,12 +80,5 @@
         """Intstruct the visualiser to render cube axes around the render.
         """
-        self.sync_configFuncs.put(self._render_axes, True)
-        self.sync_configFuncs.put(())
-
-    def _render_axes(self):
-        """Add the axes to the visualiser.
-        """
         self.vtk_drawAxes = True
-        self.vtk_axes = vtkCubeAxesActor2D()
 
     def draw_axes(self):
@@ -90,4 +90,5 @@
             self.vtk_axes.SetCamera(self.vtk_renderer.GetActiveCamera())
             self.vtk_renderer.AddActor(self.vtk_axes)
+            self.vtk_renderer.ResetCamera(self.get_3d_bounds())
         
     def alter_axes(self, func, args):
@@ -100,12 +101,5 @@
         alter_axes(vtkCubeAxesActor2D.SetNumberOfPoints, (5,))
         """
-        self.sync_configFuncs.put(self._alter_axes, True)
-        self.sync_configFuncs.put((func,)+args, True)
-
-    def _alter_axes(self, func, *args):
-        """Apply func, with args *args to the axes actor. This function should be called from
-        within the visualiser thread after the axes have been initialised.
-        """
-        func(*((self.vtk_axes,) + args))
+        self.conf_axesAlterations.append((func, args))
             
     # --- Height Based Rendering --- #
@@ -218,8 +212,7 @@
         colour is the colour of the polygon, as a 3-tuple representing
         r, g, b values between 0 and 1."""
-        self.sync_configFuncs.put(self._overlay_polygon, True)
-        self.sync_configFuncs.put((coords, height, colour), True)
-
-    def _overlay_polygon(self, coords, height, colour):
+        self.conf_overlaidPolygons.append((coords, height, colour))
+
+    def overlay_polygon_internal(self, coords, height, colour):
         """Add a polygon to the output of the visualiser.
 
@@ -276,13 +269,5 @@
         """Apply func, with arguments tuple args to the root tk window for this visualiser.
         """
-        self.sync_configFuncs.put(self._alter_tkroot, True)
-        self.sync_configFuncs.put((func,)+args, True)
-
-    def _alter_tkroot(self, func, *args):
-        """Apply func, with arguments tuple args to the root tk window for this visualiser.
-        This function should only be called from within the visualiser after the tk root window
-        has been created.
-        """
-        func(*((self.tk_root,) + args))
+        self.conf_tkAlterations.append((func, args))
 
     # --- GUI Events --- #
Index: uga_core/source/anuga/visualiser/vtk_realtime_visualiser.py
===================================================================
--- /anuga_core/source/anuga/visualiser/vtk_realtime_visualiser.py	(revision 3957)
+++ 	(revision )
@@ -1,249 +1,0 @@
-# VTK-Based visualiser
-# intended to replace realtime_visualisation_new.py
-
-import threading
-import Tkinter
-import vtk
-from Numeric import *
-from vtk.tk.vtkTkRenderWidget import vtkTkRenderWidget
-#from vtk_visualiser_ext import make_vtkpoints
-
-class Visualiser(threading.Thread):
-
-    """A VTK-powered visualiser, designed to replace the VPython one.
-    Intended to be run in its own thread.
-
-    Customisation options for the visualiser are as follows:
-
-    setup: Dictionary mapping quantity name -> boolean.
-    if setup[q] is true, draw the quantity when the visualiser starts.
-
-    updating: Dictionary mapping quantity name -> boolean.
-    if updating[q] is true, update the rendering of this quantity each
-    timestep.
-
-    qcolor: Dictionary mapping quantity name -> (float, float, float)
-    if the name of a quantity is found in qcolor, the colour specified (in
-    (r, g, b) from 0.0 to 1.0) is used for display of that quantity instead of
-    (0.5, 0.5, 0.5) (the default)
-
-    scale_z: Dictionary mapping quantity name -> float
-    Override the z scaling of this quantity with the float specified.
-
-    default_scale_z: float
-    multiply all z coordinates by this amount unless an overriding value
-    exists in scale_z.
-    """
-
-    def __init__(self, domain, default_scale_z=1.0, title='Test'):
-        threading.Thread.__init__(self)
-        # Initialise data structures. setup and updating are maps
-        # quantity name -> boolean, setup means to render it,
-        # update means to update with time.
-        # qcolor maps quantity name -> (float, float, float): the colour (r, g, b)
-        self.setup = {}
-        self.updating = {}
-        self.qcolor = {}
-        self.scale_z = {}
-        self.coloring = {}
-        self.default_scale_z = default_scale_z
-        self.domain = domain
-        self.vertices = domain.vertex_coordinates
-        
-        self.idle = threading.Event()
-        self.redraw_ready = threading.Event()
-        self.unpaused = threading.Event()
-        self.unpaused.set()
-
-        # Internal use - storage of vtk objects
-        self.grids = {}
-        self.scalars = {}
-        self.actors = {}
-        self.polydata = {}
-        self.mappers = {}
-
-        self.running = True
-
-        # Default options
-        for x in self.domain.quantities:
-            self.setup[x] = False
-            self.updating[x] = False
-            self.coloring[x] = False
-        self.start()
-            
-    def run(self):
-        self.initialise_gui()
-        self.add_axes()
-        self.setup_all()
-        self.root.after(100, self.idle.set)
-        self.root.mainloop()
-
-    def initialise_gui(self):
-        """Prepare the GUI for the Visualiser, and set up the
-        renderer.
-
-        """
-        # Using the TK VTK widget allows extendability
-        # should a gui need adding.
-        self.root = Tkinter.Tk()
-
-        # Message handling with after
-        self.root.after(100, self.redraw)
-
-        self.renderWidget = vtkTkRenderWidget(self.root, width=400, height=400)
-        self.renderWidget.pack(expand='true', fill='both')
-        self.renderWindow = self.renderWidget.GetRenderWindow()
-        self.renderer = vtk.vtkRenderer()
-        self.renderWindow.AddRenderer(self.renderer)
-
-        self.quitButton = Tkinter.Button(self.root, text='Quit', command=self.shutdown)
-        self.quitButton.pack(side=Tkinter.BOTTOM)
-
-        self.pauseButton = Tkinter.Button(self.root, text='Pause', command=self.unpaused.clear)
-        self.pauseButton.pack(side=Tkinter.LEFT)
-
-        self.resumeButton = Tkinter.Button(self.root, text='Resume', command=self.unpaused.set)
-        self.resumeButton.pack(side=Tkinter.LEFT)
-        
-        #self.w2if = vtk.vtkWindowToImageFilter()
-        #self.w2if.SetInput(self.renderWindow)
-        
-        #self.pnmWr = vtk.vtkPNMWriter() 
-        #self.pnmWr.SetInput(self.w2if.GetOutput())
-
-
-    def add_axes(self):
-        """Add axes to this Visualiser - TODO
-        """
-        pass
-
-    def setup_all(self):
-        """Draw in the data that is specified by setup or update
-        """
-
-        self.N_tri = len(self.domain.triangles)
-        self.N_vert = len(self.vertices)
-        self.cells = vtk.vtkCellArray()
-        self.vertices = self.domain.get_vertex_coordinates()
-        self.vert_index = zeros((self.N_vert,2), Float)
-        for n in range(self.N_vert):
-            for i in range(3):
-                self.vert_index[self.domain.triangles[n][i]] = self.vertices[n][i*2:i*2+2]
-
-        # Prepare the list of cells
-        for t in self.domain.triangles:
-            self.cells.InsertNextCell(3)
-            for i in range(3):
-                self.cells.InsertCellPoint(t[i])
-
-        # Set up the rendering of each quantity
-        for q in self.domain.quantities:
-            if self.setup[q] | self.updating[q]:
-                self.draw_quantity(q)
-
-    def draw_quantity(self, q):
-        if self.scale_z.has_key(q):
-            scale = self.scale_z[q]
-        else:
-            scale = self.default_scale_z
-            
-        if q == 'elevation':
-            shift = 0.001
-        else:
-            shift = 0.0
-            
-        #############################################################
-        # Disabled the make_vtkpoints call because the extension is
-        # difficult to get to link under windows
-        #############################################################
-        #self.grids[q] = make_vtkpoints(self.N_tri,
-        #                           self.N_vert,
-        #                           scale,
-        #                           self.domain.quantities[q].vertex_values,
-        #                           self.vert_index,
-        #                           self.domain.triangles)
-        #grid = self.grids[q]
-        #############################################################
-
-        qty_index = zeros(self.N_vert, Float)
-        for n in range(self.N_tri):
-            for v in range(3):
-                qty_index[self.domain.triangles[n][v]] = self.domain.quantities[q].vertex_values[n][v]
-
-        self.grids[q] = vtk.vtkPoints()
-        self.scalars[q] = vtk.vtkFloatArray()
-        grid = self.grids[q]
-        scalars = self.scalars[q]
-
-        for v in range(self.N_vert):
-            grid.InsertNextPoint(self.vert_index[v][0],
-                                 self.vert_index[v][1],
-                                 shift + qty_index[v] * scale)
-            scalars.InsertNextValue(qty_index[v]);
-
-        # Can't recycle vtkPolyData objects: Apparently they behave
-        # unusually if the points (i.e. vertex data) is set after
-        # the polys (i.e. triangle data)
-        self.polydata[q] = vtk.vtkPolyData()
-        polydata = self.polydata[q]
-
-        polydata.SetPoints(grid)
-        if self.coloring[q]:
-            polydata.GetPointData().SetScalars(scalars);
-        polydata.SetPolys(self.cells)
-
-        if self.mappers.has_key(q):
-            mapper = self.mappers[q]
-            mapper.SetInput(polydata)
-            mapper.SetScalarRange(0.0,0.5)
-            mapper.Update()
-        else:
-            self.mappers[q] = vtk.vtkPolyDataMapper()
-            mapper = self.mappers[q]
-            mapper.SetInput(polydata)
-
-        if not self.actors.has_key(q):
-            self.actors[q] = vtk.vtkActor()
-            actor = self.actors[q]
-            actor.SetMapper(mapper)
-
-            if self.qcolor.has_key(q):
-                actor.GetProperty().SetColor(self.qcolor[q])
-            else:
-                actor.GetProperty().SetColor(0.5, 0.5, 0.5)
-
-            self.renderer.AddActor(actor)
-
-    def redraw(self):
-        if self.redraw_ready.isSet():
-            self.redraw_ready.wait()
-            self.redraw_ready.clear()
-            for q in self.domain.quantities:
-                if self.updating[q]:
-                    self.draw_quantity(q)
-
-            self.renderWindow.Render()
-             
-            self.root.update_idletasks()
-            self.idle.set()
-        self.root.after(100, self.redraw)     
-    
-    def shutdown(self):
-        """Shutdown the visualiser
-        """
-        self.running = False
-        self.idle.set()
-        self.unpaused.set()
-        self.root.withdraw()
-        self.root.quit()
-
-    def update(self):
-        """Update the visualiser's display.
-        Clients are expected to call this in their evolve() loop,
-        to keep the visualiser in sync with the simulation.
-        """
-        if self.running:
-            self.redraw_ready.set()
-            self.idle.wait()
-            self.idle.clear()
-            self.unpaused.wait()
Index: /anuga_core/source/obsolete_code/visualisation/vtk_realtime_visualiser.py
===================================================================
--- /anuga_core/source/obsolete_code/visualisation/vtk_realtime_visualiser.py	(revision 3958)
+++ /anuga_core/source/obsolete_code/visualisation/vtk_realtime_visualiser.py	(revision 3958)
@@ -0,0 +1,249 @@
+# VTK-Based visualiser
+# intended to replace realtime_visualisation_new.py
+
+import threading
+import Tkinter
+import vtk
+from Numeric import *
+from vtk.tk.vtkTkRenderWidget import vtkTkRenderWidget
+#from vtk_visualiser_ext import make_vtkpoints
+
+class Visualiser(threading.Thread):
+
+    """A VTK-powered visualiser, designed to replace the VPython one.
+    Intended to be run in its own thread.
+
+    Customisation options for the visualiser are as follows:
+
+    setup: Dictionary mapping quantity name -> boolean.
+    if setup[q] is true, draw the quantity when the visualiser starts.
+
+    updating: Dictionary mapping quantity name -> boolean.
+    if updating[q] is true, update the rendering of this quantity each
+    timestep.
+
+    qcolor: Dictionary mapping quantity name -> (float, float, float)
+    if the name of a quantity is found in qcolor, the colour specified (in
+    (r, g, b) from 0.0 to 1.0) is used for display of that quantity instead of
+    (0.5, 0.5, 0.5) (the default)
+
+    scale_z: Dictionary mapping quantity name -> float
+    Override the z scaling of this quantity with the float specified.
+
+    default_scale_z: float
+    multiply all z coordinates by this amount unless an overriding value
+    exists in scale_z.
+    """
+
+    def __init__(self, domain, default_scale_z=1.0, title='Test'):
+        threading.Thread.__init__(self)
+        # Initialise data structures. setup and updating are maps
+        # quantity name -> boolean, setup means to render it,
+        # update means to update with time.
+        # qcolor maps quantity name -> (float, float, float): the colour (r, g, b)
+        self.setup = {}
+        self.updating = {}
+        self.qcolor = {}
+        self.scale_z = {}
+        self.coloring = {}
+        self.default_scale_z = default_scale_z
+        self.domain = domain
+        self.vertices = domain.vertex_coordinates
+        
+        self.idle = threading.Event()
+        self.redraw_ready = threading.Event()
+        self.unpaused = threading.Event()
+        self.unpaused.set()
+
+        # Internal use - storage of vtk objects
+        self.grids = {}
+        self.scalars = {}
+        self.actors = {}
+        self.polydata = {}
+        self.mappers = {}
+
+        self.running = True
+
+        # Default options
+        for x in self.domain.quantities:
+            self.setup[x] = False
+            self.updating[x] = False
+            self.coloring[x] = False
+        self.start()
+            
+    def run(self):
+        self.initialise_gui()
+        self.add_axes()
+        self.setup_all()
+        self.root.after(100, self.idle.set)
+        self.root.mainloop()
+
+    def initialise_gui(self):
+        """Prepare the GUI for the Visualiser, and set up the
+        renderer.
+
+        """
+        # Using the TK VTK widget allows extendability
+        # should a gui need adding.
+        self.root = Tkinter.Tk()
+
+        # Message handling with after
+        self.root.after(100, self.redraw)
+
+        self.renderWidget = vtkTkRenderWidget(self.root, width=400, height=400)
+        self.renderWidget.pack(expand='true', fill='both')
+        self.renderWindow = self.renderWidget.GetRenderWindow()
+        self.renderer = vtk.vtkRenderer()
+        self.renderWindow.AddRenderer(self.renderer)
+
+        self.quitButton = Tkinter.Button(self.root, text='Quit', command=self.shutdown)
+        self.quitButton.pack(side=Tkinter.BOTTOM)
+
+        self.pauseButton = Tkinter.Button(self.root, text='Pause', command=self.unpaused.clear)
+        self.pauseButton.pack(side=Tkinter.LEFT)
+
+        self.resumeButton = Tkinter.Button(self.root, text='Resume', command=self.unpaused.set)
+        self.resumeButton.pack(side=Tkinter.LEFT)
+        
+        #self.w2if = vtk.vtkWindowToImageFilter()
+        #self.w2if.SetInput(self.renderWindow)
+        
+        #self.pnmWr = vtk.vtkPNMWriter() 
+        #self.pnmWr.SetInput(self.w2if.GetOutput())
+
+
+    def add_axes(self):
+        """Add axes to this Visualiser - TODO
+        """
+        pass
+
+    def setup_all(self):
+        """Draw in the data that is specified by setup or update
+        """
+
+        self.N_tri = len(self.domain.triangles)
+        self.N_vert = len(self.vertices)
+        self.cells = vtk.vtkCellArray()
+        self.vertices = self.domain.get_vertex_coordinates()
+        self.vert_index = zeros((self.N_vert,2), Float)
+        for n in range(self.N_vert):
+            for i in range(3):
+                self.vert_index[self.domain.triangles[n][i]] = self.vertices[n][i*2:i*2+2]
+
+        # Prepare the list of cells
+        for t in self.domain.triangles:
+            self.cells.InsertNextCell(3)
+            for i in range(3):
+                self.cells.InsertCellPoint(t[i])
+
+        # Set up the rendering of each quantity
+        for q in self.domain.quantities:
+            if self.setup[q] | self.updating[q]:
+                self.draw_quantity(q)
+
+    def draw_quantity(self, q):
+        if self.scale_z.has_key(q):
+            scale = self.scale_z[q]
+        else:
+            scale = self.default_scale_z
+            
+        if q == 'elevation':
+            shift = 0.001
+        else:
+            shift = 0.0
+            
+        #############################################################
+        # Disabled the make_vtkpoints call because the extension is
+        # difficult to get to link under windows
+        #############################################################
+        #self.grids[q] = make_vtkpoints(self.N_tri,
+        #                           self.N_vert,
+        #                           scale,
+        #                           self.domain.quantities[q].vertex_values,
+        #                           self.vert_index,
+        #                           self.domain.triangles)
+        #grid = self.grids[q]
+        #############################################################
+
+        qty_index = zeros(self.N_vert, Float)
+        for n in range(self.N_tri):
+            for v in range(3):
+                qty_index[self.domain.triangles[n][v]] = self.domain.quantities[q].vertex_values[n][v]
+
+        self.grids[q] = vtk.vtkPoints()
+        self.scalars[q] = vtk.vtkFloatArray()
+        grid = self.grids[q]
+        scalars = self.scalars[q]
+
+        for v in range(self.N_vert):
+            grid.InsertNextPoint(self.vert_index[v][0],
+                                 self.vert_index[v][1],
+                                 shift + qty_index[v] * scale)
+            scalars.InsertNextValue(qty_index[v]);
+
+        # Can't recycle vtkPolyData objects: Apparently they behave
+        # unusually if the points (i.e. vertex data) is set after
+        # the polys (i.e. triangle data)
+        self.polydata[q] = vtk.vtkPolyData()
+        polydata = self.polydata[q]
+
+        polydata.SetPoints(grid)
+        if self.coloring[q]:
+            polydata.GetPointData().SetScalars(scalars);
+        polydata.SetPolys(self.cells)
+
+        if self.mappers.has_key(q):
+            mapper = self.mappers[q]
+            mapper.SetInput(polydata)
+            mapper.SetScalarRange(0.0,0.5)
+            mapper.Update()
+        else:
+            self.mappers[q] = vtk.vtkPolyDataMapper()
+            mapper = self.mappers[q]
+            mapper.SetInput(polydata)
+
+        if not self.actors.has_key(q):
+            self.actors[q] = vtk.vtkActor()
+            actor = self.actors[q]
+            actor.SetMapper(mapper)
+
+            if self.qcolor.has_key(q):
+                actor.GetProperty().SetColor(self.qcolor[q])
+            else:
+                actor.GetProperty().SetColor(0.5, 0.5, 0.5)
+
+            self.renderer.AddActor(actor)
+
+    def redraw(self):
+        if self.redraw_ready.isSet():
+            self.redraw_ready.wait()
+            self.redraw_ready.clear()
+            for q in self.domain.quantities:
+                if self.updating[q]:
+                    self.draw_quantity(q)
+
+            self.renderWindow.Render()
+             
+            self.root.update_idletasks()
+            self.idle.set()
+        self.root.after(100, self.redraw)     
+    
+    def shutdown(self):
+        """Shutdown the visualiser
+        """
+        self.running = False
+        self.idle.set()
+        self.unpaused.set()
+        self.root.withdraw()
+        self.root.quit()
+
+    def update(self):
+        """Update the visualiser's display.
+        Clients are expected to call this in their evolve() loop,
+        to keep the visualiser in sync with the simulation.
+        """
+        if self.running:
+            self.redraw_ready.set()
+            self.idle.wait()
+            self.idle.clear()
+            self.unpaused.wait()
