From: Emden R. Gansner Date: Wed, 19 Mar 2014 14:20:59 +0000 (-0400) Subject: Modify dot to using packing rather than the built-in component handling, which X-Git-Tag: 2.38.0~24 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=22966330a07ba159f82ac16f9c0698979f7a089a;p=graphviz Modify dot to using packing rather than the built-in component handling, which places all the components on a single row; as a side-effect, parameterize dot_layout to distinguish between the absolute root graph (for various parameters) and the local root used for layout, which will hold the various rank information. --- diff --git a/lib/dotgen/Makefile.am b/lib/dotgen/Makefile.am index 468c16b9b..db8d3115b 100644 --- a/lib/dotgen/Makefile.am +++ b/lib/dotgen/Makefile.am @@ -4,6 +4,7 @@ AM_CPPFLAGS = \ -I$(top_srcdir) \ -I$(top_srcdir)/lib/common \ + -I$(top_srcdir)/lib/pack \ -I$(top_srcdir)/lib/gvc \ -I$(top_srcdir)/lib/ortho \ -I$(top_srcdir)/lib/cgraph \ diff --git a/lib/dotgen/aspect.c b/lib/dotgen/aspect.c index 684b41e1b..561e7a017 100644 --- a/lib/dotgen/aspect.c +++ b/lib/dotgen/aspect.c @@ -1256,7 +1256,7 @@ static void applyPromotionHeuristic(graph_t * g) static int allNeighborsAreBelow(Agnode_t * n) { Agedge_t *e; - graph_t *g = agraphof(n); + /* graph_t *g = agraphof(n); */ int i; //for (e = agfstout(g,n); e; e = agnxtout(g,e)) diff --git a/lib/dotgen/class2.c b/lib/dotgen/class2.c index 509ddc9ad..c3cc60244 100644 --- a/lib/dotgen/class2.c +++ b/lib/dotgen/class2.c @@ -25,7 +25,7 @@ label_vnode(graph_t * g, edge_t * orig) dimen = ED_label(orig)->dimen; v = virtual_node(g); ND_label(v) = ED_label(orig); - ND_lw(v) = GD_nodesep(agroot(agraphof(v))); + ND_lw(v) = GD_nodesep(agroot(v)); if (!ED_label_ontop(orig)) { if (GD_flip(agroot(g))) { ND_ht(v) = dimen.x; @@ -300,7 +300,7 @@ void class2(graph_t * g) } } /* since decompose() is not called on subgraphs */ - if (g != agroot(g)) { + if (g != dot_root(g)) { GD_comp(g).list = ALLOC(1, GD_comp(g).list, node_t *); GD_comp(g).list[0] = GD_nlist(g); } diff --git a/lib/dotgen/cluster.c b/lib/dotgen/cluster.c index 5fd08a118..c84ef3fa4 100644 --- a/lib/dotgen/cluster.c +++ b/lib/dotgen/cluster.c @@ -97,7 +97,7 @@ map_path(node_t * from, node_t * to, edge_t * orig, edge_t * ve, int type) u = from; for (r = ND_rank(from); r < ND_rank(to); r++) { if (r < ND_rank(to) - 1) - v = clone_vn(agraphof(from), aghead(ve)); + v = clone_vn(dot_root(from), aghead(ve)); else v = to; e = virtual_edge(u, v, orig); @@ -167,13 +167,13 @@ void interclexp(graph_t * subg) node_t *n; edge_t *e, *prev, *next; - g = agroot(subg); + g = dot_root(subg); 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(agroot(subg), n); e; e = next) { - next = agnxtedge(agroot(subg), e, n); + for (e = agfstedge(g, n); e; e = next) { + next = agnxtedge(g, e, n); if (agcontains(subg, e)) continue; @@ -217,7 +217,7 @@ void interclexp(graph_t * subg) /* I think that make_interclust_chain should create call other_edge(e) anyway if (agcontains(subg,agtail(e)) - && agfindedge(subg->root,aghead(e),agtail(e))) other_edge(e); + && agfindedge(g,aghead(e),agtail(e))) other_edge(e); */ make_interclust_chain(g, aghead(e), agtail(e), e); prev = e; @@ -233,7 +233,7 @@ merge_ranks(graph_t * subg) node_t *v; graph_t *root; - root = agroot(subg); + root = dot_root(subg); if (GD_minrank(subg) > 0) GD_rank(root)[GD_minrank(subg) - 1].valid = FALSE; for (r = GD_minrank(subg); r <= GD_maxrank(subg); r++) { @@ -245,10 +245,10 @@ merge_ranks(graph_t * subg) ND_order(v) = pos++; /* real nodes automatically have v->root = root graph */ if (ND_node_type(v) == VIRTUAL) - v->root = root; + v->root = agroot(root); delete_fast_node(subg, v); - fast_node(agroot(subg), v); - GD_n_nodes(agroot(subg))++; + fast_node(root, v); + GD_n_nodes(root)++; } GD_rank(subg)[r].v = GD_rank(root)[r].v + ipos; GD_rank(root)[r].valid = FALSE; @@ -273,7 +273,7 @@ remove_rankleaders(graph_t * g) delete_fast_edge(e); while ((e = ND_in(v).list[0])) delete_fast_edge(e); - delete_fast_node(agroot(g), v); + delete_fast_node(dot_root(g), v); GD_rankleader(g)[r] = NULL; } } diff --git a/lib/dotgen/conc.c b/lib/dotgen/conc.c index ccabde01a..dd13e936b 100644 --- a/lib/dotgen/conc.c +++ b/lib/dotgen/conc.c @@ -159,13 +159,13 @@ static void rebuild_vlists(graph_t * g) for (r = GD_minrank(g); r <= GD_maxrank(g); r++) { lead = GD_rankleader(g)[r]; - if (GD_rank(agroot(g))[r].v[ND_order(lead)] != lead) { + if (GD_rank(dot_root(g))[r].v[ND_order(lead)] != lead) { agerr(AGERR, "rebuiltd_vlists: rank lead %s not in order %d of rank %d\n", agnameof(lead), ND_order(lead), r); longjmp(jbuf, 1); } GD_rank(g)[r].v = - GD_rank(agroot(g))[r].v + ND_order((GD_rankleader(g)[r])); + GD_rank(dot_root(g))[r].v + ND_order((GD_rankleader(g)[r])); maxi = -1; for (i = 0; i < GD_rank(g)[r].n; i++) { if ((n = GD_rank(g)[r].v[i]) == NULL) diff --git a/lib/dotgen/dotinit.c b/lib/dotgen/dotinit.c index cd23aa313..fe41c52e1 100644 --- a/lib/dotgen/dotinit.c +++ b/lib/dotgen/dotinit.c @@ -14,17 +14,20 @@ #include #include "dot.h" +#include "pack.h" #include "aspect.h" static void -dot_init_subg(graph_t * g) +dot_init_subg(graph_t * g, graph_t* droot) { graph_t* subg; if ((g != agroot(g))) agbindrec(g, "Agraphinfo_t", sizeof(Agraphinfo_t), TRUE); + GD_dotroot(g) = droot; + for (subg = agfstsubg(g); subg; subg = agnxtsubg(subg)) { - dot_init_subg(subg); + dot_init_subg(subg, droot); } } @@ -103,6 +106,7 @@ dot_cleanup_node(node_t * n) free_list(ND_flat_in(n)); free_list(ND_other(n)); free_label(ND_label(n)); + free_label(ND_xlabel(n)); if (ND_shape(n)) ND_shape(n)->fns->freefn(n); agdelrec(n, "Agnodeinfo_t"); @@ -285,7 +289,7 @@ attach_phase_attrs (Agraph_t * g, int maxphase) } } -void dot_layout(Agraph_t * g) +static void dotLayout(Agraph_t * g) { aspect_t aspect; aspect_t* asp; @@ -294,7 +298,7 @@ void dot_layout(Agraph_t * g) setEdgeType (g, ET_SPLINE); asp = setAspect (g, &aspect); - dot_init_subg(g); + dot_init_subg(g,g); dot_init_node_edge(g); do { @@ -326,6 +330,115 @@ void dot_layout(Agraph_t * g) dot_splines(g); if (mapbool(agget(g, "compound"))) dot_compoundEdges(g); +} + +static void +initSubg (Agraph_t* sg, Agraph_t* g) +{ + agbindrec(sg, "Agraphinfo_t", sizeof(Agraphinfo_t), TRUE); + GD_drawing(sg) = NEW(layout_t); + GD_drawing(sg)->quantum = GD_drawing(g)->quantum; + GD_drawing(sg)->dpi = GD_drawing(g)->dpi; + GD_gvc(sg) = GD_gvc (g); + GD_charset(sg) = GD_charset (g); + GD_rankdir2(sg) = GD_rankdir2 (g); + GD_nodesep(sg) = GD_nodesep(g); + GD_ranksep(sg) = GD_ranksep(g); + GD_fontnames(sg) = GD_fontnames(g); +} + +static void +attachPos (Agraph_t* g) +{ + node_t* np; + double* ps = N_NEW(2*agnnodes(g), double); + + for (np = agfstnode(g); np; np = agnxtnode(g, np)) { + ND_pos(np) = ps; + ps[0] = PS2INCH(ND_coord(np).x); + ps[1] = PS2INCH(ND_coord(np).y); + ps += 2; + } +} + +static void +resetCoord (Agraph_t* g) +{ + node_t* np = agfstnode(g); + double* sp = ND_pos(np); + double* ps = sp; + + for (np = agfstnode(g); np; np = agnxtnode(g, np)) { + ND_pos(np) = 0; + ND_coord(np).x = INCH2PS(ps[0]); + ND_coord(np).y = INCH2PS(ps[1]); + ps += 2; + } + free (sp); +} + +/* doDot: + * Assume g has nodes. + */ +static void doDot (Agraph_t* g) +{ + Agraph_t **ccs; + Agraph_t *sg; + int ncc; + int i; + pack_info pinfo; + int Pack = getPack(g, -1, CL_OFFSET); + pack_mode mode = getPackModeInfo (g, l_undef, &pinfo); + getPackInfo(g, l_node, CL_OFFSET, &pinfo); + + if ((mode == l_undef) && (Pack < 0)) { + /* No pack information; use old dot with components + * handled during layout + */ + dotLayout(g); + } else { + /* fill in default values */ + if (mode == l_undef) + pinfo.mode = l_node; + else if (Pack < 0) + Pack = CL_OFFSET; + pinfo.margin = Pack; + pinfo.fixed = 0; + + /* components using clusters */ + ccs = cccomps(g, &ncc, 0); + if (ncc == 1) { + dotLayout(g); + } else if (GD_drawing(g)->ratio_kind == R_NONE) { + pinfo.doSplines = 1; + + for (i = 0; i < ncc; i++) { + sg = ccs[i]; + initSubg (sg, g); + dotLayout (sg); + } + attachPos (g); + packSubgraphs(ncc, ccs, g, &pinfo); + resetCoord (g); + } else { + } + + for (i = 0; i < ncc; i++) { + free (GD_drawing(ccs[i])); + agdelete(g, ccs[i]); + } + free(ccs); + } +} + +void dot_layout(Agraph_t * g) +{ + if (agnnodes(g)) doDot (g); dotneato_postprocess(g); +} +Agraph_t * dot_root (Agraph_t* g) +{ + return GD_dotroot(g); } + diff --git a/lib/dotgen/dotprocs.h b/lib/dotgen/dotprocs.h index 6c5351587..9c8ebf597 100644 --- a/lib/dotgen/dotprocs.h +++ b/lib/dotgen/dotprocs.h @@ -77,6 +77,7 @@ extern "C" { #if defined(_BLD_dot) && defined(_DLL) # define extern __EXPORT__ #endif + extern Agraph_t* dot_root(Agraph_t *); extern void dot_concentrate(Agraph_t *); extern void dot_mincross(Agraph_t *, int); extern void dot_position(Agraph_t *, aspect_t*); diff --git a/lib/dotgen/dotsplines.c b/lib/dotgen/dotsplines.c index 199af4e42..dac80c15b 100644 --- a/lib/dotgen/dotsplines.c +++ b/lib/dotgen/dotsplines.c @@ -60,16 +60,16 @@ typedef struct { static void adjustregularpath(path *, int, int); static Agedge_t *bot_bound(Agedge_t *, int); static boolean pathscross(Agnode_t *, Agnode_t *, Agedge_t *, Agedge_t *); -static Agraph_t *cl_bound(Agnode_t *, Agnode_t *); +static Agraph_t *cl_bound(graph_t*, Agnode_t *, Agnode_t *); static int cl_vninside(Agraph_t *, Agnode_t *); static void completeregularpath(path *, Agedge_t *, Agedge_t *, pathend_t *, pathend_t *, boxf *, int, int); static int edgecmp(Agedge_t **, Agedge_t **); -static void make_flat_edge(spline_info_t*, path *, Agedge_t **, int, int, int); -static void make_regular_edge(spline_info_t*, path *, Agedge_t **, int, int, int); +static void make_flat_edge(graph_t*, spline_info_t*, path *, Agedge_t **, int, int, int); +static void make_regular_edge(graph_t* g, spline_info_t*, path *, Agedge_t **, int, int, int); static boxf makeregularend(boxf, int, double); -static boxf maximal_bbox(spline_info_t*, Agnode_t *, Agedge_t *, Agedge_t *); -static Agnode_t *neighbor(Agnode_t *, Agedge_t *, Agedge_t *, int); +static boxf maximal_bbox(graph_t* g, spline_info_t*, Agnode_t *, Agedge_t *, Agedge_t *); +static Agnode_t *neighbor(graph_t*, Agnode_t *, Agedge_t *, Agedge_t *, int); static void place_vnlabel(Agnode_t *); static boxf rank_box(spline_info_t* sp, Agraph_t *, int); static void recover_slack(Agedge_t *, path *); @@ -451,10 +451,10 @@ static void _dot_splines(graph_t * g, int normalize) } } else if (ND_rank(agtail(e0)) == ND_rank(aghead(e0))) { - make_flat_edge(&sd, P, edges, ind, cnt, et); + make_flat_edge(g, &sd, P, edges, ind, cnt, et); } else - make_regular_edge(&sd, P, edges, ind, cnt, et); + make_regular_edge(g, &sd, P, edges, ind, cnt, et); } /* place regular edge labels */ @@ -1177,14 +1177,13 @@ makeSimpleFlat (node_t* tn, node_t* hn, edge_t** edges, int ind, int cnt, int et * more straightforward and laborious fashion. */ static void -make_flat_adj_edges(path* P, edge_t** edges, int ind, int cnt, edge_t* e0, +make_flat_adj_edges(graph_t* g, path* P, edge_t** edges, int ind, int cnt, edge_t* e0, int et) { node_t* n; node_t *tn, *hn; edge_t* e; int labels = 0, ports = 0; - graph_t* g; graph_t* auxg; graph_t* subg; node_t *auxt, *auxh; @@ -1194,7 +1193,6 @@ make_flat_adj_edges(path* P, edge_t** edges, int ind, int cnt, edge_t* e0, edge_t* hvye = NULL; attr_state_t* attrs; - g = agraphof(agtail(e0)); tn = agtail(e0), hn = aghead(e0); for (i = 0; i < cnt; i++) { e = edges[ind + i]; @@ -1321,13 +1319,12 @@ make_flat_adj_edges(path* P, edge_t** edges, int ind, int cnt, edge_t* e0, /* makeFlatEnd; */ static void -makeFlatEnd (spline_info_t* sp, path* P, node_t* n, edge_t* e, pathend_t* endp, +makeFlatEnd (graph_t* g, spline_info_t* sp, path* P, node_t* n, edge_t* e, pathend_t* endp, boolean isBegin) { boxf b; - graph_t* g = agraphof(n); - b = endp->nb = maximal_bbox(sp, n, NULL, e); + b = endp->nb = maximal_bbox(g, sp, n, NULL, e); endp->sidemask = TOP; if (isBegin) beginpath(P, e, FLATEDGE, endp, FALSE); else endpath(P, e, FLATEDGE, endp, FALSE); @@ -1340,13 +1337,12 @@ makeFlatEnd (spline_info_t* sp, path* P, node_t* n, edge_t* e, pathend_t* endp, /* makeBottomFlatEnd; */ static void -makeBottomFlatEnd (spline_info_t* sp, path* P, node_t* n, edge_t* e, +makeBottomFlatEnd (graph_t* g, spline_info_t* sp, path* P, node_t* n, edge_t* e, pathend_t* endp, boolean isBegin) { boxf b; - graph_t* g = agraphof(n); - b = endp->nb = maximal_bbox(sp, n, NULL, e); + b = endp->nb = maximal_bbox(g, sp, n, NULL, e); endp->sidemask = BOTTOM; if (isBegin) beginpath(P, e, FLATEDGE, endp, FALSE); else endpath(P, e, FLATEDGE, endp, FALSE); @@ -1361,9 +1357,8 @@ makeBottomFlatEnd (spline_info_t* sp, path* P, node_t* n, edge_t* e, /* make_flat_labeled_edge: */ static void -make_flat_labeled_edge(spline_info_t* sp, path* P, edge_t* e, int et) +make_flat_labeled_edge(graph_t* g, spline_info_t* sp, path* P, edge_t* e, int et) { - graph_t *g; node_t *tn, *hn, *ln; pointf *ps; pathend_t tend, hend; @@ -1374,7 +1369,6 @@ make_flat_labeled_edge(spline_info_t* sp, path* P, edge_t* e, int et) tn = agtail(e); hn = aghead(e); - g = agraphof(tn); for (f = ED_to_virt(e); ED_to_virt(f); f = ED_to_virt(f)); ln = agtail(f); @@ -1405,8 +1399,8 @@ make_flat_labeled_edge(spline_info_t* sp, path* P, edge_t* e, int et) lb.LL.y = lb.UR.y - MAX(5.,ydelta); boxn = 0; - makeFlatEnd (sp, P, tn, e, &tend, TRUE); - makeFlatEnd (sp, P, hn, e, &hend, FALSE); + makeFlatEnd (g, sp, P, tn, e, &tend, TRUE); + makeFlatEnd (g, sp, P, hn, e, &hend, FALSE); boxes[boxn].LL.x = tend.boxes[tend.boxn - 1].LL.x; boxes[boxn].LL.y = tend.boxes[tend.boxn - 1].UR.y; @@ -1438,7 +1432,7 @@ make_flat_labeled_edge(spline_info_t* sp, path* P, edge_t* e, int et) /* make_flat_bottom_edges: */ static void -make_flat_bottom_edges(spline_info_t* sp, path * P, edge_t ** edges, int +make_flat_bottom_edges(graph_t* g, spline_info_t* sp, path * P, edge_t ** edges, int ind, int cnt, edge_t* e, int splines) { node_t *tn, *hn; @@ -1448,11 +1442,9 @@ make_flat_bottom_edges(spline_info_t* sp, path * P, edge_t ** edges, int int pn; pointf *ps; pathend_t tend, hend; - graph_t* g; tn = agtail(e); hn = aghead(e); - g = agraphof(tn); r = ND_rank(tn); if (r < GD_maxrank(g)) { nextr = GD_rank(g) + (r+1); @@ -1465,8 +1457,8 @@ make_flat_bottom_edges(spline_info_t* sp, path * P, edge_t ** edges, int stepx = ((double)(sp->Multisep)) / (cnt+1); stepy = vspace / (cnt+1); - makeBottomFlatEnd (sp, P, tn, e, &tend, TRUE); - makeBottomFlatEnd (sp, P, hn, e, &hend, FALSE); + makeBottomFlatEnd (g, sp, P, tn, e, &tend, TRUE); + makeBottomFlatEnd (g, sp, P, hn, e, &hend, FALSE); for (i = 0; i < cnt; i++) { int boxn; @@ -1515,7 +1507,7 @@ make_flat_bottom_edges(spline_info_t* sp, path * P, edge_t ** edges, int * = the rest - route along top */ static void -make_flat_edge(spline_info_t* sp, path * P, edge_t ** edges, int ind, int cnt, int et) +make_flat_edge(graph_t* g, spline_info_t* sp, path * P, edge_t ** edges, int ind, int cnt, int et) { node_t *tn, *hn; Agedgeinfo_t fwdedgei; @@ -1526,7 +1518,6 @@ make_flat_edge(spline_info_t* sp, path * P, edge_t ** edges, int ind, int cnt, i int tside, hside, pn; pointf *ps; pathend_t tend, hend; - graph_t* g; fwdedge.out.base.data = (Agrec_t*)&fwdedgei; @@ -1547,11 +1538,11 @@ make_flat_edge(spline_info_t* sp, path * P, edge_t ** edges, int ind, int cnt, i * so check them all. */ if (isAdjacent) { - make_flat_adj_edges (P, edges, ind, cnt, e, et); + make_flat_adj_edges (g, P, edges, ind, cnt, e, et); return; } if (ED_label(e)) { /* edges with labels aren't multi-edges */ - make_flat_labeled_edge (sp, P, e, et); + make_flat_labeled_edge (g, sp, P, e, et); return; } @@ -1564,13 +1555,12 @@ make_flat_edge(spline_info_t* sp, path * P, edge_t ** edges, int ind, int cnt, i hside = ED_head_port(e).side; if (((tside == BOTTOM) && (hside != TOP)) || ((hside == BOTTOM) && (tside != TOP))) { - make_flat_bottom_edges (sp, P, edges, ind, cnt, e, et == ET_SPLINE); + make_flat_bottom_edges (g, sp, P, edges, ind, cnt, e, et == ET_SPLINE); return; } tn = agtail(e); hn = aghead(e); - g = agraphof(tn); r = ND_rank(tn); if (r > 0) { rank_t* prevr; @@ -1586,8 +1576,8 @@ make_flat_edge(spline_info_t* sp, path * P, edge_t ** edges, int ind, int cnt, i stepx = ((double)sp->Multisep) / (cnt+1); stepy = vspace / (cnt+1); - makeFlatEnd (sp, P, tn, e, &tend, TRUE); - makeFlatEnd (sp, P, hn, e, &hend, FALSE); + makeFlatEnd (g, sp, P, tn, e, &tend, TRUE); + makeFlatEnd (g, sp, P, hn, e, &hend, FALSE); for (i = 0; i < cnt; i++) { int boxn; @@ -1655,7 +1645,7 @@ leftOf (pointf p1, pointf p2, pointf p3) * multiple edges better. */ static int -makeLineEdge(edge_t* fe, pointf* points, node_t** hp) +makeLineEdge(graph_t* g, edge_t* fe, pointf* points, node_t** hp) { int delr, pn; node_t* hn; @@ -1670,7 +1660,7 @@ makeLineEdge(edge_t* fe, pointf* points, node_t** hp) hn = aghead(e); tn = agtail(e); delr = ABS(ND_rank(hn)-ND_rank(tn)); - if ((delr == 1) || ((delr == 2) && (GD_has_labels(agraphof(hn)) & EDGE_LABEL))) + if ((delr == 1) || ((delr == 2) && (GD_has_labels(g) & EDGE_LABEL))) return 0; if (agtail(fe) == agtail(e)) { *hp = hn; @@ -1723,9 +1713,8 @@ makeLineEdge(edge_t* fe, pointf* points, node_t** hp) /* make_regular_edge: */ static void -make_regular_edge(spline_info_t* sp, path * P, edge_t ** edges, int ind, int cnt, int et) +make_regular_edge(graph_t* g, spline_info_t* sp, path * P, edge_t ** edges, int ind, int cnt, int et) { - graph_t *g; node_t *tn, *hn; Agedgeinfo_t fwdedgeai, fwdedgebi, fwdedgei; Agedgepair_t fwdedgea, fwdedgeb, fwdedge; @@ -1752,7 +1741,6 @@ make_regular_edge(spline_info_t* sp, path * P, edge_t ** edges, int ind, int cnt } sl = 0; e = edges[ind]; - g = agraphof(agtail(e)); hackflag = FALSE; if (ABS(ND_rank(agtail(e)) - ND_rank(aghead(e))) > 1) { fwdedgeai = *(Agedgeinfo_t*)e->base.data; @@ -1788,7 +1776,7 @@ make_regular_edge(spline_info_t* sp, path * P, edge_t ** edges, int ind, int cnt /* compute the spline points for the edge */ - if ((et == ET_LINE) && (pointn = makeLineEdge (fe, pointfs, &hn))) { + if ((et == ET_LINE) && (pointn = makeLineEdge (g, fe, pointfs, &hn))) { } else { int splines = et == ET_SPLINE; @@ -1797,12 +1785,12 @@ make_regular_edge(spline_info_t* sp, path * P, edge_t ** edges, int ind, int cnt segfirst = e; tn = agtail(e); hn = aghead(e); - b = tend.nb = maximal_bbox(sp, tn, NULL, e); + b = tend.nb = maximal_bbox(g, sp, tn, NULL, e); beginpath(P, e, REGULAREDGE, &tend, spline_merge(tn)); b.UR.y = tend.boxes[tend.boxn - 1].UR.y; b.LL.y = tend.boxes[tend.boxn - 1].LL.y; b = makeregularend(b, BOTTOM, - ND_coord(tn).y - GD_rank(agraphof(tn))[ND_rank(tn)].ht1); + ND_coord(tn).y - GD_rank(g)[ND_rank(tn)].ht1); if (b.LL.x < b.UR.x && b.LL.y < b.UR.y) tend.boxes[tend.boxn++] = b; longedge = 0; @@ -1818,16 +1806,16 @@ make_regular_edge(spline_info_t* sp, path * P, edge_t ** edges, int ind, int cnt } if (!smode || si > 0) { si--; - boxes[boxn++] = maximal_bbox(sp, hn, e, ND_out(hn).list[0]); + boxes[boxn++] = maximal_bbox(g, sp, hn, e, ND_out(hn).list[0]); e = ND_out(hn).list[0]; tn = agtail(e); hn = aghead(e); continue; } - hend.nb = maximal_bbox(sp, hn, e, ND_out(hn).list[0]); + hend.nb = maximal_bbox(g, sp, hn, e, ND_out(hn).list[0]); endpath(P, e, REGULAREDGE, &hend, spline_merge(aghead(e))); b = makeregularend(hend.boxes[hend.boxn - 1], TOP, - ND_coord(hn).y + GD_rank(agraphof(hn))[ND_rank(hn)].ht2); + ND_coord(hn).y + GD_rank(g)[ND_rank(hn)].ht2); if (b.LL.x < b.UR.x && b.LL.y < b.UR.y) hend.boxes[hend.boxn++] = b; P->end.theta = M_PI / 2, P->end.constrained = TRUE; @@ -1860,22 +1848,22 @@ make_regular_edge(spline_info_t* sp, path * P, edge_t ** edges, int ind, int cnt tn = agtail(e); hn = aghead(e); boxn = 0; - tend.nb = maximal_bbox(sp, tn, ND_in(tn).list[0], e); + tend.nb = maximal_bbox(g, sp, tn, ND_in(tn).list[0], e); beginpath(P, e, REGULAREDGE, &tend, spline_merge(tn)); b = makeregularend(tend.boxes[tend.boxn - 1], BOTTOM, - ND_coord(tn).y - GD_rank(agraphof(tn))[ND_rank(tn)].ht1); + ND_coord(tn).y - GD_rank(g)[ND_rank(tn)].ht1); if (b.LL.x < b.UR.x && b.LL.y < b.UR.y) tend.boxes[tend.boxn++] = b; P->start.theta = -M_PI / 2, P->start.constrained = TRUE; smode = FALSE; } boxes[boxn++] = rank_box(sp, g, ND_rank(tn)); - b = hend.nb = maximal_bbox(sp, hn, e, NULL); + b = hend.nb = maximal_bbox(g, sp, hn, e, NULL); endpath(P, hackflag ? &fwdedgeb.out : e, REGULAREDGE, &hend, spline_merge(aghead(e))); b.UR.y = hend.boxes[hend.boxn - 1].UR.y; b.LL.y = hend.boxes[hend.boxn - 1].LL.y; b = makeregularend(b, TOP, - ND_coord(hn).y + GD_rank(agraphof(hn))[ND_rank(hn)].ht2); + ND_coord(hn).y + GD_rank(g)[ND_rank(hn)].ht2); if (b.LL.x < b.UR.x && b.LL.y < b.UR.y) hend.boxes[hend.boxn++] = b; completeregularpath(P, segfirst, e, &tend, &hend, boxes, boxn, @@ -2369,12 +2357,11 @@ static int cl_vninside(graph_t * cl, node_t * n) * It is not clear this will handle all potential problems. It seems one * could have hcl and tcl contained in cl, which would also cause problems. */ -#define REAL_CLUSTER(n) (ND_clust(n)==agraphof(n)?NULL:ND_clust(n)) +#define REAL_CLUSTER(n) (ND_clust(n)==g?NULL:ND_clust(n)) /* returns the cluster of (adj) that interferes with n, */ -static Agraph_t *cl_bound(n, adj) -node_t *n, *adj; +static Agraph_t *cl_bound(graph_t* g, node_t *n, node_t *adj) { graph_t *rv, *cl, *tcl, *hcl; edge_t *orig; @@ -2415,10 +2402,10 @@ node_t *n, *adj; */ #define FUDGE 4 -static boxf maximal_bbox(spline_info_t* sp, node_t* vn, edge_t* ie, edge_t* oe) +static boxf maximal_bbox(graph_t* g, spline_info_t* sp, node_t* vn, edge_t* ie, edge_t* oe) { double b, nb; - graph_t *g = agraphof(vn), *left_cl, *right_cl; + graph_t *left_cl, *right_cl; node_t *left, *right; boxf rv; @@ -2426,8 +2413,8 @@ static boxf maximal_bbox(spline_info_t* sp, node_t* vn, edge_t* ie, edge_t* oe) /* give this node all the available space up to its neighbors */ b = (double)(ND_coord(vn).x - ND_lw(vn) - FUDGE); - if ((left = neighbor(vn, ie, oe, -1))) { - if ((left_cl = cl_bound(vn, left))) + if ((left = neighbor(g, vn, ie, oe, -1))) { + if ((left_cl = cl_bound(g, vn, left))) nb = GD_bb(left_cl).UR.x + (double)(sp->Splinesep); else { nb = (double)(ND_coord(left).x + ND_mval(left)); @@ -2447,8 +2434,8 @@ static boxf maximal_bbox(spline_info_t* sp, node_t* vn, edge_t* ie, edge_t* oe) b = (double)(ND_coord(vn).x + 10); else b = (double)(ND_coord(vn).x + ND_rw(vn) + FUDGE); - if ((right = neighbor(vn, ie, oe, 1))) { - if ((right_cl = cl_bound(vn, right))) + if ((right = neighbor(g, vn, ie, oe, 1))) { + if ((right_cl = cl_bound(g, vn, right))) nb = GD_bb(right_cl).LL.x - (double)(sp->Splinesep); else { nb = ND_coord(right).x - ND_lw(right); @@ -2473,14 +2460,12 @@ static boxf maximal_bbox(spline_info_t* sp, node_t* vn, edge_t* ie, edge_t* oe) return rv; } -static node_t *neighbor(vn, ie, oe, dir) -node_t *vn; -edge_t *ie, *oe; -int dir; +static node_t * +neighbor(graph_t* g, node_t *vn, edge_t *ie, edge_t *oe, int dir) { int i; node_t *n, *rv = NULL; - rank_t *rank = &(GD_rank(agraphof(vn))[ND_rank(vn)]); + rank_t *rank = &(GD_rank(g)[ND_rank(vn)]); for (i = ND_order(vn) + dir; ((i >= 0) && (i < rank->n)); i += dir) { n = rank->v[i]; diff --git a/lib/dotgen/fastgr.c b/lib/dotgen/fastgr.c index a3a16185c..7d55d1be2 100644 --- a/lib/dotgen/fastgr.c +++ b/lib/dotgen/fastgr.c @@ -261,7 +261,7 @@ void flat_edge(graph_t * g, edge_t * e) { elist_append(e, ND_flat_out(agtail(e))); elist_append(e, ND_flat_in(aghead(e))); - GD_has_flat_edges(agroot(g)) = GD_has_flat_edges(g) = TRUE; + GD_has_flat_edges(dot_root(g)) = GD_has_flat_edges(g) = TRUE; } void delete_flat_edge(edge_t * e) @@ -294,7 +294,7 @@ void fastgr(graph_t * g) for (i = 0; (e = ND_out(n).list[i]); i++) { fprintf(stderr, " %s:%d", NAME(aghead(e)), ED_count(e)); w = aghead(e); - if (g == g->root) { + if (g == agroot(g)) { for (j = 0; (f = ND_in(w).list[j]); j++) if (e == f) break; @@ -305,7 +305,7 @@ void fastgr(graph_t * g) for (i = 0; (e = ND_in(n).list[i]); i++) { fprintf(stderr, " %s:%d", NAME(agtail(e)), ED_count(e)); w = agtail(e); - if (g == g->root) { + if (g == agroot(g)) { for (j = 0; (f = ND_out(w).list[j]); j++) if (e == f) break; diff --git a/lib/dotgen/flat.c b/lib/dotgen/flat.c index 4be132d05..b87ee365e 100644 --- a/lib/dotgen/flat.c +++ b/lib/dotgen/flat.c @@ -143,7 +143,7 @@ flat_node(edge_t * e) if (ED_label(e) == NULL) return; - g = agraphof(agtail(e)); + g = dot_root(agtail(e)); r = ND_rank(agtail(e)); place = flat_limits(g, e); @@ -224,7 +224,7 @@ checkFlatAdjacent (edge_t* e) lo = ND_order(hn); hi = ND_order(tn); } - rank = &(GD_rank(agraphof(tn))[ND_rank(tn)]); + rank = &(GD_rank(dot_root(tn))[ND_rank(tn)]); for (i = lo + 1; i < hi; i++) { n = rank->v[i]; if ((ND_node_type(n) == VIRTUAL && ND_label(n)) || diff --git a/lib/dotgen/mincross.c b/lib/dotgen/mincross.c index f14dfd3c3..5142feec5 100644 --- a/lib/dotgen/mincross.c +++ b/lib/dotgen/mincross.c @@ -580,7 +580,7 @@ static int mincross(graph_t * g, int startpass, int endpass, int doBalance) for (pass = startpass; pass <= endpass; pass++) { if (pass <= 1) { maxthispass = MIN(4, MaxIter); - if (g == agroot(g)) + if (g == dot_root(g)) build_ranks(g, pass); if (pass == 0) flat_breakcycles(g); @@ -837,9 +837,9 @@ void rec_reset_vlists(graph_t * g) w = furthestnode(g, v, 1); GD_rankleader(g)[r] = u; #ifdef DEBUG - assert(GD_rank(g->root)[r].v[ND_order(u)] == u); + assert(GD_rank(dot_root(g)[r].v[ND_order(u)] == u); #endif - GD_rank(g)[r].v = GD_rank(agroot(g))[r].v + ND_order(u); + GD_rank(g)[r].v = GD_rank(dot_root(g))[r].v + ND_order(u); GD_rank(g)[r].n = ND_order(w) - ND_order(u) + 1; } } @@ -866,7 +866,7 @@ realFillRanks (Agraph_t* g, int rnks[], int rnks_sz, Agraph_t* sg) for (c = 1; c <= GD_n_cluster(g); c++) sg = realFillRanks (GD_clust(g)[c], rnks, rnks_sz, sg); - if (agroot(g) == g) + if (dot_root(g) == g) return sg; memset (rnks, 0, sizeof(int)*rnks_sz); for (n = agfstnode(g); n; n = agnxtnode(g,n)) { @@ -879,7 +879,7 @@ realFillRanks (Agraph_t* g, int rnks[], int rnks_sz, Agraph_t* sg) for (i = GD_minrank(g); i <= GD_maxrank(g); i++) { if (rnks[i] == 0) { if (!sg) { - sg = agsubg (agroot(g), "_new_rank", 1); + sg = agsubg (dot_root(g), "_new_rank", 1); } n = agnode (sg, NULL, 1); agbindrec(n, "Agnodeinfo_t", sizeof(Agnodeinfo_t), TRUE); @@ -917,7 +917,7 @@ static void init_mincross(graph_t * g) /* alloc +1 for the null terminator usage in do_ordering() */ /* also, the +1 avoids attempts to alloc 0 sizes, something that efence complains about */ - size = agnedges(agroot(g)) + 1; + size = agnedges(dot_root(g)) + 1; TE_list = N_NEW(size, edge_t *); TI_list = N_NEW(size, int); mincross_options(g); @@ -970,7 +970,7 @@ static void flat_search(graph_t * g, node_t * v) ND_mark(v) = TRUE; ND_onstack(v) = TRUE; - hascl = (GD_n_cluster(agroot(g)) > 0); + hascl = (GD_n_cluster(dot_root(g)) > 0); if (ND_flat_out(v).list) for (i = 0; (e = ND_flat_out(v).list[i]); i++) { if (hascl @@ -1164,7 +1164,7 @@ void build_ranks(graph_t * g, int pass) } } - if ((g == agroot(g)) && ncross(g) > 0) + if ((g == dot_root(g)) && ncross(g) > 0) transpose(g, FALSE); free_queue(q); } @@ -1709,7 +1709,7 @@ void check_exchange(node_t * v, node_t * w) r = ND_rank(v); for (i = ND_order(v) + 1; i < ND_order(w); i++) { - u = GD_rank(agraphof(v))[r].v[i]; + u = GD_rank(dot_root(v))[r].v[i]; if (ND_clust(u)) abort(); } diff --git a/lib/dotgen/position.c b/lib/dotgen/position.c index 60a81b1b3..b81cd8762 100644 --- a/lib/dotgen/position.c +++ b/lib/dotgen/position.c @@ -305,6 +305,7 @@ make_LR_constraints(graph_t * g) if (m0 > USHRT_MAX) m0 = largeMinlen (m0); ED_minlen(e0) = MAX(ED_minlen(e0), m0); + ED_weight(e0) = MAX(ED_weight(e0), ED_weight(e)); } else if (!ED_label(e)) { /* unlabeled flat edge between non-neighbors @@ -364,7 +365,7 @@ static void contain_clustnodes(graph_t * g) int c; edge_t *e; - if (g != agroot(g)) { + if (g != dot_root(g)) { contain_nodes(g); if ((e = find_fast_edge(GD_ln(g),GD_rn(g)))) /* maybe from lrvn()?*/ ED_weight(e) += 128; @@ -412,16 +413,16 @@ static void keepout_othernodes(graph_t * g) if (v == NULL) continue; for (i = ND_order(v) - 1; i >= 0; i--) { - u = GD_rank(agroot(g))[r].v[i]; + u = GD_rank(dot_root(g))[r].v[i]; /* can't use "is_a_vnode_of" because elists are swapped */ if ((ND_node_type(u) == NORMAL) || vnode_not_related_to(g, u)) { make_aux_edge(u, GD_ln(g), margin + ND_rw(u), 0); break; } } - for (i = ND_order(v) + GD_rank(g)[r].n; i < GD_rank(agroot(g))[r].n; + for (i = ND_order(v) + GD_rank(g)[r].n; i < GD_rank(dot_root(g))[r].n; i++) { - u = GD_rank(agroot(g))[r].v[i]; + u = GD_rank(dot_root(g))[r].v[i]; if ((ND_node_type(u) == NORMAL) || vnode_not_related_to(g, u)) { make_aux_edge(GD_rn(g), u, margin + ND_lw(u), 0); break; @@ -611,7 +612,7 @@ set_xcoords(graph_t * g) static void adjustSimple(graph_t * g, int delta, int margin_total) { int r, bottom, deltop, delbottom; - graph_t *root = agroot(g); + graph_t *root = dot_root(g); rank_t *rank = GD_rank(root); int maxr = GD_maxrank(g); int minr = GD_minrank(g); @@ -651,8 +652,8 @@ static void adjustRanks(graph_t * g, int margin_total) int c; double delta, ht1, ht2; - rank_t *rank = GD_rank(agroot(g)); - if (g == agroot(g)) + rank_t *rank = GD_rank(dot_root(g)); + if (g == dot_root(g)) margin = 0; else margin = late_int (g, G_margin, CL_OFFSET, 0); @@ -672,7 +673,7 @@ static void adjustRanks(graph_t * g, int margin_total) GD_ht1(g) = ht1; GD_ht2(g) = ht2; - if ((g != agroot(g)) && GD_label(g)) { + if ((g != dot_root(g)) && GD_label(g)) { lht = MAX(GD_border(g)[LEFT_IX].y, GD_border(g)[RIGHT_IX].y); maxr = GD_maxrank(g); minr = GD_minrank(g); @@ -684,7 +685,7 @@ static void adjustRanks(graph_t * g, int margin_total) } /* update the global ranks */ - if (g != agroot(g)) { + if (g != dot_root(g)) { rank[GD_minrank(g)].ht2 = MAX(rank[GD_minrank(g)].ht2, GD_ht2(g)); rank[GD_maxrank(g)].ht1 = MAX(rank[GD_maxrank(g)].ht1, GD_ht1(g)); } @@ -701,10 +702,10 @@ static int clust_ht(Agraph_t * g) int c; double ht1, ht2; graph_t *subg; - rank_t *rank = GD_rank(agroot(g)); + rank_t *rank = GD_rank(dot_root(g)); int margin, haveClustLabel = 0; - if (g == agroot(g)) + if (g == dot_root(g)) margin = CL_OFFSET; else margin = late_int (g, G_margin, CL_OFFSET, 0); @@ -724,7 +725,7 @@ static int clust_ht(Agraph_t * g) /* account for a possible cluster label in clusters */ /* room for root graph label is handled in dotneato_postprocess */ - if ((g != agroot(g)) && GD_label(g)) { + if ((g != dot_root(g)) && GD_label(g)) { haveClustLabel = 1; if (!GD_flip(agroot(g))) { ht1 += GD_border(g)[BOTTOM_IX].y; @@ -735,7 +736,7 @@ static int clust_ht(Agraph_t * g) GD_ht2(g) = ht2; /* update the global ranks */ - if (g != agroot(g)) { + if (g != dot_root(g)) { rank[GD_minrank(g)].ht2 = MAX(rank[GD_minrank(g)].ht2, ht2); rank[GD_maxrank(g)].ht1 = MAX(rank[GD_maxrank(g)].ht1, ht1); } @@ -860,7 +861,7 @@ static void dot_compute_bb(graph_t * g, graph_t * root) node_t *v; pointf LL, UR; - if (g == agroot(g)) { + if (g == dot_root(g)) { LL.x = (double)(INT_MAX); UR.x = (double)(-INT_MAX); for (r = GD_minrank(g); r <= GD_maxrank(g); r++) { @@ -1043,10 +1044,10 @@ static point resize_leaf(node_t * leaf, point lbound) return lbound; } -static point place_leaf(node_t * leaf, point lbound, int order) +static point place_leaf(graph_t* ing, node_t * leaf, point lbound, int order) { node_t *leader; - graph_t *g = agraphof(leaf); + graph_t *g = dot_root(ing); leader = UF_find(leaf); if (leaf != leader) @@ -1103,7 +1104,7 @@ static void do_leaves(graph_t * g, node_t * leader) for (e = agfstin(g, n); e; e = agnxtin(g, e)) { edge_t *e1 = AGMKOUT(e); if ((agtail(e1) != leader) && (UF_find(agtail(e1)) == leader)) { - lbound = place_leaf(agtail(e1), lbound, j++); + lbound = place_leaf(g, agtail(e1), lbound, j++); unmerge_oneway(e1); elist_append(e1, ND_in(aghead(e1))); } @@ -1113,7 +1114,7 @@ static void do_leaves(graph_t * g, node_t * leader) j = ND_order(leader) + 1; for (e = agfstout(g, n); e; e = agnxtout(g, e)) { if ((aghead(e) != leader) && (UF_find(aghead(e)) == leader)) { - lbound = place_leaf(aghead(e), lbound, j++); + lbound = place_leaf(g, aghead(e), lbound, j++); unmerge_oneway(e); elist_append(e, ND_out(agtail(e))); } @@ -1181,12 +1182,12 @@ static void make_lrvn(graph_t * g) if (GD_ln(g)) return; - ln = virtual_node(agroot(g)); + ln = virtual_node(dot_root(g)); ND_node_type(ln) = SLACKNODE; - rn = virtual_node(agroot(g)); + rn = virtual_node(dot_root(g)); ND_node_type(rn) = SLACKNODE; - if (GD_label(g) && (g != agroot(g)) && !GD_flip(agroot(g))) { + if (GD_label(g) && (g != dot_root(g)) && !GD_flip(agroot(g))) { int w = MAX(GD_border(g)[BOTTOM_IX].x, GD_border(g)[TOP_IX].x); make_aux_edge(ln, rn, w, 0); } diff --git a/lib/dotgen/rank.c b/lib/dotgen/rank.c index a284f789e..042612b26 100644 --- a/lib/dotgen/rank.c +++ b/lib/dotgen/rank.c @@ -193,7 +193,7 @@ node_induce(graph_t * par, graph_t * g) } for (n = agfstnode(g); n; n = agnxtnode(g, n)) { - for (e = agfstout(agroot(g), n); e; e = agnxtout(agroot(g), e)) { + for (e = agfstout(dot_root(g), n); e; e = agnxtout(dot_root(g), e)) { if (agcontains(g, aghead(e))) agsubedge(g,e,1); } @@ -305,7 +305,7 @@ static void find_clusters(graph_t * g) { graph_t *subg; - for (subg = agfstsubg(agroot(g)); subg; subg = agnxtsubg(subg)) { + for (subg = agfstsubg(dot_root(g)); subg; subg = agnxtsubg(subg)) { if (GD_set_type(subg) == CLUSTER) collapse_cluster(g, subg); } @@ -428,7 +428,7 @@ static void expand_ranksets(graph_t * g, aspect_t* asp) UF_singleton(n); n = agnxtnode(g, n); } - if (g == agroot(g)) { + if (g == dot_root(g)) { if (CL_type == LOCAL) { for (c = 1; c <= GD_n_cluster(g); c++) set_minmax(GD_clust(g)[c]);