From 1950fcf12e6568274272aac98ae3a14689d7b736 Mon Sep 17 00:00:00 2001 From: erg Date: Mon, 14 Mar 2005 23:25:29 +0000 Subject: [PATCH] Rationalize use of pboxfn: give it the port rather than making it figure it out; tell it which side the boxes should go towards. At present, not much of this is being used anyway, so keep it simple. Still need to finish code for flat edges going to ports on boundary of node. --- lib/common/htmltable.c | 2 +- lib/common/htmltable.h | 2 +- lib/common/shapes.c | 47 ++----- lib/common/splines.c | 55 +++++---- lib/common/types.h | 4 +- lib/dotgen/dotinit.c | 36 ++++++ lib/dotgen/dotsplines.c | 268 ++++++++++++++++++++++++++++------------ 7 files changed, 271 insertions(+), 143 deletions(-) diff --git a/lib/common/htmltable.c b/lib/common/htmltable.c index 1d7be9462..8bb9512e2 100644 --- a/lib/common/htmltable.c +++ b/lib/common/htmltable.c @@ -553,7 +553,7 @@ box *html_port(node_t * n, char *pname, int* sides) * At present, unimplemented, since the label may be inside a * non-box node and we need to figure out what this means. */ -int html_path(node_t * n, edge_t * e, int pt, box * rv, int *k) +int html_path(node_t * n, port* p, int side, box * rv, int *k) { #ifdef UNIMPL point p; diff --git a/lib/common/htmltable.h b/lib/common/htmltable.h index 341b6f00c..aac73df19 100644 --- a/lib/common/htmltable.h +++ b/lib/common/htmltable.h @@ -146,7 +146,7 @@ extern "C" { extern void free_html_text(htmltxt_t *); extern box *html_port(node_t * n, char *pname, int* sides); - extern int html_path(node_t * n, edge_t * e, int pt, box * rv, int *k); + extern int html_path(node_t * n, port* p, int side, box * rv, int *k); extern int html_inside(node_t * n, pointf p, edge_t * e); #endif diff --git a/lib/common/shapes.c b/lib/common/shapes.c index 52c4ba09f..c13b5dd92 100644 --- a/lib/common/shapes.c +++ b/lib/common/shapes.c @@ -52,15 +52,14 @@ static void poly_init(node_t * n); static void poly_free(node_t * n); static port poly_port(node_t * n, char *portname, char *); static boolean poly_inside(inside_t * inside_context, pointf p); -static int poly_path(node_t * n, edge_t * e, int pt, box rv[], int *kptr); +static int poly_path(node_t* n, port* p, int side, box rv[], int *kptr); static void poly_gencode(GVC_t * gvc, node_t * n); static void record_init(node_t * n); static void record_free(node_t * n); static port record_port(node_t * n, char *portname, char *); static boolean record_inside(inside_t * inside_context, pointf p); -static int record_path(node_t * n, edge_t * e, int pt, box rv[], - int *kptr); +static int record_path(node_t* n, port* p, int side, box rv[], int *kptr); static void record_gencode(GVC_t * gvc, node_t * n); static void point_init(node_t * n); @@ -820,17 +819,16 @@ static boolean poly_inside(inside_t * inside_context, pointf p) /* poly_path: * Generate box path from port to border. + * Store boxes in rv and number of boxes in kptr. + * side gives preferred side of bounding box for last node. + * Return actual side. Returning 0 indicates nothing done. */ -static int poly_path(node_t * n, edge_t * e, int pt, box rv[], int *kptr) +static int poly_path(node_t* n, port* p, int side, box rv[], int *kptr) { - int side = 0; - edge_t *f; + side = 0; if (ND_label(n)->html && ND_has_port(n)) { - for (f = e; ED_edge_type(f) != NORMAL; f = ED_to_orig(f)); - e = f; - if (GET_PORT_BOX(n, e)) - side = html_path(n, e, pt, rv, kptr); + side = html_path(n, p, side, rv, kptr); } return side; } @@ -1702,16 +1700,13 @@ record_inside(inside_t * inside_context, pointf p) * Generate box path from port to border. * See poly_path for constraints. */ -static int record_path(node_t * n, edge_t * e, int pt, box rv[], int *kptr) +static int record_path(node_t* n, port* prt, int side, box rv[], int *kptr) { - int i, side, ls, rs; + int i, ls, rs; point p; field_t *info; - if (pt == 1) - p = ED_tail_port(e).p; - else - p = ED_head_port(e).p; + p = prt->p; info = (field_t *) ND_shape_info(n); for (i = 0; i < info->n_flds; i++) { @@ -1726,36 +1721,16 @@ static int record_path(node_t * n, edge_t * e, int pt, box rv[], int *kptr) /* FIXME: I don't understand this code */ if (GD_flip(n->graph)) { rv[0] = flip_rec_box(info->fld[i]->b, ND_coord_i(n)); -#if 0 - experiment for bigjoe record spline routing problem { - int xc = (rv[0].UR.x + rv[0].LL.x) - /2; - rv[0].UR.x = xc + 2; - rv[0].LL.x = xc - 2; - } -#endif } else { rv[0].LL.x = ND_coord_i(n).x + ls; rv[0].LL.y = ND_coord_i(n).y - ND_ht_i(n) / 2; rv[0].UR.x = ND_coord_i(n).x + rs; } -#if 0 - s0 = (rv[0].UR.x - rv[0].LL.x) / 6; - s0 = MIN(s0, n->GD_nodesep(graph)); - s1 = MIN(p.x - rv[0].LL.x, rv[0].UR.x - p.x) / 2; - sep = MIN(s0, s1); - rv[0].LL.x += sep; - rv[0].UR.x -= sep; -#endif rv[0].UR.y = ND_coord_i(n).y + ND_ht_i(n) / 2; *kptr = 1; break; } } - if (pt == 1) - side = BOTTOM; - else - side = TOP; return side; } diff --git a/lib/common/splines.c b/lib/common/splines.c index 17736ebfc..a3930849a 100644 --- a/lib/common/splines.c +++ b/lib/common/splines.c @@ -361,9 +361,9 @@ void add_box(path * P, box b) void beginpath(path * P, edge_t * e, int et, pathend_t * endp, boolean merge) { - int flag, side, mask; + int side, mask; node_t *n; - int (*pboxfn) (node_t * n, edge_t * e, int, box *, int *); + int (*pboxfn) (node_t*, port*, int, box*, int*); n = e->tail; @@ -446,6 +446,7 @@ beginpath(path * P, edge_t * e, int et, pathend_t * endp, boolean merge) #ifdef IMPL if ((et == FLATEDGE) && (ND_node_type(n) == NORMAL) && ((side = ED_tail_port(e).side))) { + box b = endp->nb; switch (side) { case LEFT: b.UR.x = P->start.p.x; @@ -499,20 +500,21 @@ beginpath(path * P, edge_t * e, int et, pathend_t * endp, boolean merge) } #endif - /* flag = (et == REGULAREDGE) ? 1 : et; */ - flag = 1; + if (et == REGULAREDGE) side = BOTTOM; + else side = TOP; /* for flat edges */ if (pboxfn - && (mask = (*pboxfn) (n, e, flag, &endp->boxes[0], &endp->boxn))) + && (mask = (*pboxfn) (n, &ED_tail_port(e), side, &endp->boxes[0], &endp->boxn))) endp->sidemask = mask; else { endp->boxes[0] = endp->nb; endp->boxn = 1; - } + switch (et) { case SELFEDGE: /* moving the box UR.y by + 1 avoids colinearity between port point and box that confuses Proutespline(). it's a bug in Proutespline() but this is the easiest fix. */ + assert(0); /* at present, we don't use beginpath for selfedges */ endp->boxes[0].UR.y = P->start.p.y - 1; endp->sidemask = BOTTOM; break; @@ -525,13 +527,14 @@ beginpath(path * P, edge_t * e, int et, pathend_t * endp, boolean merge) endp->sidemask = BOTTOM; break; } + } } void endpath(path * P, edge_t * e, int et, pathend_t * endp, boolean merge) { int side, mask; node_t *n; - int (*pboxfn) (node_t * n, edge_t * e, int, box *, int *); + int (*pboxfn) (node_t* n, port*, int, box*, int*); n = e->head; @@ -609,29 +612,31 @@ void endpath(path * P, edge_t * e, int et, pathend_t * endp, boolean merge) endp->sidemask = side; return; } + side = TOP; if (pboxfn - && (mask = (*pboxfn) (n, e, 2, &endp->boxes[0], &endp->boxn))) + && (mask = (*pboxfn) (n, &ED_head_port(e), side, &endp->boxes[0], &endp->boxn))) endp->sidemask = mask; else { endp->boxes[0] = endp->nb; endp->boxn = 1; - } - switch (et) { - case SELFEDGE: - /* offset of -1 is symmetric w.r.t. beginpath() - * FIXME: is any of this right? what if self-edge - * doesn't connect from BOTTOM to TOP??? */ - endp->boxes[0].LL.y = P->end.p.y + 1; - endp->sidemask = TOP; - break; - case FLATEDGE: - endp->boxes[0].LL.y = P->end.p.y; - endp->sidemask = TOP; - break; - case REGULAREDGE: - endp->boxes[0].LL.y = P->end.p.y; - endp->sidemask = TOP; - break; + switch (et) { + case SELFEDGE: + /* offset of -1 is symmetric w.r.t. beginpath() + * FIXME: is any of this right? what if self-edge + * doesn't connect from BOTTOM to TOP??? */ + assert(0); /* at present, we don't use endpath for selfedges */ + endp->boxes[0].LL.y = P->end.p.y + 1; + endp->sidemask = TOP; + break; + case FLATEDGE: + endp->boxes[0].LL.y = P->end.p.y; + endp->sidemask = TOP; + break; + case REGULAREDGE: + endp->boxes[0].LL.y = P->end.p.y; + endp->sidemask = TOP; + break; + } } } diff --git a/lib/common/types.h b/lib/common/types.h index 48b50897d..68be02c0a 100644 --- a/lib/common/types.h +++ b/lib/common/types.h @@ -185,7 +185,7 @@ extern "C" { void (*freefn) (node_t *); /* frees shape from node u.shape_info structure */ port(*portfn) (node_t *, char *, char *); /* finds aiming point and slope of port */ boolean(*insidefn) (inside_t * inside_context, pointf); /* clips incident gvc->e spline on shape of gvc->n */ - int (*pboxfn) (node_t * n, edge_t * e, int, box *, int *); /* finds box path to reach port */ + int (*pboxfn)(node_t* n, port* p, int side, box rv[], int *kptr); /* finds box path to reach port */ void (*codefn) (GVC_t * gvc, node_t * n); /* emits graphics code for node */ } shape_functions; @@ -545,6 +545,7 @@ extern "C" { port tail_port, head_port; /* might be used someday */ textlabel_t *label, *head_label, *tail_label; char edge_type; + char adjacent; /* true for flat edge with adjacent nodes */ char label_ontop; edge_t *to_orig; /* for dot's shapes.c */ void *alg; @@ -572,6 +573,7 @@ extern "C" { #define ED_cutvalue(e) (e)->u.cutvalue #define ED_dist(e) (e)->u.dist #define ED_edge_type(e) (e)->u.edge_type +#define ED_adjacent(e) (e)->u.adjacent #define ED_factor(e) (e)->u.factor #define ED_head_label(e) (e)->u.head_label #define ED_head_port(e) (e)->u.head_port diff --git a/lib/dotgen/dotinit.c b/lib/dotgen/dotinit.c index 96128bd0e..d1f138be7 100644 --- a/lib/dotgen/dotinit.c +++ b/lib/dotgen/dotinit.c @@ -216,12 +216,48 @@ dot_init_graph(Agraph_t * g) dot_init_node_edge(g); } +#ifdef DEBUG +int +fastn (graph_t * g) +{ + node_t* u; + int cnt = 0; + for (u = GD_nlist(g); u; u = ND_next(u)) cnt++; + return cnt; +} + +static void +dumpRanks (graph_t * g) +{ + int i, j; + node_t* u; + rank_t *rank = GD_rank(g); + int rcnt = 0; + 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]; + rcnt++; + if (streq(u->name,"virtual")) + fprintf (stderr, " %x", u); + else + fprintf (stderr, " %s", u->name); + + } + fprintf (stderr, "\n"); + } + fprintf (stderr, "count %d rank count = %d\n", fastn(g), rcnt); +} +#endif + void dot_layout(Agraph_t * g) { dot_init_graph(g); dot_rank(g); dot_mincross(g); + /* dumpRanks (g); */ dot_position(g); + /* dumpRanks (g); */ dot_sameports(g); dot_splines(g); if (mapbool(agget(g, "compound"))) diff --git a/lib/dotgen/dotsplines.c b/lib/dotgen/dotsplines.c index 3997c3efb..38fb97d19 100644 --- a/lib/dotgen/dotsplines.c +++ b/lib/dotgen/dotsplines.c @@ -90,7 +90,7 @@ static void completeregularpath(path *, Agedge_t *, Agedge_t *, static int edgecmp(Agedge_t **, Agedge_t **); static Agedge_t *getmainedge(Agedge_t *); static box makeflatcomponent(box, box, int, int, int, int, int); -static int make_flat_edge(path *, Agedge_t **, int, int); +static void make_flat_edge(path *, Agedge_t **, int, int); static box makeflatend(box, int, int, box); static void make_regular_edge(path *, Agedge_t **, int, int); static box makeregularend(box, int, int); @@ -192,6 +192,10 @@ static void swap_spline(splines * s) } /* edge_normalize: + * Some back edges are reversed during layout and the reversed edge + * is used to compute the spline. We would like to guarantee that + * the order of control points always goes from tail to head, so + * we reverse them if necessary. */ static void edge_normalize(graph_t * g) { @@ -205,6 +209,9 @@ static void edge_normalize(graph_t * g) } } } + +/* dot_splines: + */ void dot_splines(graph_t * g) { int i, j, k, n_nodes, n_edges, ind, cnt; @@ -235,6 +242,14 @@ void dot_splines(graph_t * g) for (j = 0; j < GD_rank(g)[i].n; j++) { n = GD_rank(g)[i].v[j]; + /* if n is the label of a flat edge, copy its position to + * the label. + */ + if (ND_alg(n)) { + edge_t* fe = (edge_t*)ND_alg(n); + assert (ED_label(fe)); + ED_label(fe)->p = ND_coord_i(n); + } if ((ND_node_type(n) != NORMAL) && (sinfo.splineMerge(n) == FALSE)) continue; @@ -300,6 +315,7 @@ void dot_splines(graph_t * g) for (cnt = 1; i < n_edges; cnt++, i++) { if (le0 != (le1 = getmainedge((e1 = edges[i])))) break; + if (ED_adjacent(e0)) continue; /* all flat adjacent edges at once */ eb = (ED_tail_port(e1).defined || ED_head_port(e1).defined) ? e1 : le1; if (ED_tree_index(eb) & BWDEDGE) { @@ -310,27 +326,22 @@ void dot_splines(graph_t * g) break; if (portcmp(ED_head_port(ea), ED_head_port(eb))) break; -/* #ifdef OBSOLETE */ if ((ED_tree_index(e0) & EDGETYPEMASK) == FLATEDGE && ED_label(e0) != ED_label(e1)) break; -/* #endif */ if (ED_tree_index(edges[i]) & MAINGRAPH) /* Aha! -C is on */ break; } if (e0->tail == e0->head) makeSelfEdge(P, edges, ind, cnt, Multisep, &sinfo); else if (ND_rank(e0->tail) == ND_rank(e0->head)) { - int end_index = ind+cnt; - while (ind < end_index) { - ind = make_flat_edge(P, edges, ind, cnt); - } + make_flat_edge(P, edges, ind, cnt); } else make_regular_edge(P, edges, ind, cnt); } - /* make the other splines and place labels */ + /* place regular edge labels */ for (n = GD_nlist(g); n; n = ND_next(n)) { if ((ND_node_type(n) == VIRTUAL) && (ND_label(n))) place_vnlabel(n); @@ -371,8 +382,12 @@ void dot_splines(graph_t * g) State = GVSPLINES; } - /* compute position of an edge label from its virtual node */ -static void place_vnlabel(node_t * n) +/* place_vnlabel: + * assign position of an edge label from its virtual node + * This is for regular edges only. + */ +static void +place_vnlabel(node_t * n) { pointf dimen; double width; @@ -387,9 +402,8 @@ static void place_vnlabel(node_t * n) ED_label(e)->p.y = ND_coord_i(n).y; } -static void setflags(e, hint1, hint2, f3) -edge_t *e; -int hint1, hint2, f3; +static void +setflags(edge_t *e, int hint1, int hint2, int f3) { int f1, f2; if (hint1 != 0) @@ -424,14 +438,13 @@ int hint1, hint2, f3; * - edge type * - |rank difference of nodes| * - |x difference of nodes| - * - id of original edge (How is this defined?) + * - id of witness edge for equivalence class * - port comparison * - graph type * - labels if flat edges * - edge id */ -static int edgecmp(ptr0, ptr1) -edge_t **ptr0, **ptr1; +static int edgecmp(edge_t** ptr0, edge_t** ptr1) { edge_t fwdedgea, fwdedgeb, *e0, *e1, *ea, *eb, *le0, *le1; int et0, et1, v0, v1, rv; @@ -452,6 +465,8 @@ edge_t **ptr0, **ptr1; v1 = ND_coord_i(le1->tail).x - ND_coord_i(le1->head).x, v1 = ABS(v1); if (v0 != v1) return (v0 - v1); + /* This provides a cheap test for edges having the same set of endpoints. + */ if (le0->id != le1->id) return (le0->id - le1->id); ea = (ED_tail_port(e0).defined || ED_head_port(e0).defined) ? e0 : le0; @@ -477,54 +492,112 @@ edge_t **ptr0, **ptr1; return (e0->id - e1->id); } -/* make_flat_edge: - * Construct flat edges edges[ind...ind+cnt-1] - * In some cases, we can do all of them. +/* fledgecmp: + * Sort edges by mid y value of ports. + * If this is the same, and all y values are the same, + * check if one segment lies within the other. */ static int -make_flat_edge(path * P, edge_t ** edges, int ind, int cnt) +fledgecmp(edge_t** ptr0, edge_t** ptr1) { - node_t *tn, *hn, *n; - edge_t fwdedge, *e; - int i, stepx, stepy, /* dx, */ dy, ht1, ht2; - int tside, hside, mside, tdir, hdir, cross, pn; - point *ps; - point tp, hp; - pathend_t tend, hend; - box lb, rb, wlb, wrb; - rank_t *rank; - point points[1000]; - int blockingNode, pointn; - - /* dx = 0; */ - e = edges[ind]; - if (ED_tree_index(e) & BWDEDGE) { - MAKEFWDEDGE(&fwdedge, e); - e = &fwdedge; + edge_t* e0 = *ptr0; + edge_t* e1 = *ptr1; + point tp0, tp1, hp0, hp1; + tp0 = ED_tail_port(e0).p; + hp0 = ED_head_port(e0).p; + tp1 = ED_tail_port(e1).p; + hp1 = ED_head_port(e1).p; + int y0 = (tp0.y + hp0.y)/2; + int y1 = (tp1.y + hp1.y)/2; + if (y0 != y1) return (y0-y1); + if ((tp0.y == hp0.y) && (tp1.y == hp1.y)) { + if ((tp0.x <= tp1.x) && (hp0.x >= hp1.x)) { + if (tp0.y <= 0) return -1; + else return 1; + } + else if ((tp0.x >= tp1.x) && (hp0.x <= hp1.x)) { + if (tp0.y <= 0) return 1; + else return -1; + } } - tn = e->tail, hn = e->head; + return (e0->id - e1->id); - /* flat edge without ports that can go straight left to right */ +} + +#define LABEL_SPACE 8 - if (ED_label(e)) { - edge_t *f; - for (f = ED_to_virt(e); ED_to_virt(f); f = ED_to_virt(f)); - ED_label(e)->p = ND_coord_i(f->tail); +/* setFlatAdjPos: + * Create middle boxes for routing using ordered list of edges going from + * bottom to top. + * Also, set label positions. + */ +static void +setFlatAdjPos (edge_t** edges, int n_edges, int flip, box* boxes, edge_t* e0) +{ + int r, i, x, boxw, availht; + edge_t* e; + double y, wd, ht, totalht = 0; + textlabel_t* lbl; + node_t *tn, *hn; + graph_t* g; + +assert(0); + tn = e0->tail, hn = e0->head; + g = tn->graph; + x = (ND_coord_i(tn).x + ND_coord_i(hn).x)/2; + y = ND_coord_i(tn).y; + r = ND_rank(tn); + availht = GD_rank(g)[r].ht2 + GD_rank(g)[r].ht1 + GD_ranksep(g); + boxw = (ND_coord_i(hn).x - ND_coord_i(tn).x - ND_rw_i(tn) - ND_lw_i(hn))/3; + for (i = 0; i < n_edges; i++) { + if (!((lbl = ED_label(e)))) continue; + if (flip) { + ht = lbl->dimen.x; + wd = lbl->dimen.y; + } + else { + ht = lbl->dimen.y; + wd = lbl->dimen.x; + } + totalht += ht; + boxw = MAX(boxw, wd); + } + for (i = 0; i < n_edges; i++) { + e = edges[i]; + lbl = ED_label(e); + if (GD_flip(g)) ht = lbl->dimen.x; + else ht = lbl->dimen.y; + lbl->p.x = x; + lbl->p.y = ROUND(y - ht/2); + y -= ht + LABEL_SPACE; } +} + +/* make_flat_adj_edges: + */ +static void +make_flat_adj_edges(path* P, edge_t** edges, int ind, int cnt, edge_t* e0) +{ + node_t *tn, *hn; + edge_t* e; + int labels = 0, ports = 0; + point tp, hp; + int i, stepy, dy; + graph_t* g; + box* boxes; + int pointn; + point points[1000]; - rank = &(GD_rank(tn->graph)[ND_rank(tn)]); - for (i = ND_order(tn) + 1; i < ND_order(hn); i++) { - n = rank->v[i]; - if ((ND_node_type(n) == VIRTUAL && ND_label(n)) || - ND_node_type(n) == NORMAL) - break; + g = e0->tail->graph; + tn = e0->tail, hn = e0->head; + for (i = 0; i < cnt; i++) { + e = edges[ind + i]; + if (ND_label(e)) labels++; + if (ED_tail_port(e).defined || ED_head_port(e).defined) ports = 1; } - if (i != ND_order(hn)) - blockingNode = 1; - else - blockingNode = 0; - if (!blockingNode && !ED_tail_port(e).defined && !ED_head_port(e).defined){ + /* flat edges without ports and labels can go straight left to right */ + if ((labels == 0) && (ports == 0)) { stepy = (cnt > 1) ? ND_ht_i(tn) / (cnt - 1) : 0; tp = ND_coord_i(tn); hp = ND_coord_i(hn); @@ -536,33 +609,73 @@ make_flat_edge(path * P, edge_t ** edges, int ind, int cnt) points[pointn++] = pointof((2 * tp.x + hp.x) / 3, dy); points[pointn++] = pointof((2 * hp.x + tp.x) / 3, dy); points[pointn++] = hp; -#ifdef OBSOLETE - if (ED_label(e)) { /* FIXME: fix label positioning */ - labelw = ED_label(e)->dimen.x; - ED_label(e)->p = pointof(tp.x + labelw / 2, tp.y); - /* dx += labelw; */ - } -#endif dy += stepy; clip_and_install(e, e, points, pointn, &sinfo); } - return (ind+cnt); + return; } - /* !(flat edge without ports that can go straight left to right) */ + if (cnt > 2) qsort((char *) &edges[ind], cnt, sizeof(edges[0]), + (qsort_cmpf) fledgecmp); + + if (ports == 0) { + boxes = N_GNEW(cnt, box); + setFlatAdjPos (&edges[ind], cnt, GD_flip(g), boxes, e0); + free (boxes); + } + if (labels == 0) { + } + if (cnt == 1) { + } + /* General case: multiple edges with labels and ports + * use network simplex a la position? + */ +} + +/* make_flat_edge: + * Construct flat edges edges[ind...ind+cnt-1] + * There are 3 main cases: + * - all edges between a and b where a and b are adjacent + * - all non-labeled edges with identical ports between non-adjacent a and b + * - one labeled edge + */ +static void +make_flat_edge(path * P, edge_t ** edges, int ind, int cnt) +{ + node_t *tn, *hn; + edge_t fwdedge, *e; + int i, stepx, stepy, ht1, ht2; + int tside, hside, mside, tdir, hdir, cross, pn; + point *ps; + pathend_t tend, hend; + box lb, rb, wlb, wrb; + graph_t* g; + + e = edges[ind]; + if (ED_tree_index(e) & BWDEDGE) { + MAKEFWDEDGE(&fwdedge, e); + e = &fwdedge; + } + if (ED_adjacent(edges[ind])) { + make_flat_adj_edges (P, edges, ind, cnt, e); + return; + } + + tn = e->tail, hn = e->head; + g = tn->graph; tend.nb = boxof(ND_coord_i(tn).x - ND_lw_i(tn), - ND_coord_i(tn).y - ND_ht_i(tn) / 2, + ND_coord_i(tn).y - ND_ht_i(tn)/2, ND_coord_i(tn).x + ND_rw_i(tn), - ND_coord_i(tn).y + ND_ht_i(tn) / 2); + ND_coord_i(tn).y + ND_ht_i(tn)/2); hend.nb = boxof(ND_coord_i(hn).x - ND_lw_i(hn), - ND_coord_i(hn).y - ND_ht_i(hn) / 2, + ND_coord_i(hn).y - ND_ht_i(hn)/2, ND_coord_i(hn).x + ND_rw_i(hn), - ND_coord_i(hn).y + ND_ht_i(hn) / 2); - ht1 = GD_rank(tn->graph)[ND_rank(tn)].pht1; - ht2 = GD_rank(tn->graph)[ND_rank(tn)].pht2; + ND_coord_i(hn).y + ND_ht_i(hn)/2); + ht1 = GD_rank(g)[ND_rank(tn)].pht1; + ht2 = GD_rank(g)[ND_rank(tn)].pht2; stepx = Multisep / cnt, stepy = ht2 / cnt; lb = boxof(ND_coord_i(tn).x - ND_lw_i(tn), ND_coord_i(tn).y - ht1, ND_coord_i(tn).x + ND_rw_i(tn), ND_coord_i(tn).y + ht2); @@ -583,19 +696,16 @@ make_flat_edge(path * P, edge_t ** edges, int ind, int cnt) chooseflatsides(&tend, &hend, &tside, &hside, &mside, &tdir, &hdir, &cross); - if (ED_label(e)) { /* edges with labels aren't multi-edges */ - edge_t *le; - node_t *ln; - for (le = e; ED_to_virt(le); le = ED_to_virt(le)); - ln = le->tail; /* ln is virtual node containing label */ + if (ED_label(e)) { /* edges with labels aren't multi-edges */ + node_t* ln = (node_t*)ED_alg(e); wlb.LL.x = lb.LL.x; wlb.LL.y = lb.LL.y; wlb.UR.x = lb.UR.x; - wlb.UR.y = ND_coord_i(ln).y - ND_ht_i(ln) / 2; + wlb.UR.y = ND_coord_i(ln).y - ND_ht_i(ln)/2; wrb.LL.x = rb.LL.x; wrb.LL.y = rb.LL.y; wrb.UR.x = rb.UR.x; - wrb.UR.y = ND_coord_i(ln).y - ND_ht_i(ln) / 2; + wrb.UR.y = ND_coord_i(ln).y - ND_ht_i(ln)/2; } else { wlb.LL.x = lb.LL.x - (i + 1) * stepx; wlb.LL.y = lb.LL.y - (i + 1) * stepy; @@ -618,10 +728,9 @@ make_flat_edge(path * P, edge_t ** edges, int ind, int cnt) ps = routesplines(P, &pn); if (pn == 0) - return (ind+1+1); + return; clip_and_install(e, e, ps, pn, &sinfo); } - return (ind+cnt); } static void make_regular_edge(path * P, edge_t ** edges, int ind, int cnt) @@ -1447,7 +1556,8 @@ point closest(splines * spl, point p) /* common routines */ -static edge_t *getmainedge(edge_t * e) +edge_t* +getmainedge(edge_t * e) { edge_t *le = e; while (ED_to_virt(le)) -- 2.40.0