[libchamplain] Improve bounding box use



commit b048845f782218178bfcddabc42984bc8cb153c8
Author: JiÅ?í Techet <techet gmail com>
Date:   Tue Feb 15 00:15:03 2011 +0100

    Improve bounding box use
    
    Add an ensure_visible function for layers in view, make bounding
    box query a virtual function of layers and add some extra utility
    functions to bounding box.

 champlain/champlain-bounding-box.c       |   65 +++++++++++++++++++++++++++++-
 champlain/champlain-bounding-box.h       |    5 ++
 champlain/champlain-layer.c              |   20 +++++++++
 champlain/champlain-layer.h              |    4 ++
 champlain/champlain-marker-layer.c       |   38 ++++--------------
 champlain/champlain-marker-layer.h       |    1 -
 champlain/champlain-path-layer.c         |   38 ++++-------------
 champlain/champlain-path-layer.h         |    2 -
 champlain/champlain-view.c               |   44 ++++++++++++++++++++
 champlain/champlain-view.h               |    2 +
 docs/reference/libchamplain-sections.txt |    7 ++-
 11 files changed, 161 insertions(+), 65 deletions(-)
---
diff --git a/champlain/champlain-bounding-box.c b/champlain/champlain-bounding-box.c
index 7915893..1833525 100644
--- a/champlain/champlain-bounding-box.c
+++ b/champlain/champlain-bounding-box.c
@@ -28,6 +28,7 @@
  */
 
 #include "champlain-bounding-box.h"
+#include "champlain-defines.h"
 
 GType
 champlain_bounding_box_get_type (void)
@@ -59,7 +60,16 @@ champlain_bounding_box_get_type (void)
 ChamplainBoundingBox *
 champlain_bounding_box_new (void)
 {
-  return g_slice_new (ChamplainBoundingBox);
+  ChamplainBoundingBox *bbox;
+  
+  bbox = g_slice_new (ChamplainBoundingBox);
+  
+  bbox->left = CHAMPLAIN_MAX_LONGITUDE;
+  bbox->right = CHAMPLAIN_MIN_LONGITUDE;
+  bbox->bottom = CHAMPLAIN_MAX_LATITUDE;
+  bbox->top = CHAMPLAIN_MIN_LATITUDE;
+
+  return bbox;
 }
 
 
@@ -153,3 +163,56 @@ champlain_bounding_box_compose (ChamplainBoundingBox *bbox,
     bbox->bottom = other->bottom;
 }
 
+
+/**
+ * champlain_bounding_box_extend:
+ * @bbox: a #ChamplainBoundingBox
+ * @latitude: latitude
+ * @longitude: longitude
+ *
+ * Extend the bounding box so it contains a point with @latitude and @longitude.
+ * Do nothing if the point is already inside the bounding box.
+ *
+ * Since: 0.10
+ */
+void champlain_bounding_box_extend (ChamplainBoundingBox *bbox,
+    gdouble latitude, gdouble longitude)
+{
+  g_return_if_fail (CHAMPLAIN_BOUNDING_BOX (bbox));
+  
+  if (longitude < bbox->left)
+    bbox->left = longitude;
+
+  if (latitude < bbox->bottom)
+    bbox->bottom = latitude;
+
+  if (longitude > bbox->right)
+    bbox->right = longitude;
+
+  if (latitude > bbox->top)
+    bbox->top = latitude;
+}
+
+
+/**
+ * champlain_bounding_box_is_valid:
+ * @bbox: a #ChamplainBoundingBox
+ *
+ * Checks whether bbox represents a valid bounding box on the map.
+ *
+ * Returns: TRUE when the bounding box is valid, FALSE otherwise.
+ *
+ * Since: 0.10
+ */
+gboolean
+champlain_bounding_box_is_valid (ChamplainBoundingBox *bbox)
+{
+  g_return_val_if_fail (CHAMPLAIN_BOUNDING_BOX (bbox), FALSE);
+
+  return (bbox->left < bbox->right) && (bbox->bottom < bbox->top) &&
+      (bbox->left > CHAMPLAIN_MIN_LONGITUDE) && (bbox->left < CHAMPLAIN_MAX_LONGITUDE) &&
+      (bbox->right > CHAMPLAIN_MIN_LONGITUDE) && (bbox->right < CHAMPLAIN_MAX_LONGITUDE) &&
+      (bbox->bottom > CHAMPLAIN_MIN_LATITUDE) && (bbox->bottom < CHAMPLAIN_MAX_LATITUDE) &&
+      (bbox->top > CHAMPLAIN_MIN_LATITUDE) && (bbox->top < CHAMPLAIN_MAX_LATITUDE);
+}
+
diff --git a/champlain/champlain-bounding-box.h b/champlain/champlain-bounding-box.h
index 874519f..bbd3715 100644
--- a/champlain/champlain-bounding-box.h
+++ b/champlain/champlain-bounding-box.h
@@ -67,6 +67,11 @@ void champlain_bounding_box_get_center (ChamplainBoundingBox *bbox,
 void champlain_bounding_box_compose (ChamplainBoundingBox *bbox,
     ChamplainBoundingBox *other);
 
+void champlain_bounding_box_extend (ChamplainBoundingBox *bbox,
+    gdouble latitude, gdouble longitude);
+
+gboolean champlain_bounding_box_is_valid (ChamplainBoundingBox *bbox);
+
 G_END_DECLS
 
 #endif
diff --git a/champlain/champlain-layer.c b/champlain/champlain-layer.c
index 630d77f..fc77898 100644
--- a/champlain/champlain-layer.c
+++ b/champlain/champlain-layer.c
@@ -51,6 +51,7 @@ champlain_layer_class_init (ChamplainLayerClass *klass)
   object_class->dispose = champlain_layer_dispose;
 
   klass->set_view = NULL;
+  klass->get_bounding_box = NULL;
 }
 
 /**
@@ -75,6 +76,25 @@ void champlain_layer_set_view (ChamplainLayer *layer,
 }
 
 
+/**
+ * champlain_layer_get_bounding_box:
+ * @layer: a #ChamplainLayer
+ *
+ * Gets the bounding box occupied by the elements inside the layer.
+ *
+ * Returns: The bounding box.
+ * 
+ * Since: 0.10
+ */
+ChamplainBoundingBox *
+champlain_layer_get_bounding_box (ChamplainLayer *layer)
+{
+  g_return_val_if_fail (CHAMPLAIN_IS_LAYER (layer), NULL);
+
+  return CHAMPLAIN_LAYER_GET_CLASS (layer)->get_bounding_box (layer);
+}
+
+
 static void
 champlain_layer_init (ChamplainLayer *self)
 {
diff --git a/champlain/champlain-layer.h b/champlain/champlain-layer.h
index f425ef3..aca14d6 100644
--- a/champlain/champlain-layer.h
+++ b/champlain/champlain-layer.h
@@ -25,6 +25,7 @@
 
 #include <clutter/clutter.h>
 #include <champlain/champlain-defines.h>
+#include <champlain/champlain-bounding-box.h>
 
 G_BEGIN_DECLS
 
@@ -59,6 +60,7 @@ struct _ChamplainLayerClass
 
   void (*set_view)(ChamplainLayer *layer,
       ChamplainView *view);
+  ChamplainBoundingBox * (*get_bounding_box) (ChamplainLayer *layer);
 };
 
 GType champlain_layer_get_type (void);
@@ -67,6 +69,8 @@ GType champlain_layer_get_type (void);
 void champlain_layer_set_view (ChamplainLayer *layer,
     ChamplainView *view);
 
+ChamplainBoundingBox *champlain_layer_get_bounding_box (ChamplainLayer *layer);
+
 G_END_DECLS
 
 #endif /* __CHAMPLAIN_LAYER_H__ */
diff --git a/champlain/champlain-marker-layer.c b/champlain/champlain-marker-layer.c
index 9af841a..1356f28 100644
--- a/champlain/champlain-marker-layer.c
+++ b/champlain/champlain-marker-layer.c
@@ -70,6 +70,8 @@ static void marker_selected_cb (ChamplainMarker *marker,
 static void set_view (ChamplainLayer *layer,
     ChamplainView *view);
 
+static ChamplainBoundingBox *get_bounding_box (ChamplainLayer *layer);
+
 
 static void
 champlain_marker_layer_get_property (GObject *object,
@@ -256,7 +258,8 @@ champlain_marker_layer_class_init (ChamplainMarkerLayerClass *klass)
   actor_class->unmap = unmap;
   
   layer_class->set_view = set_view;
-  
+  layer_class->get_bounding_box = get_bounding_box;
+
   /**
    * ChamplainMarkerLayer:selection-mode:
    *
@@ -858,20 +861,9 @@ set_view (ChamplainLayer *layer,
     }
 }
 
-/**
- * champlain_marker_layer_get_bounding_box:
- * @layer: a #ChamplainMarkerLayer
- *
- * Gets the bounding box occupied by the markers in the layer
- *
- * Returns: The bounding box.
- * 
- * FIXME: This doesn't take into account the marker's actor size yet
- *
- * Since: 0.10
- */
-ChamplainBoundingBox *
-champlain_marker_layer_get_bounding_box (ChamplainMarkerLayer *layer)
+
+static ChamplainBoundingBox *
+get_bounding_box (ChamplainLayer *layer)
 {
   ChamplainMarkerLayerPrivate *priv = GET_PRIVATE (layer);
   GList *elem;
@@ -881,10 +873,6 @@ champlain_marker_layer_get_bounding_box (ChamplainMarkerLayer *layer)
   g_return_val_if_fail (CHAMPLAIN_IS_MARKER_LAYER (layer), NULL);
   
   bbox = champlain_bounding_box_new ();
-  bbox->left = CHAMPLAIN_MAX_LONGITUDE;
-  bbox->right = CHAMPLAIN_MIN_LONGITUDE;
-  bbox->bottom = CHAMPLAIN_MAX_LATITUDE;
-  bbox->top = CHAMPLAIN_MIN_LATITUDE;
 
   markers = clutter_container_get_children (CLUTTER_CONTAINER (priv->content_group));
 
@@ -896,17 +884,7 @@ champlain_marker_layer_get_bounding_box (ChamplainMarkerLayer *layer)
       g_object_get (G_OBJECT (marker), "latitude", &lat, "longitude", &lon,
           NULL);
 
-      if (lon < bbox->left)
-        bbox->left = lon;
-
-      if (lat < bbox->bottom)
-        bbox->bottom = lat;
-
-      if (lon > bbox->right)
-        bbox->right = lon;
-
-      if (lat > bbox->top)
-        bbox->top = lat;
+      champlain_bounding_box_extend (bbox, lat, lon); 
     }
 
   g_list_free (markers);
diff --git a/champlain/champlain-marker-layer.h b/champlain/champlain-marker-layer.h
index ccddab9..3f44649 100644
--- a/champlain/champlain-marker-layer.h
+++ b/champlain/champlain-marker-layer.h
@@ -109,7 +109,6 @@ void champlain_marker_layer_set_selection_mode (ChamplainMarkerLayer *layer,
     ChamplainSelectionMode mode);
 ChamplainSelectionMode champlain_marker_layer_get_selection_mode (
     ChamplainMarkerLayer *layer);
-ChamplainBoundingBox *champlain_marker_layer_get_bounding_box (ChamplainMarkerLayer *layer);
 
 G_END_DECLS
 
diff --git a/champlain/champlain-path-layer.c b/champlain/champlain-path-layer.c
index 45cf04a..67c1e02 100644
--- a/champlain/champlain-path-layer.c
+++ b/champlain/champlain-path-layer.c
@@ -91,6 +91,8 @@ static void redraw_path (ChamplainPathLayer *layer);
 static void set_view (ChamplainLayer *layer,
     ChamplainView *view);
 
+static ChamplainBoundingBox *get_bounding_box (ChamplainLayer *layer);
+
 
 static void
 champlain_path_layer_get_property (GObject *object,
@@ -340,7 +342,8 @@ champlain_path_layer_class_init (ChamplainPathLayerClass *klass)
   actor_class->unmap = unmap;
   
   layer_class->set_view = set_view;
-  
+  layer_class->get_bounding_box = get_bounding_box;
+
   /**
    * ChamplainPathLayer:closed:
    *
@@ -774,28 +777,15 @@ set_view (ChamplainLayer *layer,
     }
 }
 
-/**
- * champlain_path_layer_get_bounding_box:
- * @layer: a #ChamplainPathLayer
- *
- * Gets the bounding box occupied by the #ChamplainLocation objects in the layer
- *
- * Returns: The bounding box.
- * 
- * Since: 0.10
- */
-ChamplainBoundingBox *
-champlain_path_layer_get_bounding_box (ChamplainPathLayer *layer)
+
+static ChamplainBoundingBox *
+get_bounding_box (ChamplainLayer *layer)
 {
   ChamplainPathLayerPrivate *priv = GET_PRIVATE (layer);
   GList *elem;
   ChamplainBoundingBox *bbox;
   
   bbox = champlain_bounding_box_new ();
-  bbox->left = CHAMPLAIN_MAX_LONGITUDE;
-  bbox->right = CHAMPLAIN_MIN_LONGITUDE;
-  bbox->bottom = CHAMPLAIN_MAX_LATITUDE;
-  bbox->top = CHAMPLAIN_MIN_LATITUDE;
 
   for (elem = priv->nodes; elem != NULL; elem = elem->next)
     {
@@ -804,18 +794,8 @@ champlain_path_layer_get_bounding_box (ChamplainPathLayer *layer)
       
       g_object_get (G_OBJECT (location), "latitude", &lat, "longitude", &lon,
           NULL);
-
-      if (lon < bbox->left)
-        bbox->left = lon;
-
-      if (lat < bbox->bottom)
-        bbox->bottom = lat;
-
-      if (lon > bbox->right)
-        bbox->right = lon;
-
-      if (lat > bbox->top)
-        bbox->top = lat;
+          
+      champlain_bounding_box_extend (bbox, lat, lon); 
     }
 
   return bbox;
diff --git a/champlain/champlain-path-layer.h b/champlain/champlain-path-layer.h
index 93744d3..f132af9 100644
--- a/champlain/champlain-path-layer.h
+++ b/champlain/champlain-path-layer.h
@@ -82,8 +82,6 @@ void champlain_path_layer_insert_node (ChamplainPathLayer *layer,
     guint position);
 GList *champlain_path_layer_get_nodes (ChamplainPathLayer *layer);
 
-ChamplainBoundingBox *champlain_path_layer_get_bounding_box (ChamplainPathLayer *layer);
-
 ClutterColor *champlain_path_layer_get_fill_color (ChamplainPathLayer *layer);
 void champlain_path_layer_set_fill_color (ChamplainPathLayer *layer,
     const ClutterColor *color);
diff --git a/champlain/champlain-view.c b/champlain/champlain-view.c
index 5663eb5..ad1a003 100644
--- a/champlain/champlain-view.c
+++ b/champlain/champlain-view.c
@@ -2265,6 +2265,9 @@ champlain_view_ensure_visible (ChamplainView *view,
   guint zoom_level = priv->zoom_level;
   gboolean good_size = FALSE;
   gdouble lat, lon;
+  
+  if (!champlain_bounding_box_is_valid (bbox))
+    return;
 
   champlain_bounding_box_get_center (bbox, &lat, &lon);
 
@@ -2300,6 +2303,47 @@ champlain_view_ensure_visible (ChamplainView *view,
 }
 
 
+/**
+ * champlain_view_ensure_layers_visible:
+ * @view: a #ChamplainView
+ * @animate: perform animation
+ *
+ * Changes the map's zoom level and center to make sure that the bounding
+ * boxes of all inserted layers are visible.
+ *
+ * Since: 0.10
+ */
+void
+champlain_view_ensure_layers_visible (ChamplainView *view,
+    gboolean animate)
+{
+  DEBUG_LOG ()
+
+  GList *layers, *elem;
+  ChamplainBoundingBox *bbox;
+  
+  bbox = champlain_bounding_box_new ();
+  
+  layers = clutter_container_get_children (CLUTTER_CONTAINER (view->priv->user_layers));
+  
+  for (elem = layers; elem != NULL; elem = elem->next)
+    {
+      ChamplainLayer *layer = CHAMPLAIN_LAYER (elem->data);
+      ChamplainBoundingBox *other;
+
+      other = champlain_layer_get_bounding_box (layer);
+      champlain_bounding_box_compose (bbox, other);
+      champlain_bounding_box_free (other);
+    }
+
+  g_list_free (layers);
+
+  champlain_view_ensure_visible (view, bbox, animate);
+
+  champlain_bounding_box_free (bbox);
+}
+
+
 /* Sets the zoom level, leaving the (x, y) at the exact same point in the view */
 static gboolean
 view_set_zoom_level_at (ChamplainView *view,
diff --git a/champlain/champlain-view.h b/champlain/champlain-view.h
index cc182bb..b253b6b 100644
--- a/champlain/champlain-view.h
+++ b/champlain/champlain-view.h
@@ -92,6 +92,8 @@ void champlain_view_set_max_zoom_level (ChamplainView *view,
 void champlain_view_ensure_visible (ChamplainView *view,
     ChamplainBoundingBox *bbox,
     gboolean animate);
+void champlain_view_ensure_layers_visible (ChamplainView *view,
+    gboolean animate);
 
 void champlain_view_set_map_source (ChamplainView *view,
     ChamplainMapSource *map_source);
diff --git a/docs/reference/libchamplain-sections.txt b/docs/reference/libchamplain-sections.txt
index 0706bce..38855e3 100644
--- a/docs/reference/libchamplain-sections.txt
+++ b/docs/reference/libchamplain-sections.txt
@@ -128,6 +128,7 @@ champlain_view_set_zoom_level
 champlain_view_set_min_zoom_level
 champlain_view_set_max_zoom_level
 champlain_view_ensure_visible
+champlain_view_ensure_layers_visible
 champlain_view_set_map_source
 champlain_view_set_decel_rate
 champlain_view_set_kinetic_mode
@@ -290,6 +291,7 @@ ChamplainTilePrivate
 <TITLE>ChamplainLayer</TITLE>
 ChamplainLayer
 champlain_layer_set_view
+champlain_layer_get_bounding_box
 <SUBSECTION Standard>
 CHAMPLAIN_LAYER
 CHAMPLAIN_IS_LAYER
@@ -322,7 +324,6 @@ champlain_marker_layer_select_all_markers
 champlain_marker_layer_unselect_all_markers
 champlain_marker_layer_set_selection_mode
 champlain_marker_layer_get_selection_mode
-champlain_marker_layer_get_bounding_box
 <SUBSECTION Standard>
 CHAMPLAIN_MARKER_LAYER
 CHAMPLAIN_IS_MARKER_LAYER
@@ -459,6 +460,8 @@ champlain_bounding_box_copy
 champlain_bounding_box_free
 champlain_bounding_box_get_center
 champlain_bounding_box_compose
+champlain_bounding_box_extend
+champlain_bounding_box_is_valid
 <SUBSECTION Standard>
 CHAMPLAIN_BOUNDING_BOX
 CHAMPLAIN_TYPE_BOUNDING_BOX
@@ -695,6 +698,7 @@ ChamplainMemphisRendererClass
 ChamplainMemphisRendererPrivate
 </SECTION>
 
+
 <SECTION>
 <FILE>champlain-custom-marker</FILE>
 <TITLE>ChamplainCustomMarker</TITLE>
@@ -723,7 +727,6 @@ champlain_path_layer_remove_node
 champlain_path_layer_remove_all
 champlain_path_layer_insert_node
 champlain_path_layer_get_nodes
-champlain_path_layer_get_bounding_box
 champlain_path_layer_get_fill_color
 champlain_path_layer_set_fill_color
 champlain_path_layer_get_stroke_color



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