]> granicus.if.org Git - graphviz/commitdiff
Fix twopi to allow root as a node attribute, and allow multiple usages
authorEmden R. Gansner <erg@alum.mit.edu>
Wed, 1 Oct 2014 16:38:15 +0000 (12:38 -0400)
committerEmden R. Gansner <erg@alum.mit.edu>
Wed, 1 Oct 2014 16:38:15 +0000 (12:38 -0400)
in order to specify the roots of separate components.

doc/info/attrs.html
doc/infosrc/attrs
lib/twopigen/twopiinit.c

index faadeccb387705c10094697725397cb09bc60cbc..215f590ee6be305ad250ed23c9eecdeb5812d1f0 100644 (file)
@@ -1718,7 +1718,7 @@ of the layout programs.
 <DT><A NAME=d:root HREF=#a:root><STRONG>root</STRONG></A>
 <DD>  This specifies nodes to be used as the center of the
   layout and the root of the generated spanning tree. As a graph attribute,
-  this gives the name of the node. As a node attribute (circo only), it
+  this gives the name of the node. As a node attribute, it
   specifies that the node should be used as a central node. In twopi,
   this will actually be the central node. In circo, the block containing
   the node will be central in the drawing of its connected component.
@@ -1727,6 +1727,10 @@ of the layout programs.
   <P>
   If the root attribute is defined as the empty string, twopi will reset it
   to name of the node picked as the root node.
+  <P>
+  For twopi, it is possible to have multiple roots, presumably one for each
+  component. If more than one node in a component is marked as the root, twopi
+  will pick one.
 
 <DT><A NAME=d:rotate HREF=#a:rotate><STRONG>rotate</STRONG></A>
 <DD>  If 90, set drawing orientation to landscape.
index e534a183a6503d3035874ab486ee7f17d1a278a3..9196884f335d3ab4300896ee4c351b621dc28ca2 100644 (file)
@@ -1129,7 +1129,7 @@ This is a synonym for the <A HREF=#d:dpi>dpi</A> attribute.
 :root:GN:string/bool:<none>(graphs)/false(nodes);  twopi,circo
 This specifies nodes to be used as the center of the
 layout and the root of the generated spanning tree. As a graph attribute,
-this gives the name of the node. As a node attribute (circo only), it
+this gives the name of the node. As a node attribute, it
 specifies that the node should be used as a central node. In twopi,
 this will actually be the central node. In circo, the block containing
 the node will be central in the drawing of its connected component.
@@ -1138,6 +1138,10 @@ twopi will pick a most central node, and circo will pick a random node.
 <P>
 If the root attribute is defined as the empty string, twopi will reset it
 to name of the node picked as the root node.
+<P>
+For twopi, it is possible to have multiple roots, presumably one for each
+component. If more than one node in a component is marked as the root, twopi
+will pick one.
 :rotate:G:int:0;
 If 90, set drawing orientation to landscape.
 :rotation:G:double:0;   sfdp
index a5fabeb828452017f686b28cffa445a59e04f227..ff9ea1165f67ffd8b94c562862a69e65183bc847 100644 (file)
@@ -59,6 +59,17 @@ void twopi_init_graph(graph_t * g)
     twopi_init_node_edge(g);
 }
 
+static Agnode_t* findRootNode (Agraph_t* sg, Agsym_t* rootattr)
+{
+    Agnode_t* n;
+
+    for (n = agfstnode(sg); n; n = agnxtnode(sg,n)) {
+       if (mapbool(agxget(n,rootattr))) return n;
+    }
+    return NULL;
+
+}
+
 /* twopi_layout:
  */
 void twopi_layout(Agraph_t * g)
@@ -66,14 +77,15 @@ void twopi_layout(Agraph_t * g)
     Agnode_t *ctr = 0;
     char *s;
     int setRoot = 0;
+    int setLocalRoot = 0;
     pointf sc;
     int doScale = 0;
     int r;
+    Agsym_t* rootattr;
 
     if (agnnodes(g) == 0) return;
 
     twopi_init_graph(g);
-    s = agget(g, "root");
     if ((s = agget(g, "root"))) {
        if (*s) {
            ctr = agfindnode(g, s);
@@ -87,6 +99,9 @@ void twopi_layout(Agraph_t * g)
            setRoot = 1;
        }
     }
+    if ((rootattr = agattr(g, AGNODE, "root", 0))) {
+       setLocalRoot = 1;
+    }
 
     if ((s = agget(g, "scale")) && *s) {
        if ((r = sscanf (s, "%lf,%lf",&sc.x,&sc.y))) {
@@ -102,12 +117,19 @@ void twopi_layout(Agraph_t * g)
        Agnode_t *n;
        int ncc;
        int i;
+       Agnode_t* lctr;
 
        ccs = ccomps(g, &ncc, 0);
        if (ncc == 1) {
-           c = circleLayout(g, ctr);
+           if (ctr)
+               lctr = ctr;
+           else if (!(lctr = findRootNode(g, rootattr)))
+               lctr = 0;
+           c = circleLayout(g, lctr);
            if (setRoot && !ctr)
                ctr = c;
+           if (setLocalRoot && !lctr)
+               agxset (c, rootattr, "1"); 
            n = agfstnode(g);
            free(ND_alg(n));
            ND_alg(n) = NULL;
@@ -121,13 +143,15 @@ void twopi_layout(Agraph_t * g)
            for (i = 0; i < ncc; i++) {
                sg = ccs[i];
                if (ctr && agcontains(sg, ctr))
-                   c = ctr;
-               else
-                   c = 0;
+                   lctr = ctr;
+               else if (!(lctr = findRootNode(sg, rootattr)))
+                   lctr = 0;
                nodeInduce(sg);
-               c = circleLayout(sg, c);
+               c = circleLayout(sg, lctr);
                if (setRoot && !ctr)
                    ctr = c;
+               if (setLocalRoot && (!lctr || (lctr == ctr)))
+                   agxset (c, rootattr, "1"); 
                adjustNodes(sg);
            }
            n = agfstnode(g);