From 416d7e36b60b161eda9d4ab220c3029811c05ba0 Mon Sep 17 00:00:00 2001 From: ellson Date: Sun, 1 May 2005 15:08:54 +0000 Subject: [PATCH] Factor out overlap_node(node_t *,boxf) and overlap_edge(node_t *,boxf) and use for both mouse_in_node/edge and node/edge_in_clip_region. --- lib/common/arrows.c | 38 ++++++++++++ lib/common/emit.c | 121 +++++++++++++++------------------------ lib/common/renderprocs.h | 4 ++ lib/common/utils.c | 78 +++++++++++++++++++++++++ lib/gvc/gvevent.c | 86 +--------------------------- 5 files changed, 168 insertions(+), 159 deletions(-) diff --git a/lib/common/arrows.c b/lib/common/arrows.c index f1c453274..b8504b3ea 100644 --- a/lib/common/arrows.c +++ b/lib/common/arrows.c @@ -510,6 +510,44 @@ static pointf arrow_gen_type(GVJ_t * job, pointf p, pointf u, int flag) return p; } +boxf arrow_bb(GVJ_t * job, pointf p, pointf u, double scale, int flag) +{ + double s; + boxf bb; + double ax,ay,bx,by,cx,cy,dx,dy; + double ux2, uy2; + + /* generate arrowhead vector */ + u.x -= p.x; + u.y -= p.y; + /* the EPSILONs are to keep this stable as length of u approaches 0.0 */ + s = ARROW_LENGTH * scale / (sqrt(u.x * u.x + u.y * u.y) + EPSILON); + u.x += (u.x >= 0.0) ? EPSILON : -EPSILON; + u.y += (u.y >= 0.0) ? EPSILON : -EPSILON; + u.x *= s; + u.y *= s; + + /* compute all 4 corners of rotated arrowhead bounding box */ + ux2 = u.x / 2.; + uy2 = u.y / 2.; + ax = p.x - uy2; + ay = p.y - ux2; + bx = p.x + uy2; + by = p.y + ux2; + cx = ax + u.x; + cy = ay + u.y; + dx = bx + u.x; + dy = by + u.y; + + /* compute a right bb */ + bb.UR.x = MAX(ax, MAX(bx, MAX(cx, dx))); + bb.UR.y = MAX(ay, MAX(by, MAX(cy, dy))); + bb.LL.x = MIN(ax, MIN(bx, MIN(cx, dx))); + bb.LL.y = MIN(ay, MIN(by, MIN(cy, dy))); + + return bb; +} + void arrow_newgen(GVJ_t * job, pointf p, pointf u, double scale, int flag) { double s; diff --git a/lib/common/emit.c b/lib/common/emit.c index 32643fc7c..75a85d58b 100644 --- a/lib/common/emit.c +++ b/lib/common/emit.c @@ -427,11 +427,6 @@ fprintf(stderr,"pagesArrayElem = %d,%d pageSize = %g,%g pageOffset = %g,%g\n", emit_defaults(job); } -static boolean node_in_view(GVJ_t *job, node_t * n) -{ - return boxf_overlap(job->pageBoxClip, ND_bb(n)); -} - static boolean is_natural_number(char *sstr) { unsigned char *str = (unsigned char *) sstr; @@ -566,7 +561,7 @@ static void emit_node(GVJ_t * job, node_t * n) return; if (node_in_layer(job, n->graph, n) - && node_in_view(job, n) + && overlap_node(n, job->pageBoxClip) && (ND_state(n) != gvc->viewNum)) { gvrender_comment(job, n->name); @@ -666,46 +661,6 @@ static void emit_attachment(GVJ_t * job, textlabel_t * lp, splines * spl) gvrender_polyline(job, A, 3); } -static boolean edge_in_view(GVJ_t *job, edge_t * e) -{ - int i, j, np; - bezier bz; - point *p; - pointf pp, pn; - double sx, sy; - boxf b; - textlabel_t *lp; - splines *spl; - - spl = ED_spl(e); - if (spl == NULL) - return FALSE; - if (! boxf_overlap(job->pageBoxClip, spl->bb)) - return FALSE; - for (i = 0; i < spl->size; i++) { - bz = spl->list[i]; - np = bz.size; - p = bz.list; - P2PF(p[0],pp); - for (j = 0; j < np; j++) { - P2PF(p[j],pn); - b = mkboxf(pp, pn); - if (boxf_overlap(job->pageBoxClip, b)) - return TRUE; - pp = pn; - } - } - if ((lp = ED_label(e)) == NULL) - return FALSE; - sx = lp->dimen.x / 2.; - sy = lp->dimen.y / 2.; - b.LL.x = lp->p.x - sx; - b.UR.x = lp->p.x + sx; - b.LL.y = lp->p.y - sy; - b.UR.y = lp->p.y + sy; - return boxf_overlap(job->pageBoxClip, b); -} - void emit_edge_graphics(GVJ_t * job, edge_t * e) { int i, j, cnum, numc = 0; @@ -884,8 +839,9 @@ static void emit_edge(GVJ_t * job, edge_t * e) char *s, *url = NULL, *label = NULL, *tooltip = NULL, *target = NULL; textlabel_t *lab = NULL; - if (! edge_in_view(job, e) || ! edge_in_layer(job, e->head->graph, e)) - return; + if (! overlap_edge(e, job->pageBoxClip) + || ! edge_in_layer(job, e->head->graph, e)) + return; s = malloc(strlen(e->tail->name) + 2 + strlen(e->head->name) + 1); strcpy(s,e->tail->name); @@ -1608,46 +1564,61 @@ static void init_bb_node(node_t *n) ND_bb(n).UR.y = ND_coord_i(n).y + ND_ht_i(n) / 2.; } -static void init_bb_spl(splines *spl) +static box bezier_bb(bezier bz) { - int i, j; - bezier bz; + int i; box bb; - boxf bbf; - - for (i = 0; i < spl->size; i++) { - bz = spl->list[i]; - bb.UR = bb.LL = bz.list[0]; - for (j = 1; j < bz.size; j++) { - bb.LL.x = MIN(bb.LL.x, bz.list[j].x); - bb.LL.y = MIN(bb.LL.y, bz.list[j].y); - bb.UR.x = MAX(bb.UR.x, bz.list[j].x); - bb.UR.y = MAX(bb.UR.y, bz.list[j].y); - } - B2BF(bb, bbf); - if (i == 0) - spl->bb = bbf; - else { - spl->bb.LL.x = MIN(spl->bb.LL.x, bbf.LL.x); - spl->bb.LL.y = MIN(spl->bb.LL.y, bbf.LL.y); - spl->bb.UR.x = MAX(spl->bb.UR.x, bbf.UR.x); - spl->bb.UR.y = MAX(spl->bb.UR.y, bbf.UR.y); - } + + assert(bz.size > 0); + bb.LL = bb.UR = bz.list[0]; + for (i = 1; i < bz.size; i++) { + bb.LL.x = MIN(bb.LL.x, bz.list[i].x); + bb.LL.y = MIN(bb.LL.y, bz.list[i].y); + bb.UR.x = MAX(bb.UR.x, bz.list[i].x); + bb.UR.y = MAX(bb.UR.y, bz.list[i].y); + } + return bb; +} + +static void init_splines_bb(splines *spl) +{ + int i; + box bb, b; + + assert(spl->size > 0); + bb = bezier_bb(spl->list[0]); + for (i = 1; i < spl->size; i++) { + b = bezier_bb(spl->list[0]); + bb.LL.x = MIN(bb.LL.x, b.LL.x); + bb.LL.y = MIN(bb.LL.y, b.LL.y); + bb.UR.x = MAX(bb.UR.x, b.UR.x); + bb.UR.y = MAX(bb.UR.y, b.UR.y); } + B2BF(bb,spl->bb); +} + +static void init_bb_edge(edge_t *e) +{ + splines *spl; + + spl = ED_spl(e); + if (spl) + init_splines_bb(spl); + +// lp = ED_label(e); +// if (lp) +// {} } static void init_bb(graph_t *g) { node_t *n; edge_t *e; - splines *spl; for (n = agfstnode(g); n; n = agnxtnode(g, n)) { init_bb_node(n); for (e = agfstout(g, n); e; e = agnxtout(g, e)) { - spl = ED_spl(e); - if (spl) - init_bb_spl(spl); + init_bb_edge(e); } } } diff --git a/lib/common/renderprocs.h b/lib/common/renderprocs.h index 571f2e7c4..5e11ed075 100644 --- a/lib/common/renderprocs.h +++ b/lib/common/renderprocs.h @@ -27,6 +27,8 @@ extern "C" { extern point add_points(point, point); extern pointf add_pointfs(pointf, pointf); extern void arrow_flags(Agedge_t * e, int *sflag, int *eflag); + extern boxf arrow_bb(GVJ_t * job, pointf p, pointf u, double scale, + int flag); extern void arrow_gen(GVJ_t * job, point p, point u, double scale, int flag); extern double arrow_length(edge_t * e, int flag); @@ -150,6 +152,8 @@ extern "C" { extern nodequeue *new_queue(int); extern Agraph_t *next_input_graph(void); extern void osize_label(textlabel_t *, int *, int *, int *, int *); + extern boolean overlap_edge(edge_t *e, boxf b); + extern boolean overlap_node(node_t *n, boxf b); extern char **parse_style(char *s); extern void place_graph_label(Agraph_t *); extern void place_portlabel(edge_t * e, boolean head_p); diff --git a/lib/common/utils.c b/lib/common/utils.c index a37262193..198389838 100644 --- a/lib/common/utils.c +++ b/lib/common/utils.c @@ -1887,3 +1887,81 @@ utf8ToLatin1 (char* s) return ns; } +boolean overlap_node(node_t *n, boxf b) +{ + boxf bb; +// inside_t ictxt; + + bb = ND_bb(n); + if (! OVERLAP(b, bb)) + return FALSE; + +// ictxt.s.n = n; +// ictxt.s.bp = NULL; + +// return ND_shape(n)->fns->insidefn(&ictxt, p); + return TRUE; +} + +static boolean overlap_label(textlabel_t *lp, boxf b) +{ + double sx, sy; + boxf bb; + + sx = lp->dimen.x / 2.; + sy = lp->dimen.y / 2.; + bb.LL.x = lp->p.x - sx; + bb.UR.x = lp->p.x + sx; + bb.LL.y = lp->p.y - sy; + bb.UR.y = lp->p.y + sy; + return OVERLAP(b, bb); +} + +static boolean overlap_bezier(bezier bz, boxf b) +{ + int i, j; + box bb; + boxf bbf; + + for (i = 0; i < bz.size -1; i += 3) { + /* compute a bb for the bezier segment */ + bb.LL = bb.UR = bz.list[i]; + for (j = i+1; j < i+4; j++) { + bb.LL.x = MIN(bb.LL.x,bz.list[j].x); + bb.LL.y = MIN(bb.LL.y,bz.list[j].y); + bb.UR.x = MAX(bb.UR.x,bz.list[j].x); + bb.UR.y = MAX(bb.UR.y,bz.list[j].y); + } + B2BF(bb, bbf); + if (OVERLAP(b, bbf)) { + /* FIXME - check if really close enough to actual curve */ + return TRUE; + } + } + return FALSE; +} + +boolean overlap_edge(edge_t *e, boxf b) +{ + int i; + splines *spl; + textlabel_t *lp; + + spl = ED_spl(e); + if (spl && boxf_overlap(spl->bb, b)) { + for (i = 0; i < spl->size; i++) + if (overlap_bezier(spl->list[i], b)) + return TRUE; + +// if (inside_arrow(e)) +// return TRUE; + } + + lp = ED_label(e); + if (lp && overlap_label(lp, b)) + return TRUE; + + return FALSE; +} + + diff --git a/lib/gvc/gvevent.c b/lib/gvc/gvevent.c index 54c5e3568..93c8ee07b 100644 --- a/lib/gvc/gvevent.c +++ b/lib/gvc/gvevent.c @@ -37,88 +37,6 @@ void gvevent_refresh(GVJ_t * job) emit_graph(job, job->g); } -static boolean inside_node(node_t *n, boxf b) -{ - boxf bb; -// inside_t ictxt; - - bb = ND_bb(n); - if (! OVERLAP(b, bb)) - return FALSE; - -// ictxt.s.n = n; -// ictxt.s.bp = NULL; - -// return ND_shape(n)->fns->insidefn(&ictxt, p); - return TRUE; -} - -static boolean inside_label(edge_t *e, boxf b) -{ - textlabel_t *lp; - double sx, sy; - boxf bb; - - lp = ED_label(e); - if (lp == NULL) - return FALSE; - sx = lp->dimen.x / 2.; - sy = lp->dimen.y / 2.; - bb.LL.x = lp->p.x - sx; - bb.UR.x = lp->p.x + sx; - bb.LL.y = lp->p.y - sy; - bb.UR.y = lp->p.y + sy; - return OVERLAP(b, bb); -} - -static boolean inside_spline(edge_t *e, boxf b) -{ - int i, j, k; - bezier bz; - box bb; - boxf bbf; - splines *spl; - - spl = ED_spl(e); - if (spl == NULL) - return FALSE; - - bbf = spl->bb; - if (! OVERLAP(b, bbf)) - return FALSE; - - for (i = 0; i < spl->size; i++) { - bz = spl->list[i]; - for (j = 0; j < bz.size -1; j += 3) { - /* compute a bb for the bezier segment */ - bb.LL = bb.UR = bz.list[j]; - for (k = j+1; k < j+4; k++) { - bb.LL.x = MIN(bb.LL.x,bz.list[k].x); - bb.LL.y = MIN(bb.LL.y,bz.list[k].y); - bb.UR.x = MAX(bb.UR.x,bz.list[k].x); - bb.UR.y = MAX(bb.UR.y,bz.list[k].y); - } - B2BF(bb, bbf); - if (OVERLAP(b, bbf)) { - /* FIXME - check if really close enough to actual curve */ - return TRUE; - } - } - } - return FALSE; -} - -static boolean inside_edge(edge_t *e, boxf b) -{ - if (inside_spline(e, b)) - return TRUE; -// FIXME -// if (inside_arrow(e)) -// return TRUE; - - return inside_label(e, b); -} - /* recursively find innermost cluster containing the point */ static graph_t *gvevent_find_cluster(graph_t *g, boxf b) { @@ -146,11 +64,11 @@ static void * gvevent_find_obj(graph_t *g, boxf b) /* edges might overlap nodes, so search them first */ for (n = agfstnode(g); n; n = agnxtnode(g, n)) for (e = agfstout(g, n); e; e = agnxtout(g, e)) - if (inside_edge(e, b)) + if (overlap_edge(e, b)) return (void *)e; /* search graph backwards to get topmost node, in case of overlap */ for (n = aglstnode(g); n; n = agprvnode(g, n)) - if (inside_node(n, b)) + if (overlap_node(n, b)) return (void *)n; /* search for innermost cluster */ sg = gvevent_find_cluster(g, b); -- 2.40.0