From: ellson Date: Wed, 23 Jul 2008 18:09:55 +0000 (+0000) Subject: perform an accurate computation of bezier bb when calculating graph bb. X-Git-Tag: LAST_LIBGRAPH~32^2~3825 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=1db9698774c62b1b7b194149d1ad7c78798bbde7;p=graphviz perform an accurate computation of bezier bb when calculating graph bb. --- diff --git a/lib/common/emit.c b/lib/common/emit.c index c906f5b4e..0af7460cb 100644 --- a/lib/common/emit.c +++ b/lib/common/emit.c @@ -287,6 +287,44 @@ static int check_control_points(pointf *cp) return 0; } +/* update bounding box to contain a bezier segment */ +void update_bb_bz(boxf *bb, pointf *cp) +{ + + /* if any control point of the segment is outside the bounding box */ + if (cp[0].x > bb->UR.x || cp[0].x < bb->LL.x || + cp[0].y > bb->UR.y || cp[0].y < bb->LL.y || + cp[1].x > bb->UR.x || cp[1].x < bb->LL.x || + cp[1].y > bb->UR.y || cp[1].y < bb->LL.y || + cp[2].x > bb->UR.x || cp[2].x < bb->LL.x || + cp[2].y > bb->UR.y || cp[2].y < bb->LL.y || + cp[3].x > bb->UR.x || cp[3].x < bb->LL.x || + cp[3].y > bb->UR.y || cp[3].y < bb->LL.y) { + + /* if the segment is sufficiently refined */ + if (check_control_points(cp)) { + int i; + /* expand the bounding box */ + for (i = 0; i < 4; i++) { + if (cp[i].x > bb->UR.x) + bb->UR.x = cp[i].x; + else if (cp[i].x < bb->LL.x) + bb->LL.x = cp[i].x; + if (cp[i].y > bb->UR.y) + bb->UR.y = cp[i].y; + else if (cp[i].y < bb->LL.y) + bb->LL.y = cp[i].y; + } + } + else { /* else refine the segment */ + pointf left[4], right[4]; + Bezier (cp, 3, 0.5, left, right); + update_bb_bz(bb, left); + update_bb_bz(bb, right); + } + } +} + #ifdef DEBUG static void psmapOutput (pointf* ps, int n) { diff --git a/lib/common/render.h b/lib/common/render.h index 8a4d809fb..d8ed56b14 100644 --- a/lib/common/render.h +++ b/lib/common/render.h @@ -148,6 +148,7 @@ extern "C" { extern void start_timer(void); extern pointf textsize(graph_t *g, textpara_t * para, char *fontname, double fontsize); extern void translate_bb(Agraph_t *, int); + extern void update_bb_bz(boxf *bb, pointf *cp); extern void write_attributed_dot(graph_t *g, FILE *f); extern void write_canonical_dot(graph_t *g, FILE *f); extern void write_plain(GVJ_t * job, graph_t * g, FILE * f, boolean extend); diff --git a/lib/common/splines.c b/lib/common/splines.c index fe3491f68..6c262b4c9 100644 --- a/lib/common/splines.c +++ b/lib/common/splines.c @@ -224,22 +224,6 @@ bezier *new_spline(edge_t * e, int sz) return rv; } -/* update_bb: - * Update the bounding box of g based on the addition of - * point p. - */ -void update_bb(graph_t * g, point pt) -{ - if (pt.x > GD_bb(g).UR.x) - GD_bb(g).UR.x = pt.x; - if (pt.y > GD_bb(g).UR.y) - GD_bb(g).UR.y = pt.y; - if (pt.x < GD_bb(g).LL.x) - GD_bb(g).LL.x = pt.x; - if (pt.y < GD_bb(g).LL.y) - GD_bb(g).LL.y = pt.y; -} - /* clip_and_install: * Given a raw spline (pn control points in ps), representing * a path from edge fe->tail ending in node hn, clip the ends to @@ -256,8 +240,8 @@ clip_and_install(edge_t * fe, node_t * hn, point * ps, int pn, int start, end, i, clipTail, clipHead; graph_t *g; edge_t *orig; - box* tbox; - box* hbox; + box *tbox, *hbox; + boxf bb; inside_t inside_context; tn = fe->tail; @@ -319,22 +303,24 @@ clip_and_install(edge_t * fe, node_t * hn, point * ps, int pn, if (ps[end].x != ps[end + 3].x || ps[end].y != ps[end + 3].y) break; arrow_clip(fe, hn, ps, &start, &end, newspl, info); + B2BF(GD_bb(g), bb); for (i = start; i < end + 4; ) { - point pt, pt1, pt2; - pt = newspl->list[i - start] = ps[i]; + pointf cp[4]; + newspl->list[i - start] = ps[i]; + P2PF(ps[i], cp[0]); i++; - update_bb(g, pt); - if ( i >= end + 4) + if ( i >= end + 4) break; - /* take the mid-point between the two control points in bb calculation */ - pt1 = newspl->list[i - start] = ps[i]; + newspl->list[i - start] = ps[i]; + P2PF(ps[i], cp[1]); i++; - pt2 = newspl->list[i - start] = ps[i]; + newspl->list[i - start] = ps[i]; + P2PF(ps[i], cp[2]); i++; - pt.x = ( pt1.x + pt2.x ) / 2; - pt.y = ( pt1.y + pt2.y ) / 2; - update_bb(g, pt); + P2PF(ps[i], cp[3]); + update_bb_bz(&bb, cp); } + BF2B(bb, GD_bb(g)); newspl->size = end - start + 4; } diff --git a/lib/common/utils.h b/lib/common/utils.h index a53de3859..73e3b69e2 100644 --- a/lib/common/utils.h +++ b/lib/common/utils.h @@ -56,7 +56,6 @@ extern "C" { extern int common_init_edge(edge_t * e); extern void updateBB(graph_t * g, textlabel_t * lp); - extern void update_bb(graph_t * g, point p); extern void compute_bb(Agraph_t *); extern boolean overlap_node(node_t *n, boxf b); extern boolean overlap_label(textlabel_t *lp, boxf b); diff --git a/lib/dotgen/dotsplines.c b/lib/dotgen/dotsplines.c index 4c857b558..3c0564eca 100644 --- a/lib/dotgen/dotsplines.c +++ b/lib/dotgen/dotsplines.c @@ -836,6 +836,7 @@ make_flat_adj_edges(path* P, edge_t** edges, int ind, int cnt, edge_t* e0, int i, j, midx, midy, leftx, rightx; point del; edge_t* hvye = NULL; + boxf bb; g = e0->tail->graph; tn = e0->tail, hn = e0->head; @@ -936,22 +937,26 @@ make_flat_adj_edges(path* P, edge_t** edges, int ind, int cnt, edge_t* e0, bz->eflag = auxbz->eflag; bz->ep = transform(auxbz->ep, del, 0); } + B2BF(GD_bb(g), bb); for (j = 0; j < auxbz->size; ) { - point pt, pt1, pt2; + point pt; + pointf cp[4]; pt = bz->list[j] = transform(auxbz->list[j], del, GD_flip(g)); + P2PF(pt,cp[0]); j++; - update_bb(g, pt); if ( j >= auxbz->size ) break; - /* take the mid-point between the two control points in bb calculation */ - pt1 = bz->list[j] = transform(auxbz->list[j], del, GD_flip(g)); + pt = bz->list[j] = transform(auxbz->list[j], del, GD_flip(g)); + P2PF(pt,cp[1]); j++; - pt2 = bz->list[j] = transform(auxbz->list[j], del, GD_flip(g)); + pt = bz->list[j] = transform(auxbz->list[j], del, GD_flip(g)); + P2PF(pt,cp[2]); j++; - pt.x = ( pt1.x + pt2.x ) / 2; - pt.y = ( pt1.y + pt2.y ) / 2; - update_bb(g, pt); + pt = transform(auxbz->list[j], del, GD_flip(g)); + P2PF(pt,cp[3]); + update_bb_bz(&bb, cp); } + BF2B(bb, GD_bb(g)); if (ED_label(e)) { ED_label(e)->p = transform(ED_label(auxe)->p, del, GD_flip(g)); updateBB(g, ED_label(e));