[dia] path: Fix bezier bounding box calculation glitches



commit 7ef29f3c807610cd24d65ae21e0db3c1d69aab59
Author: Hans Breuer <hans breuer org>
Date:   Fri Sep 26 14:13:08 2014 +0200

    path: Fix bezier bounding box calculation glitches
    
    Without a 'pointy join' there is no point in calculating the overshot,
    actually this was growing the bounding box arbitrarily. (First line
    of bezier-extreme.dia)
    
    Also handle slightly degenerated bezier where the control point and
    the start or end point are in the same place. Now we are using the
    other control point to have a direction for add_arrow_rectangle()
    in bicubicbezier2D_bbox(). Otherwise there would be no bounding box
    contribution from line ends of this kind (see second line of
    bezier-extreme.dia)
    
    Having this fix also seems to be a precondition for properly behaving
    StdPath::move_handle(). Previously, e.g. with commit 14e05d51d99e1457
    it was possible to go over the constraints implemented, presumably
    due to bounding box miscalculations leading to wrong handle positions.
    
    Still with line-join round the bezier is drawn a bit outside of the box.

 lib/boundingbox.c          |   25 +++++++++++++++++--------
 samples/bezier-extreme.dia |  Bin 0 -> 4724 bytes
 2 files changed, 17 insertions(+), 8 deletions(-)
---
diff --git a/lib/boundingbox.c b/lib/boundingbox.c
index 4c14892..83c7350 100644
--- a/lib/boundingbox.c
+++ b/lib/boundingbox.c
@@ -158,12 +158,16 @@ bicubicbezier2D_bbox(const Point *p0,const Point *p1,
   rectangle_add_point(rect,p3);
   /* start point */  
   point_copy_add_scaled(&vl,p0,p1,-1);
+  if (point_len(&vl) == 0)
+    point_copy_add_scaled(&vl,p0,p2,-1);
   point_normalize(&vl); 
   add_arrow_rectangle(rect,p0,&vl,extra->start_long,MAX(extra->start_trans,
                                                          extra->middle_trans));
 
   /* end point */
   point_copy_add_scaled(&vl,p3,p2,-1);
+  if (point_len(&vl) == 0)
+    point_copy_add_scaled(&vl,p3,p1,-1);
   point_normalize(&vl); 
   add_arrow_rectangle(rect,p3,&vl,extra->end_long,MAX(extra->end_trans,
                                                       extra->middle_trans));
@@ -312,7 +316,7 @@ polybezier_bbox(const BezPoint *pts, int numpoints,
   Point vx,vn,vsc,vp;
   int i,prev,next;
   Rectangle rt;
-  PolyBBExtras bextra,start_bextra,end_bextra;
+  PolyBBExtras bextra,start_bextra,end_bextra,full_bextra;
   LineBBExtras lextra,start_lextra,end_lextra,full_lextra;
   gboolean start,end;
 
@@ -342,6 +346,11 @@ polybezier_bbox(const BezPoint *pts, int numpoints,
   full_lextra.start_trans = MAX(extra->start_trans,extra->middle_trans);
   full_lextra.end_long = extra->end_long;
   full_lextra.end_trans = MAX(extra->end_trans,extra->middle_trans);
+  full_bextra.start_long = extra->start_long;
+  full_bextra.start_trans = MAX(extra->start_trans,extra->middle_trans);
+  full_bextra.middle_trans = extra->middle_trans;
+  full_bextra.end_long = extra->end_long;
+  full_bextra.end_trans = MAX(extra->end_trans,extra->middle_trans);
 
   if (!closed) {
     lextra.start_long = 0;
@@ -453,7 +462,7 @@ polybezier_bbox(const BezPoint *pts, int numpoints,
         if (end) {
           bicubicbezier2D_bbox(&vsc,
                                &pts[i].p1,&pts[i].p2,&pts[i].p3,
-                               extra,
+                               &full_bextra,
                                &rt);
         } else {
           bicubicbezier2D_bbox(&vsc,
@@ -497,12 +506,7 @@ polybezier_bbox(const BezPoint *pts, int numpoints,
       point_normalize(&vxn);
 
       co = point_dot(&vpx,&vxn);
-      if (co >= 1.0)
-        alpha = 0.0;
-      else if (co <= -1.0)
-        alpha = M_PI;
-      else
-        alpha = dia_acos(-co);
+      alpha = dia_acos(-co);
       if (co > -0.9816) { /* 0.9816 = cos(11deg) */
         /* we have a pointy join. */
         real overshoot;
@@ -520,6 +524,10 @@ polybezier_bbox(const BezPoint *pts, int numpoints,
         rectangle_add_point(rect,&pto);
       } else {
         /* we don't have a pointy join. */
+#if 0
+       /* so nothing to do really - this code would be growing the
+        * bounding box arbitrarily. See e.g with bezier-extreme.dia
+        */
         Point vpxt,vxnt,tmp;
 
         point_get_perp(&vpxt,&vpx);
@@ -533,6 +541,7 @@ polybezier_bbox(const BezPoint *pts, int numpoints,
         rectangle_add_point(rect,&tmp);
         point_copy_add_scaled(&tmp,&vx,&vxnt,-1);
         rectangle_add_point(rect,&tmp);
+#endif
       }
     }
   }
diff --git a/samples/bezier-extreme.dia b/samples/bezier-extreme.dia
new file mode 100644
index 0000000..63262da
Binary files /dev/null and b/samples/bezier-extreme.dia differ


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]