]> granicus.if.org Git - graphviz/commitdiff
perform an accurate computation of bezier bb when calculating graph bb.
authorellson <devnull@localhost>
Wed, 23 Jul 2008 18:09:55 +0000 (18:09 +0000)
committerellson <devnull@localhost>
Wed, 23 Jul 2008 18:09:55 +0000 (18:09 +0000)
lib/common/emit.c
lib/common/render.h
lib/common/splines.c
lib/common/utils.h
lib/dotgen/dotsplines.c

index c906f5b4efa3bbb14b7edaba241c33bc2a6ec963..0af7460cb59a2398a7cbb6d125b68173902c1d0d 100644 (file)
@@ -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)
 {
index 8a4d809fb7c3e9a352459f6bc162d8e3306b1606..d8ed56b145435293fc1da55e2318b39ca9460357 100644 (file)
@@ -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);
index fe3491f68334fa24fd25c1f88570cff11f203abd..6c262b4c97a74c1b6c55f70eaaef496c30b25256 100644 (file)
@@ -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;
 }
 
index a53de38597aa31332889533f2a32a67dcb057c86..73e3b69e2cbf3a346af91156be835dd93ce440ae 100644 (file)
@@ -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);
index 4c857b5585ee92a1bcb5411853a41fb04f63b204..3c0564ecacd653c3e321be057442fff4d5baaf9b 100644 (file)
@@ -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));