/misc/src/release/graphviz-2.18-1/src/graphviz-2.18/lib/fdpgen/comp.c

Go to the documentation of this file.
00001 /* $Id: comp.c,v 1.1.1.1 2004/12/23 04:05:07 ellson Exp $ $Revision: 1.1.1.1 $ */
00002 /* vim:set shiftwidth=4 ts=8: */
00003 
00004 /**********************************************************
00005 *      This software is part of the graphviz package      *
00006 *                http://www.graphviz.org/                 *
00007 *                                                         *
00008 *            Copyright (c) 1994-2004 AT&T Corp.           *
00009 *                and is licensed under the                *
00010 *            Common Public License, Version 1.0           *
00011 *                      by AT&T Corp.                      *
00012 *                                                         *
00013 *        Information and Software Systems Research        *
00014 *              AT&T Research, Florham Park NJ             *
00015 **********************************************************/
00016 
00017 
00018 /* comp.c:
00019  * Written by Emden R. Gansner
00020  *
00021  * Support for "connected components". Components are either connected
00022  * or have a port node or have a pinned node.
00023  *
00024  */
00025 
00026 /* use PRIVATE interface */
00027 #define FDP_PRIVATE 1
00028 
00029 #include <fdp.h>
00030 #include <comp.h>
00031 #include <pack.h>
00032 #include <assert.h>
00033 
00034 #define MARK(n) (marks[ND_id(n)])
00035 
00036 static void dfs(Agraph_t * g, Agnode_t * n, Agraph_t * out, char *marks)
00037 {
00038     Agedge_t *e;
00039     Agnode_t *other;
00040 
00041     MARK(n) = 1;
00042     aginsert(out, n);
00043     for (e = agfstedge(g, n); e; e = agnxtedge(g, e, n)) {
00044         if ((other = e->tail) == n)
00045             other = e->head;
00046         if (!MARK(other))
00047             dfs(g, other, out, marks);
00048     }
00049 }
00050 
00051 /* findCComp:
00052  * Finds generalized connected components of graph g.
00053  * This merges all components containing a port node or a pinned node.
00054  * Assumes nodes have unique id's in range [0,agnnodes(g)-1].
00055  * Components are stored as subgraphs of g, with name sg_<i>.
00056  * Returns 0-terminated array of components.
00057  * If cnt is non-0, count of components is stored there.
00058  * If pinned is non-0, *pinned is set to 1 if there are pinned nodes.
00059  * Note that if ports and/or pinned nodes exists, they will all be
00060  * in the first component returned by findCComp.
00061  */
00062 static int C_cnt = 0;
00063 graph_t **findCComp(graph_t * g, int *cnt, int *pinned)
00064 {
00065     node_t *n;
00066     graph_t *subg;
00067     char name[128];
00068     int c_cnt = 0;
00069     char *marks;
00070     bport_t *pp;
00071     graph_t **comps;
00072     graph_t **cp;
00073     graph_t *mg;
00074     edge_t *me;
00075     node_t *mn;
00076     int pinflag = 0;
00077 
00078 /* fprintf (stderr, "comps of %s starting at %d \n", g->name, c_cnt); */
00079     marks = N_NEW(agnnodes(g), char);   /* freed below */
00080 
00081     /* Create component based on port nodes */
00082     subg = 0;
00083     if ((pp = PORTS(g))) {
00084         sprintf(name, "cc%s_%d", g->name, c_cnt++ + C_cnt);
00085         subg = agsubg(g, name);
00086         GD_alg(subg) = (void *) NEW(gdata);
00087         PORTS(subg) = pp;
00088         NPORTS(subg) = NPORTS(g);
00089         for (; pp->n; pp++) {
00090             if (MARK(pp->n))
00091                 continue;
00092             dfs(g, pp->n, subg, marks);
00093         }
00094     }
00095 
00096     /* Create/extend component based on pinned nodes */
00097     /* Note that ports cannot be pinned */
00098     for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
00099         if (MARK(n))
00100             continue;
00101         if (ND_pinned(n) != P_PIN)
00102             continue;
00103         if (!subg) {
00104             sprintf(name, "cc%s_%d", g->name, c_cnt++ + C_cnt);
00105             subg = agsubg(g, name);
00106             GD_alg(subg) = (void *) NEW(gdata);
00107         }
00108         pinflag = 1;
00109         dfs(g, n, subg, marks);
00110     }
00111     if (subg)
00112         nodeInduce(subg);
00113 
00114     /* Pick up remaining components */
00115     for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
00116         if (MARK(n))
00117             continue;
00118         sprintf(name, "cc%s+%d", g->name, c_cnt++ + C_cnt);
00119         subg = agsubg(g, name);
00120         GD_alg(subg) = (void *) NEW(gdata);
00121         dfs(g, n, subg, marks);
00122         nodeInduce(subg);
00123     }
00124     free(marks);
00125     C_cnt += c_cnt;
00126 
00127     if (cnt)
00128         *cnt = c_cnt;
00129     if (pinned)
00130         *pinned = pinflag;
00131     /* freed in layout */
00132     comps = cp = N_NEW(c_cnt + 1, graph_t *);
00133     mg = g->meta_node->graph;
00134     for (me = agfstout(mg, g->meta_node); me; me = agnxtout(mg, me)) {
00135         mn = me->head;
00136         *cp++ = agusergraph(mn);
00137         c_cnt--;
00138     }
00139     assert(c_cnt == 0);
00140     *cp = 0;
00141 
00142     return comps;
00143 }

Generated on Mon Mar 31 19:03:26 2008 for Graphviz by  doxygen 1.5.1