From d157c363247a7a34c6accebb712a014482785332 Mon Sep 17 00:00:00 2001 From: ellson Date: Sat, 7 May 2005 18:06:39 +0000 Subject: [PATCH] detect mouse in arrows (or to be accurate, arrow_bb) --- lib/common/arrows.c | 2 +- lib/common/emit.c | 83 +++++++++++++++++++++++++--------------- lib/common/macros.h | 9 +++++ lib/common/renderprocs.h | 3 +- lib/common/utils.c | 41 +++++++++++++++----- 5 files changed, 96 insertions(+), 42 deletions(-) diff --git a/lib/common/arrows.c b/lib/common/arrows.c index b8504b3ea..72d45a16e 100644 --- a/lib/common/arrows.c +++ b/lib/common/arrows.c @@ -510,7 +510,7 @@ 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) +boxf arrow_bb(pointf p, pointf u, double scale, int flag) { double s; boxf bb; diff --git a/lib/common/emit.c b/lib/common/emit.c index 0590420ef..eba0918bd 100644 --- a/lib/common/emit.c +++ b/lib/common/emit.c @@ -1636,45 +1636,53 @@ static FILE *file_select(char *str) return rv; } -static void init_bb_node(node_t *n) -{ - ND_bb(n).LL.x = ND_coord_i(n).x - ND_lw_i(n); - ND_bb(n).LL.y = ND_coord_i(n).y - ND_ht_i(n) / 2.; - ND_bb(n).UR.x = ND_coord_i(n).x + ND_rw_i(n); - ND_bb(n).UR.y = ND_coord_i(n).y + ND_ht_i(n) / 2.; -} - -static box bezier_bb(bezier bz) +static boxf bezier_bb(bezier bz) { int i; + point p; box bb; + boxf bbf; 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); + p=bz.list[i]; + EXPANDBP(bb,p); } - return bb; + B2BF(bb, bbf); + return bbf; } static void init_splines_bb(splines *spl) { int i; - box bb, b; + bezier bz; + boxf bb, b; + pointf p, u; 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); + bz = spl->list[0]; + bb = bezier_bb(bz); + for (i = 0; i < spl->size; i++) { + if (i > 0) { + bz = spl->list[i]; + b = bezier_bb(bz); + EXPANDBB(bb, b); + } + if (bz.sflag) { + P2PF(bz.sp, p); + P2PF(bz.list[0], u); + b = arrow_bb(p, u, 1, bz.sflag); + EXPANDBB(bb, b); + } + if (bz.eflag) { + P2PF(bz.ep, p); + P2PF(bz.list[bz.size - 1], u); + b = arrow_bb(p, u, 1, bz.eflag); + EXPANDBB(bb, b); + } } - B2BF(bb,spl->bb); + spl->bb = bb; } static void init_bb_edge(edge_t *e) @@ -1690,17 +1698,32 @@ static void init_bb_edge(edge_t *e) // {} } +static void init_bb_node(graph_t *g, node_t *n) +{ + edge_t *e; + + ND_bb(n).LL.x = ND_coord_i(n).x - ND_lw_i(n); + ND_bb(n).LL.y = ND_coord_i(n).y - ND_ht_i(n) / 2.; + ND_bb(n).UR.x = ND_coord_i(n).x + ND_rw_i(n); + ND_bb(n).UR.y = ND_coord_i(n).y + ND_ht_i(n) / 2.; + + for (e = agfstout(g, n); e; e = agnxtout(g, e)) + init_bb_edge(e); + + /* IDEA - could also save in the node the bb of the node and + all of its outedges, then the scan time would be proportional + to just the number of nodes for many graphs. + Wouldn't work so well if the edges are sprawling all over the place + but it wouldn't add much to the cost to try before trying individual + nodes and edges. */ +} + static void init_bb(graph_t *g) { node_t *n; - edge_t *e; - for (n = agfstnode(g); n; n = agnxtnode(g, n)) { - init_bb_node(n); - for (e = agfstout(g, n); e; e = agnxtout(g, e)) { - init_bb_edge(e); - } - } + for (n = agfstnode(g); n; n = agnxtnode(g, n)) + init_bb_node(g, n); } void emit_jobs (GVC_t * gvc, graph_t * g) diff --git a/lib/common/macros.h b/lib/common/macros.h index 3e0869354..59776c8aa 100644 --- a/lib/common/macros.h +++ b/lib/common/macros.h @@ -83,10 +83,19 @@ #undef BETWEEN #endif #define BETWEEN(a,b,c) (((a) <= (b)) && ((b) <= (c))) + +/* true if point p is inside box b */ #define INSIDE(p,b) (BETWEEN((b).LL.x,(p).x,(b).UR.x) && BETWEEN((b).LL.y,(p).y,(b).UR.y)) +/* true if boxes b0 and b1 overlap */ #define OVERLAP(b0,b1) (((b0).UR.x >= (b1).LL.x) && ((b1).UR.x >= (b0).LL.x) && ((b0).UR.y >= (b1).LL.y) && ((b1).UR.y >= (b0).LL.y)) +/* true if box b0 completely contains b1*/ #define CONTAINS(b0,b1) (((b0).UR.x >= (b1).UR.x) && ((b0).UR.y >= (b1).UR.y) && ((b0).LL.x <= (b1).LL.x) && ((b0).LL.y <= (b1).LL.y)) +/* expand box b as needed to enclose point p */ +#define EXPANDBP(b, p) (b.LL.x = MIN(b.LL.x, p.x), b.LL.y = MIN(b.LL.y, p.y), b.UR.x = MAX(b.UR.x, p.x), b.UR.y = MAX(b.UR.y, p.y)) +/* expand box b0 as needed to enclose box b1 */ +#define EXPANDBB(b0, b1) (b0.LL.x = MIN(b0.LL.x, b1.LL.x), b0.LL.y = MIN(b0.LL.y, b1.LL.y), b0.UR.x = MAX(b0.UR.x, b1.UR.x), b0.UR.y = MAX(b0.UR.y, b1.UR.y)) + #define ROUND(f) ((f>=0)?(int)(f + .5):(int)(f - .5)) #define RADIANS(deg) ((deg)/180.0 * PI) #define DEGREES(rad) ((rad)/PI * 180.0) diff --git a/lib/common/renderprocs.h b/lib/common/renderprocs.h index c77956785..b163f4b80 100644 --- a/lib/common/renderprocs.h +++ b/lib/common/renderprocs.h @@ -27,8 +27,7 @@ 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 boxf arrow_bb(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); diff --git a/lib/common/utils.c b/lib/common/utils.c index 070823528..57873dae5 100644 --- a/lib/common/utils.c +++ b/lib/common/utils.c @@ -666,6 +666,7 @@ boolean box_contains(box b0, box b1) { return CONTAINS(b0, b1); } + boolean boxf_contains(boxf b0, boxf b1) { return CONTAINS(b0, b1); @@ -1923,20 +1924,32 @@ boolean overlap_label(textlabel_t *lp, boxf b) return OVERLAP(b, bb); } +static boolean overlap_arrow(pointf p, pointf u, double scale, int flag, boxf b) +{ + boxf bb; + + bb = arrow_bb(p, u, scale, flag); + if (OVERLAP(b, bb)) { + /* FIXME - check inside arrow shape */ + return TRUE; + } + return FALSE; +} + static boolean overlap_bezier(bezier bz, boxf b) { int i, j; + point pp; box bb; boxf bbf; + pointf p, u; 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); + pp = bz.list[j]; + EXPANDBP(bb, pp); } B2BF(bb, bbf); if (OVERLAP(b, bbf)) { @@ -1944,6 +1957,20 @@ static boolean overlap_bezier(bezier bz, boxf b) return TRUE; } } + + /* check arrows */ + if (bz.sflag) { + P2PF(bz.sp, p); + P2PF(bz.list[0], u); + if (overlap_arrow(p, u, 1, bz.sflag, b)) + return TRUE; + } + if (bz.eflag) { + P2PF(bz.ep, p); + P2PF(bz.list[bz.size - 1], u); + if (overlap_arrow(p, u, 1, bz.eflag, b)) + return TRUE; + } return FALSE; } @@ -1954,15 +1981,11 @@ boolean overlap_edge(edge_t *e, boxf b) textlabel_t *lp; spl = ED_spl(e); - if (spl && boxf_overlap(spl->bb, b)) { + 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; -- 2.40.0