Example #1
0
    def run(self):
        with SDHistoryUtils.UndoGroup("Auto-Format Layout"):
            selected_nodes = uiMgr.getCurrentGraphSelection()
            hierarchy = NodesHierarchy(ctx, selected_nodes)
            vertexes = [Vertex(data) for data in range(len(hierarchy.nodes))]
            nodesConnections = hierarchy.getEdges()
            edges = [Edge(vertexes[vertex], vertexes[w]) for (vertex, w) in nodesConnections]
            graph = SubstanceGraph(vertexes, edges)

            for vertex in vertexes:
                vertex.view = VertexView(hierarchy.nodes[vertex.data])
            # For each separate graph
            for subGraph in range(len(graph.C)):
                center = graph.getSubgraphCenter(subGraph)

                sug = SugiyamaLayout(graph.C[subGraph])
                # Vertexes without input edges
                roots = list(filter(lambda x: len(x.e_in()) == 0, graph.C[subGraph].sV))
                sug.init_all(roots=roots)
                sug.draw()

                newCenter = graph.getSubgraphCenter(subGraph)
                if len(selected_nodes) == 1:
                    # Offset everything to save the selected node initial position
                    rootPosition = hierarchy.nodes[roots[0].data].getPosition()
                    # Have to compensate the final root node offset
                    offset = float2(rootPosition[1] - roots[0].view.xy[0], -rootPosition[0] - roots[0].view.xy[1])
                else:
                    offset = float2(center[0] - newCenter[0], center[1] - newCenter[1])

                for i, vertex in enumerate(graph.C[subGraph].sV):
                    vertex.view.node.setPosition(float2(-vertex.view.xy[1] - offset[1], vertex.view.xy[0] + offset[0]))
Example #2
0
def test_001_Sugiyama(sample_G02):
    gr = graph_core(*sample_G02)
    for v in gr.V():
        v.view = VertexViewer(10, 10)
    sug = SugiyamaLayout(gr)
    sug.init_all(roots=[gr.sV[0]], inverted_edges=[])
    for _ in sug.draw_step():
        for v, x in sug.grx.items():
            print(x, v.view.xy)
Example #3
0
 def initView(self):
     cfg = self.func.cfg
     vertexs = {}
     done = set()
     for block in cfg.blocks:
         if block in done:
             continue
         done.add(block)
         startLockey = block.loc_key
         endLockey = block.loc_key
         blocks = [block]
         while (block.lines[-1].name == 'CALL') and (len(cfg.predecessors(block.get_next())) == 1):
             nextLockey = block.get_next()
             if block.loc_key in cfg.successors(nextLockey):
                 break
             block = cfg.loc_key_to_block(nextLockey)
             blocks.append(block)
             endLockey = block.loc_key
             done.add(block)
         vertex = Vertex(startLockey)
         vertexs[startLockey] = vertex
         vertex.view = AsmBlockView(startLockey, endLockey, blocks, self.func)
     edges = []
     for src in vertexs.values():
         successLocKeys = cfg.successors(src.view.endLockey)
         for key in successLocKeys:
             vSrc = vertexs[src.view.lockey]
             vDst = vertexs[key]
             edge = Edge(vSrc, vDst)
             edge.view = BasicEdge(vDst)
             edges.append(edge)
             vSrc.view.outBlocks.append(vDst.view)
             vDst.view.inBlocks.append(vSrc.view)
     self.graph = Graph(vertexs.values(), edges)
     sugLayout = SugiyamaLayout(self.graph.C[0])
     sugLayout.route_edge = route_with_lines
     sugLayout.init_all()
     sugLayout.draw()
     for v in vertexs.values():
         self.addBlock(v.view, v.view.xy[0] - (v.view.w / 2), v.view.xy[1] - (v.view.h / 2))
         v.view.gotoAddress.connect(self.selectAddress)
     for e in edges:
         srcView = e.v[0].view
         srcBlock = e.v[0].data
         dstBlock = e.v[1].data
         if len(srcView.outBlocks) == 1:
             color = Qt.darkBlue
         elif dstBlock == cfg.successors(srcBlock)[0]:
             color = Qt.darkRed
         else:
             color = Qt.darkGreen
         edge_view = e.view
         edge_view.color = color
         self.scene.addItem(edge_view)
Example #4
0
def draw_graph(G, simple=False, pause=False):
    print("...drawing graph...")

    if simple:
        poses = simple_sugi.pos(G)
    else:
        g = grutils.convert_nextworkx_graph_to_grandalf(G)
        from grandalf.layouts import SugiyamaLayout

        class DefaultView(object):
            w, h = 10, 10

        for v in g.V():
            v.view = DefaultView()
        sug = SugiyamaLayout(g.C[0])
        sug.init_all()  # roots=[V[0]]) #, inverted_edges=[V[4].e_to(V[0])])
        sug.draw()
        poses = {v.data: (-v.view.xy[0], -v.view.xy[1]) for v in g.C[0].sV}

    node_colors = nx.get_node_attributes(G, 'color')
    if node_colors:
        nx.draw(G,
                pos=poses,
                with_labels=True,
                node_color=node_colors.values())
    else:
        global colors
        try:
            node_colors = {node: colors[node.o_id] for node in G.nodes}
            nx.draw(G,
                    pos=poses,
                    with_labels=True,
                    node_color=node_colors.values())
        except AttributeError:
            warnings.warn("Node didn't have color?")
            nx.draw(G, pos=poses, with_labels=True)

    # x.draw_networkx_edges(G, pos=poses)

    if pause:
        plt.show()
    else:
        # plt.pause(0.01) pauses for 0.01s, and runs plt's GUI main loop
        plt.pause(0.01)
        fixins._is_plot_active = True
Example #5
0
    def __init__(self, vertexes, edges):
        #
        # Just a reminder about naming conventions:
        # +------------X
        # |
        # |
        # |
        # |
        # Y
        #

        V = {v: Vertex(" {} ".format(v)) for v in vertexes}
        # NOTE: reverting edges to correctly orientate the graph
        E = [Edge(V[e], V[s]) for s, e in edges]
        V = V.values()
        g = Graph(V, E)

        class VertexViewer(object):
            h = 3  # top and bottom box edges + text

            def __init__(self, name):
                self.w = len(name) + 2  # right and left bottom edges + text

        for v in V:
            v.view = VertexViewer(v.data)

        # NOTE: determine min box length to create the best layout
        minw = min([v.view.w for v in V])

        for e in E:
            e.view = EdgeViewer()

        sug = SugiyamaLayout(g.C[0])
        gr = g.C[0]
        r = list(filter(lambda x: len(x.e_in()) == 0, gr.sV))

        sug.init_all(roots=r, optimize=True)

        sug.yspace = VertexViewer.h
        sug.xspace = minw
        sug.route_edge = route_with_lines

        sug.draw()

        self.sug = sug
Example #6
0
def sugiyama_layout(g):
    """
    Position nodes using Sugiyama algorithm.
    Returns dictionary of positions keyed by node.

    :param g: NetworkX graph. A position will be assigned to every node in G.

    :type g: networkx.classes.digraph.DiGraph
    :return: dict
    """

    # verteces (for grandalf lib)
    vertices = {node: Vertex(node) for node in g.nodes}
    # edges (for grandalf lib)
    edges = [
        Edge(vertices[v_from], vertices[v_to]) for v_from, v_to in g.edges
    ]
    # build graph
    for v_name in vertices:
        vertices[v_name].view = _DefaultView()
    g = Graph(vertices.values(), edges)

    sug = SugiyamaLayout(g.C[0])
    sug.init_all(optimize=True)
    sug.draw()

    pos_names = []
    pos_xs = []
    pos_ys = []
    for v in g.C[0].sV:
        pos_names.append(v.data)
        pos_xs.append(v.view.xy[0])
        pos_ys.append(v.view.xy[1])

    scaler = MinMaxScaler()
    scaled_x = scaler.fit_transform(np.array(pos_xs).reshape(-1, 1))[:, 0]
    scaled_y = scaler.fit_transform(np.array(pos_ys).reshape(-1, 1))[:, 0]

    pos = {
        pos_names[i]: np.array([scaled_x[i], scaled_y[i]])
        for i in range(len(pos_names))
    }
    return pos
Example #7
0
def _build_sugiyama_layout(vertexes: Union[List, Dict, ValuesView],
                           edges: List) -> SugiyamaLayout:
    #
    # Just a reminder about naming conventions:
    # +------------X
    # |
    # |
    # |
    # |
    # Y
    #

    vertexes = {v: Vertex(f" {v} ") for v in vertexes}
    # NOTE: reverting edges to correctly orientate the graph
    edges = [Edge(vertexes[e], vertexes[s]) for s, e in edges]
    vertexes = vertexes.values()
    graph = Graph(vertexes, edges)

    for vertex in vertexes:
        vertex.view = VertexViewer(vertex.data)

    # NOTE: determine min box length to create the best layout
    minw = min(v.view.w for v in vertexes)

    for edge in edges:
        edge.view = EdgeViewer()

    sug = SugiyamaLayout(graph.C[0])
    graph = graph.C[0]
    roots = list(filter(lambda x: len(x.e_in()) == 0, graph.sV))

    sug.init_all(roots=roots, optimize=True)

    sug.yspace = VertexViewer.HEIGHT
    sug.xspace = minw
    sug.route_edge = route_with_lines

    sug.draw()

    return sug
Example #8
0
def test_sugiyama_ranking():
    gr, data_to_vertex = create_scenario()
    sug = SugiyamaLayout(gr)
    sug.route_edge = route_with_rounded_corners
    sug.init_all()
    # rank 0: v4      v0
    #          \     / |
    # rank 1:   \   v1 |
    #            \ /   |
    # rank 2:    v5   /
    #             \  /
    # rank 3:     v2
    #             |
    # rank 4:     v3
    rank_to_data = _compute_rank_to_data(sug)
    assert rank_to_data == {
        0: ['v4', 'v0'],
        1: ['v1'],
        2: ['v5'],
        3: ['v2'],
        4: ['v3'],
    }
    sug.draw(N=10)
Example #9
0
 def initView(self):
     vertexs = {}
     for lockey, block in self.ircfg.blocks.items():
         vertexs[lockey] = Vertex(block)
         vertexs[lockey].view = IRBlockView(lockey, block, False)
     edges = []
     for src in vertexs:
         successLocKeys = self.ircfg.successors(src)
         for key in successLocKeys:
             if key in vertexs:
                 vSrc = vertexs[src]
                 vDst = vertexs[key]
                 edge = Edge(vSrc, vDst)
                 edge.view = BasicEdge(vDst)
                 edges.append(edge)
                 vSrc.view.outBlocks.append(vDst.view)
                 vDst.view.inBlocks.append(vSrc.view)
     self.graph = Graph(vertexs.values(), edges)
     sugLayout = SugiyamaLayout(self.graph.C[0])
     sugLayout.route_edge = route_with_lines
     sugLayout.init_all()
     sugLayout.draw()
     for v in vertexs.values():
         self.addBlock(v.view, v.view.xy[0] - (v.view.w / 2), v.view.xy[1] - (v.view.h / 2))
     for e in edges:
         srcView = e.v[0].view
         srcBlock = e.v[0].data
         dstBlock = e.v[1].data
         if len(srcView.outBlocks) == 1:
             color = Qt.darkBlue
         elif dstBlock.loc_key == self.ircfg.successors(srcBlock.loc_key)[0]:
             color = Qt.darkRed
         else:
             color = Qt.darkGreen
         edge_view = e.view
         edge_view.color = color
         self.scene.addItem(edge_view)
Example #10
0
    for row in reader:
        G.add_edge(row[0], row[1])

g = grandalf.utils.convert_nextworkx_graph_to_grandalf(
    G)  # undocumented function


class defaultview(object):
    w, h = 10, 10


for v in g.C[0].sV:
    v.view = defaultview()

sug = SugiyamaLayout(g.C[0])
sug.init_all()  # roots=[V[0]])
sug.draw(
)  # This is a bit of a misnomer, as grandalf doesn't actually come with any visualization methods. This method instead calculates positions

poses = {v.data: (v.view.xy[0], v.view.xy[1])
         for v in g.C[0].sV}  # Extracts the positions

nodesWithPosition = list(poses.values())
nodesWithPosition.sort(key=lambda x: x[1], reverse=True)

counter = -1
distance = 30
previousY = nodesWithPosition[0][1]
offsetedNodes = []
for node in nodesWithPosition:
    currentY = node[1]
Example #11
0
def _layout_graph_sugiyama(graph):
    """
    Arrange the graph automatically using grandalf package
    """

    from grandalf.graphs import Graph, Vertex, Edge
    from grandalf.layouts import SugiyamaLayout

    # Build the viez class for grandalf vertices
    class View(object):
        def __init__(self, w, h):
            self.w = w
            self.h = h
            self.xy = (0, 0)

    # Build the grandalf graph
    ggraph = Graph()

    # Vertices
    vertices_by_id = {}

    all_nodes_by_id = {n.id: n for n in graph.all_nodes()}

    # Get average width for distance between nodes
    avg_width = 0
    avg_height = 0

    for n in all_nodes_by_id.values():
        v = Vertex(n.id)
        if NODE_LAYOUT_DIRECTION == NODE_LAYOUT_HORIZONTAL:
            view = View(n.view.height, n.view.width)
        else:
            view = View(n.view.width, n.view.height)

        avg_width += n.view.width
        avg_height += n.view.height
        v.view = view

        vertices_by_id[n.id] = v

    avg_width /= len(all_nodes_by_id)
    avg_height /= len(all_nodes_by_id)

    for v in vertices_by_id.values():
        ggraph.add_vertex(v)

    # Edges
    inverted_edges = []

    looked_up_nodes = set([])

    for n in all_nodes_by_id.values():

        for cns in n.connected_output_nodes().values():

            for cn in cns:

                e = Edge(vertices_by_id[n.id], vertices_by_id[cn.id])

                if cn.id in looked_up_nodes:
                    inverted_edges.append(e)
                else:
                    looked_up_nodes.add(cn.id)

                ggraph.add_edge(e)

    # Build the layout
    sug = SugiyamaLayout(ggraph.C[0])
    sug.yspace = avg_width if NODE_LAYOUT_DIRECTION == NODE_LAYOUT_HORIZONTAL else avg_height
    sug.xspace = avg_height if NODE_LAYOUT_DIRECTION == NODE_LAYOUT_HORIZONTAL else avg_width
    print(inverted_edges)
    # sug.init_all(inverted_edges=inverted_edges or None)
    sug.init_all()

    sug.draw(10)

    for v in ggraph.C[0].sV:
        node = all_nodes_by_id[v.data]

        if NODE_LAYOUT_DIRECTION == NODE_LAYOUT_HORIZONTAL:
            node.set_pos(*reversed(v.view.xy))
        else:
            node.set_pos(*v.view.xy)
Example #12
0
(71.38960484928593,200),
(67.53662520941695,200),
(49.73541984499222,200),
]
for i,v in enumerate(V):
	v.view = defaultview()
	v.view.w, v.view.h = sizeList[i]

packSpace = 4
sug = SugiyamaLayout(g.C[0])
#sug.init_all(roots=[V[0]],inverted_edges=[V[4].e_to(V[0])])
sug.xspace = packSpace
sug.yspace = packSpace
#sug.order_iter = 32
sug.dirvh = 3
sug.init_all()
sug.draw()

# pos:0 (0.0,100.0)
# pos:1 (-62.14111896447103,304.0)
# pos:2 (2.867435005484097,304.0)
# pos:3 (-79.36272225037119,304.0)
# pos:4 (-378.7738580569366,508.0)
# pos:5 (-309.1942538205011,508.0)
# pos:6 (-247.25828385704486,508.0)
# pos:7 (-190.04345576434469,508.0)
# pos:8 (-138.28357561291625,508.0)
# pos:9 (-78.42501252755235,508.0)
# pos:10 (-15.966297766115446,508.0)
# pos:11 (31.318011263602294,508.0)
# pos:12 (-63.59926743717183,712.0)
Example #13
0
    def get_json(self, params, id):
        persons = PersonSet()
        persons.add_folks(int(id), Relationship.ANCESTORS)
        persons.add_folks(int(id), Relationship.DESCENDANTS)
        persons.fetch_p2e(
            event_types=(models.Event_Type.PK_birth,
                         models.Event_Type.PK_marriage))

        decujus = persons.get_from_id(int(id))

        # Recreate the birth events, we need child, father and mother to build
        # the links. Likewise for marriage events.

        births = collections.defaultdict(BirthEvent)
        marriages = collections.defaultdict(MarriageEvent)

        for a in persons.asserts:
            if isinstance(a, models.P2E) and not a.disproved:
                if a.event.type_id == models.Event_Type.PK_birth:
                    if a.role_id == models.Event_Type_Role.PK_principal:
                        births[a.event.id].set_child(a.person_id)
                    elif a.role_id == models.Event_Type_Role.PK_birth__father:
                        births[a.event.id].add_father(a.person_id)
                    elif a.role_id == models.Event_Type_Role.PK_birth__mother:
                        births[a.event.id].add_mother(a.person_id)

                elif a.event.type_id == models.Event_Type.PK_marriage:
                    if a.role_id == models.Event_Type_Role.PK_principal:
                        marriages[a.event.id].add_spouse(a.person_id)

        # Organize persons into layers, based on child->parent relationships
        nodes = {main_id: Vertex(person)
                 for main_id, person in persons.persons.items()}
        edges = [Edge(nodes[b.child], nodes[p])
                 for b in births.values()
                 for p in itertools.chain(b.fathers, b.mothers)
                 if b.child]
        g = Graph(list(nodes.values()), edges)

        for n in nodes.values():
            n.view = NodeLayout()

        perlayer = collections.defaultdict(list)  # main_id for each layer
        person_to_layer = {}   # main_id => layer

        for core in g.C:
            sug = SugiyamaLayout(core)
            sug.init_all(optimize=True)
            sug.draw()

            for layerIndex, layer in enumerate(sug.layers):
                for node in layer:
                    # ignore dummy vertices
                    if hasattr(node, "data"):
                        perlayer[layerIndex].append(node.data.main_id)
                        person_to_layer[node.data.main_id] = layerIndex

        # Build the list of families. Each family is described as a list
        #   [parent1, parent2, child1, child2,...]
        children = collections.defaultdict(list)
        for b in births.values():
            if b.child:
                for f in (b.fathers or [None]):
                    for m in (b.mothers or [None]):
                        if f is not None or m is not None:
                            children[(f, m)].append(b.child)

        couples = set(children.keys())
        for event in marriages.values():
            for idx, p1 in enumerate(event.spouses):
                for p2 in event.spouses[idx + 1:]:
                    couples.add((p1, p2))

        families_by_layer = collections.defaultdict(list)
        for c in couples:
            family = list(a for a in c) + children[c]
            layer = min(person_to_layer[p] for p in family if p is not None)

            # If there are no children:
            if len(family) <= 2:
                layer -= 1

            families_by_layer[layer].append(family)

        flatten_families = [
            families_by_layer[layerIndex]
            for layerIndex, layer in enumerate(sug.layers)]

        return {
            "persons": persons.persons,
            "perlayer": [perlayer[a]for a in sorted(perlayer)],
            "families": flatten_families,
            "decujus_name": decujus.display_name,
            "decujus": decujus.main_id}
Example #14
0
    def json(self, subset=None):
        """
        Return a json structure that can be sent to the GUI.

        :param set[PersonaNode] subset: which persons to take into account
        """

        def __build_families():
            """
            Return a list of families found in the subset of self.
            :rtype list[list[id]]:  [parent1,parent2,child1.child2,...]
            """

            tmp = {}  # indexed on (father, mother)
            for n in self:
                if not subset or n in subset:
                    father = mother = None

                    for e in self.in_edges(n):
                        if e.kind == P2P_Link.KIND_FATHER:
                            father = e[0]
                        elif e.kind == P2P_Link.KIND_MOTHER:
                            mother = e[0]
                        elif e.kind == P2P_Link.KIND_SPOUSE:
                            n2 = e[0].main_id
                            if not subset or n2 in subset:
                                tmp.setdefault((n2, n.main_id), [n2, n.main_id])
                        else:
                            raise Exception("Unknown edge in graph: %s" % e.kind)

                    # Filter events irrelevant to our subset of the graph
                    if subset:
                        if father and father not in subset:
                            logger.debug('Cancel father')
                            father = None
                        if mother and mother not in subset:
                            logger.debug('Cancel mother')
                            mother = None

                    if father:
                        father = father.main_id
                    if mother:
                        mother = mother.main_id

                    if father or mother:
                        t = tmp.setdefault((father, mother), [father, mother])
                        if n:
                            t.append(n.main_id)

            return list(tmp.values())

        # Prepare a temporary graph: it is used to subset the list of nodes
        # to those specified in argument, and the list of edges to the
        # parent/child relationships

        tmp = Digraph()
        for e in self.edges():
            if e.kind in (P2P_Link.KIND_MOTHER, P2P_Link.KIND_FATHER) and \
               (subset is None or (
                  (e[0] in subset) and \
                  (e[1] in subset))):

                tmp.add_edge(e)

        families = __build_families()
        logger.debug('%s families' % (len(families), ))

        # Using an external library for layout

        subset2 = [n.main_id for n in subset] if subset else None
        Vmap = {v.main_id: Vertex(v)
                for v in self
                if subset2 is None or not v.ids.isdisjoint(subset2)}
        V = [v for v in Vmap.values()]
        E = [Edge(Vmap[e[0].main_id], Vmap[e[1].main_id])
             for e in self.edges()
             if e.kind in (P2P_Link.KIND_MOTHER, P2P_Link.KIND_FATHER) and \
                (e[0].main_id in Vmap) and
                (e[1].main_id in Vmap)
            ]
        g = Graph(V, E)

        # for v in V:
        #     logger.info('%s [label="%s"];' % (v.data.main_id, v.data.name))
        # for e in E:
        #     logger.info('%s -> %s;' % (e.v[0].data.main_id, e.v[1].data.main_id))

        class defaultview(object):
            w = 10
            h = 10
        for v in V:
            v.view = defaultview()

        persons = {}
        perlayer = []
        persons_to_layer = {}

        logger.debug('%s components in graph' % (len(g.C), ))

        for core in g.C:
           sug = SugiyamaLayout(core)
           sug.init_all(optimize=True, cons=False)
           sug.draw()
           sug.layers.reverse()

           for layerIndex, layer in enumerate(sug.layers):
               if layerIndex not in perlayer:
                   perlayer.extend([[]] * (layerIndex + 1 - len(perlayer)))

               for node in layer:
                   # ignore dummy vertices
                   if hasattr(node, "data"):
                       persons[node.data.main_id] = {
                           "id": node.data.main_id,
                           "name": node.data.name,
                           "sex": node.data.sex,
                       }
                       perlayer[layerIndex].append(node.data.main_id)

               for node in layer:
                   if hasattr(node, "data"):
                       persons_to_layer[node.data.main_id] = layerIndex

        families_by_layer = {}
        for f in families:
            l = min(persons_to_layer[id] for id in f if id is not None)
            # If there are no children
            if len(f) <= 2:
                l -= 1
            families_by_layer.setdefault(l, []).append(f)

        flatten_families = [
            families_by_layer.get(layerIndex, [])
            for layerIndex, layer in enumerate(sug.layers)
        ]

        return {
            "perlayer": perlayer,
            "persons": persons,
            "families": flatten_families
        }
Example #15
0
	def updateLayeredLayoutWithComp(self): 
		class Vtx(object):
			def __init__(self, name, idx, radius = 1, height = 1):
				self.inNodes = set()
				self.outNodes = set()
				self.name = name
				self.idx = idx
				self.comp = None
				self.compIdx = None
				self.pos = None
				self.radius = radius
				self.fontHeight = height
				self.height = max(radius, height)
				self.firstKey = 0.0
				self.secondKey = 0.0
				self.thirdKey = 0.0

			def getLayoutHeight(self):
				return self.height + self.radius

			def setLayoutPos(self,x,y):
				self.pos = (x, y-0.5*(self.height - self.radius))

			def getMinX(self):
				return self.pos[0] - self.radius

			def getMaxX(self):
				return self.pos[0] + self.radius

			def getMinY(self):
				return self.pos[1] - self.radius

			def getMaxY(self):
				return self.pos[1] + self.height

			def getPos(self):
				return self.pos

		if len(self.scene.itemDict) == 0:
			return
		vtxName2Id = {}
		vtxList = []
		edgeList = []
		for name, item in self.scene.itemDict.items():
			ithVtx = len(vtxList)
			v = Vtx(name, ithVtx, item.getRadius(), item.getHeight())
			v.dispName = item.name
			vtxList.append(v)
			vtxName2Id[name] = ithVtx

		for edgeKey, edge in self.scene.edgeDict.items():
			v1 = vtxName2Id[edgeKey[0]]
			v2 = vtxName2Id[edgeKey[1]]
			vtxList[v1].outNodes.add(v2)
			vtxList[v2].inNodes.add(v1)
			edgeList.append((v1,v2))

		# 构造连通分量
		remainSet = set([i for i in range(len(vtxList))])
		compList = []   # [[idx1,idx2,...],[...]]
		while len(remainSet) > 0:
			# 找出剩余一个顶点并加入队列
			ids = [list(remainSet)[0]]
			ithComp = len(compList)
			vtxList[ids[0]].comp = ithComp
			compMap = []
			# 遍历一个连通分量
			while len(ids) > 0:
				newIds = []
				for id in ids:
					# 把一个顶点加入连通分量
					vtx = vtxList[id]
					vtx.compIdx = len(compMap)
					compMap.append(id)
					# 把周围未遍历顶点加入队列
					for inId in vtx.inNodes:
						inVtx = vtxList[inId]
						if inVtx.comp is None:
							inVtx.comp = ithComp
							newIds.append(inId)
					for outId in vtx.outNodes:
						outVtx = vtxList[outId]
						if outVtx.comp is None:
							outVtx.comp = ithComp
							newIds.append(outId)
					remainSet.discard(id)
				ids = newIds

			# 增加一个连通分量
			compList.append(compMap)

		from grandalf.graphs import Vertex, Edge, Graph
		class VtxView(object):
			def __init__(self, w, h):
				self.w = w
				self.h = h

		# 构造每个连通分量的图结构
		offset = (0,0)
		bboxMin = [1e6,1e6]
		bboxMax = [-1e6,-1e6]
		self.scene.boxTest = []
		for ithComp, compMap in enumerate(compList):
			minPnt = [1e6,1e6]
			maxPnt = [-1e6,-1e6]

			# 构造图数据并布局
			V = []
			for oldId in compMap:
				w = vtxList[oldId].getLayoutHeight()
				vtx = Vertex(oldId)
				height = 200
				vtx.view = VtxView(w, height)
				V.append(vtx)

			E = []
			for edgeKey in edgeList:
				if vtxList[edgeKey[0]].comp == ithComp:
					E.append(Edge(V[vtxList[edgeKey[0]].compIdx], V[vtxList[edgeKey[1]].compIdx]))

			g = Graph(V,E)
			from grandalf.layouts import SugiyamaLayout
			packSpace = 4
			sug = SugiyamaLayout(g.C[0])
			sug.xspace = packSpace
			sug.yspace = packSpace
			#sug.order_iter = 32
			sug.dirvh = 3
			sug.init_all()
			sug.draw(10)

			# 统计包围盒
			for v in g.C[0].sV:
				oldV = vtxList[v.data]
				x= v.view.xy[1]
				y= v.view.xy[0]
				oldV.setLayoutPos(x,y)

				minPnt[0] = min(minPnt[0],oldV.getMinX())
				minPnt[1] = min(minPnt[1],oldV.getMinY())
				maxPnt[0] = max(maxPnt[0],oldV.getMaxX())
				maxPnt[1] = max(maxPnt[1],oldV.getMaxY())

			for v in g.C[0].sV:
				oldV = vtxList[v.data]
				posInComp = oldV.getPos()
				newPos = (posInComp[0], posInComp[1]-minPnt[1]+offset[1])
				self.scene.itemDict[oldV.name].setTargetPos(QtCore.QPointF(newPos[0], newPos[1]))
				bboxMin[0] = min(bboxMin[0], newPos[0])
				bboxMin[1] = min(bboxMin[1], newPos[1])
				bboxMax[0] = max(bboxMax[0], newPos[0])
				bboxMax[1] = max(bboxMax[1], newPos[1])

			offset = (offset[0], offset[1]+maxPnt[1]-minPnt[1]+packSpace)

		# 设置四个角的item
		cornerList = self.scene.cornerItem
		mar = 2000
		cornerList[0].setPos(bboxMin[0]-mar, bboxMin[1]-mar)
		cornerList[1].setPos(bboxMin[0]-mar, bboxMax[1]+mar)
		cornerList[2].setPos(bboxMax[0]+mar, bboxMin[1]-mar)
		cornerList[3].setPos(bboxMax[0]+mar, bboxMax[1]+mar)

		# 更新标志数据
		self.itemSet = set(self.scene.itemDict.keys())
		self.edgeNum = len(self.scene.edgeDict)
Example #16
0
 def create_sug_layout(self, graph):
     sug = SugiyamaLayout(graph.C[0])
     sug.route_edge = route_with_splines
     sug.init_all(optimize=True)
     sug.draw(10)
     return sug
Example #17
0
    def _layout_nodes_and_edges(self, start):
        """
        Compute coordinates for all CFG nodes and edges in the view

        :param int start: The starting address
        :return: a mapping between nodes' names and their coordinates (dict), and a list of edge coordinates (list)
        :rtype: tuple
        """

        coordinates = {}
        node_map = {}

        # Create the map
        for child in self.children():
            if not isinstance(child, QtContainer):
                continue
            node_map[child.declaration.addr] = child

        if start not in node_map:
            return { }

        vertices = {}
        edges = [ ]
        # Create all edges
        for s, d in self.declaration.edges:
            src, dst = int(s), int(d)
            if src in vertices:
                src_v = vertices[src]
            else:
                src_v = Vertex(src)
                vertices[src] = src_v

            if dst in vertices:
                dst_v = vertices[dst]
            else:
                dst_v = Vertex(dst)
                vertices[dst] = dst_v

            edge = Edge(src_v, dst_v)
            edge.view = EdgeViewer()
            edges.append(edge)

        # Create all vertices
        for child in self.children():
            addr = child.declaration.addr
            if addr not in vertices:
                vertices[addr] = Vertex(addr)

        g = Graph(vertices.values(), edges)

        # create a view for each node
        for addr, vertex in vertices.iteritems():
            node = node_map[addr]
            width, height = node._layout_manager.best_size()
            vertex.view = VertexViewer(width, height)

        sug = SugiyamaLayout(g.C[0])
        sug.route_edge = self._route_edges
        sug.init_all(roots=[vertices[start]])
        sug.draw()

        # extract coordinates for nodes
        for addr, vertex in vertices.iteritems():
            x, y = vertex.view.xy
            # Convert the center coordinate to left corner coordinate
            coordinates[addr] = (x - vertex.view.w / 2, y - vertex.view.h / 2)

        # extract coordinates for edges
        edge_coordinates = [ ]
        for edge in edges:
            if hasattr(edge.view, '_pts'):
                edge_coordinates.append(edge.view._pts)

        return coordinates, edge_coordinates
Example #18
0
    (71.38960484928593, 200),
    (67.53662520941695, 200),
    (49.73541984499222, 200),
]
for i, v in enumerate(V):
    v.view = defaultview()
    v.view.w, v.view.h = sizeList[i]

packSpace = 4
sug = SugiyamaLayout(g.C[0])
#sug.init_all(roots=[V[0]],inverted_edges=[V[4].e_to(V[0])])
sug.xspace = packSpace
sug.yspace = packSpace
#sug.order_iter = 32
sug.dirvh = 3
sug.init_all()
sug.draw()

# pos:0 (0.0,100.0)
# pos:1 (-62.14111896447103,304.0)
# pos:2 (2.867435005484097,304.0)
# pos:3 (-79.36272225037119,304.0)
# pos:4 (-378.7738580569366,508.0)
# pos:5 (-309.1942538205011,508.0)
# pos:6 (-247.25828385704486,508.0)
# pos:7 (-190.04345576434469,508.0)
# pos:8 (-138.28357561291625,508.0)
# pos:9 (-78.42501252755235,508.0)
# pos:10 (-15.966297766115446,508.0)
# pos:11 (31.318011263602294,508.0)
# pos:12 (-63.59926743717183,712.0)
Example #19
0
	def updateLayeredLayoutWithComp(self): 
		class Vtx(object):
			def __init__(self, name, idx, radius = 1, height = 1):
				self.inNodes = set()
				self.outNodes = set()
				self.name = name
				self.idx = idx
				self.comp = None
				self.compIdx = None
				self.pos = None
				self.radius = radius
				self.fontHeight = height
				self.height = max(radius, height)
				self.firstKey = 0.0
				self.secondKey = 0.0
				self.thirdKey = 0.0

			def getLayoutHeight(self):
				return self.height + self.radius

			def setLayoutPos(self,x,y):
				self.pos = (x, y-0.5*(self.height - self.radius))

			def getMinX(self):
				return self.pos[0] - self.radius

			def getMaxX(self):
				return self.pos[0] + self.radius

			def getMinY(self):
				return self.pos[1] - self.radius

			def getMaxY(self):
				return self.pos[1] + self.height

			def getPos(self):
				return self.pos

		if len(self.scene.itemDict) == 0:
			return
		vtxName2Id = {}
		vtxList = []
		edgeList = []
		for name, item in self.scene.itemDict.items():
			ithVtx = len(vtxList)
			v = Vtx(name, ithVtx, item.getRadius(), item.getHeight())
			v.dispName = item.name
			vtxList.append(v)
			vtxName2Id[name] = ithVtx

		for edgeKey, edge in self.scene.edgeDict.items():
			v1 = vtxName2Id[edgeKey[0]]
			v2 = vtxName2Id[edgeKey[1]]
			vtxList[v1].outNodes.add(v2)
			vtxList[v2].inNodes.add(v1)
			edgeList.append((v1,v2))

		# 构造连通分量
		remainSet = set([i for i in range(len(vtxList))])
		compList = []   # [[idx1,idx2,...],[...]]
		while len(remainSet) > 0:
			# 找出剩余一个顶点并加入队列
			ids = [list(remainSet)[0]]
			ithComp = len(compList)
			vtxList[ids[0]].comp = ithComp
			compMap = []
			# 遍历一个连通分量
			while len(ids) > 0:
				newIds = []
				for id in ids:
					# 把一个顶点加入连通分量
					vtx = vtxList[id]
					vtx.compIdx = len(compMap)
					compMap.append(id)
					# 把周围未遍历顶点加入队列
					for inId in vtx.inNodes:
						inVtx = vtxList[inId]
						if inVtx.comp is None:
							inVtx.comp = ithComp
							newIds.append(inId)
					for outId in vtx.outNodes:
						outVtx = vtxList[outId]
						if outVtx.comp is None:
							outVtx.comp = ithComp
							newIds.append(outId)
					remainSet.discard(id)
				ids = newIds

			# 增加一个连通分量
			compList.append(compMap)

		from grandalf.graphs import Vertex, Edge, Graph
		class VtxView(object):
			def __init__(self, w, h):
				self.w = w
				self.h = h

		# 构造每个连通分量的图结构
		offset = (0,0)
		bboxMin = [1e6,1e6]
		bboxMax = [-1e6,-1e6]
		self.scene.boxTest = []
		for ithComp, compMap in enumerate(compList):
			minPnt = [1e6,1e6]
			maxPnt = [-1e6,-1e6]

			# 构造图数据并布局
			V = []
			for oldId in compMap:
				w = vtxList[oldId].getLayoutHeight()
				vtx = Vertex(oldId)
				height = 200
				vtx.view = VtxView(w, height)
				V.append(vtx)

			E = []
			for edgeKey in edgeList:
				if vtxList[edgeKey[0]].comp == ithComp:
					E.append(Edge(V[vtxList[edgeKey[0]].compIdx], V[vtxList[edgeKey[1]].compIdx]))

			g = Graph(V,E)
			from grandalf.layouts import SugiyamaLayout
			packSpace = 4
			sug = SugiyamaLayout(g.C[0])
			sug.xspace = packSpace
			sug.yspace = packSpace
			#sug.order_iter = 32
			sug.dirvh = 3
			sug.init_all()
			sug.draw(10)

			# 统计包围盒
			for v in g.C[0].sV:
				oldV = vtxList[v.data]
				x= v.view.xy[1]
				y= v.view.xy[0]
				oldV.setLayoutPos(x,y)

				minPnt[0] = min(minPnt[0],oldV.getMinX())
				minPnt[1] = min(minPnt[1],oldV.getMinY())
				maxPnt[0] = max(maxPnt[0],oldV.getMaxX())
				maxPnt[1] = max(maxPnt[1],oldV.getMaxY())

			for v in g.C[0].sV:
				oldV = vtxList[v.data]
				posInComp = oldV.getPos()
				newPos = (posInComp[0], posInComp[1]-minPnt[1]+offset[1])
				self.scene.itemDict[oldV.name].setTargetPos(QtCore.QPointF(newPos[0], newPos[1]))
				bboxMin[0] = min(bboxMin[0], newPos[0])
				bboxMin[1] = min(bboxMin[1], newPos[1])
				bboxMax[0] = max(bboxMax[0], newPos[0])
				bboxMax[1] = max(bboxMax[1], newPos[1])

			offset = (offset[0], offset[1]+maxPnt[1]-minPnt[1]+packSpace)

		# 设置四个角的item
		cornerList = self.scene.cornerItem
		mar = 2000
		cornerList[0].setPos(bboxMin[0]-mar, bboxMin[1]-mar)
		cornerList[1].setPos(bboxMin[0]-mar, bboxMax[1]+mar)
		cornerList[2].setPos(bboxMax[0]+mar, bboxMin[1]-mar)
		cornerList[3].setPos(bboxMax[0]+mar, bboxMax[1]+mar)

		# 更新标志数据
		self.itemSet = set(self.scene.itemDict.keys())
		self.edgeNum = len(self.scene.edgeDict)