Graphviz  2.29.20120523.0446
lib/dotgen/decomp.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 /* 
00016  * Decompose finds the connected components of a graph.
00017  * It searches the temporary edges and ignores non-root nodes.
00018  * The roots of the search are the real nodes of the graph,
00019  * but any virtual nodes discovered are also included in the
00020  * component.
00021  */
00022 
00023 #include "dot.h"
00024 
00025 
00026 static graph_t *G;
00027 static node_t *Last_node;
00028 static char Cmark;
00029 
00030 static void 
00031 begin_component(void)
00032 {
00033     Last_node = GD_nlist(G) = NULL;
00034 }
00035 
00036 static void 
00037 add_to_component(node_t * n)
00038 {
00039     GD_n_nodes(G)++;
00040     ND_mark(n) = Cmark;
00041     if (Last_node) {
00042         ND_prev(n) = Last_node;
00043         ND_next(Last_node) = n;
00044     } else {
00045         ND_prev(n) = NULL;
00046         GD_nlist(G) = n;
00047     }
00048     Last_node = n;
00049     ND_next(n) = NULL;
00050 }
00051 
00052 static void 
00053 end_component(void)
00054 {
00055     int i;
00056 
00057     i = GD_comp(G).size++;
00058     GD_comp(G).list = ALLOC(GD_comp(G).size, GD_comp(G).list, node_t *);
00059     GD_comp(G).list[i] = GD_nlist(G);
00060 }
00061 
00062 static void
00063 search_component(graph_t * g, node_t * n)
00064 {
00065     int c, i;
00066     elist vec[4];
00067     node_t *other;
00068     edge_t *e;
00069 
00070     add_to_component(n);
00071     vec[0] = ND_out(n);
00072     vec[1] = ND_in(n);
00073     vec[2] = ND_flat_out(n);
00074     vec[3] = ND_flat_in(n);
00075 
00076     for (c = 0; c <= 3; c++) {
00077         if (vec[c].list)
00078             for (i = 0; (e = vec[c].list[i]); i++) {
00079                 if ((other = aghead(e)) == n)
00080                     other = agtail(e);
00081                 if ((ND_mark(other) != Cmark) && (other == UF_find(other)))
00082                     search_component(g, other);
00083             }
00084     }
00085 }
00086 
00087 void decompose(graph_t * g, int pass)
00088 {
00089     graph_t *subg;
00090     node_t *n, *v;
00091 
00092     G = g;
00093     if (++Cmark == 0)
00094         Cmark = 1;
00095     GD_n_nodes(g) = GD_comp(g).size = 0;
00096     for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
00097         v = n;
00098         if ((pass > 0) && (subg = ND_clust(v)))
00099             v = GD_rankleader(subg)[ND_rank(v)];
00100         else if (v != UF_find(v))
00101             continue;
00102         if (ND_mark(v) != Cmark) {
00103             begin_component();
00104             search_component(g, v);
00105             end_component();
00106         }
00107     }
00108 }