From: Emden R. Gansner Date: Wed, 1 Oct 2014 16:38:15 +0000 (-0400) Subject: Fix twopi to allow root as a node attribute, and allow multiple usages X-Git-Tag: TRAVIS_CI_BUILD_EXPERIMENTAL~157 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=3c9ce30f37b15b2b72214b7bc901582b0fd40b04;p=graphviz Fix twopi to allow root as a node attribute, and allow multiple usages in order to specify the roots of separate components. --- diff --git a/doc/info/attrs.html b/doc/info/attrs.html index faadeccb3..215f590ee 100644 --- a/doc/info/attrs.html +++ b/doc/info/attrs.html @@ -1718,7 +1718,7 @@ of the layout programs.
root
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.

If the root attribute is defined as the empty string, twopi will reset it to name of the node picked as the root node. +

+ 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
If 90, set drawing orientation to landscape. diff --git a/doc/infosrc/attrs b/doc/infosrc/attrs index e534a183a..9196884f3 100644 --- a/doc/infosrc/attrs +++ b/doc/infosrc/attrs @@ -1129,7 +1129,7 @@ This is a synonym for the dpi attribute. :root:GN:string/bool:(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.

If the root attribute is defined as the empty string, twopi will reset it to name of the node picked as the root node. +

+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 diff --git a/lib/twopigen/twopiinit.c b/lib/twopigen/twopiinit.c index a5fabeb82..ff9ea1165 100644 --- a/lib/twopigen/twopiinit.c +++ b/lib/twopigen/twopiinit.c @@ -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);