]> 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/dotinit.c
lib/dotgen/dotprocs.h
lib/dotgen/fastgr.c
lib/dotgen/mincross.c
lib/dotgen/position.c
lib/dotgen/rank.c
lib/dotgen/sameport.c

index 9467d728bd7c03a853660bf96039ebf91a58d820..96128bd0ef13c04204181bbd48c390c089afa8c9 100644 (file)
@@ -37,7 +37,8 @@ void dot_nodesize(node_t * n, boolean flip)
     ND_ht_i(n) = POINTS(y);
 }
 
-void dot_init_node(node_t * n)
+static void 
+dot_init_node(node_t * n)
 {
     common_init_node(n);
     dot_nodesize(n, GD_flip(n->graph));
@@ -49,7 +50,8 @@ void dot_init_node(node_t * n)
     ND_UF_size(n) = 1;
 }
 
-void dot_init_edge(edge_t * e)
+static void 
+dot_init_edge(edge_t * e)
 {
     char *tailgroup, *headgroup;
 
@@ -72,7 +74,8 @@ void dot_init_edge(edge_t * e)
     ED_minlen(e) = late_int(e, E_minlen, 1, 0);
 }
 
-void dot_init_node_edge(graph_t * g)
+static void 
+dot_init_node_edge(graph_t * g)
 {
     node_t *n;
     edge_t *e;
@@ -98,7 +101,8 @@ static void free_edge_list(elist L)
 }
 #endif
 
-void dot_cleanup_node(node_t * n)
+static void 
+dot_cleanup_node(node_t * n)
 {
     free_list(ND_in(n));
     free_list(ND_out(n));
@@ -111,7 +115,8 @@ void dot_cleanup_node(node_t * n)
     memset(&(n->u), 0, sizeof(Agnodeinfo_t));
 }
 
-void dot_free_splines(edge_t * e)
+static void 
+dot_free_splines(edge_t * e)
 {
     int i;
     if (ED_spl(e)) {
@@ -123,7 +128,8 @@ void dot_free_splines(edge_t * e)
     ED_spl(e) = NULL;
 }
 
-void dot_cleanup_edge(edge_t * e)
+static void 
+dot_cleanup_edge(edge_t * e)
 {
     dot_free_splines(e);
     free_label(ED_label(e));
@@ -163,7 +169,8 @@ static void free_virtual_node_list(node_t * vn)
     }
 }
 
-void dot_cleanup_graph(graph_t * g)
+static void 
+dot_cleanup_graph(graph_t * g)
 {
     int i, c;
     graph_t *clust;
@@ -200,7 +207,8 @@ void dot_cleanup(graph_t * g)
     dot_cleanup_graph(g);
 }
 
-void dot_init_graph(Agraph_t * g)
+static void 
+dot_init_graph(Agraph_t * g)
 {
     UseRankdir = TRUE;
     graph_init(g);
index f26f7b53f399e9cb427e07af0f3eacd12e7962f9..7ff0c48a0e0788bd4a4a028b745fbfdbefc675fa 100644 (file)
@@ -26,127 +26,48 @@ extern "C" {
 #endif
 
     extern void acyclic(Agraph_t *);
-    extern void add_to_component(Agnode_t *);
     extern void allocate_ranks(Agraph_t *);
-    extern void basic_merge(Agedge_t *, Agedge_t *);
-    extern void begin_component(void);
     extern void build_ranks(Agraph_t *, int);
     extern void build_skeleton(Agraph_t *, Agraph_t *);
     extern void class1(Agraph_t *);
     extern void class2(Agraph_t *);
-    extern void cleanup1(Agraph_t *);
-    extern Agnode_t *clone_vn(Agraph_t *, Agnode_t *);
-    extern void cluster_leader(Agraph_t *);
-    extern void collapse_cluster(Agraph_t *, Agraph_t *);
-    extern void collapse_leaves(Agraph_t *);
-    extern void collapse_rankset(Agraph_t *, Agraph_t *, int);
-    extern void collapse_sets(Agraph_t *);
     extern void decompose(Agraph_t *, int);
     extern void delete_fast_edge(Agedge_t *);
     extern void delete_fast_node(Agraph_t *, Agnode_t *);
     extern void delete_flat_edge(Agedge_t *);
-    extern void delete_other_edge(Agedge_t *);
-    extern void dfs(Agnode_t *);
-    extern void do_ordering(Agraph_t *, int);
     extern void dot_cleanup(graph_t * g);
-    extern void dot_cleanup_edge(edge_t * e);
-    extern void dot_cleanup_graph(graph_t * g);
-    extern void dot_cleanup_node(node_t * n);
-    extern void dot_free_splines(edge_t * e);
-    extern void dot_init_node_edge(Agraph_t *);
-    extern void dot_init_edge(Agedge_t *);
-    extern void dot_init_node(Agnode_t *);
     extern void dot_layout(Agraph_t * g);
-    extern void dot_init_graph(graph_t * g);
-    extern void edgelabel_ranks(Agraph_t *);
-    extern void end_component(void);
-    extern void exchange(Agnode_t *, Agnode_t *);
     extern void expand_cluster(Agraph_t *);
-    extern void expand_ranksets(Agraph_t *);
     extern Agedge_t *fast_edge(Agedge_t *);
     extern void fast_node(Agraph_t *, Agnode_t *);
     extern void fast_nodeapp(Agnode_t *, Agnode_t *);
-    extern void find_clusters(Agraph_t *);
     extern Agedge_t *find_fast_edge(Agnode_t *, Agnode_t *);
-    extern Agnode_t *find_fast_node(Agraph_t *, Agnode_t *);
     extern Agedge_t *find_flat_edge(Agnode_t *, Agnode_t *);
     extern void flat_edge(Agraph_t *, Agedge_t *);
     extern int flat_edges(Agraph_t *);
-    extern int flat_mval(Agnode_t *);
-    extern int in_cross(Agnode_t *, Agnode_t *);
-    extern void incr_width(Agraph_t *, Agnode_t *);
-    extern int inside_cluster(Agraph_t *, Agnode_t *);
     extern void install_cluster(Agraph_t *, Agnode_t *, int, queue *);
     extern void install_in_rank(Agraph_t *, Agnode_t *);
-    extern void interclexp(Agraph_t *);
-    extern void interclrep(Agraph_t *, Agedge_t *);
-    extern void interclust1(Agraph_t *, Agnode_t *, Agnode_t *,
-                           Agedge_t *);
-    extern int is_a_normal_node_of(Agraph_t *, Agnode_t *);
-    extern int is_a_vnode_of_an_edge_of(Agraph_t *, Agnode_t *);
     extern int is_cluster(Agraph_t *);
-    extern int is_cluster_edge(Agedge_t *);
-    extern int is_fast_node(Agraph_t *, Agnode_t *);
-    extern Agnode_t *label_vnode(Agraph_t *, Agedge_t *);
-    extern Agnode_t *leader_of(Agraph_t *, Agnode_t *);
-    extern int left2right(Agraph_t *, Agnode_t *, Agnode_t *);
-    extern int local_cross(elist, int);
     extern void dot_compoundEdges(Agraph_t *);
     extern Agedge_t *make_aux_edge(Agnode_t *, Agnode_t *, int, int);
-    extern void make_chain(Agraph_t *, Agnode_t *, Agnode_t *, Agedge_t *);
-    extern void make_interclust_chain(Agraph_t *, Agnode_t *, Agnode_t *,
-                                     Agedge_t *);
-    extern int make_new_cluster(Agraph_t *, Agraph_t *);
-    extern void make_slots(Agraph_t *, int, int, int);
-    extern Agnode_t *map_interclust_node(Agnode_t *);
-    extern void map_path(Agnode_t *, Agnode_t *, Agedge_t *, Agedge_t *,
-                        int);
     extern void mark_clusters(Agraph_t *);
     extern void mark_lowclusters(Agraph_t *);
     extern int mergeable(edge_t * e, edge_t * f);
     extern void merge_chain(Agraph_t *, Agedge_t *, Agedge_t *, int);
-    extern void merge_components(Agraph_t *);
-    extern Agnode_t *merge_leaves(Agraph_t *, Agnode_t *, Agnode_t *);
     extern void merge_oneway(Agedge_t *, Agedge_t *);
-    extern void merge_ranks(Agraph_t *);
-    extern void minmax_edges(Agraph_t *);
     extern int ncross(Agraph_t *);
     extern Agedge_t *new_virtual_edge(Agnode_t *, Agnode_t *, Agedge_t *);
-    extern void node_induce(Agraph_t *, Agraph_t *);
     extern int nonconstraint_edge(Agedge_t *);
-    extern int ordercmpf(int *, int *);
-    extern void ordered_edges(Agraph_t *);
     extern void other_edge(Agedge_t *);
-    extern int out_cross(Agnode_t *, Agnode_t *);
-    extern Agnode_t *plain_vnode(Agraph_t *, Agedge_t *);
     extern int portcmp(port p0, port p1);
-    extern void potential_leaf(Agraph_t *, Agedge_t *, Agnode_t *);
     extern int ports_eq(edge_t *, edge_t *);
-    extern void rank1(Agraph_t *);
     extern void rank(Agraph_t *, int, int);
-    extern int rank_set_class(Agraph_t *);
-    extern int rcross(Agraph_t *, int);
     extern void rec_reset_vlists(Agraph_t *);
     extern void rec_save_vlists(Agraph_t *);
-    extern void remove_rankleaders(Agraph_t *);
-    extern void renewlist(elist *);
-    extern void reorder(Agraph_t *, int, int, int);
     extern void reverse_edge(Agedge_t *);
-    extern void safe_delete_fast_edge(Agedge_t *);
-    extern void safe_list_append(Agedge_t *, elist *);
     extern void safe_other_edge(Agedge_t *);
     extern void save_vlist(Agraph_t *);
-    extern void scan_ranks(Agraph_t *);
-    extern void scan_result(void);
-    extern void search_component(Agraph_t *, Agnode_t *);
-    extern void set_minmax(Agraph_t *);
-    extern void setup_page(Agraph_t *, point);
-    extern int strccnt(char *, char);
-    extern void transpose(Agraph_t *, int);
-    extern int transpose_step(Agraph_t *, int, int);
     extern void unmerge_oneway(Agedge_t *);
-    extern void update(Agedge_t *, Agedge_t *);
-    extern void update_bb(Agraph_t *, point);
     extern Agedge_t *virtual_edge(Agnode_t *, Agnode_t *, Agedge_t *);
     extern Agnode_t *virtual_node(Agraph_t *);
     extern void virtual_weight(Agedge_t *);
index 98253a4f64419c970407d71a3841c5da344ae66c..b300403fce3b74aa731154f8cc01b18c67ba2228 100644 (file)
@@ -47,7 +47,8 @@ edge_t *find_fast_edge(node_t * u, node_t * v)
     return ffe(u, ND_out(u), v, ND_in(v));
 }
 
-node_t *find_fast_node(graph_t * g, node_t * n)
+static node_t*
+find_fast_node(graph_t * g, node_t * n)
 {
     node_t *v;
     for (v = GD_nlist(g); v; v = ND_next(v))
@@ -62,7 +63,8 @@ edge_t *find_flat_edge(node_t * u, node_t * v)
 }
 
 /* safe_list_append - append e to list L only if e not already a member */
-void safe_list_append(edge_t * e, elist * L)
+static void 
+safe_list_append(edge_t * e, elist * L)
 {
     int i;
 
@@ -120,7 +122,8 @@ void delete_fast_edge(edge_t * e)
     zapinlist(&(ND_in(e->head)), e);
 }
 
-void safe_delete_fast_edge(edge_t * e)
+static void 
+safe_delete_fast_edge(edge_t * e)
 {
     int i;
     edge_t *f;
@@ -144,11 +147,14 @@ void safe_other_edge(edge_t * e)
     safe_list_append(e, &(ND_other(e->tail)));
 }
 
-void delete_other_edge(edge_t * e)
+#ifdef OBSOLETET
+static void 
+delete_other_edge(edge_t * e)
 {
     assert(e != NULL);
     zapinlist(&(ND_other(e->tail)), e);
 }
+#endif
 
 /* orig might be an input edge, reverse of an input edge, or virtual edge */
 edge_t *new_virtual_edge(node_t * u, node_t * v, edge_t * orig)
@@ -302,18 +308,8 @@ void fastgr(graph_t * g)
 }
 #endif
 
-void merge_oneway(edge_t * e, edge_t * rep)
-{
-    if (rep == ED_to_virt(e)) {
-       agerr(AGWARN, "merge_oneway glitch\n");
-       return;
-    }
-    assert(ED_to_virt(e) == NULL);
-    ED_to_virt(e) = rep;
-    basic_merge(e, rep);
-}
-
-void basic_merge(edge_t * e, edge_t * rep)
+static void 
+basic_merge(edge_t * e, edge_t * rep)
 {
     if (ED_minlen(rep) < ED_minlen(e))
        ED_minlen(rep) = ED_minlen(e);
@@ -325,7 +321,20 @@ void basic_merge(edge_t * e, edge_t * rep)
     }
 }
 
-static void unrep(edge_t * rep, edge_t * e)
+void 
+merge_oneway(edge_t * e, edge_t * rep)
+{
+    if (rep == ED_to_virt(e)) {
+       agerr(AGWARN, "merge_oneway glitch\n");
+       return;
+    }
+    assert(ED_to_virt(e) == NULL);
+    ED_to_virt(e) = rep;
+    basic_merge(e, rep);
+}
+
+static void 
+unrep(edge_t * rep, edge_t * e)
 {
     ED_count(rep) -= ED_count(e);
     ED_xpenalty(rep) -= ED_xpenalty(e);
@@ -352,7 +361,9 @@ void unmerge_oneway(edge_t * e)
     ED_to_virt(e) = NULL;
 }
 
-int is_fast_node(graph_t * g, node_t * v)
+#ifdef OBSOLETET
+static int 
+is_fast_node(graph_t * g, node_t * v)
 {
     node_t *n;
 
@@ -361,3 +372,4 @@ int is_fast_node(graph_t * g, node_t * v)
            return TRUE;
     return FALSE;
 }
+#endif
index db64720df63980e57f43f00bf528a6c19339f532..621412563e817004e3375e1f48b66b7aa7cc115b 100644 (file)
@@ -67,6 +67,23 @@ static edge_t **TE_list;
 static int *TI_list;
 static boolean ReMincross;
 
+static void
+dumpRanks (graph_t * g)
+{
+    int i, j;
+    node_t* u;
+    rank_t *rank = GD_rank(g);
+    for (i = GD_minrank(g); i <= GD_maxrank(g); i++) {
+       fprintf (stderr, "[%d] :", i);
+       for (j = 0; j < rank[i].n; j++) {
+           u = rank[i].v[j];
+           fprintf (stderr, " %s", u->name);
+      
+        }
+       fprintf (stderr, "\n");
+    }
+}
+
 void dot_mincross(graph_t * g)
 {
     int c, nc;
@@ -101,6 +118,7 @@ void dot_mincross(graph_t * g)
 #endif
     }
     cleanup2(g, nc);
+    dumpRanks (g);
 }
 
 static adjmatrix_t *new_matrix(int i, int j)
@@ -122,7 +140,8 @@ static void free_matrix(adjmatrix_t * p)
 
 #define ELT(M,i,j)             (M->data[((i)*M->ncols)+(j)])
 
-static void init_mccomp(graph_t * g, int c)
+static void 
+init_mccomp(graph_t * g, int c)
 {
     int r;
 
@@ -135,7 +154,91 @@ static void init_mccomp(graph_t * g, int c)
     }
 }
 
-static int mincross_clust(graph_t * par, graph_t * g)
+static int betweenclust(edge_t * e)
+{
+    while (ED_to_orig(e))
+       e = ED_to_orig(e);
+    return (ND_clust(e->tail) != ND_clust(e->head));
+}
+
+static void 
+do_ordering(graph_t * g, int outflag)
+{
+    int i, ne;
+    node_t *n, *u, *v;
+    edge_t *e, *f, *fe;
+    edge_t **sortlist = TE_list;
+
+    for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
+       if (ND_clust(n))
+           continue;
+       if (outflag) {
+           for (i = ne = 0; (e = ND_out(n).list[i]); i++)
+               if (!betweenclust(e))
+                   sortlist[ne++] = e;
+       } else {
+           for (i = ne = 0; (e = ND_in(n).list[i]); i++)
+               if (!betweenclust(e))
+                   sortlist[ne++] = e;
+       }
+       if (ne <= 1)
+           continue;
+       /* write null terminator at end of list.
+          requires +1 in TE_list alloccation */
+       sortlist[ne] = 0;
+       qsort(sortlist, ne, sizeof(sortlist[0]), (qsort_cmpf) edgeidcmpf);
+       for (ne = 1; (f = sortlist[ne]); ne++) {
+           e = sortlist[ne - 1];
+           if (outflag) {
+               u = e->head;
+               v = f->head;
+           } else {
+               u = e->tail;
+               v = f->tail;
+           }
+           if (find_flat_edge(u, v))
+               continue;
+           fe = new_virtual_edge(u, v, NULL);
+           ED_edge_type(fe) = FLATORDER;
+           flat_edge(g, fe);
+       }
+    }
+}
+
+static void 
+ordered_edges(graph_t * g)
+{
+    char *ordering;
+
+    if ((ordering = agget(g, "ordering"))) {
+       if (streq(ordering, "out"))
+           do_ordering(g, TRUE);
+       else if (streq(ordering, "in"))
+           do_ordering(g, FALSE);
+       else if (ordering[0])
+           agerr(AGERR, "ordering '%s' not recognized.\n", ordering);
+    }
+
+    else {
+       /* search meta-graph to find subgraphs that may be ordered */
+       graph_t *mg, *subg;
+       node_t *mm, *mn;
+       edge_t *me;
+
+       mm = g->meta_node;
+       mg = mm->graph;
+       for (me = agfstout(mg, mm); me; me = agnxtout(mg, me)) {
+           mn = me->head;
+           subg = agusergraph(mn);
+           /* clusters are processed by seperate calls to ordered_edges */
+           if (!is_cluster(subg))
+               ordered_edges(subg);
+       }
+    }
+}
+
+static int 
+mincross_clust(graph_t * par, graph_t * g)
 {
     int c, nc;
 
@@ -152,6 +255,166 @@ static int mincross_clust(graph_t * par, graph_t * g)
     return nc;
 }
 
+static int 
+left2right(graph_t * g, node_t * v, node_t * w)
+{
+    adjmatrix_t *M;
+    int rv;
+
+    /* CLUSTER indicates orig nodes of clusters, and vnodes of skeletons */
+    if (ReMincross == FALSE) {
+       if ((ND_clust(v) != ND_clust(w)) && (ND_clust(v)) && (ND_clust(w))) {
+           /* the following allows cluster skeletons to be swapped */
+           if ((ND_ranktype(v) == CLUSTER)
+               && (ND_node_type(v) == VIRTUAL))
+               return FALSE;
+           if ((ND_ranktype(w) == CLUSTER)
+               && (ND_node_type(w) == VIRTUAL))
+               return FALSE;
+           return TRUE;
+           /*return ((ND_ranktype(v) != CLUSTER) && (ND_ranktype(w) != CLUSTER)); */
+       }
+    } else {
+       if ((ND_clust(v)) != (ND_clust(w)))
+           return TRUE;
+    }
+    M = GD_rank(g)[ND_rank(v)].flat;
+    if (M == NULL)
+       rv = FALSE;
+    else {
+       if (GD_flip(g)) {
+           node_t *t = v;
+           v = w;
+           w = t;
+       }
+       rv = ELT(M, flatindex(v), flatindex(w));
+    }
+    return rv;
+}
+
+static int 
+in_cross(node_t * v, node_t * w)
+{
+    register edge_t **e1, **e2;
+    register int inv, cross = 0, t;
+
+    for (e2 = ND_in(w).list; *e2; e2++) {
+       register int cnt = (*e2)->u.xpenalty;
+       inv = ((*e2)->tail)->u.order;
+
+       for (e1 = ND_in(v).list; *e1; e1++) {
+           t = ((*e1)->tail)->u.order - inv;
+           if ((t > 0)
+               || ((t == 0)
+                   && ((*e1)->u.tail_port.p.x > (*e2)->u.tail_port.p.x)))
+               cross += (*e1)->u.xpenalty * cnt;
+       }
+    }
+    return cross;
+}
+
+static int
+out_cross(node_t * v, node_t * w)
+{
+    register edge_t **e1, **e2;
+    register int inv, cross = 0, t;
+
+    for (e2 = ND_out(w).list; *e2; e2++) {
+       register int cnt = (*e2)->u.xpenalty;
+       inv = ((*e2)->head)->u.order;
+
+       for (e1 = ND_out(v).list; *e1; e1++) {
+           t = ((*e1)->head)->u.order - inv;
+           if ((t > 0)
+               || ((t == 0)
+                   && ((*e1)->u.head_port.p.x > (*e2)->u.head_port.p.x)))
+               cross += (*e1)->u.xpenalty * cnt;
+       }
+    }
+    return cross;
+
+}
+
+static void 
+exchange(node_t * v, node_t * w)
+{
+    int vi, wi, r;
+
+    r = ND_rank(v);
+    vi = ND_order(v);
+    wi = ND_order(w);
+    ND_order(v) = wi;
+    GD_rank(Root)[r].v[wi] = v;
+    ND_order(w) = vi;
+    GD_rank(Root)[r].v[vi] = w;
+}
+
+static int 
+transpose_step(graph_t * g, int r, int reverse)
+{
+    int i, c0, c1, rv;
+    node_t *v, *w;
+
+    rv = 0;
+    GD_rank(g)[r].candidate = FALSE;
+    for (i = 0; i < GD_rank(g)[r].n - 1; i++) {
+       v = GD_rank(g)[r].v[i];
+       w = GD_rank(g)[r].v[i + 1];
+       assert(ND_order(v) < ND_order(w));
+       if (left2right(g, v, w))
+           continue;
+       c0 = c1 = 0;
+       if (r > 0) {
+           c0 += in_cross(v, w);
+           c1 += in_cross(w, v);
+       }
+       if (GD_rank(g)[r + 1].n > 0) {
+           c0 += out_cross(v, w);
+           c1 += out_cross(w, v);
+       }
+       if ((c1 < c0) || ((c0 > 0) && reverse && (c1 == c0))) {
+           exchange(v, w);
+           rv += (c0 - c1);
+           GD_rank(Root)[r].valid = FALSE;
+           GD_rank(g)[r].candidate = TRUE;
+
+           if (r > GD_minrank(g)) {
+               GD_rank(Root)[r - 1].valid = FALSE;
+               GD_rank(g)[r - 1].candidate = TRUE;
+           }
+           if (r < GD_maxrank(g)) {
+               GD_rank(Root)[r + 1].valid = FALSE;
+               GD_rank(g)[r + 1].candidate = TRUE;
+           }
+       }
+    }
+    return rv;
+}
+
+static void 
+transpose(graph_t * g, int reverse)
+{
+    int r, delta;
+
+    for (r = GD_minrank(g); r <= GD_maxrank(g); r++)
+       GD_rank(g)[r].candidate = TRUE;
+    do {
+       delta = 0;
+#ifdef NOTDEF
+       /* don't run both the upward and downward passes- they cancel. 
+          i tried making it depend on whether an odd or even pass, 
+          but that didn't help. */
+       for (r = GD_maxrank(g); r >= GD_minrank(g); r--)
+           if (GD_rank(g)[r].candidate)
+               delta += transpose_step(g, r, reverse);
+#endif
+       for (r = GD_minrank(g); r <= GD_maxrank(g); r++)
+           if (GD_rank(g)[r].candidate)
+               delta += transpose_step(g, r, reverse);
+       /*} while (delta > ncross(g)*(1.0 - Convergence)); */
+    } while (delta >= 1);
+}
+
 static int mincross(graph_t * g, int startpass, int endpass)
 {
     int maxthispass, iter, trying, pass;
@@ -233,28 +496,54 @@ static void save_best(graph_t * g)
        saveorder(n) = ND_order(n);
 }
 
-/* merge connected components, create globally consistent rank lists */
-static void merge2(graph_t * g)
+/* merges the connected components of g */
+static void 
+merge_components(graph_t * g)
 {
-    int i, r;
-    node_t *v;
-
-    /* merge the components and rank limits */
-    merge_components(g);
+    int c;
+    node_t *u, *v;
 
-    /* install complete ranks */
-    for (r = GD_minrank(g); r <= GD_maxrank(g); r++) {
-       GD_rank(g)[r].n = GD_rank(g)[r].an;
-       GD_rank(g)[r].v = GD_rank(g)[r].av;
-       for (i = 0; i < GD_rank(g)[r].n; i++) {
-           v = GD_rank(g)[r].v[i];
-           if (v == NULL) {
-               if (Verbose)
-                   fprintf(stderr,
-                           "merge2: graph %s, rank %d has only %d < %d nodes\n",
-                           g->name, r, i, GD_rank(g)[r].n);
-               GD_rank(g)[r].n = i;
-               break;
+    if (GD_comp(g).size <= 1)
+       return;
+    u = NULL;
+    for (c = 0; c < GD_comp(g).size; c++) {
+       v = GD_comp(g).list[c];
+       if (u)
+           ND_next(u) = v;
+       ND_prev(v) = u;
+       while (ND_next(v)) {
+           v = ND_next(v);
+       }
+       u = v;
+    }
+    GD_comp(g).size = 1;
+    GD_nlist(g) = GD_comp(g).list[0];
+    GD_minrank(g) = GlobalMinRank;
+    GD_maxrank(g) = GlobalMaxRank;
+}
+
+/* merge connected components, create globally consistent rank lists */
+static void merge2(graph_t * g)
+{
+    int i, r;
+    node_t *v;
+
+    /* merge the components and rank limits */
+    merge_components(g);
+
+    /* install complete ranks */
+    for (r = GD_minrank(g); r <= GD_maxrank(g); r++) {
+       GD_rank(g)[r].n = GD_rank(g)[r].an;
+       GD_rank(g)[r].v = GD_rank(g)[r].av;
+       for (i = 0; i < GD_rank(g)[r].n; i++) {
+           v = GD_rank(g)[r].v[i];
+           if (v == NULL) {
+               if (Verbose)
+                   fprintf(stderr,
+                           "merge2: graph %s, rank %d has only %d < %d nodes\n",
+                           g->name, r, i, GD_rank(g)[r].n);
+               GD_rank(g)[r].n = i;
+               break;
            }
            ND_order(v) = i;
        }
@@ -313,17 +602,14 @@ static node_t *neighbor(node_t * v, int dir)
     return rv;
 }
 
-int inside_cluster(graph_t * g, node_t * v)
-{
-    return (is_a_normal_node_of(g, v) | is_a_vnode_of_an_edge_of(g, v));
-}
-
-int is_a_normal_node_of(graph_t * g, node_t * v)
+static int 
+is_a_normal_node_of(graph_t * g, node_t * v)
 {
     return ((ND_node_type(v) == NORMAL) && agcontains(g, v));
 }
 
-int is_a_vnode_of_an_edge_of(graph_t * g, node_t * v)
+static int 
+is_a_vnode_of_an_edge_of(graph_t * g, node_t * v)
 {
     if ((ND_node_type(v) == VIRTUAL)
        && (ND_in(v).size == 1) && (ND_out(v).size == 1)) {
@@ -336,6 +622,12 @@ int is_a_vnode_of_an_edge_of(graph_t * g, node_t * v)
     return FALSE;
 }
 
+static int 
+inside_cluster(graph_t * g, node_t * v)
+{
+    return (is_a_normal_node_of(g, v) | is_a_vnode_of_an_edge_of(g, v));
+}
+
 static node_t *furthestnode(graph_t * g, node_t * v, int dir)
 {
     node_t *u, *rv;
@@ -500,42 +792,6 @@ static void flat_breakcycles(graph_t * g)
     }
 }
 
-int left2right(graph_t * g, node_t * v, node_t * w)
-{
-    adjmatrix_t *M;
-    int rv;
-
-    /* CLUSTER indicates orig nodes of clusters, and vnodes of skeletons */
-    if (ReMincross == FALSE) {
-       if ((ND_clust(v) != ND_clust(w)) && (ND_clust(v)) && (ND_clust(w))) {
-           /* the following allows cluster skeletons to be swapped */
-           if ((ND_ranktype(v) == CLUSTER)
-               && (ND_node_type(v) == VIRTUAL))
-               return FALSE;
-           if ((ND_ranktype(w) == CLUSTER)
-               && (ND_node_type(w) == VIRTUAL))
-               return FALSE;
-           return TRUE;
-           /*return ((ND_ranktype(v) != CLUSTER) && (ND_ranktype(w) != CLUSTER)); */
-       }
-    } else {
-       if ((ND_clust(v)) != (ND_clust(w)))
-           return TRUE;
-    }
-    M = GD_rank(g)[ND_rank(v)].flat;
-    if (M == NULL)
-       rv = FALSE;
-    else {
-       if (GD_flip(g)) {
-           node_t *t = v;
-           v = w;
-           w = t;
-       }
-       rv = ELT(M, flatindex(v), flatindex(w));
-    }
-    return rv;
-}
-
 void allocate_ranks(graph_t * g)
 {
     int r, low, high, *cn;
@@ -775,7 +1031,61 @@ static void flat_reorder(graph_t * g)
        free(temprank);
 }
 
-static void mincross_step(graph_t * g, int pass)
+static void 
+reorder(graph_t * g, int r, int reverse, int hasfixed)
+{
+    int changed = 0, nelt;
+    boolean muststay, sawclust;
+    node_t **vlist = GD_rank(g)[r].v;
+    node_t **lp, **rp, **ep = vlist + GD_rank(g)[r].n;
+
+    for (nelt = GD_rank(g)[r].n - 1; nelt >= 0; nelt--) {
+       lp = vlist;
+       while (lp < ep) {
+           /* find leftmost node that can be compared */
+           while ((lp < ep) && ((*lp)->u.mval < 0))
+               lp++;
+           if (lp >= ep)
+               break;
+           /* find the node that can be compared */
+           sawclust = muststay = FALSE;
+           for (rp = lp + 1; rp < ep; rp++) {
+               if (sawclust && (*rp)->u.clust)
+                   continue;   /* ### */
+               if (left2right(g, *lp, *rp)) {
+                   muststay = TRUE;
+                   break;
+               }
+               if ((*rp)->u.mval >= 0)
+                   break;
+               if ((*rp)->u.clust)
+                   sawclust = TRUE;    /* ### */
+           }
+           if (rp >= ep)
+               break;
+           if (muststay == FALSE) {
+               register int p1 = ((*lp)->u.mval);
+               register int p2 = ((*rp)->u.mval);
+               if ((p1 > p2) || ((p1 == p2) && (reverse))) {
+                   exchange(*lp, *rp);
+                   changed++;
+               }
+           }
+           lp = rp;
+       }
+       if ((hasfixed == FALSE) && (reverse == FALSE))
+           ep--;
+    }
+
+    if (changed) {
+       GD_rank(Root)[r].valid = FALSE;
+       if (r > 0)
+           GD_rank(Root)[r - 1].valid = FALSE;
+    }
+}
+
+static void 
+mincross_step(graph_t * g, int pass)
 {
     int r, other, first, last, dir;
     int hasfixed, reverse;
@@ -815,30 +1125,8 @@ static void mincross_step(graph_t * g, int pass)
     transpose(g, NOT(reverse));
 }
 
-void transpose(graph_t * g, int reverse)
-{
-    int r, delta;
-
-    for (r = GD_minrank(g); r <= GD_maxrank(g); r++)
-       GD_rank(g)[r].candidate = TRUE;
-    do {
-       delta = 0;
-#ifdef NOTDEF
-       /* don't run both the upward and downward passes- they cancel. 
-          i tried making it depend on whether an odd or even pass, 
-          but that didn't help. */
-       for (r = GD_maxrank(g); r >= GD_minrank(g); r--)
-           if (GD_rank(g)[r].candidate)
-               delta += transpose_step(g, r, reverse);
-#endif
-       for (r = GD_minrank(g); r <= GD_maxrank(g); r++)
-           if (GD_rank(g)[r].candidate)
-               delta += transpose_step(g, r, reverse);
-       /*} while (delta > ncross(g)*(1.0 - Convergence)); */
-    } while (delta >= 1);
-}
-
-int local_cross(elist l, int dir)
+static int 
+local_cross(elist l, int dir)
 {
     int i, j, is_out;
     int cross = 0;
@@ -865,7 +1153,8 @@ int local_cross(elist l, int dir)
     return cross;
 }
 
-int rcross(graph_t * g, int r)
+static int 
+rcross(graph_t * g, int r)
 {
     static int *Count, C;
     int top, bot, cross, max, i, k;
@@ -929,50 +1218,39 @@ int ncross(graph_t * g)
     return count;
 }
 
-int ordercmpf(int *i0, int *i1)
+static int 
+ordercmpf(int *i0, int *i1)
 {
     return (*i0) - (*i1);
 }
 
-int out_cross(node_t * v, node_t * w)
+static int 
+flat_mval(node_t * n)
 {
-    register edge_t **e1, **e2;
-    register int inv, cross = 0, t;
-
-    for (e2 = ND_out(w).list; *e2; e2++) {
-       register int cnt = (*e2)->u.xpenalty;
-       inv = ((*e2)->head)->u.order;
-
-       for (e1 = ND_out(v).list; *e1; e1++) {
-           t = ((*e1)->head)->u.order - inv;
-           if ((t > 0)
-               || ((t == 0)
-                   && ((*e1)->u.head_port.p.x > (*e2)->u.head_port.p.x)))
-               cross += (*e1)->u.xpenalty * cnt;
-       }
-    }
-    return cross;
-
-}
-
-int in_cross(node_t * v, node_t * w)
-{
-    register edge_t **e1, **e2;
-    register int inv, cross = 0, t;
-
-    for (e2 = ND_in(w).list; *e2; e2++) {
-       register int cnt = (*e2)->u.xpenalty;
-       inv = ((*e2)->tail)->u.order;
+    int i;
+    edge_t *e, **fl;
+    node_t *nn;
 
-       for (e1 = ND_in(v).list; *e1; e1++) {
-           t = ((*e1)->tail)->u.order - inv;
-           if ((t > 0)
-               || ((t == 0)
-                   && ((*e1)->u.tail_port.p.x > (*e2)->u.tail_port.p.x)))
-               cross += (*e1)->u.xpenalty * cnt;
+    if ((ND_in(n).size == 0) && (ND_out(n).size == 0)) {
+       if (ND_flat_in(n).size > 0) {
+           fl = ND_flat_in(n).list;
+           nn = fl[0]->tail;
+           for (i = 1; (e = fl[i]); i++)
+               if (ND_order(e->tail) > ND_order(nn))
+                   nn = e->tail;
+           ND_mval(n) = ND_mval(nn) + 1;
+           return FALSE;
+       } else if (ND_flat_out(n).size > 0) {
+           fl = ND_flat_out(n).list;
+           nn = fl[0]->head;
+           for (i = 1; (e = fl[i]); i++)
+               if (ND_order(e->head) < ND_order(nn))
+                   nn = e->head;
+           ND_mval(n) = ND_mval(nn) - 1;
+           return FALSE;
        }
     }
-    return cross;
+    return TRUE;
 }
 
 #define VAL(node,port) (MC_SCALE * (node)->u.order + (port).order)
@@ -1035,112 +1313,6 @@ static boolean medians(graph_t * g, int r0, int r1)
     return hasfixed;
 }
 
-int transpose_step(graph_t * g, int r, int reverse)
-{
-    int i, c0, c1, rv;
-    node_t *v, *w;
-
-    rv = 0;
-    GD_rank(g)[r].candidate = FALSE;
-    for (i = 0; i < GD_rank(g)[r].n - 1; i++) {
-       v = GD_rank(g)[r].v[i];
-       w = GD_rank(g)[r].v[i + 1];
-       assert(ND_order(v) < ND_order(w));
-       if (left2right(g, v, w))
-           continue;
-       c0 = c1 = 0;
-       if (r > 0) {
-           c0 += in_cross(v, w);
-           c1 += in_cross(w, v);
-       }
-       if (GD_rank(g)[r + 1].n > 0) {
-           c0 += out_cross(v, w);
-           c1 += out_cross(w, v);
-       }
-       if ((c1 < c0) || ((c0 > 0) && reverse && (c1 == c0))) {
-           exchange(v, w);
-           rv += (c0 - c1);
-           GD_rank(Root)[r].valid = FALSE;
-           GD_rank(g)[r].candidate = TRUE;
-
-           if (r > GD_minrank(g)) {
-               GD_rank(Root)[r - 1].valid = FALSE;
-               GD_rank(g)[r - 1].candidate = TRUE;
-           }
-           if (r < GD_maxrank(g)) {
-               GD_rank(Root)[r + 1].valid = FALSE;
-               GD_rank(g)[r + 1].candidate = TRUE;
-           }
-       }
-    }
-    return rv;
-}
-
-void exchange(node_t * v, node_t * w)
-{
-    int vi, wi, r;
-
-    r = ND_rank(v);
-    vi = ND_order(v);
-    wi = ND_order(w);
-    ND_order(v) = wi;
-    GD_rank(Root)[r].v[wi] = v;
-    ND_order(w) = vi;
-    GD_rank(Root)[r].v[vi] = w;
-}
-
-void reorder(graph_t * g, int r, int reverse, int hasfixed)
-{
-    int changed = 0, nelt;
-    boolean muststay, sawclust;
-    node_t **vlist = GD_rank(g)[r].v;
-    node_t **lp, **rp, **ep = vlist + GD_rank(g)[r].n;
-
-    for (nelt = GD_rank(g)[r].n - 1; nelt >= 0; nelt--) {
-       lp = vlist;
-       while (lp < ep) {
-           /* find leftmost node that can be compared */
-           while ((lp < ep) && ((*lp)->u.mval < 0))
-               lp++;
-           if (lp >= ep)
-               break;
-           /* find the node that can be compared */
-           sawclust = muststay = FALSE;
-           for (rp = lp + 1; rp < ep; rp++) {
-               if (sawclust && (*rp)->u.clust)
-                   continue;   /* ### */
-               if (left2right(g, *lp, *rp)) {
-                   muststay = TRUE;
-                   break;
-               }
-               if ((*rp)->u.mval >= 0)
-                   break;
-               if ((*rp)->u.clust)
-                   sawclust = TRUE;    /* ### */
-           }
-           if (rp >= ep)
-               break;
-           if (muststay == FALSE) {
-               register int p1 = ((*lp)->u.mval);
-               register int p2 = ((*rp)->u.mval);
-               if ((p1 > p2) || ((p1 == p2) && (reverse))) {
-                   exchange(*lp, *rp);
-                   changed++;
-               }
-           }
-           lp = rp;
-       }
-       if ((hasfixed == FALSE) && (reverse == FALSE))
-           ep--;
-    }
-
-    if (changed) {
-       GD_rank(Root)[r].valid = FALSE;
-       if (r > 0)
-           GD_rank(Root)[r - 1].valid = FALSE;
-    }
-}
-
 static int nodeposcmpf(node_t ** n0, node_t ** n1)
 {
     return ((*n0)->u.order - (*n1)->u.order);
@@ -1184,112 +1356,6 @@ void virtual_weight(edge_t * e)
     ED_weight(e) *= t;
 }
 
-void ordered_edges(graph_t * g)
-{
-    char *ordering;
-
-    if ((ordering = agget(g, "ordering"))) {
-       if (streq(ordering, "out"))
-           do_ordering(g, TRUE);
-       else if (streq(ordering, "in"))
-           do_ordering(g, FALSE);
-       else if (ordering[0])
-           agerr(AGERR, "ordering '%s' not recognized.\n", ordering);
-    }
-
-    else {
-       /* search meta-graph to find subgraphs that may be ordered */
-       graph_t *mg, *subg;
-       node_t *mm, *mn;
-       edge_t *me;
-
-       mm = g->meta_node;
-       mg = mm->graph;
-       for (me = agfstout(mg, mm); me; me = agnxtout(mg, me)) {
-           mn = me->head;
-           subg = agusergraph(mn);
-           /* clusters are processed by seperate calls to ordered_edges */
-           if (!is_cluster(subg))
-               ordered_edges(subg);
-       }
-    }
-}
-
-static int betweenclust(edge_t * e)
-{
-    while (ED_to_orig(e))
-       e = ED_to_orig(e);
-    return (ND_clust(e->tail) != ND_clust(e->head));
-}
-
-void do_ordering(graph_t * g, int outflag)
-{
-    int i, ne;
-    node_t *n, *u, *v;
-    edge_t *e, *f, *fe;
-    edge_t **sortlist = TE_list;
-
-    for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
-       if (ND_clust(n))
-           continue;
-       if (outflag) {
-           for (i = ne = 0; (e = ND_out(n).list[i]); i++)
-               if (!betweenclust(e))
-                   sortlist[ne++] = e;
-       } else {
-           for (i = ne = 0; (e = ND_in(n).list[i]); i++)
-               if (!betweenclust(e))
-                   sortlist[ne++] = e;
-       }
-       if (ne <= 1)
-           continue;
-       /* write null terminator at end of list.
-          requires +1 in TE_list alloccation */
-       sortlist[ne] = 0;
-       qsort(sortlist, ne, sizeof(sortlist[0]), (qsort_cmpf) edgeidcmpf);
-       for (ne = 1; (f = sortlist[ne]); ne++) {
-           e = sortlist[ne - 1];
-           if (outflag) {
-               u = e->head;
-               v = f->head;
-           } else {
-               u = e->tail;
-               v = f->tail;
-           }
-           if (find_flat_edge(u, v))
-               continue;
-           fe = new_virtual_edge(u, v, NULL);
-           ED_edge_type(fe) = FLATORDER;
-           flat_edge(g, fe);
-       }
-    }
-}
-
-/* merges the connected components of g */
-void merge_components(graph_t * g)
-{
-    int c;
-    node_t *u, *v;
-
-    if (GD_comp(g).size <= 1)
-       return;
-    u = NULL;
-    for (c = 0; c < GD_comp(g).size; c++) {
-       v = GD_comp(g).list[c];
-       if (u)
-           ND_next(u) = v;
-       ND_prev(v) = u;
-       while (ND_next(v)) {
-           v = ND_next(v);
-       }
-       u = v;
-    }
-    GD_comp(g).size = 1;
-    GD_nlist(g) = GD_comp(g).list[0];
-    GD_minrank(g) = GlobalMinRank;
-    GD_maxrank(g) = GlobalMaxRank;
-}
-
 #ifdef DEBUG
 void check_rs(graph_t * g, int null_ok)
 {
@@ -1348,34 +1414,6 @@ static void mincross_options(graph_t * g)
     }
 }
 
-int flat_mval(node_t * n)
-{
-    int i;
-    edge_t *e, **fl;
-    node_t *nn;
-
-    if ((ND_in(n).size == 0) && (ND_out(n).size == 0)) {
-       if (ND_flat_in(n).size > 0) {
-           fl = ND_flat_in(n).list;
-           nn = fl[0]->tail;
-           for (i = 1; (e = fl[i]); i++)
-               if (ND_order(e->tail) > ND_order(nn))
-                   nn = e->tail;
-           ND_mval(n) = ND_mval(nn) + 1;
-           return FALSE;
-       } else if (ND_flat_out(n).size > 0) {
-           fl = ND_flat_out(n).list;
-           nn = fl[0]->head;
-           for (i = 1; (e = fl[i]); i++)
-               if (ND_order(e->head) < ND_order(nn))
-                   nn = e->head;
-           ND_mval(n) = ND_mval(nn) - 1;
-           return FALSE;
-       }
-    }
-    return TRUE;
-}
-
 #ifdef DEBUG
 void check_exchange(node_t * v, node_t * w)
 {
index 61a75249c7b0b3d6975b3c34b9456d4251b0658e..bf2806bb3b126b5dd2c9d786fbadfcca82aaa8c2 100644 (file)
@@ -36,6 +36,25 @@ static void make_lrvn(graph_t * g);
 static void contain_nodes(graph_t * g);
 static int idealsize(graph_t * g, double);
 
+static void
+dumpNS (graph_t * g)
+{
+    node_t* n = GD_nlist(g);
+    elist el;
+    edge_t* e;
+    int i;
+
+    while (n) {
+       el = ND_out(n);
+       for (i = 0; i < el.size; i++) {
+           e = el.list[i];
+           fprintf (stderr, "%s(%x) -> %s(%x) : %d\n", e->tail->name,e->tail, e->head->name, e->head,
+               ED_minlen(e));
+       }
+       n = ND_next(n); 
+    }
+}
+
 void dot_position(graph_t * g)
 {
     if (GD_nlist(g) == NULL)
@@ -48,6 +67,7 @@ void dot_position(graph_t * g)
     if (flat_edges(g))
        set_ycoords(g);
     create_aux_edges(g);
+/* dumpNS (g); */
     rank(g, 2, nsiter2(g));    /* LR balance == 2 */
     set_xcoords(g);
     set_aspect(g);
@@ -136,17 +156,18 @@ static void make_LR_constraints(graph_t * g)
            u = rank[i].v[j];
            ND_mval(u) = ND_rw_i(u);    /* keep it somewhere safe */
            if (ND_other(u).size > 0) { /* compute self size */
+               /* FIX: dot assumes all self-edges go to the right. This
+                 * is no longer true, though makeSelfEdge still attempts to
+                 * put as many as reasonable on the right. The dot code
+                 * should be modified to allow a box reflecting the placement
+                 * of all self-edges, and use that to reposition the nodes.
+                 * Note that this would not only affect left and right
+                 * positioning but may also affect interrank spacing.
+                 */
                sw = 0;
                for (k = 0; (e = ND_other(u).list[k]); k++) {
                    if (e->tail == e->head) {
-                       sw += SELF_EDGE_SIZE;
-                       if (ED_label(e)) {
-                           double label_width;
-                           label_width =
-                               GD_flip(g) ? ED_label(e)->dimen.
-                               y : ED_label(e)->dimen.x;
-                           sw += label_width;
-                       }
+                       sw += selfRightSpace (e);
                    }
                }
                ND_rw_i(u) += sw;       /* increment to include self edges */
index a645f6da848fd7deca1906891fa005d337830958..d3f428dc43979d41bd5012a8441c5326f165ba68 100644 (file)
 
 #include       "dot.h"
 
+static void 
+renewlist(elist * L)
+{
+    int i;
+    for (i = L->size; i >= 0; i--)
+       L->list[i] = NULL;
+    L->size = 0;
+}
 
-void dot_rank(graph_t * g)
+static void 
+cleanup1(graph_t * g)
 {
-    edgelabel_ranks(g);
-    collapse_sets(g);
-    /*collapse_leaves(g); */
-    class1(g);
-    minmax_edges(g);
-    decompose(g, 0);
-    acyclic(g);
-    rank1(g);
-    expand_ranksets(g);
-    cleanup1(g);
+    node_t *n;
+    edge_t *e, *f;
+    int c;
+
+    for (c = 0; c < GD_comp(g).size; c++) {
+       GD_nlist(g) = GD_comp(g).list[c];
+       for (n = GD_nlist(g); n; n = ND_next(n)) {
+           renewlist(&ND_in(n));
+           renewlist(&ND_out(n));
+           ND_mark(n) = FALSE;
+       }
+    }
+    for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
+       for (e = agfstout(g, n); e; e = agnxtout(g, e)) {
+           f = ED_to_virt(e);
+           if (f && (e == ED_to_orig(f))) {
+               /* Null out any other references to f to make sure we don't handle it
+                * a second time. For example, parallel multiedges share a virtual edge.
+                */
+               edge_t *e1, *f1;
+               for (e1 = agfstout(g, n); e1; e1 = agnxtout(g, e1)) {
+                   if (e != e1) {
+                       f1 = ED_to_virt(e1);
+                       if (f1 && (f == f1)) {
+                           ED_to_virt(e1) = NULL;
+                       }
+                   }
+               }
+               free(f);
+           }
+           ED_to_virt(e) = NULL;
+       }
+    }
+    free(GD_comp(g).list);
+    GD_comp(g).list = NULL;
+    GD_comp(g).size = 0;
 }
 
 /* When there are edge labels, extra ranks are reserved here for the virtual
  * nodes of the labels.  This is done by doubling the input edge lengths.
  * The input rank separation is adjusted to compensate.
  */
-void edgelabel_ranks(graph_t * g)
+static void 
+edgelabel_ranks(graph_t * g)
 {
     node_t *n;
     edge_t *e;
@@ -63,70 +99,9 @@ void edgelabel_ranks(graph_t * g)
     }
 }
 
-/* Run the network simplex algorithm on each component. */
-void rank1(graph_t * g)
-{
-    int maxiter = MAXINT;
-    int c;
-    char *s;
-
-    if ((s = agget(g, "nslimit1")))
-       maxiter = atof(s) * agnnodes(g);
-    for (c = 0; c < GD_comp(g).size; c++) {
-       GD_nlist(g) = GD_comp(g).list[c];
-       rank(g, (GD_n_cluster(g) == 0 ? 1 : 0), maxiter);       /* TB balance */
-    }
-}
-
-int is_cluster(graph_t * g)
-{
-    return (strncmp(g->name, "cluster", 7) == 0);
-}
-
-int rank_set_class(graph_t * g)
-{
-    static char *name[] = { "same", "min", "source", "max", "sink", NULL };
-    static int class[] =
-       { SAMERANK, MINRANK, SOURCERANK, MAXRANK, SINKRANK, 0 };
-    int val;
-
-    if (is_cluster(g))
-       return CLUSTER;
-    val = maptoken(agget(g, "rank"), name, class);
-    GD_set_type(g) = val;
-    return val;
-}
-
-/* Execute union commands for "same rank" subgraphs and clusters. */
-void collapse_sets(graph_t * g)
-{
-    int c;
-    graph_t *mg, *subg;
-    node_t *mn, *n;
-    edge_t *me;
-
-    mg = g->meta_node->graph;
-    for (me = agfstout(mg, g->meta_node); me; me = agnxtout(mg, me)) {
-       mn = me->head;
-       subg = agusergraph(mn);
-
-       c = rank_set_class(subg);
-       if (c) {
-           if ((c == CLUSTER) && CL_type == LOCAL)
-               collapse_cluster(g, subg);
-           else
-               collapse_rankset(g, subg, c);
-       }
-
-       /* mark nodes with ordered edges so their leaves are not collapsed */
-       if (agget(subg, "ordering"))
-           for (n = agfstnode(subg); n; n = agnxtnode(subg, n))
-               ND_order(n) = 1;
-    }
-}
-
 /* Merge the nodes of a min, max, or same rank set. */
-void collapse_rankset(graph_t * g, graph_t * subg, int kind)
+static void 
+collapse_rankset(graph_t * g, graph_t * subg, int kind)
 {
     node_t *u, *v;
 
@@ -164,101 +139,104 @@ void collapse_rankset(graph_t * g, graph_t * subg, int kind)
     }
 }
 
-node_t *merge_leaves(graph_t * g, node_t * cur, node_t * new)
+static int 
+rank_set_class(graph_t * g)
 {
-    node_t *rv;
+    static char *name[] = { "same", "min", "source", "max", "sink", NULL };
+    static int class[] =
+       { SAMERANK, MINRANK, SOURCERANK, MAXRANK, SINKRANK, 0 };
+    int val;
 
-    if (cur == NULL)
-       rv = new;
-    else {
-       rv = UF_union(cur, new);
-       ND_ht_i(rv) = MAX(ND_ht_i(cur), ND_ht_i(new));
-       ND_lw_i(rv) = ND_lw_i(cur) + ND_lw_i(new) + GD_nodesep(g) / 2;
-       ND_rw_i(rv) = ND_rw_i(cur) + ND_rw_i(new) + GD_nodesep(g) / 2;
-    }
-    return rv;
+    if (is_cluster(g))
+       return CLUSTER;
+    val = maptoken(agget(g, "rank"), name, class);
+    GD_set_type(g) = val;
+    return val;
 }
 
-void potential_leaf(graph_t * g, edge_t * e, node_t * leaf)
+static int 
+make_new_cluster(graph_t * g, graph_t * subg)
 {
-    node_t *par;
-
-    if ((ED_tail_port(e).p.x) || (ED_head_port(e).p.x))
-       return;
-    if ((ED_minlen(e) != 1) || (ND_order(e->tail) > 0))
-       return;
-    par = ((leaf != e->head) ? e->head : e->tail);
-    ND_ranktype(leaf) = LEAFSET;
-    if (par == e->tail)
-       GD_outleaf(par) = merge_leaves(g, GD_outleaf(par), leaf);
-    else
-       GD_inleaf(par) = merge_leaves(g, GD_inleaf(par), leaf);
+    int cno;
+    cno = ++(GD_n_cluster(g));
+    GD_clust(g) = ZALLOC(cno + 1, GD_clust(g), graph_t *, GD_n_cluster(g));
+    GD_clust(g)[cno] = subg;
+    do_graph_label(subg);
+    return cno;
 }
 
-void collapse_leaves(graph_t * g)
+static void 
+node_induce(graph_t * par, graph_t * g)
 {
-    node_t *n;
+    node_t *n, *nn;
     edge_t *e;
+    int i;
 
-    for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
-
-       /* consider n as a potential leaf of some other node. */
-       if ((ND_ranktype(n) != NOCMD) || (ND_order(n)))
+    /* enforce that a node is in at most one cluster at this level */
+    for (n = agfstnode(g); n; n = nn) {
+       nn = agnxtnode(g, n);
+       if (ND_ranktype(n)) {
+           agdelete(g, n);
            continue;
-       if (agfstout(g, n) == NULL) {
-           if ((e = agfstin(g, n)) && (agnxtin(g, e) == NULL)) {
-               potential_leaf(g, e, n);
-               continue;
-           }
        }
-       if (agfstin(g, n) == NULL) {
-           if ((e = agfstout(g, n)) && (agnxtout(g, e) == NULL)) {
-               potential_leaf(g, e, n);
-               continue;
-           }
+       for (i = 1; i < GD_n_cluster(par); i++)
+           if (agcontains(GD_clust(par)[i], n))
+               break;
+       if (i < GD_n_cluster(par))
+           agdelete(g, n);
+       ND_clust(n) = NULL;
+    }
+
+    for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
+       for (e = agfstout(g->root, n); e; e = agnxtout(g->root, e)) {
+           if (agcontains(g, e->head))
+               aginsert(g, e);
        }
     }
 }
 
-/* To ensure that min and max rank nodes always have the intended rank
- * assignment, reverse any incompatible edges.
- */
-void minmax_edges(graph_t * g)
+static void 
+scan_ranks(graph_t * g)
 {
-    node_t *n;
-    edge_t *e;
-    int srclen, sinklen;
-
-    srclen = sinklen = 0;
-    if ((GD_maxset(g) == NULL) && (GD_minset(g) == NULL))
-       return;
-    if (GD_minset(g) != NULL)
-       GD_minset(g) = UF_find(GD_minset(g));
-    if (GD_maxset(g) != NULL)
-       GD_maxset(g) = UF_find(GD_maxset(g));
-
-    if ((n = GD_maxset(g))) {
-       sinklen = (GD_maxset(g)->u.ranktype == SINKRANK);
-       while ((e = ND_out(n).list[0])) {
-           assert(e->head == UF_find(e->head));
-           reverse_edge(e);
+    node_t *n, *leader = NULL;
+    GD_minrank(g) = MAXSHORT;
+    GD_maxrank(g) = -1;
+    for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
+       if (GD_maxrank(g) < ND_rank(n))
+           GD_maxrank(g) = ND_rank(n);
+       if (GD_minrank(g) > ND_rank(n))
+           GD_minrank(g) = ND_rank(n);
+       if (leader == NULL)
+           leader = n;
+       else {
+           if (ND_rank(n) < ND_rank(leader))
+               leader = n;
        }
     }
-    if ((n = GD_minset(g))) {
-       srclen = (GD_minset(g)->u.ranktype == SOURCERANK);
-       while ((e = ND_in(n).list[0])) {
-           assert(e->tail == UF_find(e->tail));
-           reverse_edge(e);
-       }
+    GD_leader(g) = leader;
+}
+
+static void
+cluster_leader(graph_t * clust)
+{
+    node_t *leader, *n;
+    int maxrank = 0;
+
+    /* find number of ranks and select a leader */
+    leader = NULL;
+    for (n = GD_nlist(clust); n; n = ND_next(n)) {
+       if ((ND_rank(n) == 0) && (ND_node_type(n) == NORMAL))
+           leader = n;
+       if (maxrank < ND_rank(n))
+           maxrank = ND_rank(n);
     }
+    assert(leader != NULL);
+    GD_leader(clust) = leader;
 
-    for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
-       if (n != UF_find(n))
-           continue;
-       if ((ND_out(n).size == 0) && GD_maxset(g) && (n != GD_maxset(g)))
-           virtual_edge(n, GD_maxset(g), NULL)->u.minlen = sinklen;
-       if ((ND_in(n).size == 0) && GD_minset(g) && (n != GD_minset(g)))
-           virtual_edge(GD_minset(g), n, NULL)->u.minlen = srclen;
+    for (n = agfstnode(clust); n; n = agnxtnode(clust, n)) {
+       assert((ND_UF_size(n) <= 1) || (n == leader));
+       UF_union(n, leader);
+       ND_ranktype(n) = CLUSTER;
     }
 }
 
@@ -269,7 +247,8 @@ void minmax_edges(graph_t * g)
  * 3) In class1(), any inter-cluster edges are converted using
  *    the "virtual node + 2 edges" trick.
  */
-void collapse_cluster(graph_t * g, graph_t * subg)
+static void 
+collapse_cluster(graph_t * g, graph_t * subg)
 {
     if (GD_cluster_was_collapsed(subg))
        return;
@@ -285,65 +264,119 @@ void collapse_cluster(graph_t * g, graph_t * subg)
        scan_ranks(subg);
 }
 
-int make_new_cluster(graph_t * g, graph_t * subg)
+/* Execute union commands for "same rank" subgraphs and clusters. */
+static void 
+collapse_sets(graph_t * g)
 {
-    int cno;
-    cno = ++(GD_n_cluster(g));
-    GD_clust(g) = ZALLOC(cno + 1, GD_clust(g), graph_t *, GD_n_cluster(g));
-    GD_clust(g)[cno] = subg;
-    do_graph_label(subg);
-    return cno;
+    int c;
+    graph_t *mg, *subg;
+    node_t *mn, *n;
+    edge_t *me;
+
+    mg = g->meta_node->graph;
+    for (me = agfstout(mg, g->meta_node); me; me = agnxtout(mg, me)) {
+       mn = me->head;
+       subg = agusergraph(mn);
+
+       c = rank_set_class(subg);
+       if (c) {
+           if ((c == CLUSTER) && CL_type == LOCAL)
+               collapse_cluster(g, subg);
+           else
+               collapse_rankset(g, subg, c);
+       }
+
+       /* mark nodes with ordered edges so their leaves are not collapsed */
+       if (agget(subg, "ordering"))
+           for (n = agfstnode(subg); n; n = agnxtnode(subg, n))
+               ND_order(n) = 1;
+    }
 }
 
-void node_induce(graph_t * par, graph_t * g)
+static void 
+find_clusters(graph_t * g)
 {
-    node_t *n, *nn;
+    graph_t *mg, *subg;
+    node_t *mn;
+    edge_t *me;
+
+    mg = g->meta_node->graph;
+    for (me = agfstout(mg, g->meta_node); me; me = agnxtout(mg, me)) {
+       mn = me->head;
+       subg = agusergraph(mn);
+
+       if (GD_set_type(subg) == CLUSTER)
+           collapse_cluster(g, subg);
+    }
+}
+
+static void 
+set_minmax(graph_t * g)
+{
+    int c;
+
+    GD_minrank(g) += GD_leader(g)->u.rank;
+    GD_maxrank(g) += GD_leader(g)->u.rank;
+    for (c = 1; c <= GD_n_cluster(g); c++)
+       set_minmax(GD_clust(g)[c]);
+}
+
+/* To ensure that min and max rank nodes always have the intended rank
+ * assignment, reverse any incompatible edges.
+ */
+static void 
+minmax_edges(graph_t * g)
+{
+    node_t *n;
     edge_t *e;
-    int i;
+    int srclen, sinklen;
 
-    /* enforce that a node is in at most one cluster at this level */
-    for (n = agfstnode(g); n; n = nn) {
-       nn = agnxtnode(g, n);
-       if (ND_ranktype(n)) {
-           agdelete(g, n);
-           continue;
+    srclen = sinklen = 0;
+    if ((GD_maxset(g) == NULL) && (GD_minset(g) == NULL))
+       return;
+    if (GD_minset(g) != NULL)
+       GD_minset(g) = UF_find(GD_minset(g));
+    if (GD_maxset(g) != NULL)
+       GD_maxset(g) = UF_find(GD_maxset(g));
+
+    if ((n = GD_maxset(g))) {
+       sinklen = (GD_maxset(g)->u.ranktype == SINKRANK);
+       while ((e = ND_out(n).list[0])) {
+           assert(e->head == UF_find(e->head));
+           reverse_edge(e);
+       }
+    }
+    if ((n = GD_minset(g))) {
+       srclen = (GD_minset(g)->u.ranktype == SOURCERANK);
+       while ((e = ND_in(n).list[0])) {
+           assert(e->tail == UF_find(e->tail));
+           reverse_edge(e);
        }
-       for (i = 1; i < GD_n_cluster(par); i++)
-           if (agcontains(GD_clust(par)[i], n))
-               break;
-       if (i < GD_n_cluster(par))
-           agdelete(g, n);
-       ND_clust(n) = NULL;
     }
 
     for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
-       for (e = agfstout(g->root, n); e; e = agnxtout(g->root, e)) {
-           if (agcontains(g, e->head))
-               aginsert(g, e);
-       }
+       if (n != UF_find(n))
+           continue;
+       if ((ND_out(n).size == 0) && GD_maxset(g) && (n != GD_maxset(g)))
+           virtual_edge(n, GD_maxset(g), NULL)->u.minlen = sinklen;
+       if ((ND_in(n).size == 0) && GD_minset(g) && (n != GD_minset(g)))
+           virtual_edge(GD_minset(g), n, NULL)->u.minlen = srclen;
     }
 }
 
-void cluster_leader(graph_t * clust)
+/* Run the network simplex algorithm on each component. */
+static void 
+rank1(graph_t * g)
 {
-    node_t *leader, *n;
-    int maxrank = 0;
-
-    /* find number of ranks and select a leader */
-    leader = NULL;
-    for (n = GD_nlist(clust); n; n = ND_next(n)) {
-       if ((ND_rank(n) == 0) && (ND_node_type(n) == NORMAL))
-           leader = n;
-       if (maxrank < ND_rank(n))
-           maxrank = ND_rank(n);
-    }
-    assert(leader != NULL);
-    GD_leader(clust) = leader;
+    int maxiter = MAXINT;
+    int c;
+    char *s;
 
-    for (n = agfstnode(clust); n; n = agnxtnode(clust, n)) {
-       assert((ND_UF_size(n) <= 1) || (n == leader));
-       UF_union(n, leader);
-       ND_ranktype(n) = CLUSTER;
+    if ((s = agget(g, "nslimit1")))
+       maxiter = atof(s) * agnnodes(g);
+    for (c = 0; c < GD_comp(g).size; c++) {
+       GD_nlist(g) = GD_comp(g).list[c];
+       rank(g, (GD_n_cluster(g) == 0 ? 1 : 0), maxiter);       /* TB balance */
     }
 }
 
@@ -391,96 +424,83 @@ void expand_ranksets(graph_t * g)
     }
 }
 
-void renewlist(elist * L)
+void dot_rank(graph_t * g)
 {
-    int i;
-    for (i = L->size; i >= 0; i--)
-       L->list[i] = NULL;
-    L->size = 0;
+    edgelabel_ranks(g);
+    collapse_sets(g);
+    /*collapse_leaves(g); */
+    class1(g);
+    minmax_edges(g);
+    decompose(g, 0);
+    acyclic(g);
+    rank1(g);
+    expand_ranksets(g);
+    cleanup1(g);
 }
 
-void cleanup1(graph_t * g)
+int is_cluster(graph_t * g)
 {
-    node_t *n;
-    edge_t *e, *f;
-    int c;
-
-    for (c = 0; c < GD_comp(g).size; c++) {
-       GD_nlist(g) = GD_comp(g).list[c];
-       for (n = GD_nlist(g); n; n = ND_next(n)) {
-           renewlist(&ND_in(n));
-           renewlist(&ND_out(n));
-           ND_mark(n) = FALSE;
-       }
-    }
-    for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
-       for (e = agfstout(g, n); e; e = agnxtout(g, e)) {
-           f = ED_to_virt(e);
-           if (f && (e == ED_to_orig(f))) {
-               /* Null out any other references to f to make sure we don't handle it
-                * a second time. For example, parallel multiedges share a virtual edge.
-                */
-               edge_t *e1, *f1;
-               for (e1 = agfstout(g, n); e1; e1 = agnxtout(g, e1)) {
-                   if (e != e1) {
-                       f1 = ED_to_virt(e1);
-                       if (f1 && (f == f1)) {
-                           ED_to_virt(e1) = NULL;
-                       }
-                   }
-               }
-               free(f);
-           }
-           ED_to_virt(e) = NULL;
-       }
-    }
-    free(GD_comp(g).list);
-    GD_comp(g).list = NULL;
-    GD_comp(g).size = 0;
+    return (strncmp(g->name, "cluster", 7) == 0);
 }
 
-void set_minmax(graph_t * g)
+static node_t*
+merge_leaves(graph_t * g, node_t * cur, node_t * new)
 {
-    int c;
+    node_t *rv;
 
-    GD_minrank(g) += GD_leader(g)->u.rank;
-    GD_maxrank(g) += GD_leader(g)->u.rank;
-    for (c = 1; c <= GD_n_cluster(g); c++)
-       set_minmax(GD_clust(g)[c]);
+    if (cur == NULL)
+       rv = new;
+    else {
+       rv = UF_union(cur, new);
+       ND_ht_i(rv) = MAX(ND_ht_i(cur), ND_ht_i(new));
+       ND_lw_i(rv) = ND_lw_i(cur) + ND_lw_i(new) + GD_nodesep(g) / 2;
+       ND_rw_i(rv) = ND_rw_i(cur) + ND_rw_i(new) + GD_nodesep(g) / 2;
+    }
+    return rv;
 }
 
-void scan_ranks(graph_t * g)
+static void 
+potential_leaf(graph_t * g, edge_t * e, node_t * leaf)
 {
-    node_t *n, *leader = NULL;
-    GD_minrank(g) = MAXSHORT;
-    GD_maxrank(g) = -1;
-    for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
-       if (GD_maxrank(g) < ND_rank(n))
-           GD_maxrank(g) = ND_rank(n);
-       if (GD_minrank(g) > ND_rank(n))
-           GD_minrank(g) = ND_rank(n);
-       if (leader == NULL)
-           leader = n;
-       else {
-           if (ND_rank(n) < ND_rank(leader))
-               leader = n;
-       }
-    }
-    GD_leader(g) = leader;
+    node_t *par;
+
+    if ((ED_tail_port(e).p.x) || (ED_head_port(e).p.x))
+       return;
+    if ((ED_minlen(e) != 1) || (ND_order(e->tail) > 0))
+       return;
+    par = ((leaf != e->head) ? e->head : e->tail);
+    ND_ranktype(leaf) = LEAFSET;
+    if (par == e->tail)
+       GD_outleaf(par) = merge_leaves(g, GD_outleaf(par), leaf);
+    else
+       GD_inleaf(par) = merge_leaves(g, GD_inleaf(par), leaf);
 }
 
-void find_clusters(graph_t * g)
+#ifdef OBSOLETE
+static void 
+collapse_leaves(graph_t * g)
 {
-    graph_t *mg, *subg;
-    node_t *mn;
-    edge_t *me;
+    node_t *n;
+    edge_t *e;
 
-    mg = g->meta_node->graph;
-    for (me = agfstout(mg, g->meta_node); me; me = agnxtout(mg, me)) {
-       mn = me->head;
-       subg = agusergraph(mn);
+    for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
 
-       if (GD_set_type(subg) == CLUSTER)
-           collapse_cluster(g, subg);
+       /* consider n as a potential leaf of some other node. */
+       if ((ND_ranktype(n) != NOCMD) || (ND_order(n)))
+           continue;
+       if (agfstout(g, n) == NULL) {
+           if ((e = agfstin(g, n)) && (agnxtin(g, e) == NULL)) {
+               potential_leaf(g, e, n);
+               continue;
+           }
+       }
+       if (agfstin(g, n) == NULL) {
+           if ((e = agfstout(g, n)) && (agnxtout(g, e) == NULL)) {
+               potential_leaf(g, e, n);
+               continue;
+           }
+       }
     }
 }
+#endif
+
index 79132bb176611ffe8942e345cb733e70a5ddb702..86c55de28d3537f92f040f037611bc6bbeee532d 100644 (file)
@@ -152,7 +152,7 @@ static void sameport(node_t * u, elist * l, double arr_len)
        curve[3].x = ROUND(x2);
        curve[3].y = ROUND(y2);
 
-       shape_clip(u, curve, 0);
+       shape_clip(u, curve);
        x1 = curve[0].x - ND_coord_i(u).x;
        y1 = curve[0].y - ND_coord_i(u).y;
     }
@@ -169,7 +169,7 @@ static void sameport(node_t * u, elist * l, double arr_len)
     prt.theta = 0;
     prt.side = 0;
 
-#ifdef OLD
+#ifdef OBSOLETE
 This code appears obsolete and wrong. First, we don't use arr_prt
 anymore, as we have previously ifdef'ed out the code below where it
 is used. In addition, it resets the rank height. But we've already
@@ -208,7 +208,7 @@ nodes and maintaining equal separation when specified
     for (i = 0; i < l->size; i++) {
        e = l->list[i];
        arrow_flags(e, &sflag, &eflag);
-#ifndef OLD
+#ifndef OBSOLETE
        for (; e; e = ED_to_virt(e)) {  /* assign to all virt edges of e */
            for (f = e; f;
                 f = ED_edge_type(f) == VIRTUAL &&