[dia] [matherr] Fix distance_ellipse_point() against returning NAN



commit 6b9494fc729475d2f8cf53ee344ba2fd7dbc7f8e
Author: Hans Breuer <hans breuer org>
Date:   Mon Oct 15 12:18:22 2012 +0200

    [matherr] Fix distance_ellipse_point() against returning NAN
    
    The newest unit test checks DiaObject::distance_from(center), which
    revealed some mathematical instability in distance_ellipse_point().
    Now this code was copied twice to object implementations.

 lib/geometry.c              |    2 ++
 objects/Istar/actor.c       |   33 ++-------------------------------
 objects/flowchart/ellipse.c |    9 ++++-----
 3 files changed, 8 insertions(+), 36 deletions(-)
---
diff --git a/lib/geometry.c b/lib/geometry.c
index 588d75b..7cf4916 100644
--- a/lib/geometry.c
+++ b/lib/geometry.c
@@ -403,6 +403,8 @@ distance_ellipse_point(const Point *centre, real width, real height,
   pt.x *= pt.x;
   pt.y *= pt.y;  /* pt = (point - centre).^2 */
 
+  if (pt.x <= 0.0 && pt.y <= 0.0)
+    return 0.0; /* instead of division by zero */
   scale = w2 * h2 / (4*h2*pt.x + 4*w2*pt.y);
   rad = sqrt((pt.x + pt.y)*scale) + line_width/2;
 
diff --git a/objects/Istar/actor.c b/objects/Istar/actor.c
index f1e5702..43f8a05 100644
--- a/objects/Istar/actor.c
+++ b/objects/Istar/actor.c
@@ -183,31 +183,6 @@ actor_set_props(Actor *actor, GPtrArray *props)
   actor_update_data(actor, ANCHOR_MIDDLE, ANCHOR_MIDDLE);
 }
 
-/* returns the radius of the actor along the ray from the centre of the
- * actor to the point (px, py) */
-static real
-actor_radius(Actor *actor, real px, real py)
-{
-  Element *elem = &actor->element;
-  real w2 = elem->width * elem->width;
-  real h2 = elem->height * elem->height;
-  real scale;
-
-  /* find the point of intersection between line (x=cx+(px-cx)t; y=cy+(py-cy)t)
-   * and actor ((x-cx)^2)/(w/2)^2 + ((y-cy)^2)/(h/2)^2 = 1 */
-  /* radius along ray is sqrt((px-cx)^2 * t^2 + (py-cy)^2 * t^2) */
-
-  /* normalize coordinates ... */
-  px -= elem->corner.x + elem->width  / 2;
-  py -= elem->corner.y + elem->height / 2;
-  /* square them ... */
-  px *= px;
-  py *= py;
-
-  scale = w2 * h2 / (4*h2*px + 4*w2*py);
-  return sqrt((px + py)*scale);
-}
-
 static real
 actor_distance_from(Actor *actor, Point *point)
 {
@@ -217,13 +192,9 @@ actor_distance_from(Actor *actor, Point *point)
 
   c.x = elem->corner.x + elem->width / 2;
   c.y = elem->corner.y + elem->height/ 2;
-  dist = distance_point_point(point, &c);
-  rad = actor_radius(actor, point->x, point->y) + ACTOR_BORDER_WIDTH/2;
-
 
-  if (dist <= rad)
-    return 0;
-  return dist - rad;
+  return distance_ellipse_point (&c, elem->width / 2, elem->height/ 2,
+				 ACTOR_BORDER_WIDTH, point);
 }
 
 static void
diff --git a/objects/flowchart/ellipse.c b/objects/flowchart/ellipse.c
index 6bed6e2..d3723e5 100644
--- a/objects/flowchart/ellipse.c
+++ b/objects/flowchart/ellipse.c
@@ -231,6 +231,8 @@ ellipse_radius(Ellipse *ellipse, real px, real py)
   px *= px;
   py *= py;
 
+  if (px <= 0.0 && py <= 0.0)
+    return 0; /* avoid division by zero */
   scale = w2 * h2 / (4*h2*px + 4*w2*py);
   return sqrt((px + py)*scale);
 }
@@ -244,12 +246,9 @@ ellipse_distance_from(Ellipse *ellipse, Point *point)
 
   c.x = elem->corner.x + elem->width / 2;
   c.y = elem->corner.y + elem->height/ 2;
-  dist = distance_point_point(point, &c);
-  rad = ellipse_radius(ellipse, point->x, point->y) + ellipse->border_width/2;
 
-  if (dist <= rad)
-    return 0;
-  return dist - rad;
+  return distance_ellipse_point (&c, elem->width / 2, elem->height/ 2,
+				 ellipse->border_width, point);
 }
 
 static void



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