Animated graphs / wxPython

Philip Swartzleonard starx at pacbell.net
Sun Feb 10 00:06:29 CET 2002


Duncan Smith || Sat 09 Feb 2002 11:04:01a:

> I need to frequently redraw a graph (ie. nodes and edges) to a wxPython
> panel.  ie. I remove and/or add edges to the graph and then redraw it. 
> I am currently using wxPython ellipses and lines for drawing the nodes
> and edges. The problems are the speed of redrawing and the flickering
> as the window is redrawn.  SetClippingRegion() doesn't help a great
> deal as the clipping region is usually nearly as large as the full
> graph.  I am currently using a workaround whereby I draw edges in the
> background colour in order to remove them.  But after a number of
> redraws the graph starts to get noticeably whited out by drawing over
> existing nodes and edges. 
> 
> Does anyone know of a better approach?  Ideally I would like to be able
> to simply remove and add edges and send them to the back of the nodes
> rather than redrawing the relevant nodes each time I add an edge.  I
> have looked at a number of packages, but none seem to be able to do
> what I want. Essentially I want an animated graph that will show a user
> what the graph algorithms are up to.  (Gato won't do the job.)  Thanks
> in advance. 

Well, if you want to solve the flickering you either need to use double 
buffering or draw really, really, really fast. I'd suggest the former. I 
don't really know any other options, but you could use basic 2d opengl with 
pyopengl and pyopenglcontext's wxcontext... or something like that.

Actually, i felt like thinking a little bit, so i worked this out. This is 
a rough draft of a class that would do what you want -- just alter it's 
points and hit it's draw() for every update. You'd just have to set a 
background color (optionally) and point the 'camera' where you want it 
once, and that's about it-- just call this with an initilized GL setup 
available. Note that i haven't tested this at all, but if you want to go 
this way it should get you started :).

(Also, it's probably overkill, but it's the only graphics system i'm very 
familiar with, and it can do this job :)

class graph_rep(object):
    def __init__( self, initial_points, nodesize=.25 ):
        self.points = initial_points
        self.nodelist = self.gennode( nodesize )

    def __del__( self ):
        glDeleteLists( self.nodelist, 1 )


    def gennode( self, nodesize ):
        # Generate a simple hexagon
        glNewList( listnum, GL_COMPILE )
        glBegin( GL_POLYGON )
        
        for deg in range( 0, 360, 60 ):
            rads = math.pi * (deg/180.0)
            glVertex2d( nodesize * math.cos(rads),
                        nodesize * math.sin(rads) )

        glEnd
        glEndList()

        return listnum

    def draw( self, mode ):

        # So we don't do this for every mouseover, etc
        if mode == 1:
            glBegin( GL_LINESTRIP )
            glColor3d( 0,0,0 ) #black
            for point in self.points:
                glVertex2d( point.x, point.y )
            glEnd()

            glColor3d( 1,0,0 ) #red
            for point in self.points:
                glPushMatrix()
                glTranslated( point.x, point.y, 0 )
                glCallList( self.nodelist )
                glPopMatrix()
                
        myapp.3display.triggerRedraw()
        # or a swap-buffer command and GLUTpostRedisplay, or whatever
        # it is that you need to do to update the screen. This could
        # easily be done in whatever calls the draw function, too.
    	


-- 
Philip Sw "Starweaver" [rasx] :: www.rubydragon.com



More information about the Python-list mailing list