]> granicus.if.org Git - graphviz/commitdiff
add a CLOSEENOUGH factor for mouse in objects
authorellson <devnull@localhost>
Sat, 30 Apr 2005 22:41:36 +0000 (22:41 +0000)
committerellson <devnull@localhost>
Sat, 30 Apr 2005 22:41:36 +0000 (22:41 +0000)
add an OVERLAP macro

lib/common/macros.h
lib/common/renderprocs.h
lib/common/utils.c
lib/gvc/gvevent.c

index 078d326640eae89fbf5b10ccbb01049c517c5e2e..3e086935477d2fb01265ee7c4f7d370d3c811aea 100644 (file)
@@ -83,7 +83,9 @@
 #undef BETWEEN
 #endif
 #define BETWEEN(a,b,c) (((a) <= (b)) && ((b) <= (c)))
-#define INSIDE(p,b)    (BETWEEN(b.LL.x,p.x,b.UR.x) && BETWEEN(b.LL.y,p.y,b.UR.y))
+#define INSIDE(p,b)    (BETWEEN((b).LL.x,(p).x,(b).UR.x) && BETWEEN((b).LL.y,(p).y,(b).UR.y))
+#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))
+#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))
 
 #define ROUND(f)        ((f>=0)?(int)(f + .5):(int)(f - .5))
 #define RADIANS(deg)   ((deg)/180.0 * PI)
index 1d4e18bea6b9af3fa10fcf2fec052d7b0d413329..571f2e7c483b49bcffc0a39c535bf0d5dd4e3363 100644 (file)
@@ -48,6 +48,8 @@ extern "C" {
     extern boxf boxf_intersect(boxf, boxf);
     extern boolean box_overlap(box, box);
     extern boolean boxf_overlap(boxf, boxf);
+    extern boolean box_contains(box, box);
+    extern boolean boxf_contains(boxf, boxf);
     extern void cat_libfile(FILE *, char **, char **);
     extern void clip_and_install(edge_t *, edge_t *, point *, int,
                                 splineInfo *);
index 6dd4812ad46c89e4fc3d862260dcebf7e6fd333d..a37262193b3654c2d79b4087a49a3a78a2f33516 100644 (file)
@@ -654,26 +654,21 @@ boxf boxf_intersect(boxf b0, boxf b1)
 
 boolean box_overlap(box b0, box b1)
 {
-    if ((b0.UR.x < b1.LL.x) || (b1.UR.x < b0.LL.x)
-       || (b0.UR.y < b1.LL.y) || (b1.UR.y < b0.LL.y))
-       return FALSE;
-    return TRUE;
+    return OVERLAP(b0, b1);
 }
 
 boolean boxf_overlap(boxf b0, boxf b1)
 {
-    if ((b0.UR.x < b1.LL.x) || (b1.UR.x < b0.LL.x)
-       || (b0.UR.y < b1.LL.y) || (b1.UR.y < b0.LL.y))
-       return FALSE;
-    return TRUE;
+    return OVERLAP(b0, b1);
 }
 
-boolean boxf_contains_p(boxf b0, boxf b1)
+boolean box_contains(box b0, box b1)
 {
-    if ((b0.UR.x >= b1.UR.x) && (b0.UR.y >= b1.UR.y)
-       && (b0.LL.x <= b1.LL.x) && (b0.LL.y <= b1.LL.y))
-       return TRUE;
-    return FALSE;
+    return CONTAINS(b0, b1);
+}
+boolean boxf_contains(boxf b0, boxf b1)
+{
+    return CONTAINS(b0, b1);
 }
 
 int maptoken(char *p, char **name, int *val)
index 8c01749806bd47eb85d06f50a1c17b1c83ce2929..54c5e35682a45987636ca0d62ff4f75b4cd76845 100644 (file)
@@ -37,11 +37,13 @@ void gvevent_refresh(GVJ_t * job)
     emit_graph(job, job->g);
 }
 
-static boolean inside_node(node_t *n, pointf p)
+static boolean inside_node(node_t *n, boxf b)
 {
+    boxf bb;
 //    inside_t ictxt;
 
-    if (! INSIDE(p, ND_bb(n)))
+    bb = ND_bb(n);
+    if (! OVERLAP(b, bb))
        return FALSE;
 
 //    ictxt.s.n = n;
@@ -51,7 +53,7 @@ static boolean inside_node(node_t *n, pointf p)
     return TRUE;
 }
 
-static boolean inside_label(edge_t *e, pointf p)
+static boolean inside_label(edge_t *e, boxf b)
 {
     textlabel_t *lp;
     double sx, sy;
@@ -66,10 +68,10 @@ static boolean inside_label(edge_t *e, pointf p)
     bb.UR.x = lp->p.x + sx;
     bb.LL.y = lp->p.y - sy;
     bb.UR.y = lp->p.y + sy;
-    return INSIDE(p, bb);
+    return OVERLAP(b, bb);
 }
 
-static boolean inside_spline(edge_t *e, pointf p)
+static boolean inside_spline(edge_t *e, boxf b)
 {
     int i, j, k;
     bezier bz;
@@ -80,8 +82,9 @@ static boolean inside_spline(edge_t *e, pointf p)
     spl = ED_spl(e);
     if (spl == NULL)
         return FALSE;
-    
-    if (! INSIDE(p, spl->bb))
+
+    bbf = spl->bb;
+    if (! OVERLAP(b, bbf))
        return FALSE;
 
     for (i = 0; i < spl->size; i++) {
@@ -95,8 +98,8 @@ static boolean inside_spline(edge_t *e, pointf p)
                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 (INSIDE(p,bbf)) {
+           B2BF(bb, bbf);
+           if (OVERLAP(b, bbf)) {
                /* FIXME - check if really close enough to actual curve */
                return TRUE;
            }
@@ -105,36 +108,36 @@ static boolean inside_spline(edge_t *e, pointf p)
     return FALSE;
 }
 
-static boolean inside_edge(edge_t *e, pointf p)
+static boolean inside_edge(edge_t *e, boxf b)
 {
-    if (inside_spline(e, p))
+    if (inside_spline(e, b))
        return TRUE;
 // FIXME
 //    if (inside_arrow(e))
 //     return TRUE;
 
-    return inside_label(e, p);
+    return inside_label(e, b);
 }
 
 /* recursively find innermost cluster containing the point */
-static graph_t *gvevent_find_cluster(graph_t *g, pointf p)
+static graph_t *gvevent_find_cluster(graph_t *g, boxf b)
 {
     int i;
     graph_t *sg;
     boxf bb;
 
     for (i = 1; i <= GD_n_cluster(g); i++) {
-       sg = gvevent_find_cluster(GD_clust(g)[i], p);
+       sg = gvevent_find_cluster(GD_clust(g)[i], b);
        if (sg)
            return(sg);
     }
     B2BF(GD_bb(g), bb);
-    if (INSIDE(p, bb))
+    if (OVERLAP(b, bb))
        return g;
     return NULL;
 }
 
-static void * gvevent_find_obj(graph_t *g, pointf p)
+static void * gvevent_find_obj(graph_t *g, boxf b)
 {
     graph_t *sg;
     node_t *n;
@@ -143,14 +146,14 @@ static void * gvevent_find_obj(graph_t *g, pointf p)
     /* 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, p))
+           if (inside_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, p))
+       if (inside_node(n, b))
            return (void *)n;
     /* search for innermost cluster */
-    sg = gvevent_find_cluster(g, p);
+    sg = gvevent_find_cluster(g, b);
     if (sg)
        return (void *)sg;
 
@@ -158,10 +161,15 @@ static void * gvevent_find_obj(graph_t *g, pointf p)
     return (void *)g;
 }
 
+/* CLOSEENOUGH is in window units - probably should be a feature... */
+#define CLOSEENOUGH 1
+
 static void gvevent_find_current_obj(GVJ_t * job, double x, double y)
 {
     void *obj;
     pointf p;
+    boxf b;
+    double closeenough;
 
     /* convert window point to graph coordinates */
     if (job->rotation) {
@@ -172,8 +180,14 @@ static void gvevent_find_current_obj(GVJ_t * job, double x, double y)
        p.x = job->focus.x + (x - job->width / 2.) / job->compscale.x;
        p.y = job->focus.y + (y - job->height / 2.) / job->compscale.y;
     }
+    closeenough = CLOSEENOUGH / job->compscale.x;
+
+    b.UR.x = p.x + closeenough;
+    b.UR.y = p.y + closeenough;
+    b.LL.x = p.x - closeenough;
+    b.LL.y = p.y - closeenough;
 
-    obj = gvevent_find_obj(job->g, p);
+    obj = gvevent_find_obj(job->g, b);
     if (obj != job->current_obj) {
        job->current_obj = obj;
 fprintf(stderr,"obj=%x kind=%d\n",obj,agobjkind(obj));