From: Pierre-Luc Beaudoin Date: Tue, 19 Aug 2008 01:37:20 +0000 (-0400) Subject: Tile loading X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0f8fda86a48f8f5a76c6dd915ca71ddd5b70a46b;p=libchamplain Tile loading --- diff --git a/src/champlain.h b/src/champlain.h index ec3f515..26909f1 100644 --- a/src/champlain.h +++ b/src/champlain.h @@ -25,6 +25,15 @@ #define CHAMPLAIN_MIN_LONG -180 #define CHAMPLAIN_MAX_LONG 180 +#include + +typedef struct { + gint x; + gint y; + guint width; + guint height; +} ChamplainRect; + #include "champlain_defines.h" #include "champlainview.h" diff --git a/src/champlain_private.h b/src/champlain_private.h deleted file mode 100644 index 9235a22..0000000 --- a/src/champlain_private.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (C) 2008 Pierre-Luc Beaudoin - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - - -#ifndef CHAMPLAIN_PRIVATE_H -#define CHAMPLAIN_PRIVATE_H - -#include -#include - -void champlain_map_create_tiles(gint zoom_level); - -//gboolean tile_is_visible(ClutterUnit viewport_w, ClutterUnit viewport_h, ChamplainPoint position, ChamplainMapTile* tile); - -#endif diff --git a/src/champlainview.c b/src/champlainview.c index a7fc27c..f4925d0 100644 --- a/src/champlainview.c +++ b/src/champlainview.c @@ -19,6 +19,7 @@ #include "config.h" +#include "champlain.h" #include "champlain_defines.h" #include "champlainview.h" #include "tile.h" @@ -53,20 +54,12 @@ static guint champlain_view_signals[LAST_SIGNAL] = { 0, }; #define CHAMPLAIN_VIEW_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), CHAMPLAIN_TYPE_VIEW, ChamplainViewPrivate)) -typedef struct -{ - /* Units to store the origin of a click when scrolling */ - ClutterUnit x; - ClutterUnit y; -} ChamplainPoint; - struct _ChamplainViewPrivate { GtkWidget *clutterEmbed; ClutterActor *viewport; - ChamplainPoint viewportSize; ClutterActor *fingerScroll; - + ChamplainRect viewportSize; Map *map; }; @@ -97,16 +90,36 @@ champlain_view_init (ChamplainView *champlainView) ChamplainViewPrivate *priv = CHAMPLAIN_VIEW_GET_PRIVATE (champlainView); } +void viewport_x_changed_cb(GObject *gobject, + GParamSpec *arg1, + ChamplainView *champlainView) +{ + ChamplainViewPrivate *priv = CHAMPLAIN_VIEW_GET_PRIVATE (champlainView); + + ChamplainRect rect; + 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 && + rect.y == priv->viewportSize.y && + rect.width == priv->viewportSize.width && + rect.height == priv->viewportSize.height) + return; + priv->viewportSize.x = rect.x; + priv->viewportSize.y = rect.y; + + map_load_visible_tiles (priv->map, priv->viewportSize); +} + static void view_size_allocated_cb (GtkWidget *view, GtkAllocation *allocation, ChamplainView *champlainView) -{ +{ gdouble lower, upper; TidyAdjustment *hadjust, *vadjust; ChamplainViewPrivate *priv = CHAMPLAIN_VIEW_GET_PRIVATE (champlainView); - priv->viewportSize.x = allocation->width; - priv->viewportSize.y = allocation->height; - clutter_actor_set_size (priv->fingerScroll, priv->viewportSize.x, priv->viewportSize.y); + + clutter_actor_set_size (priv->fingerScroll, allocation->width, allocation->height); g_object_set (G_OBJECT (priv->viewport), "sync-adjustments", FALSE, NULL); @@ -114,16 +127,20 @@ view_size_allocated_cb (GtkWidget *view, GtkAllocation *allocation, ChamplainVie tidy_adjustment_get_values (hadjust, NULL, &lower, &upper, NULL, NULL, NULL); lower = 0; - upper = zoom_level_get_width(priv->map->current_level) - priv->viewportSize.x; + upper = zoom_level_get_width(priv->map->current_level) - allocation->width; 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); lower = 0; - upper = zoom_level_get_height(priv->map->current_level) - priv->viewportSize.y; + upper = zoom_level_get_height(priv->map->current_level) - allocation->height; g_object_set (vadjust, "lower", lower, "upper", upper, "step-increment", 1.0, "elastic", TRUE, NULL); + priv->viewportSize.width = allocation->width; + priv->viewportSize.height = allocation->height; + + map_load_visible_tiles (priv->map, priv->viewportSize); } GtkWidget * @@ -136,9 +153,6 @@ champlain_view_new () view = CHAMPLAIN_VIEW (g_object_new (CHAMPLAIN_TYPE_VIEW, NULL)); ChamplainViewPrivate *priv = CHAMPLAIN_VIEW_GET_PRIVATE (view); - priv->viewportSize.x = 640; - priv->viewportSize.y = 480; - priv->clutterEmbed = gtk_clutter_embed_new (); g_signal_connect (priv->clutterEmbed, "size-allocate", @@ -154,7 +168,12 @@ champlain_view_new () // Setup viewport priv->viewport = tidy_viewport_new (); ClutterActor* group = clutter_group_new(); + clutter_container_add_actor (CLUTTER_CONTAINER (priv->viewport), group); + g_signal_connect (priv->viewport, + "notify::x-origin", + G_CALLBACK (viewport_x_changed_cb), + view); // Setup finger scroll priv->fingerScroll = tidy_finger_scroll_new(TIDY_FINGER_SCROLL_MODE_KINETIC); @@ -165,7 +184,7 @@ champlain_view_new () priv->map = map_new(CHAMPLAIN_MAP_SOURCE_OPENSTREETMAP);//OPENSTREETMAP map_load(priv->map, 4); clutter_container_add_actor (CLUTTER_CONTAINER (group), priv->map->current_level->group); - + clutter_actor_show (group); return GTK_WIDGET (view); } @@ -179,5 +198,8 @@ champlain_view_center_on (ChamplainView *champlainView, gdouble longitude, gdoub 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.x/2.0, y - priv->viewportSize.y/2.0, 0); + ChamplainRect rect; + clutter_actor_get_size(priv->viewport, &rect.width, &rect.height); + + tidy_viewport_set_origin(TIDY_VIEWPORT(priv->viewport), x - rect.width/2.0, y - rect.height/2.0, 0); } diff --git a/src/map.c b/src/map.c index 01f1af6..ea8dc58 100644 --- a/src/map.c +++ b/src/map.c @@ -46,6 +46,43 @@ map_load(Map* map, gint zoom_level) guint column_count = map->get_column_count(map, zoom_level); map->current_level = zoom_level_new(zoom_level, row_count, column_count, map->tile_size); - zoom_level_create(map, zoom_level); } +void +map_load_visible_tiles (Map* map, ChamplainRect viewport) +{ + 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; + + x_count += x_first; + y_count += y_first; + + int i, j, k; + for (i = x_first; i < x_count; i++) + { + for (j = y_first; j < y_count; j++) + { + if(i >= map->current_level->row_count || j >= map->current_level->column_count) + continue; + + gboolean exist = FALSE; + for (k = 0; k < map->current_level->tiles->len && !exist; k++) + { + Tile* tile = g_ptr_array_index(map->current_level->tiles, k); + if ( tile->x == i && tile->y == j) + exist = TRUE; + } + + if(!exist) + { + Tile* tile = map->get_tile(map, map->current_level->level, i, j); + + g_ptr_array_add (map->current_level->tiles, tile); + clutter_container_add (CLUTTER_CONTAINER (map->current_level->group), tile->actor, NULL); + } + } + } +} diff --git a/src/map.h b/src/map.h index 1755b85..c9fbd96 100644 --- a/src/map.h +++ b/src/map.h @@ -20,6 +20,7 @@ #ifndef MAP_H #define MAP_H +#include "champlain.h" #include "champlainview.h" #include "champlain_defines.h" #include "zoomlevel.h" @@ -50,5 +51,6 @@ struct _Map CHAMPLAIN_API Map* champlain_map_new (ChamplainMapSource source); +void map_load_visible_tiles (Map* map, ChamplainRect viewport); #endif diff --git a/src/sources/openstreetmap.c b/src/sources/openstreetmap.c index 6bf72ec..811ab77 100644 --- a/src/sources/openstreetmap.c +++ b/src/sources/openstreetmap.c @@ -20,6 +20,7 @@ #include "sources/openstreetmap.h" #include #include +#include //http://wiki.openstreetmap.org/index.php/Slippy_map_tilenames#C.2FC.2B.2B @@ -54,12 +55,14 @@ guint osm_row_count(Map* map, guint zoom_level) return pow (2, zoom_level); } -guint osm_column_count(Map* map, guint zoom_level) +guint +osm_column_count(Map* map, guint zoom_level) { return pow (2, zoom_level); } -Tile* osm_get_tile (Map* map, guint zoom_level, guint x, guint y) +Tile* +osm_get_tile (Map* map, guint zoom_level, guint x, guint y) { Tile* tile = g_new0(Tile, 1); @@ -82,23 +85,27 @@ Tile* osm_get_tile (Map* map, guint zoom_level, guint x, guint y) } -gdouble osm_longitude_to_x (Map* map, gdouble longitude, guint zoom_level) +gdouble +osm_longitude_to_x (Map* map, gdouble longitude, guint zoom_level) { return ((longitude + 180.0) / 360.0 * pow(2.0, zoom_level)) * map->tile_size; } -gdouble osm_latitude_to_y (Map* map, gdouble latitude, guint zoom_level) +gdouble +osm_latitude_to_y (Map* map, gdouble latitude, guint zoom_level) { return ((1.0 - log( tan(latitude * M_PI/180.0) + 1.0 / cos(latitude * M_PI/180.0)) / M_PI) / 2.0 * pow(2.0, zoom_level)) * map->tile_size; } -gdouble osm_x_to_longitude (Map* map, gdouble x, guint zoom_level) +gdouble +osm_x_to_longitude (Map* map, gdouble x, guint zoom_level) { x /= map->tile_size; return x / map->tile_size * pow(2.0, zoom_level) * 360.0 - 180; } -gdouble osm_y_to_latitude (Map* map, gdouble y, guint zoom_level) +gdouble +osm_y_to_latitude (Map* map, gdouble y, guint zoom_level) { y /= map->tile_size; double n = M_PI - 2.0 * M_PI * y / pow(2.0, zoom_level); diff --git a/src/tile.c b/src/tile.c index ad1386c..b3b28fc 100644 --- a/src/tile.c +++ b/src/tile.c @@ -43,3 +43,5 @@ tile_is_visible(ClutterUnit viewport_w, ClutterUnit viewport_h, ChamplainPoint p return TRUE; }*/ + + diff --git a/src/zoomlevel.c b/src/zoomlevel.c index e56d47c..634964e 100644 --- a/src/zoomlevel.c +++ b/src/zoomlevel.c @@ -20,7 +20,6 @@ #include #include #include "map.h" -#include #include ZoomLevel* @@ -38,30 +37,14 @@ zoom_level_new(gint zoom_level, gint row, gint column, gint tile_size) return level; } -void -zoom_level_create(Map* map, gint zoom_level) -{ - int i; - for (i = 0; i < map->current_level->row_count * map->current_level->column_count; i++) - { - int x = i % map->current_level->column_count; - int y = i / map->current_level->column_count; - - Tile* tile = map->get_tile(map, zoom_level, x, y); - - clutter_container_add (CLUTTER_CONTAINER (map->current_level->group), tile->actor, NULL); - g_ptr_array_add (map->current_level->tiles, tile); - } -} - guint zoom_level_get_width(ZoomLevel* level) { - return (level->column_count + 1) * level->tile_size; + return (level->column_count) * level->tile_size; } guint zoom_level_get_height(ZoomLevel* level) { - return (level->row_count + 1) * level->tile_size; + return (level->row_count) * level->tile_size; }