[dia] [unit test] distance_from() vs. enclosing box (plus fixes)



commit 41d5d06fc270e8e59703c178881921dea6fbea7f
Author: Hans Breuer <hans breuer org>
Date:   Fri Jul 26 21:33:26 2013 +0200

    [unit test] distance_from() vs. enclosing box (plus fixes)
    
    This shall work for all objects so it does not check for full correctness,
    but is currently tolerant enough for element and connection objects.
    If it fails either the bounding calculation is bogus or distance_from method.
    
    - lib/text.c(text_distance_from): use ascent and descent for first and
      last line, text height is the line height
    - Database/reference.c: missing PolyBBExtras use and arrow parts outside
      bounding box
    - Jackson/requirement.c: use distance_ellipse_point() and ellipse_bbox()
    - network/wanlink.c: use distance_polygon_point()
    - standard/image.c(text_distance_from): consider drawing border being optional

 lib/text.c                    |    2 +-
 objects/Database/reference.c  |   12 +++++++++
 objects/Jackson/requirement.c |   19 +++++++++++++--
 objects/network/wanlink.c     |   25 ++++++--------------
 objects/standard/image.c      |    9 ++++---
 tests/test-objects.c          |   50 ++++++++++++++++++++++++++++++++++++++++-
 6 files changed, 91 insertions(+), 26 deletions(-)
---
diff --git a/lib/text.c b/lib/text.c
index 00f5d2c..6dcda71 100644
--- a/lib/text.c
+++ b/lib/text.c
@@ -509,7 +509,7 @@ text_distance_from(Text *text, Point *point)
   int line;
   
   topy = text->position.y - text->ascent;
-  bottomy = topy + text->height*text->numlines;
+  bottomy = text->position.y + text->descent + text->height*(text->numlines-1);
   if (point->y <= topy) {
     dy = topy - point->y;
     line = 0;
diff --git a/objects/Database/reference.c b/objects/Database/reference.c
index 15da9d7..ff98203 100644
--- a/objects/Database/reference.c
+++ b/objects/Database/reference.c
@@ -344,8 +344,16 @@ reference_update_data (TableReference * ref)
 {
   OrthConn * orth = &ref->orth;
   Rectangle rect;
+  PolyBBExtras *extra = &orth->extra_spacing;
 
   orthconn_update_data (orth);
+
+  /* account for line_width in bounding box calculation */
+  extra->start_trans =
+    extra->start_long =
+    extra->middle_trans =
+    extra->end_trans =
+    extra->end_long = ref->line_width/2.0;
   orthconn_update_boundingbox (orth);
 
   /* compute the position of the start point description */
@@ -415,6 +423,10 @@ reference_update_data (TableReference * ref)
     {
       ref->ep_desc_width = 0.0;
     }
+  /* finally the end arrow */
+  arrow_bbox (&ref->end_arrow, ref->line_width,
+              &orth->points[orth->numpoints - 1], &orth->points[orth->numpoints - 2], &rect);
+  rectangle_union (&orth->object.bounding_box, &rect);
 }
 
 static void
diff --git a/objects/Jackson/requirement.c b/objects/Jackson/requirement.c
index 0f9a9a7..5b676f7 100644
--- a/objects/Jackson/requirement.c
+++ b/objects/Jackson/requirement.c
@@ -167,8 +167,14 @@ req_set_props(Requirement *req, GPtrArray *props)
 static real
 req_distance_from(Requirement *req, Point *point)
 {
-  DiaObject *obj = &req->element.object;
-  return distance_rectangle_point(&obj->bounding_box, point);
+  Element *elem = &req->element;
+  Point center;
+
+  center.x = elem->corner.x+elem->width/2;
+  center.y = elem->corner.y+elem->height/2;
+
+  return distance_ellipse_point(&center, elem->width, elem->height,
+                               REQ_LINEWIDTH, point);
 }
 
 static void
@@ -321,6 +327,13 @@ req_update_data(Requirement *req)
 
   element_update_handles(elem);
 
+  /* Boundingbox calculation including the line width */
+  {
+    Rectangle bbox;
+
+    ellipse_bbox (&c, elem->width, elem->height, &elem->extra_spacing, &bbox);
+    rectangle_union(&obj->bounding_box, &bbox);
+  }
 }
 
 /** creation here */
@@ -374,7 +387,7 @@ req_create(Point *startpoint,
   }
   req->connections[8].flags = CP_FLAGS_MAIN;
   req->connections[8].directions |= DIR_ALL;
-  elem->extra_spacing.border_trans = 0.0;
+  elem->extra_spacing.border_trans = REQ_LINEWIDTH / 2.0;
   req_update_data(req);
 
   for (i=0;i<8;i++) {
diff --git a/objects/network/wanlink.c b/objects/network/wanlink.c
index 143c315..32e46d3 100644
--- a/objects/network/wanlink.c
+++ b/objects/network/wanlink.c
@@ -235,14 +235,7 @@ wanlink_draw (WanLink *wanlink, DiaRenderer *renderer)
 static real
 wanlink_distance_from(WanLink *wanlink, Point *point)
 {
-  Point *endpoints;
-  real min_dist;
-
-  /* TODO: handle the fact that this is not a line */
-  endpoints = &wanlink->connection.endpoints[0];
-  min_dist = distance_line_point( &endpoints[0], &endpoints[1],
-                                  wanlink->width, point);
-  return min_dist;
+  return distance_polygon_point (wanlink->poly, WANLINK_POLY_LEN, wanlink->width, point);
 }
 
 static void
@@ -299,7 +292,8 @@ wanlink_move_handle(WanLink *wanlink, Handle *handle,
 {
   connection_move_handle(&wanlink->connection, handle->id, to, cp,
                         reason, modifiers);
-  
+  connection_adjust_for_autogap(&wanlink->connection);
+
   wanlink_update_data(wanlink);
 
   return NULL;
@@ -495,14 +489,11 @@ wanlink_update_data(WanLink *wanlink)
                        &new_pt);
       point_add (&new_pt, &origin);
       wanlink->poly[i] = new_pt;
-      if (wanlink->poly [i].y < obj->bounding_box.top)
-         obj->bounding_box.top = wanlink->poly [i].y;
-      if (wanlink->poly [i].x < obj->bounding_box.left)
-         obj->bounding_box.left = wanlink->poly [i].x;
-      if (wanlink->poly [i].y > obj->bounding_box.bottom)
-         obj->bounding_box.bottom = wanlink->poly [i].y;
-      if (wanlink->poly [i].x > obj->bounding_box.right)
-         obj->bounding_box.right = wanlink->poly [i].x;
+  }
+  /* calculate bounding box */
+  {
+    PolyBBExtras bbex = {0, 0, wanlink->width/2, 0, 0 };
+    polyline_bbox (&wanlink->poly[0], WANLINK_POLY_LEN, &bbex, TRUE, &obj->bounding_box);
   }
 
 
diff --git a/objects/standard/image.c b/objects/standard/image.c
index b1c2d8c..63de47f 100644
--- a/objects/standard/image.c
+++ b/objects/standard/image.c
@@ -254,11 +254,12 @@ image_distance_from(Image *image, Point *point)
 {
   Element *elem = &image->element;
   Rectangle rect;
+  real bw = image->draw_border ? image->border_width : 0;
 
-  rect.left = elem->corner.x - image->border_width;
-  rect.right = elem->corner.x + elem->width + image->border_width;
-  rect.top = elem->corner.y - image->border_width;
-  rect.bottom = elem->corner.y + elem->height + image->border_width;
+  rect.left = elem->corner.x - bw;
+  rect.right = elem->corner.x + elem->width + bw;
+  rect.top = elem->corner.y - bw;
+  rect.bottom = elem->corner.y + elem->height + bw;
   return distance_rectangle_point(&rect, point);
 }
 
diff --git a/tests/test-objects.c b/tests/test-objects.c
index e55b6da..dd9da08 100644
--- a/tests/test-objects.c
+++ b/tests/test-objects.c
@@ -577,11 +577,55 @@ _test_draw (gconstpointer user_data)
 
   o->ops->draw (o, renderer);
   /* finally */
-  o->ops->destroy (o);  
+  o->ops->destroy (o);
   g_free (o);
   g_object_unref (renderer);
 }
 
+static void
+_test_distance_from (gconstpointer user_data)
+{
+  const DiaObjectType *type = (const DiaObjectType *)user_data;
+  Handle *h1 = NULL, *h2 = NULL;
+  Point from = {0, 0};
+  DiaObject *o = type->ops->create (&from, type->default_user_data, &h1, &h2);
+  const Rectangle *ebox;
+  Point center;
+  real width, height;
+  Point test;
+  real outside = 0.01; /* tolerance value for being outside */
+
+  /* This shall work for all objects so it does not check for full correctness,
+   * but is currently tolerant enough for element and connection objects.
+   * If it fails either the bounding calculation is bogus or distance_from method.
+   */
+  /* Outside of the enclosing (bounding) box can not be inside the object */
+  ebox = dia_object_get_enclosing_box (o);
+  center.x = (ebox->left + ebox->right) / 2;
+  center.y = (ebox->top + ebox->bottom) / 2;
+  width = ebox->right - ebox->left;
+  height = ebox->bottom - ebox->top;
+
+  /* Some custom objects still fail this check otherwise */
+  if (   strcmp (type->name, "Civil - Gas Bottle") == 0
+      || strcmp (type->name, "Cybernetics - l-sens") == 0)
+    outside += 0.1;
+
+  test.y = center.y;
+  test.x = center.x - width/2 - outside;
+  g_assert (o->ops->distance_from (o, &test) > 0 && "left");
+  test.x = center.x + width/2 + outside;
+  g_assert (o->ops->distance_from (o, &test) > 0 && "right");
+  test.x = center.x;
+  test.y = center.y - height/2 - outside;
+  g_assert (o->ops->distance_from (o, &test) > 0 && "top");
+  test.y = center.y + height/2 + outside;
+  g_assert (o->ops->distance_from (o, &test) > 0 && "bottom");
+
+  /* finally */
+  o->ops->destroy (o);
+  g_free (o);
+}
 /*
  * A dictionary interface to all registered object(-types)
  */
@@ -628,6 +672,10 @@ _ot_item (gpointer key,
   g_test_add_data_func (testpath, type, _test_draw);
   g_free (testpath);
 
+  testpath = g_strdup_printf ("%s/%s/%s", base, name, "DistanceFrom");
+  g_test_add_data_func (testpath, type, _test_distance_from);
+  g_free (testpath);
+
   ++num_objects;
 }
 


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