Ejemplo n.º 1
0
if __name__ == '__main__':

    from graph import *
    from layout_spring import GraphLayoutSpring
    #from overlap_removal import OverlapRemoval

    g = Graph()

    n1 = GraphNode('A', 0, 0, 200, 200)
    n2 = GraphNode('B', 0, 0, 200, 200)
    g.AddEdge(n1, n2)
    """
    Spring force layout
    """

    layouter = GraphLayoutSpring(g)

    def dump():
        for node in g.nodes:
            print node, "layout info:", (node.layoutPosX, node.layoutPosY)

    print "layout pass 1"
    layouter.layout()
    dump()

    print "layout pass 2"
    layouter.layout()
    dump()
    """
    Rendering
    
Ejemplo n.º 2
0
    def LayoutMultipleChooseBest(self, numlayouts=3):
        """
        Blackboard
        Rerun layout several times, remembering each as a memento.  Then pick the best.

        Don't remember starting scale since we are going to change it anyway
        We could add mementos for a layout at the current scale - in which case
        
        Coordinate scaling runs 3.2 to max within ScaleUpMadly()
        Finish at the best scale as chosen by this algorithm
        """
        self.umlwin.AllToLayoutCoords()    # doesn't matter what scale the layout starts with
        layouter = GraphLayoutSpring(self.graph, gui=self)
        self.umlwin.snapshot_mgr.Clear()
        oriscale = self.umlwin.coordmapper.scale

        def ThinkAndAddSnapshot(res):
            num_line_line_crossings, num_node_node_overlaps, num_line_node_crossings = res

            # Calculate a layout score, lower the better?  Not used yet.
            score = 0
            bounds = self.graph.GetBounds()
            
            self.umlwin.snapshot_mgr.AddSnapshot(\
                layout_score=score,
                LL=num_line_line_crossings,
                NN=num_node_node_overlaps,
                LN=num_line_node_crossings,
                scale=self.umlwin.coordmapper.scale,
                bounds=bounds,
                bounds_area_simple=bounds[0]*bounds[1]/10000,
                graph_memento=self.graph.GetMementoOfPositions())

        # Generate several totally fresh layout variations
        for i in range(numlayouts):
            
            progress_val = i+1 # range is 1..n inclusive whereas for loop is 0..n-1 excluding n, so adjust by adding 1 for visual progress
            if not self.outer_thread.CheckContinue(statusmsg="Layout #%d of %d" % (progress_val, numlayouts), progress=progress_val):
                break
            
            # Do a layout
            self.outer_thread.Log("spring layout started")
            layouter.layout(keep_current_positions=False)
            self.outer_thread.Log("layout done")

            if not self.outer_thread.CheckContinue(logmsg="GetVitalStats"): break

            # Expand directly to the original scale, and calc vitals stats
            res = self.GetVitalStats(scale=oriscale, animate=False)
            ThinkAndAddSnapshot(res)
            
            if res[0] == 0 and res[2] <= 0:     # LL crossings solved and LN reasonable, so optimise and break - save time
                self.outer_thread.Log("LL crossings solved and LN reasonable, so optimise and break - save time")
                break

            if not self.outer_thread.CheckContinue(logmsg="ScaleUpMadly"): break

            # Expand progressively from small to large scale, and calc vitals stats
            # This can be SLOW
            res = self.ScaleUpMadly(strategy=":reduce post overlap removal LN crossings", animate=ANIMATE_BLACKBOARD_ATTEMPTS)
            ThinkAndAddSnapshot(res)
                
            if res[0] == 0 and res[2] <= 0:     # LL crossings solved and LN reasonable, so optimise and break - save time
                break
        
        #self.umlwin.snapshot_mgr.DumpSnapshots(label='Unsorted')
            
        """
        blackboard now sorting smarter because I have converted snapshots to
        dictionary format and thus can control which elements to sort by and
        whether to maximise or minimise any particular key in that snapshot
        dictionary.
        """
        def sortfunc(d):
            # this does the thinking!
          return (d['LL'], d['LN'], d['bounds_area_simple'], -d['scale'], d['NN_pre_OR'])        

        #self.umlwin.snapshot_mgr.Sort()
        self.umlwin.snapshot_mgr.Sort(sortfunc)  # this does the thinking!
        #self.umlwin.snapshot_mgr.Sort(lambda d: (d['scale'], -d['LL'], -d['LN']))   # pick biggest with most line crossings! - Ha ha          

        """Diagnostic"""        
        #self.umlwin.snapshot_mgr.DumpSnapshots('Sorted')
        
        """
        can't do the snapshot restore
            self.umlwin.snapshot_mgr.Restore(0)
        here since it will call stateofthenation(), and that is wx gui activity
        which is not allowed from inside a thread.
        So send a special message to trigger that call.
        """
        self.outer_thread.Cmd("snapshot_mgr_restore_0")
Ejemplo n.º 3
0
    def LayoutMultipleChooseBest(self, numlayouts=3):
        """
        Blackboard
        Rerun layout several times, remembering each as a memento.  Then pick the best.

        Don't remember starting scale since we are going to change it anyway
        We could add mementos for a layout at the current scale - in which case
        
        Coordinate scaling runs 3.2 to max within ScaleUpMadly()
        Finish at the best scale as chosen by this algorithm
        """
        self.umlwin.AllToLayoutCoords()    # doesn't matter what scale the layout starts with
        layouter = GraphLayoutSpring(self.graph, gui=self)
        self.umlwin.snapshot_mgr.Clear()
        oriscale = self.umlwin.coordmapper.scale

        def ThinkAndAddSnapshot(res):
            num_line_line_crossings, num_node_node_overlaps, num_line_node_crossings = res

            # Calculate a layout score, lower the better?  Not used yet.
            score = 0
            bounds = self.graph.GetBounds()
            
            self.umlwin.snapshot_mgr.AddSnapshot(\
                layout_score=score,
                LL=num_line_line_crossings,
                NN=num_node_node_overlaps,
                LN=num_line_node_crossings,
                scale=self.umlwin.coordmapper.scale,
                bounds=bounds,
                bounds_area_simple=bounds[0]*bounds[1]/10000,
                graph_memento=self.graph.GetMementoOfPositions())

        # Generate several totally fresh layout variations
        for i in range(numlayouts):
            
            progress_val = i+1 # range is 1..n inclusive whereas for loop is 0..n-1 excluding n, so adjust by adding 1 for visual progress
            if not self.outer_thread.CheckContinue(statusmsg="Layout #%d of %d" % (progress_val, numlayouts), progress=progress_val):
                break
            
            # Do a layout
            self.outer_thread.Log("spring layout started")
            layouter.layout(keep_current_positions=False)
            self.outer_thread.Log("layout done")

            if not self.outer_thread.CheckContinue(logmsg="GetVitalStats"): break

            # Expand directly to the original scale, and calc vitals stats
            res = self.GetVitalStats(scale=oriscale, animate=False)
            ThinkAndAddSnapshot(res)
            
            if res[0] == 0 and res[2] <= 0:     # LL crossings solved and LN reasonable, so optimise and break - save time
                self.outer_thread.Log("LL crossings solved and LN reasonable, so optimise and break - save time")
                break

            if not self.outer_thread.CheckContinue(logmsg="ScaleUpMadly"): break

            # Expand progressively from small to large scale, and calc vitals stats
            # This can be SLOW
            res = self.ScaleUpMadly(strategy=":reduce post overlap removal LN crossings", animate=ANIMATE_BLACKBOARD_ATTEMPTS)
            ThinkAndAddSnapshot(res)
                
            if res[0] == 0 and res[2] <= 0:     # LL crossings solved and LN reasonable, so optimise and break - save time
                break
        
        #self.umlwin.snapshot_mgr.DumpSnapshots(label='Unsorted')
            
        """
        blackboard now sorting smarter because I have converted snapshots to
        dictionary format and thus can control which elements to sort by and
        whether to maximise or minimise any particular key in that snapshot
        dictionary.
        """
        def sortfunc(d):
            # this does the thinking!
          return (d['LL'], d['LN'], d['bounds_area_simple'], -d['scale'], d['NN_pre_OR'])        

        #self.umlwin.snapshot_mgr.Sort()
        self.umlwin.snapshot_mgr.Sort(sortfunc)  # this does the thinking!
        #self.umlwin.snapshot_mgr.Sort(lambda d: (d['scale'], -d['LL'], -d['LN']))   # pick biggest with most line crossings! - Ha ha          

        """Diagnostic"""        
        #self.umlwin.snapshot_mgr.DumpSnapshots('Sorted')
        
        """
        can't do the snapshot restore
            self.umlwin.snapshot_mgr.Restore(0)
        here since it will call stateofthenation(), and that is wx gui activity
        which is not allowed from inside a thread.
        So send a special message to trigger that call.
        """
        self.outer_thread.Cmd("snapshot_mgr_restore_0")