]> granicus.if.org Git - graphviz/commitdiff
Make many functions in dotprocs.h static to help me keep my sanity
authorerg <devnull@localhost>
Tue, 8 Mar 2005 23:34:10 +0000 (23:34 +0000)
committererg <devnull@localhost>
Tue, 8 Mar 2005 23:34:10 +0000 (23:34 +0000)
trying to track down who can be called.

lib/dotgen/class2.c
lib/dotgen/cluster.c
lib/dotgen/compound.c

index 9339af438f8b7ec2e8284e075fce6d7357c0775c..eb7ccce701d579e33898b665e6b539bd48be8ed5 100644 (file)
 
 #include "dot.h"
 
+static node_t*
+label_vnode(graph_t * g, edge_t * orig)
+{
+    node_t *v;
+    pointf dimen;
+
+    dimen = ED_label(orig)->dimen;
+    v = virtual_node(g);
+    ND_label(v) = ED_label(orig);
+    ND_lw_i(v) = GD_nodesep(v->graph);
+    if (!ED_label_ontop(orig)) {
+       if (GD_flip(g)) {
+           ND_ht_i(v) = dimen.x;
+           ND_rw_i(v) = dimen.y;
+       } else {
+           ND_ht_i(v) = dimen.y;
+           ND_rw_i(v) = dimen.x;
+       }
+    }
+    return v;
+}
+
+static void 
+incr_width(graph_t * g, node_t * v)
+{
+    int width = GD_nodesep(g) / 2;
+    ND_lw_i(v) += width;
+    ND_rw_i(v) += width;
+}
+
+static node_t*
+plain_vnode(graph_t * g, edge_t * orig)
+{
+    node_t *v;
+    orig = orig;
+    v = virtual_node(g);
+    incr_width(g, v);
+    return v;
+}
+
+static node_t*
+leader_of(graph_t * g, node_t * v)
+{
+    graph_t *clust;
+    node_t *rv;
+
+    if (ND_ranktype(v) != CLUSTER) {
+       /*assert(v == UF_find(v));  could be leaf, so comment out */
+       rv = UF_find(v);
+    } else {
+       clust = ND_clust(v);
+       rv = GD_rankleader(clust)[ND_rank(v)];
+    }
+    return rv;
+}
+
+static void 
+make_chain(graph_t * g, node_t * from, node_t * to, edge_t * orig)
+{
+    int r, label_rank;
+    node_t *u, *v;
+    edge_t *e;
+
+    u = from;
+    if (ED_label(orig))
+       label_rank = (ND_rank(from) + ND_rank(to)) / 2;
+    else
+       label_rank = -1;
+    assert(ED_to_virt(orig) == NULL);
+    for (r = ND_rank(from) + 1; r <= ND_rank(to); r++) {
+       if (r < ND_rank(to)) {
+           if (r == label_rank)
+               v = label_vnode(g, orig);
+           else
+               v = plain_vnode(g, orig);
+           ND_rank(v) = r;
+       } else
+           v = to;
+       e = virtual_edge(u, v, orig);
+       virtual_weight(e);
+       u = v;
+    }
+    assert(ED_to_virt(orig) != NULL);
+}
+
+static void 
+interclrep(graph_t * g, edge_t * e)
+{
+    node_t *t, *h;
+    edge_t *ve;
+
+    t = leader_of(g, e->tail);
+    h = leader_of(g, e->head);
+    if (ND_rank(t) > ND_rank(h)) {
+       node_t *t0 = t;
+       t = h;
+       h = t0;
+    }
+    if (ND_clust(t) != ND_clust(h)) {
+       if ((ve = find_fast_edge(t, h))) {
+           merge_chain(g, e, ve, TRUE);
+           return;
+       }
+       if (ND_rank(t) == ND_rank(h))
+           return;
+       make_chain(g, t, h, e);
+
+       /* mark as cluster edge */
+       for (ve = ED_to_virt(e); ve && (ND_rank(ve->head) <= ND_rank(h));
+            ve = ND_out(ve->head).list[0])
+           ED_edge_type(ve) = CLUSTER_EDGE;
+    }
+    /* else ignore intra-cluster edges at this point */
+}
+
+static int 
+is_cluster_edge(edge_t * e)
+{
+    return ((ND_ranktype(e->tail) == CLUSTER)
+           || (ND_ranktype(e->head) == CLUSTER));
+}
+
+void merge_chain(graph_t * g, edge_t * e, edge_t * f, int flag)
+{
+    edge_t *rep;
+    int lastrank = MAX(ND_rank(e->tail), ND_rank(e->head));
+
+    assert(ED_to_virt(e) == NULL);
+    ED_to_virt(e) = f;
+    rep = f;
+    do {
+       /* interclust multi-edges are not counted now */
+       if (flag)
+           ED_count(rep) += ED_count(e);
+       ED_xpenalty(rep) += ED_xpenalty(e);
+       ED_weight(rep) += ED_weight(e);
+       if (ND_rank(rep->head) == lastrank)
+           break;
+       incr_width(g, rep->head);
+       rep = ND_out(rep->head).list[0];
+    } while (rep);
+}
+
+int mergeable(edge_t * e, edge_t * f)
+{
+    if (e && f && (e->tail == f->tail) && (e->head == f->head) &&
+       (ED_label(e) == ED_label(f)) && ports_eq(e, f))
+       return TRUE;
+    return FALSE;
+}
 
 void class2(graph_t * g)
 {
@@ -156,146 +306,3 @@ void class2(graph_t * g)
     }
 }
 
-node_t *label_vnode(graph_t * g, edge_t * orig)
-{
-    node_t *v;
-    pointf dimen;
-
-    dimen = ED_label(orig)->dimen;
-    v = virtual_node(g);
-    ND_label(v) = ED_label(orig);
-    ND_lw_i(v) = GD_nodesep(v->graph);
-    if (!ED_label_ontop(orig)) {
-       if (GD_flip(g)) {
-           ND_ht_i(v) = dimen.x;
-           ND_rw_i(v) = dimen.y;
-       } else {
-           ND_ht_i(v) = dimen.y;
-           ND_rw_i(v) = dimen.x;
-       }
-    }
-    return v;
-}
-
-node_t *plain_vnode(graph_t * g, edge_t * orig)
-{
-    node_t *v;
-    orig = orig;
-    v = virtual_node(g);
-    incr_width(g, v);
-    return v;
-}
-
-void incr_width(graph_t * g, node_t * v)
-{
-    int width = GD_nodesep(g) / 2;
-    ND_lw_i(v) += width;
-    ND_rw_i(v) += width;
-}
-
-void make_chain(graph_t * g, node_t * from, node_t * to, edge_t * orig)
-{
-    int r, label_rank;
-    node_t *u, *v;
-    edge_t *e;
-
-    u = from;
-    if (ED_label(orig))
-       label_rank = (ND_rank(from) + ND_rank(to)) / 2;
-    else
-       label_rank = -1;
-    assert(ED_to_virt(orig) == NULL);
-    for (r = ND_rank(from) + 1; r <= ND_rank(to); r++) {
-       if (r < ND_rank(to)) {
-           if (r == label_rank)
-               v = label_vnode(g, orig);
-           else
-               v = plain_vnode(g, orig);
-           ND_rank(v) = r;
-       } else
-           v = to;
-       e = virtual_edge(u, v, orig);
-       virtual_weight(e);
-       u = v;
-    }
-    assert(ED_to_virt(orig) != NULL);
-}
-
-void merge_chain(graph_t * g, edge_t * e, edge_t * f, int flag)
-{
-    edge_t *rep;
-    int lastrank = MAX(ND_rank(e->tail), ND_rank(e->head));
-
-    assert(ED_to_virt(e) == NULL);
-    ED_to_virt(e) = f;
-    rep = f;
-    do {
-       /* interclust multi-edges are not counted now */
-       if (flag)
-           ED_count(rep) += ED_count(e);
-       ED_xpenalty(rep) += ED_xpenalty(e);
-       ED_weight(rep) += ED_weight(e);
-       if (ND_rank(rep->head) == lastrank)
-           break;
-       incr_width(g, rep->head);
-       rep = ND_out(rep->head).list[0];
-    } while (rep);
-}
-
-node_t *leader_of(graph_t * g, node_t * v)
-{
-    graph_t *clust;
-    node_t *rv;
-
-    if (ND_ranktype(v) != CLUSTER) {
-       /*assert(v == UF_find(v));  could be leaf, so comment out */
-       rv = UF_find(v);
-    } else {
-       clust = ND_clust(v);
-       rv = GD_rankleader(clust)[ND_rank(v)];
-    }
-    return rv;
-}
-
-void interclrep(graph_t * g, edge_t * e)
-{
-    node_t *t, *h;
-    edge_t *ve;
-
-    t = leader_of(g, e->tail);
-    h = leader_of(g, e->head);
-    if (ND_rank(t) > ND_rank(h)) {
-       node_t *t0 = t;
-       t = h;
-       h = t0;
-    }
-    if (ND_clust(t) != ND_clust(h)) {
-       if ((ve = find_fast_edge(t, h))) {
-           merge_chain(g, e, ve, TRUE);
-           return;
-       }
-       if (ND_rank(t) == ND_rank(h))
-           return;
-       make_chain(g, t, h, e);
-
-       /* mark as cluster edge */
-       for (ve = ED_to_virt(e); ve && (ND_rank(ve->head) <= ND_rank(h));
-            ve = ND_out(ve->head).list[0])
-           ED_edge_type(ve) = CLUSTER_EDGE;
-    }
-    /* else ignore intra-cluster edges at this point */
-}
-
-int is_cluster_edge(edge_t * e)
-{
-    return ((ND_ranktype(e->tail) == CLUSTER)
-           || (ND_ranktype(e->head) == CLUSTER));
-}
-
-int mergeable(edge_t * e, edge_t * f)
-{
-    if (e && f && (e->tail == f->tail) && (e->head == f->head) &&
-       (ED_label(e) == ED_label(f)) && ports_eq(e, f))
-       return TRUE;
-    return FALSE;
-}
index 0aeeef43480df2c79594f01c6de5f66662077127..27a135acf88df6958b54cf9555f140d8584b3783 100644 (file)
 
 #include "dot.h"
 
-
-/* delete virtual nodes of a cluster, and install real nodes or sub-clusters */
-void expand_cluster(graph_t * subg)
-{
-    /* build internal structure of the cluster */
-    class2(subg);
-    GD_comp(subg).size = 1;
-    GD_comp(subg).list[0] = GD_nlist(subg);
-    allocate_ranks(subg);
-    build_ranks(subg, 0);
-    merge_ranks(subg);
-
-    /* build external structure of the cluster */
-    interclexp(subg);
-    remove_rankleaders(subg);
-}
-
-/* this function marks every node in <g> with its top-level cluster under <g> */
-void mark_clusters(graph_t * g)
-{
-    int c;
-    node_t *n, *vn;
-    edge_t *orig, *e;
-    graph_t *clust;
-
-    /* remove sub-clusters below this level */
-    for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
-       if (ND_ranktype(n) == CLUSTER)
-           UF_singleton(n);
-       ND_clust(n) = NULL;
-    }
-
-    for (c = 1; c <= GD_n_cluster(g); c++) {
-       clust = GD_clust(g)[c];
-       for (n = agfstnode(clust); n; n = agnxtnode(clust, n)) {
-           if (ND_ranktype(n) != NORMAL) {
-               agerr(AGWARN,
-                     "%s was already in a rankset, ignored in cluster %s\n",
-                     n->name, g->name);
-               continue;
-           }
-           UF_setname(n, GD_leader(clust));
-           ND_clust(n) = clust;
-           ND_ranktype(n) = CLUSTER;
-
-           /* here we mark the vnodes of edges in the cluster */
-           for (orig = agfstout(clust, n); orig;
-                orig = agnxtout(clust, orig)) {
-               if ((e = ED_to_virt(orig))) {
-                   while (e && (vn = e->head)->u.node_type == VIRTUAL) {
-                       ND_clust(vn) = clust;
-                       e = ND_out(e->head).list[0];
-                       /* trouble if concentrators and clusters are mixed */
-                   }
-               }
-           }
-       }
-    }
-}
-
-void build_skeleton(graph_t * g, graph_t * subg)
+static node_t*
+map_interclust_node(node_t * n)
 {
-    int r;
-    node_t *v, *prev, *rl;
-    edge_t *e;
-
-    prev = NULL;
-    GD_rankleader(subg) = N_NEW(GD_maxrank(subg) + 2, node_t *);
-    for (r = GD_minrank(subg); r <= GD_maxrank(subg); r++) {
-       v = GD_rankleader(subg)[r] = virtual_node(g);
-       ND_rank(v) = r;
-       ND_ranktype(v) = CLUSTER;
-       ND_clust(v) = subg;
-       if (prev) {
-           e = virtual_edge(prev, v, NULL);
-           ED_xpenalty(e) *= CL_CROSS;
-       }
-       prev = v;
-    }
-
-    /* set the counts on virtual edges of the cluster skeleton */
-    for (v = agfstnode(subg); v; v = agnxtnode(subg, v)) {
-       rl = GD_rankleader(subg)[ND_rank(v)];
-       ND_UF_size(rl)++;
-       for (e = agfstout(subg, v); e; e = agnxtout(subg, e)) {
-           for (r = ND_rank(e->tail); r < ND_rank(e->head); r++) {
-               ED_count(ND_out(rl).list[0])++;
-           }
-       }
-    }
-    for (r = GD_minrank(subg); r <= GD_maxrank(subg); r++) {
-       rl = GD_rankleader(subg)[r];
-       if (ND_UF_size(rl) > 1)
-           ND_UF_size(rl)--;
-    }
-}
-
-void merge_ranks(graph_t * subg)
-{
-    int i, d, r, pos, ipos;
-    node_t *v;
-    graph_t *root;
+    node_t *rv;
 
-    root = subg->root;
-    if (GD_minrank(subg) > 0)
-       ND_rank(root)[GD_minrank(subg) - 1].valid = FALSE;
-    for (r = GD_minrank(subg); r <= GD_maxrank(subg); r++) {
-       d = GD_rank(subg)[r].n;
-       ipos = pos = GD_rankleader(subg)[r]->u.order;
-       make_slots(root, r, pos, d);
-       for (i = 0; i < GD_rank(subg)[r].n; i++) {
-           v = ND_rank(root)[r].v[pos] = GD_rank(subg)[r].v[i];
-           ND_order(v) = pos++;
-           v->graph = subg->root;
-           delete_fast_node(subg, v);
-           fast_node(subg->root, v);
-           GD_n_nodes(subg->root)++;
-       }
-       GD_rank(subg)[r].v = ND_rank(root)[r].v + ipos;
-       ND_rank(root)[r].valid = FALSE;
-    }
-    if (r < GD_maxrank(root))
-       GD_rank(root)[r].valid = FALSE;
-    GD_expanded(subg) = TRUE;
+    if ((ND_clust(n) == NULL) || (ND_clust(n)->u.expanded))
+       rv = n;
+    else
+       rv = ND_clust(n)->u.rankleader[ND_rank(n)];
+    return rv;
 }
 
 /* make d slots starting at position pos (where 1 already exists) */
-void make_slots(graph_t * root, int r, int pos, int d)
+static void 
+make_slots(graph_t * root, int r, int pos, int d)
 {
     int i;
     node_t *v, **vlist;
@@ -170,99 +57,8 @@ void make_slots(graph_t * root, int r, int pos, int d)
     ND_rank(root)[r].n += d - 1;
 }
 
-/* 
- * attach and install edges between clusters.
- * essentially, class2() for interclust edges.
- */
-void interclexp(graph_t * subg)
-{
-    graph_t *g;
-    node_t *n;
-    edge_t *e, *prev;
-
-    g = subg->root;
-    for (n = agfstnode(subg); n; n = agnxtnode(subg, n)) {
-
-       /* N.B. n may be in a sub-cluster of subg */
-       prev = NULL;
-       for (e = agfstedge(subg->root, n); e;
-            e = agnxtedge(subg->root, e, n)) {
-           if (agcontains(subg, e))
-               continue;
-
-           /* short/flat multi edges */
-           if (mergeable(prev, e)) {
-               if (ND_rank(e->tail) == ND_rank(e->head))
-                   ED_to_virt(e) = prev;
-               else
-                   ED_to_virt(e) = NULL;
-               if (ED_to_virt(prev) == NULL)
-                   continue;   /* internal edge */
-               merge_chain(subg, e, ED_to_virt(prev), FALSE);
-               safe_other_edge(e);
-               continue;
-           }
-
-           /* flat edges */
-           if (ND_rank(e->tail) == ND_rank(e->head)) {
-               if (find_flat_edge(e->tail, e->head) == NULL) {
-                   flat_edge(g, e);
-                   prev = e;
-               } else
-                   prev = NULL;
-               continue;
-           }
-
-           assert(ED_to_virt(e) != NULL);
-
-           /* forward edges */
-           if (ND_rank(e->head) > ND_rank(e->tail)) {
-               make_interclust_chain(g, e->tail, e->head, e);
-               prev = e;
-               continue;
-           }
-
-           /* backward edges */
-           else {
-/*
-I think that make_interclust_chain should create call other_edge(e) anyway 
-                               if (agcontains(subg,e->tail)
-                                       && agfindedge(subg->root,e->head,e->tail)) other_edge(e);
-*/
-               make_interclust_chain(g, e->head, e->tail, e);
-               prev = e;
-           }
-       }
-    }
-}
-
-node_t *map_interclust_node(node_t * n)
-{
-    node_t *rv;
-
-    if ((ND_clust(n) == NULL) || (ND_clust(n)->u.expanded))
-       rv = n;
-    else
-       rv = ND_clust(n)->u.rankleader[ND_rank(n)];
-    return rv;
-}
-
-void make_interclust_chain(graph_t * g, node_t * from, node_t * to,
-                          edge_t * orig)
-{
-    int newtype;
-    node_t *u, *v;
-
-    u = map_interclust_node(from);
-    v = map_interclust_node(to);
-    if ((u == from) && (v == to))
-       newtype = VIRTUAL;
-    else
-       newtype = CLUSTER_EDGE;
-    map_path(u, v, orig, ED_to_virt(orig), newtype);
-}
-
-node_t *clone_vn(graph_t * g, node_t * vn)
+static node_t* 
+clone_vn(graph_t * g, node_t * vn)
 {
     node_t *rv;
     int r;
@@ -278,8 +74,8 @@ node_t *clone_vn(graph_t * g, node_t * vn)
     return rv;
 }
 
-void map_path(node_t * from, node_t * to, edge_t * orig, edge_t * ve,
-             int type)
+static void 
+map_path(node_t * from, node_t * to, edge_t * orig, edge_t * ve, int type)
 {
     int r;
     node_t *u, *v;
@@ -349,22 +145,119 @@ void map_path(node_t * from, node_t * to, edge_t * orig, edge_t * ve,
     }
 }
 
-void install_cluster(graph_t * g, node_t * n, int pass, queue * q)
+static void 
+make_interclust_chain(graph_t * g, node_t * from, node_t * to, edge_t * orig)
 {
-    int r;
-    graph_t *clust;
+    int newtype;
+    node_t *u, *v;
 
-    clust = ND_clust(n);
-    if (GD_installed(clust) != pass + 1) {
-       for (r = GD_minrank(clust); r <= GD_maxrank(clust); r++)
-           install_in_rank(g, GD_rankleader(clust)[r]);
-       for (r = GD_minrank(clust); r <= GD_maxrank(clust); r++)
-           enqueue_neighbors(q, GD_rankleader(clust)[r], pass);
-       GD_installed(clust) = pass + 1;
+    u = map_interclust_node(from);
+    v = map_interclust_node(to);
+    if ((u == from) && (v == to))
+       newtype = VIRTUAL;
+    else
+       newtype = CLUSTER_EDGE;
+    map_path(u, v, orig, ED_to_virt(orig), newtype);
+}
+
+/* 
+ * attach and install edges between clusters.
+ * essentially, class2() for interclust edges.
+ */
+void interclexp(graph_t * subg)
+{
+    graph_t *g;
+    node_t *n;
+    edge_t *e, *prev;
+
+    g = subg->root;
+    for (n = agfstnode(subg); n; n = agnxtnode(subg, n)) {
+
+       /* N.B. n may be in a sub-cluster of subg */
+       prev = NULL;
+       for (e = agfstedge(subg->root, n); e;
+            e = agnxtedge(subg->root, e, n)) {
+           if (agcontains(subg, e))
+               continue;
+
+           /* short/flat multi edges */
+           if (mergeable(prev, e)) {
+               if (ND_rank(e->tail) == ND_rank(e->head))
+                   ED_to_virt(e) = prev;
+               else
+                   ED_to_virt(e) = NULL;
+               if (ED_to_virt(prev) == NULL)
+                   continue;   /* internal edge */
+               merge_chain(subg, e, ED_to_virt(prev), FALSE);
+               safe_other_edge(e);
+               continue;
+           }
+
+           /* flat edges */
+           if (ND_rank(e->tail) == ND_rank(e->head)) {
+               if (find_flat_edge(e->tail, e->head) == NULL) {
+                   flat_edge(g, e);
+                   prev = e;
+               } else
+                   prev = NULL;
+               continue;
+           }
+
+           assert(ED_to_virt(e) != NULL);
+
+           /* forward edges */
+           if (ND_rank(e->head) > ND_rank(e->tail)) {
+               make_interclust_chain(g, e->tail, e->head, e);
+               prev = e;
+               continue;
+           }
+
+           /* backward edges */
+           else {
+/*
+I think that make_interclust_chain should create call other_edge(e) anyway 
+                               if (agcontains(subg,e->tail)
+                                       && agfindedge(subg->root,e->head,e->tail)) other_edge(e);
+*/
+               make_interclust_chain(g, e->head, e->tail, e);
+               prev = e;
+           }
+       }
     }
 }
 
-void remove_rankleaders(graph_t * g)
+static void 
+merge_ranks(graph_t * subg)
+{
+    int i, d, r, pos, ipos;
+    node_t *v;
+    graph_t *root;
+
+    root = subg->root;
+    if (GD_minrank(subg) > 0)
+       ND_rank(root)[GD_minrank(subg) - 1].valid = FALSE;
+    for (r = GD_minrank(subg); r <= GD_maxrank(subg); r++) {
+       d = GD_rank(subg)[r].n;
+       ipos = pos = GD_rankleader(subg)[r]->u.order;
+       make_slots(root, r, pos, d);
+       for (i = 0; i < GD_rank(subg)[r].n; i++) {
+           v = ND_rank(root)[r].v[pos] = GD_rank(subg)[r].v[i];
+           ND_order(v) = pos++;
+           v->graph = subg->root;
+           delete_fast_node(subg, v);
+           fast_node(subg->root, v);
+           GD_n_nodes(subg->root)++;
+       }
+       GD_rank(subg)[r].v = ND_rank(root)[r].v + ipos;
+       ND_rank(root)[r].valid = FALSE;
+    }
+    if (r < GD_maxrank(root))
+       GD_rank(root)[r].valid = FALSE;
+    GD_expanded(subg) = TRUE;
+}
+
+static void 
+remove_rankleaders(graph_t * g)
 {
     int r;
     node_t *v;
@@ -383,6 +276,117 @@ void remove_rankleaders(graph_t * g)
     }
 }
 
+/* delete virtual nodes of a cluster, and install real nodes or sub-clusters */
+void expand_cluster(graph_t * subg)
+{
+    /* build internal structure of the cluster */
+    class2(subg);
+    GD_comp(subg).size = 1;
+    GD_comp(subg).list[0] = GD_nlist(subg);
+    allocate_ranks(subg);
+    build_ranks(subg, 0);
+    merge_ranks(subg);
+
+    /* build external structure of the cluster */
+    interclexp(subg);
+    remove_rankleaders(subg);
+}
+
+/* this function marks every node in <g> with its top-level cluster under <g> */
+void mark_clusters(graph_t * g)
+{
+    int c;
+    node_t *n, *vn;
+    edge_t *orig, *e;
+    graph_t *clust;
+
+    /* remove sub-clusters below this level */
+    for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
+       if (ND_ranktype(n) == CLUSTER)
+           UF_singleton(n);
+       ND_clust(n) = NULL;
+    }
+
+    for (c = 1; c <= GD_n_cluster(g); c++) {
+       clust = GD_clust(g)[c];
+       for (n = agfstnode(clust); n; n = agnxtnode(clust, n)) {
+           if (ND_ranktype(n) != NORMAL) {
+               agerr(AGWARN,
+                     "%s was already in a rankset, ignored in cluster %s\n",
+                     n->name, g->name);
+               continue;
+           }
+           UF_setname(n, GD_leader(clust));
+           ND_clust(n) = clust;
+           ND_ranktype(n) = CLUSTER;
+
+           /* here we mark the vnodes of edges in the cluster */
+           for (orig = agfstout(clust, n); orig;
+                orig = agnxtout(clust, orig)) {
+               if ((e = ED_to_virt(orig))) {
+                   while (e && (vn = e->head)->u.node_type == VIRTUAL) {
+                       ND_clust(vn) = clust;
+                       e = ND_out(e->head).list[0];
+                       /* trouble if concentrators and clusters are mixed */
+                   }
+               }
+           }
+       }
+    }
+}
+
+void build_skeleton(graph_t * g, graph_t * subg)
+{
+    int r;
+    node_t *v, *prev, *rl;
+    edge_t *e;
+
+    prev = NULL;
+    GD_rankleader(subg) = N_NEW(GD_maxrank(subg) + 2, node_t *);
+    for (r = GD_minrank(subg); r <= GD_maxrank(subg); r++) {
+       v = GD_rankleader(subg)[r] = virtual_node(g);
+       ND_rank(v) = r;
+       ND_ranktype(v) = CLUSTER;
+       ND_clust(v) = subg;
+       if (prev) {
+           e = virtual_edge(prev, v, NULL);
+           ED_xpenalty(e) *= CL_CROSS;
+       }
+       prev = v;
+    }
+
+    /* set the counts on virtual edges of the cluster skeleton */
+    for (v = agfstnode(subg); v; v = agnxtnode(subg, v)) {
+       rl = GD_rankleader(subg)[ND_rank(v)];
+       ND_UF_size(rl)++;
+       for (e = agfstout(subg, v); e; e = agnxtout(subg, e)) {
+           for (r = ND_rank(e->tail); r < ND_rank(e->head); r++) {
+               ED_count(ND_out(rl).list[0])++;
+           }
+       }
+    }
+    for (r = GD_minrank(subg); r <= GD_maxrank(subg); r++) {
+       rl = GD_rankleader(subg)[r];
+       if (ND_UF_size(rl) > 1)
+           ND_UF_size(rl)--;
+    }
+}
+
+void install_cluster(graph_t * g, node_t * n, int pass, queue * q)
+{
+    int r;
+    graph_t *clust;
+
+    clust = ND_clust(n);
+    if (GD_installed(clust) != pass + 1) {
+       for (r = GD_minrank(clust); r <= GD_maxrank(clust); r++)
+           install_in_rank(g, GD_rankleader(clust)[r]);
+       for (r = GD_minrank(clust); r <= GD_maxrank(clust); r++)
+           enqueue_neighbors(q, GD_rankleader(clust)[r], pass);
+       GD_installed(clust) = pass + 1;
+    }
+}
+
 static void mark_lowcluster_basic(Agraph_t * g);
 void mark_lowclusters(Agraph_t * root)
 {
index f1805be57310f169c155f3d66840d9175ab7a937..43789b9feae93b7a119f91ed5580948a38ce46b5 100644 (file)
@@ -334,9 +334,6 @@ static void makeCompoundEdge(graph_t * g, edge_t * e)
     point pts[4];
     point p;
     int fixed;
-    inside_t inside_context;
-
-    inside_context.e = e;
 
     /* find head and tail target clusters, if defined */
     lh = getCluster(g, agget(e, "lhead"));
@@ -396,7 +393,7 @@ static void makeCompoundEdge(graph_t * g, edge_t * e)
                    bez->list[2] = midPt(bez->list[1], p);
                    if (bez->eflag)
                        endi =
-                           arrowEndClip(&inside_context, bez->list,
+                           arrowEndClip(e, bez->list,
                                         starti, 0, nbez, bez->eflag);
                    endi += 3;
                    fixed = 1;
@@ -412,7 +409,7 @@ static void makeCompoundEdge(graph_t * g, edge_t * e)
                } else {
                    if (bez->eflag)
                        endi =
-                           arrowEndClip(&inside_context, bez->list,
+                           arrowEndClip(e, bez->list,
                                         starti, endi, nbez, bez->eflag);
                    endi += 3;
                }
@@ -460,7 +457,7 @@ static void makeCompoundEdge(graph_t * g, edge_t * e)
                        midPt(bez->list[starti + 2], p);
                    if (bez->sflag)
                        starti =
-                           arrowStartClip(&inside_context, bez->list,
+                           arrowStartClip(e, bez->list,
                                           starti, endi - 3, nbez,
                                           bez->sflag);
                    fixed = 1;
@@ -483,7 +480,7 @@ static void makeCompoundEdge(graph_t * g, edge_t * e)
                    starti -= 3;
                    if (bez->sflag)
                        starti =
-                           arrowStartClip(&inside_context, bez->list,
+                           arrowStartClip(e, bez->list,
                                           starti, endi - 3, nbez,
                                           bez->sflag);
                }