From: Pierre-Luc Beaudoin Date: Thu, 4 Sep 2008 12:17:15 +0000 (-0400) Subject: Unlimited zoom X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=219a1d2107278f2cacef0886a263bdb260079b31;p=libchamplain Unlimited zoom --- diff --git a/champlain/champlainview.c b/champlain/champlainview.c index d65c461..e9e9c79 100644 --- a/champlain/champlainview.c +++ b/champlain/champlainview.c @@ -37,6 +37,8 @@ #include #include + + 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"); } diff --git a/champlain/map.c b/champlain/map.c index e5256d7..60dfbd6 100644 --- a/champlain/map.c +++ b/champlain/map.c @@ -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; diff --git a/champlain/map.h b/champlain/map.h index 7893ce4..03f3eee 100644 --- a/champlain/map.h +++ b/champlain/map.h @@ -35,6 +35,7 @@ struct _Map int zoom_levels; const gchar* name; int tile_size; + ZoomLevel* current_level; GPtrArray *levels; diff --git a/champlain/tile.c b/champlain/tile.c index 6fc2de5..717a644 100644 --- a/champlain/tile.c +++ b/champlain/tile.c @@ -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); } diff --git a/champlain/zoomlevel.c b/champlain/zoomlevel.c index 4ec0c22..8d4c86c 100644 --- a/champlain/zoomlevel.c +++ b/champlain/zoomlevel.c @@ -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; } diff --git a/champlain/zoomlevel.h b/champlain/zoomlevel.h index 806375b..ee73d0b 100644 --- a/champlain/zoomlevel.h +++ b/champlain/zoomlevel.h @@ -22,6 +22,7 @@ #include #include +#include typedef struct { @@ -32,7 +33,8 @@ typedef struct GPtrArray *tiles; ClutterActor* group; - + + GdkPoint anchor; } ZoomLevel; guint zoom_level_get_width(ZoomLevel* level);