Graphviz 2.29.20120208.0545
lib/circogen/circular.c
Go to the documentation of this file.
00001 /* $Id$ $Revision$ */
00002 /* vim:set shiftwidth=4 ts=8: */
00003 
00004 /*************************************************************************
00005  * Copyright (c) 2011 AT&T Intellectual Property 
00006  * All rights reserved. This program and the accompanying materials
00007  * are made available under the terms of the Eclipse Public License v1.0
00008  * which accompanies this distribution, and is available at
00009  * http://www.eclipse.org/legal/epl-v10.html
00010  *
00011  * Contributors: See CVS logs. Details at http://www.graphviz.org/
00012  *************************************************************************/
00013 
00014 
00015 #include    "circular.h"
00016 #include    "blocktree.h"
00017 #include    "circpos.h"
00018 #include        <string.h>
00019 
00020 #define         MINDIST                 1.0
00021 
00022 /* initGraphAttrs:
00023  * Set attributes based on original root graph.
00024  * This is obtained by taking a node of g, finding its node
00025  * in the original graph, and finding that node's graph.
00026  */
00027 static void initGraphAttrs(Agraph_t * g, circ_state * state)
00028 {
00029     static Agraph_t *rootg;
00030     static attrsym_t *N_artpos;
00031     static attrsym_t *N_root;
00032     static double min_dist;
00033     static char *rootname;
00034     Agraph_t *rg;
00035     attrsym_t *G_mindist;
00036     node_t *n = agfstnode(g);
00037 
00038     rg = agraphof(ORIGN(n));
00039     if (rg != rootg) {          /* new root graph */
00040         state->blockCount = 0;
00041         rootg = rg;
00042 #ifndef WITH_CGRAPH
00043         G_mindist = agfindattr(rootg, "mindist");
00044 #else /* WITH_CGRAPH */
00045         G_mindist = agattr(rootg,AGRAPH, "mindist", NULL);
00046 #endif /* WITH_CGRAPH */
00047         min_dist = late_double(rootg, G_mindist, MINDIST, 0.0);
00048 #ifndef WITH_CGRAPH
00049         N_artpos = agfindattr(rootg->proto->n, "articulation_pos");
00050         N_root = agfindattr(rootg->proto->n, "root");
00051 #else /* WITH_CGRAPH */
00052         N_artpos = agattr(rootg,AGNODE, "articulation_pos", NULL);
00053         N_root = agattr(rootg,AGNODE, "root", NULL);
00054 #endif /* WITH_CGRAPH */
00055         rootname = agget(rootg, "root");
00056     }
00057     initBlocklist(&state->bl);
00058     state->orderCount = 1;
00059     state->min_dist = min_dist;
00060     state->N_artpos = N_artpos;
00061     state->N_root = N_root;
00062     state->rootname = rootname;
00063 }
00064 
00065 /* cleanup:
00066  * We need to cleanup objects created in initGraphAttrs
00067  * and all blocks. All graph objects are components of the
00068  * initial derived graph and will be freed when it is closed. 
00069  */
00070 static void cleanup(block_t * root, circ_state * sp)
00071 {
00072     freeBlocktree(root);
00073 }
00074 
00075 /* circularLayout:
00076  * Do circular layout of g.
00077  * Assume g is strict.
00078  * g is a "connected" component of the derived graph of the
00079  * original graph.
00080  * We make state static so that it keeps a record of block numbers used
00081  * in a graph; it gets reset when a new root graph is used.
00082  */
00083 void circularLayout(Agraph_t * g)
00084 {
00085     block_t *root;
00086     static circ_state state;
00087 
00088     if (agnnodes(g) == 1) {
00089         Agnode_t *n = agfstnode(g);
00090         ND_pos(n)[0] = 0;
00091         ND_pos(n)[1] = 0;
00092         return;
00093     }
00094 
00095     initGraphAttrs(g, &state);
00096 
00097     root = createBlocktree(g, &state);
00098     circPos(g, root, &state);
00099 
00100     cleanup(root, &state);
00101 }
00102 
00103 #ifdef DEBUG
00104 void prGraph(Agraph_t * g)
00105 {
00106     Agnode_t *n;
00107     Agedge_t *e;
00108 
00109     fprintf(stderr, "%s\n", g->name);
00110     for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
00111         fprintf(stderr, "%s (%x)\n", n->name, (unsigned int) n);
00112         for (e = agfstout(g, n); e; e = agnxtout(g, e)) {
00113             fprintf(stderr, "%s -- %s (%x)\n", n->name, e->head->name,
00114                     (unsigned int) e);
00115         }
00116     }
00117 }
00118 
00119 cdata *cvt(Agnode_t * n)
00120 {
00121     return DATA(n);
00122 }
00123 
00124 void prData(Agnode_t * n, int pass)
00125 {
00126     char *pname;
00127     char *bname;
00128     char *tname;
00129     char *name1;
00130     char *name2;
00131     int dist1, dist2;
00132 
00133     if (PARENT(n))
00134         pname = PARENT(n)->name;
00135     else
00136         pname = "<P0>";
00137     if (BLOCK(n))
00138         bname = BLOCK(n)->sub_graph->name;
00139     else
00140         pname = "<B0>";
00141     fprintf(stderr, "%s: %x %s %s ", n->name, FLAGS(n), pname, bname);
00142     switch (pass) {
00143     case 0:
00144         fprintf(stderr, "%d %d\n", VAL(n), LOWVAL(n));
00145         break;
00146     case 1:
00147         if (TPARENT(n))
00148             tname = TPARENT(n)->name;
00149         else
00150             tname = "<ROOT>";
00151         dist1 = DISTONE(n);
00152         if (dist1 > 0)
00153             name1 = LEAFONE(n)->name;
00154         else
00155             name1 = "<null>";
00156         dist2 = DISTTWO(n);
00157         if (dist2 > 0)
00158             name2 = LEAFTWO(n)->name;
00159         else
00160             name2 = "<null>";
00161         fprintf(stderr, "%s %s %d %s %d\n", tname, name1, dist1, name2,
00162                 dist2);
00163         break;
00164     default:
00165         fprintf(stderr, "%d\n", POSITION(n));
00166         break;
00167     }
00168 }
00169 #endif