]> granicus.if.org Git - graphviz/commitdiff
Factor out overlap_node(node_t *,boxf) and overlap_edge(node_t *,boxf)
authorellson <devnull@localhost>
Sun, 1 May 2005 15:08:54 +0000 (15:08 +0000)
committerellson <devnull@localhost>
Sun, 1 May 2005 15:08:54 +0000 (15:08 +0000)
and use for both mouse_in_node/edge and node/edge_in_clip_region.

lib/common/arrows.c
lib/common/emit.c
lib/common/renderprocs.h
lib/common/utils.c
lib/gvc/gvevent.c

index f1c453274106b78f3a6745a109bab514068857f0..b8504b3eafb83d73a638a8674e2165584448e9d7 100644 (file)
@@ -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;
index 32643fc7c27276187f24c1557359c2424a7d19ed..75a85d58b91b518504c36721b48eeba73cb40453 100644 (file)
@@ -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);
        }
     }
 }
index 571f2e7c483b49bcffc0a39c535bf0d5dd4e3363..5e11ed075051184e2e027e051a5b4a564823602e 100644 (file)
@@ -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);
index a37262193b3654c2d79b4087a49a3a78a2f33516..198389838afee5363a4261c635426b93865d173b 100644 (file)
@@ -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;
+}
+
+
index 54c5e35682a45987636ca0d62ff4f75b4cd76845..93c8ee07b7668ab3bbb92d56453a960846bbbc7b 100644 (file)
@@ -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);