|
Graphviz
2.29.20120523.0446
|
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 /* comp.c: 00016 * Written by Emden R. Gansner 00017 * 00018 * Support for "connected components". Components are either connected 00019 * or have a port node or have a pinned node. 00020 * 00021 */ 00022 00023 /* use PRIVATE interface */ 00024 #define FDP_PRIVATE 1 00025 00026 #include <fdp.h> 00027 #include <comp.h> 00028 #include <pack.h> 00029 #include <assert.h> 00030 00031 #define MARK(n) (marks[ND_id(n)]) 00032 00033 static void dfs(Agraph_t * g, Agnode_t * n, Agraph_t * out, char *marks) 00034 { 00035 Agedge_t *e; 00036 Agnode_t *other; 00037 00038 MARK(n) = 1; 00039 #ifndef WITH_CGRAPH 00040 aginsert(out, n); 00041 #else /* WITH_CGRAPH */ 00042 agsubnode(out,n,1); 00043 #endif /* WITH_CGRAPH */ 00044 for (e = agfstedge(g, n); e; e = agnxtedge(g, e, n)) { 00045 if ((other = agtail(e)) == n) 00046 other = aghead(e); 00047 if (!MARK(other)) 00048 dfs(g, other, out, marks); 00049 } 00050 } 00051 00052 /* findCComp: 00053 * Finds generalized connected components of graph g. 00054 * This merges all components containing a port node or a pinned node. 00055 * Assumes nodes have unique id's in range [0,agnnodes(g)-1]. 00056 * Components are stored as subgraphs of g, with name sg_<i>. 00057 * Returns 0-terminated array of components. 00058 * If cnt is non-0, count of components is stored there. 00059 * If pinned is non-0, *pinned is set to 1 if there are pinned nodes. 00060 * Note that if ports and/or pinned nodes exists, they will all be 00061 * in the first component returned by findCComp. 00062 */ 00063 static int C_cnt = 0; 00064 graph_t **findCComp(graph_t * g, int *cnt, int *pinned) 00065 { 00066 node_t *n; 00067 graph_t *subg; 00068 char name[128]; 00069 int c_cnt = 0; 00070 char *marks; 00071 bport_t *pp; 00072 graph_t **comps; 00073 graph_t **cp; 00074 #ifndef WITH_CGRAPH 00075 graph_t *mg; 00076 node_t *mn; 00077 edge_t *me; 00078 #endif 00079 int pinflag = 0; 00080 00081 /* fprintf (stderr, "comps of %s starting at %d \n", g->name, c_cnt); */ 00082 marks = N_NEW(agnnodes(g), char); /* freed below */ 00083 00084 /* Create component based on port nodes */ 00085 subg = 0; 00086 if ((pp = PORTS(g))) { 00087 sprintf(name, "cc%s_%d", agnameof(g), c_cnt++ + C_cnt); 00088 #ifndef WITH_CGRAPH 00089 subg = agsubg(g, name); 00090 #else /* WITH_CGRAPH */ 00091 subg = agsubg(g, name,1); 00092 agbindrec(subg, "Agraphinfo_t", sizeof(Agraphinfo_t), TRUE); 00093 #endif /* WITH_CGRAPH */ 00094 GD_alg(subg) = (void *) NEW(gdata); 00095 PORTS(subg) = pp; 00096 NPORTS(subg) = NPORTS(g); 00097 for (; pp->n; pp++) { 00098 if (MARK(pp->n)) 00099 continue; 00100 dfs(g, pp->n, subg, marks); 00101 } 00102 } 00103 00104 /* Create/extend component based on pinned nodes */ 00105 /* Note that ports cannot be pinned */ 00106 for (n = agfstnode(g); n; n = agnxtnode(g, n)) { 00107 if (MARK(n)) 00108 continue; 00109 if (ND_pinned(n) != P_PIN) 00110 continue; 00111 if (!subg) { 00112 sprintf(name, "cc%s_%d", agnameof(g), c_cnt++ + C_cnt); 00113 #ifndef WITH_CGRAPH 00114 subg = agsubg(g, name); 00115 #else /* WITH_CGRAPH */ 00116 subg = agsubg(g, name,1); 00117 agbindrec(subg, "Agraphinfo_t", sizeof(Agraphinfo_t), TRUE); 00118 #endif /* WITH_CGRAPH */ 00119 GD_alg(subg) = (void *) NEW(gdata); 00120 } 00121 pinflag = 1; 00122 dfs(g, n, subg, marks); 00123 } 00124 if (subg) 00125 nodeInduce(subg); 00126 00127 /* Pick up remaining components */ 00128 for (n = agfstnode(g); n; n = agnxtnode(g, n)) { 00129 if (MARK(n)) 00130 continue; 00131 sprintf(name, "cc%s+%d", agnameof(g), c_cnt++ + C_cnt); 00132 #ifndef WITH_CGRAPH 00133 subg = agsubg(g, name); 00134 #else /* WITH_CGRAPH */ 00135 subg = agsubg(g, name,1); 00136 agbindrec(subg, "Agraphinfo_t", sizeof(Agraphinfo_t), TRUE); //node custom data 00137 #endif /* WITH_CGRAPH */ 00138 GD_alg(subg) = (void *) NEW(gdata); 00139 dfs(g, n, subg, marks); 00140 nodeInduce(subg); 00141 } 00142 free(marks); 00143 C_cnt += c_cnt; 00144 00145 if (cnt) 00146 *cnt = c_cnt; 00147 if (pinned) 00148 *pinned = pinflag; 00149 /* freed in layout */ 00150 comps = cp = N_NEW(c_cnt + 1, graph_t *); 00151 #ifndef WITH_CGRAPH 00152 mg = g->meta_node->graph; 00153 for (me = agfstout(mg, g->meta_node); me; me = agnxtout(mg, me)) { 00154 mn = me->head; 00155 *cp++ = agusergraph(mn); 00156 #else /* WITH_CGRAPH */ 00157 for (subg = agfstsubg(g); subg; subg = agnxtsubg(subg)) { 00158 *cp++ = subg; 00159 #endif /* WITH_CGRAPH */ 00160 c_cnt--; 00161 } 00162 assert(c_cnt == 0); 00163 *cp = 0; 00164 00165 return comps; 00166 }
1.7.5