]> err.no Git - libchamplain/commitdiff
Unlimited zoom
authorPierre-Luc Beaudoin <pierlux@carbon.(none)>
Thu, 4 Sep 2008 12:17:15 +0000 (08:17 -0400)
committerPierre-Luc Beaudoin <pierlux@carbon.(none)>
Thu, 4 Sep 2008 12:17:15 +0000 (08:17 -0400)
champlain/champlainview.c
champlain/map.c
champlain/map.h
champlain/tile.c
champlain/zoomlevel.c
champlain/zoomlevel.h

index d65c461a2c0ebf779ce56ecadeff54be2cbe2563..e9e9c79e86cd3c52f6bbb958125dad150d2d1d63 100644 (file)
@@ -37,6 +37,8 @@
 #include <tidy-scrollable.h>
 #include <tidy-viewport.h>
 
+
+
 enum
 {
   /* normal signals */
@@ -88,13 +90,17 @@ G_DEFINE_TYPE (ChamplainView, champlain_view, GTK_TYPE_ALIGNMENT);
 static gdouble
 viewport_get_current_longitude(ChamplainViewPrivate *priv)
 {
-  return priv->map->x_to_longitude(priv->map, priv->viewportSize.x + priv->viewportSize.width/2.0, priv->map->current_level->level);
+  return priv->map->x_to_longitude(priv->map, 
+    priv->map->current_level->anchor.x + priv->viewportSize.x + priv->viewportSize.width / 2.0, 
+    priv->map->current_level->level);
 }
 
 static gdouble
 viewport_get_current_latitude(ChamplainViewPrivate *priv)
 {
-  return priv->map->y_to_latitude(priv->map, priv->viewportSize.y + priv->viewportSize.height/2.0, priv->map->current_level->level);
+  return priv->map->y_to_latitude(priv->map, 
+    priv->map->current_level->anchor.y + priv->viewportSize.y + priv->viewportSize.height / 2.0, 
+    priv->map->current_level->level);
 }
 
 static void
@@ -111,30 +117,35 @@ resize_viewport(ChamplainView *champlainView)
       map_load_level(priv->map, priv->zoomLevel);
       clutter_container_add_actor (CLUTTER_CONTAINER (priv->viewport), priv->map->current_level->group);
       
-      
       g_object_notify(G_OBJECT(champlainView), "zoom-level");
       g_object_notify(G_OBJECT(champlainView), "map-source");
     }
   
   clutter_actor_set_size (priv->fingerScroll, priv->viewportSize.width, priv->viewportSize.height);
   
-  g_object_set (G_OBJECT (priv->viewport), "sync-adjustments", FALSE, NULL);
   
   tidy_scrollable_get_adjustments (TIDY_SCROLLABLE (priv->viewport), &hadjust, &vadjust);
   
-  tidy_adjustment_get_values (hadjust, NULL, &lower, &upper, NULL, NULL, NULL);
+  //tidy_adjustment_get_values (hadjust, NULL, &lower, &upper, NULL, NULL, NULL);
   lower = 0;
-  upper = zoom_level_get_width(priv->map->current_level) - priv->viewportSize.width; 
+  if (priv->map->current_level->level < 8)
+    upper = zoom_level_get_width(priv->map->current_level) - priv->viewportSize.width; 
+  else
+    upper = G_MAXINT16;
   g_object_set (hadjust, "lower", lower, "upper", upper,
                 "step-increment", 1.0, "elastic", TRUE, NULL);
                 
-  tidy_adjustment_get_values (vadjust, NULL, &lower, &upper, NULL, NULL, NULL);
+  //tidy_adjustment_get_values (vadjust, NULL, &lower, &upper, NULL, NULL, NULL);
   lower = 0;
-  upper = zoom_level_get_height(priv->map->current_level) - priv->viewportSize.height;
+  if (priv->map->current_level->level < 8)
+    upper = zoom_level_get_height(priv->map->current_level) - priv->viewportSize.height; 
+  else
+    upper = G_MAXINT16;
   g_object_set (vadjust, "lower", lower, "upper", upper,
                 "step-increment", 1.0, "elastic", TRUE, NULL);
   
-  //g_print("%d, %d, %d\n", zoom_level_get_width(priv->map->current_level), zoom_level_get_height(priv->map->current_level), sizeof(guint));
+  g_print("Level: %d\n", priv->map->current_level->level);
+  g_print("Upper: %f\n", upper);
 }
 
 static void 
@@ -215,15 +226,10 @@ champlain_view_set_property(GObject* object, guint prop_id, const GValue* value,
                   gdouble lat = viewport_get_current_latitude(priv);
                   if (map_zoom_to(priv->map, level)) 
                     {
-                      gint old_level = priv->map->current_level->level;
-                      gdouble x = priv->map->longitude_to_x(priv->map, lon, level);
-                      gdouble y = priv->map->latitude_to_y(priv->map, lat, level);
-
                       resize_viewport(view);
                       clutter_container_remove_actor (CLUTTER_CONTAINER (priv->viewport), group);
                       clutter_container_add_actor (CLUTTER_CONTAINER (priv->viewport), priv->map->current_level->group);
-
-                      tidy_viewport_set_origin(TIDY_VIEWPORT(priv->viewport), x - priv->viewportSize.width/2.0, y - priv->viewportSize.height/2.0, 0);
+                      champlain_view_center_on(view, lon, lat);
                     }
                 }
             }
@@ -241,13 +247,17 @@ champlain_view_set_property(GObject* object, guint prop_id, const GValue* value,
               priv->mapSource = source;
               if (priv->map) {
                 gint currentLevel = priv->map->current_level->level;
+                GdkPoint anchor = priv->map->current_level->anchor;
                 map_free(priv->map);
                 priv->map = map_new(priv->mapSource);
                 
+                // Keep same zoom level
                 if (currentLevel > priv->map->zoom_levels)
                   currentLevel = priv->map->zoom_levels;
                   
                 map_load_level(priv->map, currentLevel);
+                priv->map->current_level->anchor = anchor;
+
                 map_load_visible_tiles (priv->map, priv->viewportSize, priv->offline);
                 clutter_container_add_actor (CLUTTER_CONTAINER (priv->viewport), priv->map->current_level->group);
               }
@@ -405,11 +415,12 @@ viewport_x_changed_cb(GObject *gobject, GParamSpec *arg1, ChamplainView *champla
   tidy_viewport_get_origin(TIDY_VIEWPORT(priv->viewport), &rect.x, &rect.y, NULL);
   if (rect.x < 0 || rect.y < 0)
       return;
-  if (rect.x == priv->viewportSize.x &&
+  /*if (rect.x == priv->viewportSize.x &&
       rect.y == priv->viewportSize.y &&
       rect.width == priv->viewportSize.width &&
       rect.height == priv->viewportSize.height)
-      return;
+      return;*/
+
   priv->viewportSize.x = rect.x;
   priv->viewportSize.y = rect.y;
   
@@ -462,6 +473,7 @@ champlain_view_new (ChamplainViewMode mode)
   
   // Setup viewport
   priv->viewport = tidy_viewport_new ();
+  g_object_set (G_OBJECT (priv->viewport), "sync-adjustments", FALSE, NULL);
   
   g_signal_connect (priv->viewport,
                     "notify::x-origin",
@@ -508,8 +520,41 @@ champlain_view_center_on (ChamplainView *champlainView, gdouble longitude, gdoub
   gdouble x, y;
   x = priv->map->longitude_to_x(priv->map, longitude, priv->map->current_level->level);
   y = priv->map->latitude_to_y(priv->map, latitude, priv->map->current_level->level);
-
-  tidy_viewport_set_origin(TIDY_VIEWPORT(priv->viewport), x - priv->viewportSize.width/2.0, y - priv->viewportSize.height/2.0, 0);
+  GdkPoint* anchor = &priv->map->current_level->anchor;
+
+  if (priv->map->current_level->level >= 8) {
+    anchor->x = x - G_MAXINT16 / 2;
+    anchor->y = y - G_MAXINT16 / 2;
+
+    if ( anchor->x < 0 )
+      anchor->x = 0;
+    if ( anchor->y < 0 )
+      anchor->y = 0;
+
+    gdouble max = priv->map->longitude_to_x(priv->map, 180, priv->map->current_level->level)
+       - (G_MAXINT16 / 2);
+    if (anchor->x > max)
+      anchor->x = max;
+    if (anchor->y > max)
+      anchor->y = max;
+    
+    x -= anchor->x;
+    y -= anchor->y;
+  } else {
+    anchor->x = 0;
+    anchor->y = 0;
+  }
+
+  //FIXME: Inform tiles that there is a new anchor
+
+  g_print("Anchor: %d, %d\n", anchor->x, anchor->y);
+  g_print("Center: %f, %f\n", x, y);
+
+
+  tidy_viewport_set_origin(TIDY_VIEWPORT(priv->viewport),
+    x - priv->viewportSize.width / 2.0,
+    y - priv->viewportSize.height / 2.0,
+    0);
   
   g_object_notify(G_OBJECT(champlainView), "longitude");
   g_object_notify(G_OBJECT(champlainView), "latitude");
@@ -534,15 +579,10 @@ champlain_view_zoom_in (ChamplainView *champlainView)
   gdouble lat = viewport_get_current_latitude(priv);
   if(map_zoom_in(priv->map)) 
     {
-      gint level = priv->map->current_level->level;
-      gdouble x = priv->map->longitude_to_x(priv->map, lon, level);
-      gdouble y = priv->map->latitude_to_y(priv->map, lat, level);
-      
       resize_viewport(champlainView);
       clutter_container_remove_actor (CLUTTER_CONTAINER (priv->viewport), group);
       clutter_container_add_actor (CLUTTER_CONTAINER (priv->viewport), priv->map->current_level->group);
-      
-      tidy_viewport_set_origin(TIDY_VIEWPORT(priv->viewport), x - priv->viewportSize.width/2.0, y - priv->viewportSize.height/2.0, 0);
+      champlain_view_center_on(champlainView, lon, lat);
       
       g_object_notify(G_OBJECT(champlainView), "zoom-level");
     }
@@ -565,15 +605,10 @@ champlain_view_zoom_out (ChamplainView *champlainView)
   gdouble lat = viewport_get_current_latitude(priv);
   if(map_zoom_out(priv->map))
     {
-      gint level = priv->map->current_level->level;
-      gdouble x = priv->map->longitude_to_x(priv->map, lon, level);
-      gdouble y = priv->map->latitude_to_y(priv->map, lat, level);
-      
       resize_viewport(champlainView);
       clutter_container_remove_actor (CLUTTER_CONTAINER (priv->viewport), group);
       clutter_container_add_actor (CLUTTER_CONTAINER (priv->viewport), priv->map->current_level->group);
-      
-      tidy_viewport_set_origin(TIDY_VIEWPORT(priv->viewport), x - priv->viewportSize.width/2.0, y - priv->viewportSize.height/2.0, 0);
+      champlain_view_center_on(champlainView, lon, lat);
       
       g_object_notify(G_OBJECT(champlainView), "zoom-level");
     }
index e5256d7709ca0cc82eb82e53a74f5549e8c0722d..60dfbd6d2b9ba102fb32f82fb1d909badcbf0f89 100644 (file)
@@ -49,6 +49,7 @@ map_new (ChamplainMapSource source)
   
   map->levels = g_ptr_array_sized_new (map->zoom_levels);
   map->current_level = NULL;
+
   return map;
 }
 
@@ -68,11 +69,12 @@ map_load_visible_tiles (Map* map, GdkRectangle viewport, gboolean offline)
   gint x_count = ceil((float)viewport.width / map->tile_size) + 1;
   gint y_count = ceil((float)viewport.height / map->tile_size) + 1;
   
-  gint x_first = viewport.x / map->tile_size;
-  gint y_first = viewport.y / map->tile_size;
+  gint x_first = (map->current_level->anchor.x + viewport.x) / map->tile_size;
+  gint y_first = (map->current_level->anchor.y + viewport.y) / map->tile_size;
   
   x_count += x_first;
   y_count += y_first;
+  g_print("Tiles: %d, %d to %d, %d\n", x_first, y_first, x_count, y_count);
   
   int i, j, k;
   for (i = x_first; i < x_count; i++)
@@ -103,8 +105,7 @@ gboolean
 map_zoom_in (Map* map)
 {
   gint new_level = map->current_level->level + 1;
-  if(new_level + 1 <= map->zoom_levels &&
-     new_level + 1 <= 7) //FIXME Due to a ClutterUnit limitation (the x, y will have to be rethinked)
+  if(new_level <= map->zoom_levels)
     {
       gboolean exist = FALSE;
       int i;
@@ -169,8 +170,7 @@ gboolean
 map_zoom_to (Map* map, guint zoomLevel)
 {
   if(zoomLevel >= 0 && 
-     zoomLevel<= map->zoom_levels &&
-     zoomLevel <= 7) //FIXME Due to a ClutterUnit limitation (the x, y will have to be rethinked)
+     zoomLevel<= map->zoom_levels)
     {
       gboolean exist = FALSE;
       int i;
index 7893ce49f598629d7b2a0881e25c0b228f4cc8fd..03f3eee336fc9966db0a5dc0934f0757313a3105 100644 (file)
@@ -35,6 +35,7 @@ struct _Map
   int zoom_levels;
   const gchar* name;
   int tile_size;
+
   ZoomLevel* current_level;
   GPtrArray  *levels;
   
index 6fc2de572eadbabac67cc9fc28e387ea1e918267..717a644a0be90ae7392a9530ec314d662f10dc9d 100644 (file)
@@ -35,11 +35,14 @@ typedef struct {
 #define CACHE_DIR "champlain"
 
 void
-tile_set(Tile* tile) 
+tile_set(Map* map, Tile* tile) 
 {
-  clutter_actor_set_position (tile->actor, tile->x * tile->size, tile->y * tile->size);
+  clutter_actor_set_position (tile->actor, 
+    (tile->x * tile->size) - map->current_level->anchor.x, 
+    (tile->y * tile->size) - map->current_level->anchor.y);
   clutter_actor_set_size (tile->actor, tile->size, tile->size);
   clutter_actor_show (tile->actor);
+  g_print("Tile %d, %d\n", (tile->x * tile->size) - map->current_level->anchor.x, (tile->y * tile->size) - map->current_level->anchor.y);
 }
 
 static void 
@@ -47,7 +50,7 @@ create_error_tile(Map* map, Tile* tile)
 {
   tile->actor = clutter_texture_new_from_file("error.svg", NULL);
        
-  tile_set(tile);
+  tile_set(map, tile);
   
   clutter_container_add (CLUTTER_CONTAINER (map->current_level->group), tile->actor, NULL);
 
@@ -137,7 +140,7 @@ file_loaded_cb (SoupSession *session,
           gdk_pixbuf_get_rowstride (pixbuf),
           3, 0, NULL);
            
-      tile_set(tile);
+      tile_set(map, tile);
       
       clutter_container_add (CLUTTER_CONTAINER (map->current_level->group), tile->actor, NULL);
       
@@ -174,7 +177,7 @@ tile_load (Map* map, guint zoom_level, guint x, guint y, gboolean offline)
   if (g_file_test (filename, G_FILE_TEST_EXISTS)) 
     {
       tile->actor = clutter_texture_new_from_file(filename, NULL);
-      tile_set(tile);
+      tile_set(map, tile);
       
       clutter_container_add (CLUTTER_CONTAINER (map->current_level->group), tile->actor, NULL);
     }
index 4ec0c22506cb48d56d0f87e812cf9569465dd683..8d4c86c082d7256d2ea44138b6a48af618566d80 100644 (file)
@@ -31,11 +31,18 @@ zoom_level_new(gint zoom_level, gint row, gint column, gint tile_size)
   level->row_count = row;
   level->column_count = column;
   level->tile_size = tile_size;
-  level->tiles = g_ptr_array_sized_new (row * column);
+  gint count = row * column;
+  if (row * column > 256)
+    count = 256;
+    
+  level->tiles = g_ptr_array_sized_new (count);
   level->group = clutter_group_new ();
   
   g_object_ref(level->group); // so that the group isn't destroyed when removed from the viewport
   
+  level->anchor.x = 0;
+  level->anchor.y = 0;
+
   return level;
 }
 
index 806375bea1ec4c45a275af36c28239408625c8c7..ee73d0bf2ef380abe6b943bf86e6cc2aa80fd6a3 100644 (file)
@@ -22,6 +22,7 @@
 
 #include <glib.h>
 #include <clutter/clutter.h>
+#include <gdk/gdk.h>
 
 typedef struct
 {
@@ -32,7 +33,8 @@ typedef struct
   
   GPtrArray  *tiles;
   ClutterActor* group;
-  
+
+  GdkPoint anchor;  
 } ZoomLevel;
 
 guint zoom_level_get_width(ZoomLevel* level);