00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "dot.h"
00021
00022 static node_t*
00023 label_vnode(graph_t * g, edge_t * orig)
00024 {
00025 node_t *v;
00026 pointf dimen;
00027
00028 dimen = ED_label(orig)->dimen;
00029 v = virtual_node(g);
00030 ND_label(v) = ED_label(orig);
00031 ND_lw_i(v) = GD_nodesep(v->graph->root);
00032 if (!ED_label_ontop(orig)) {
00033 if (GD_flip(g->root)) {
00034 ND_ht_i(v) = dimen.x;
00035 ND_rw_i(v) = dimen.y;
00036 } else {
00037 ND_ht_i(v) = dimen.y;
00038 ND_rw_i(v) = dimen.x;
00039 }
00040 }
00041 return v;
00042 }
00043
00044 static void
00045 incr_width(graph_t * g, node_t * v)
00046 {
00047 int width = GD_nodesep(g) / 2;
00048 ND_lw_i(v) += width;
00049 ND_rw_i(v) += width;
00050 }
00051
00052 static node_t*
00053 plain_vnode(graph_t * g, edge_t * orig)
00054 {
00055 node_t *v;
00056 orig = orig;
00057 v = virtual_node(g);
00058 incr_width(g, v);
00059 return v;
00060 }
00061
00062 static node_t*
00063 leader_of(graph_t * g, node_t * v)
00064 {
00065 graph_t *clust;
00066 node_t *rv;
00067
00068 if (ND_ranktype(v) != CLUSTER) {
00069
00070 rv = UF_find(v);
00071 } else {
00072 clust = ND_clust(v);
00073 rv = GD_rankleader(clust)[ND_rank(v)];
00074 }
00075 return rv;
00076 }
00077
00078
00079
00080
00081 static void
00082 make_chain(graph_t * g, node_t * from, node_t * to, edge_t * orig)
00083 {
00084 int r, label_rank;
00085 node_t *u, *v;
00086 edge_t *e;
00087
00088 u = from;
00089 if (ED_label(orig))
00090 label_rank = (ND_rank(from) + ND_rank(to)) / 2;
00091 else
00092 label_rank = -1;
00093 assert(ED_to_virt(orig) == NULL);
00094 for (r = ND_rank(from) + 1; r <= ND_rank(to); r++) {
00095 if (r < ND_rank(to)) {
00096 if (r == label_rank)
00097 v = label_vnode(g, orig);
00098 else
00099 v = plain_vnode(g, orig);
00100 ND_rank(v) = r;
00101 } else
00102 v = to;
00103 e = virtual_edge(u, v, orig);
00104 virtual_weight(e);
00105 u = v;
00106 }
00107 assert(ED_to_virt(orig) != NULL);
00108 }
00109
00110 static void
00111 interclrep(graph_t * g, edge_t * e)
00112 {
00113 node_t *t, *h;
00114 edge_t *ve;
00115
00116 t = leader_of(g, e->tail);
00117 h = leader_of(g, e->head);
00118 if (ND_rank(t) > ND_rank(h)) {
00119 node_t *t0 = t;
00120 t = h;
00121 h = t0;
00122 }
00123 if (ND_clust(t) != ND_clust(h)) {
00124 if ((ve = find_fast_edge(t, h))) {
00125 merge_chain(g, e, ve, TRUE);
00126 return;
00127 }
00128 if (ND_rank(t) == ND_rank(h))
00129 return;
00130 make_chain(g, t, h, e);
00131
00132
00133 for (ve = ED_to_virt(e); ve && (ND_rank(ve->head) <= ND_rank(h));
00134 ve = ND_out(ve->head).list[0])
00135 ED_edge_type(ve) = CLUSTER_EDGE;
00136 }
00137
00138 }
00139
00140 static int
00141 is_cluster_edge(edge_t * e)
00142 {
00143 return ((ND_ranktype(e->tail) == CLUSTER)
00144 || (ND_ranktype(e->head) == CLUSTER));
00145 }
00146
00147 void merge_chain(graph_t * g, edge_t * e, edge_t * f, int flag)
00148 {
00149 edge_t *rep;
00150 int lastrank = MAX(ND_rank(e->tail), ND_rank(e->head));
00151
00152 assert(ED_to_virt(e) == NULL);
00153 ED_to_virt(e) = f;
00154 rep = f;
00155 do {
00156
00157 if (flag)
00158 ED_count(rep) += ED_count(e);
00159 ED_xpenalty(rep) += ED_xpenalty(e);
00160 ED_weight(rep) += ED_weight(e);
00161 if (ND_rank(rep->head) == lastrank)
00162 break;
00163 incr_width(g, rep->head);
00164 rep = ND_out(rep->head).list[0];
00165 } while (rep);
00166 }
00167
00168 int mergeable(edge_t * e, edge_t * f)
00169 {
00170 if (e && f && (e->tail == f->tail) && (e->head == f->head) &&
00171 (ED_label(e) == ED_label(f)) && ports_eq(e, f))
00172 return TRUE;
00173 return FALSE;
00174 }
00175
00176 void class2(graph_t * g)
00177 {
00178 int c;
00179 node_t *n, *t, *h;
00180 edge_t *e, *prev, *opp;
00181
00182 GD_nlist(g) = NULL;
00183
00184 GD_n_nodes(g) = 0;
00185
00186 mark_clusters(g);
00187 for (c = 1; c <= GD_n_cluster(g); c++)
00188 build_skeleton(g, GD_clust(g)[c]);
00189 for (n = agfstnode(g); n; n = agnxtnode(g, n))
00190 for (e = agfstout(g, n); e; e = agnxtout(g, e)) {
00191 if (ND_weight_class(e->head) <= 2)
00192 ND_weight_class(e->head)++;
00193 if (ND_weight_class(e->tail) <= 2)
00194 ND_weight_class(e->tail)++;
00195 }
00196
00197 for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
00198 if ((ND_clust(n) == NULL) && (n == UF_find(n))) {
00199 fast_node(g, n);
00200 GD_n_nodes(g)++;
00201 }
00202 prev = NULL;
00203 for (e = agfstout(g, n); e; e = agnxtout(g, e)) {
00204
00205
00206 if (ED_to_virt(e)) {
00207 prev = e;
00208 continue;
00209 }
00210
00211
00212 if (is_cluster_edge(e)) {
00213
00214 if (mergeable(prev, e)) {
00215 if (ED_to_virt(prev)) {
00216 merge_chain(g, e, ED_to_virt(prev), FALSE);
00217 other_edge(e);
00218 } else if (ND_rank(e->tail) == ND_rank(e->head)) {
00219 merge_oneway(e, prev);
00220 other_edge(e);
00221 }
00222
00223 continue;
00224 }
00225 interclrep(g, e);
00226 prev = e;
00227 continue;
00228 }
00229
00230 if (prev && (e->tail == prev->tail) && (e->head == prev->head)) {
00231 if (ND_rank(e->tail) == ND_rank(e->head)) {
00232 merge_oneway(e, prev);
00233 other_edge(e);
00234 continue;
00235 }
00236 if ((ED_label(e) == NULL) && (ED_label(prev) == NULL)
00237 && ports_eq(e, prev)) {
00238 if (Concentrate)
00239 ED_edge_type(e) = IGNORED;
00240 else {
00241 merge_chain(g, e, ED_to_virt(prev), TRUE);
00242 other_edge(e);
00243 }
00244 continue;
00245 }
00246
00247 }
00248
00249
00250 if (e->tail == e->head) {
00251 other_edge(e);
00252 prev = e;
00253 continue;
00254 }
00255
00256 t = UF_find(e->tail);
00257 h = UF_find(e->head);
00258
00259
00260 if ((e->tail != t) || (e->head != h)) {
00261
00262 continue;
00263 }
00264
00265
00266
00267 if (ND_rank(e->tail) == ND_rank(e->head)) {
00268 flat_edge(g, e);
00269 prev = e;
00270 continue;
00271 }
00272
00273
00274 if (ND_rank(e->head) > ND_rank(e->tail)) {
00275 make_chain(g, e->tail, e->head, e);
00276 prev = e;
00277 continue;
00278 }
00279
00280
00281 else {
00282
00283
00284 if ((opp = agfindedge(g, e->head, e->tail)) && (opp != e)) {
00285
00286 if (ED_to_virt(opp) == NULL)
00287 make_chain(g, opp->tail, opp->head, opp);
00288 if ((ED_label(e) == NULL) && (ED_label(opp) == NULL)
00289 && ports_eq(e, opp)) {
00290 if (Concentrate) {
00291 ED_edge_type(e) = IGNORED;
00292 ED_conc_opp_flag(opp) = TRUE;
00293 } else {
00294 other_edge(e);
00295 merge_chain(g, e, ED_to_virt(opp), TRUE);
00296 }
00297 continue;
00298 }
00299 }
00300 make_chain(g, e->head, e->tail, e);
00301 prev = e;
00302 }
00303 }
00304 }
00305
00306 if (g != g->root) {
00307 GD_comp(g).list = ALLOC(1, GD_comp(g).list, node_t *);
00308 GD_comp(g).list[0] = GD_nlist(g);
00309 }
00310 }
00311