Verified Commit 306c8fde authored by James Westman's avatar James Westman
Browse files

map-layer: Continuous zoom

The map now supports fractional zoom levels properly, which makes
zooming smoother. Eventually this will enable smooth animations and
improved touchscreen support.
parent 59815d08
Pipeline #275959 passed with stage
in 2 minutes and 56 seconds
......@@ -109,6 +109,7 @@ modadd (int current,
return r < 0 ? r + size : r;
}
static void
maybe_shift_grid (ShumateMapLayer *self,
guint n_columns,
......@@ -184,10 +185,11 @@ recompute_grid (ShumateMapLayer *self,
int height)
{
GtkWidget *widget = GTK_WIDGET (self);
ShumateViewport *viewport = shumate_layer_get_viewport (SHUMATE_LAYER (self));
guint required_tiles_columns, required_tiles_rows;
guint tile_size;
tile_size = shumate_map_source_get_tile_size (self->map_source);
tile_size = shumate_map_source_get_tile_size_at_zoom (self->map_source, shumate_viewport_get_zoom_level (viewport));
required_tiles_columns = (width / tile_size) + 2;
required_tiles_rows = (height / tile_size) + 2;
if (self->required_tiles_columns != required_tiles_columns)
......@@ -282,12 +284,13 @@ grid_needs_recompute (ShumateMapLayer *self,
int width,
int height)
{
ShumateViewport *viewport = shumate_layer_get_viewport (SHUMATE_LAYER (self));
guint required_tiles_columns, required_tiles_rows;
guint tile_size;
g_assert (SHUMATE_IS_MAP_LAYER (self));
tile_size = shumate_map_source_get_tile_size (self->map_source);
tile_size = shumate_map_source_get_tile_size_at_zoom (self->map_source, shumate_viewport_get_zoom_level (viewport));
required_tiles_columns = (width / tile_size) + 2;
required_tiles_rows = (height / tile_size) + 2;
......@@ -498,8 +501,8 @@ shumate_map_layer_size_allocate (GtkWidget *widget,
guint source_rows, source_columns;
viewport = shumate_layer_get_viewport (SHUMATE_LAYER (self));
tile_size = shumate_map_source_get_tile_size (self->map_source);
zoom_level = shumate_viewport_get_zoom_level (viewport);
tile_size = shumate_map_source_get_tile_size_at_zoom (self->map_source, zoom_level);
latitude = shumate_location_get_latitude (SHUMATE_LOCATION (viewport));
longitude = shumate_location_get_longitude (SHUMATE_LOCATION (viewport));
source_rows = shumate_map_source_get_row_count (self->map_source, zoom_level);
......@@ -540,6 +543,7 @@ shumate_map_layer_size_allocate (GtkWidget *widget,
child = tile_child->tile;
shumate_tile_set_size (child, tile_size);
gtk_widget_measure (GTK_WIDGET (child), GTK_ORIENTATION_HORIZONTAL, 0, NULL, NULL, NULL, NULL);
gtk_widget_size_allocate (GTK_WIDGET (child), &child_allocation, baseline);
......@@ -609,8 +613,8 @@ shumate_map_layer_measure (GtkWidget *widget,
guint count;
viewport = shumate_layer_get_viewport (SHUMATE_LAYER (self));
tile_size = shumate_map_source_get_tile_size (self->map_source);
zoom_level = shumate_viewport_get_zoom_level (viewport);
tile_size = shumate_map_source_get_tile_size_at_zoom (self->map_source, shumate_viewport_get_zoom_level (viewport));
zoom_level = (guint) shumate_viewport_get_zoom_level (viewport);
if (orientation == GTK_ORIENTATION_HORIZONTAL)
count = shumate_map_source_get_column_count (self->map_source, zoom_level);
else
......
......@@ -164,7 +164,11 @@ shumate_map_source_get_max_zoom_level (ShumateMapSource *map_source)
* shumate_map_source_get_tile_size:
* @map_source: a #ShumateMapSource
*
* Gets map source's tile size.
* Gets map source's tile size at integer zoom levels.
*
* This is the intended display size, not necessarily the exact size of the
* tile textures. For example, on high DPI displays, the map source might
* provide textures that are twice this size.
*
* Returns: the tile's size (width and height) in pixels for this map source
*/
......@@ -177,6 +181,30 @@ shumate_map_source_get_tile_size (ShumateMapSource *map_source)
}
/**
* shumate_map_source_get_tile_size_at_zoom:
* @self: a #ShumateMapSource
* @zoom: the zoom level to calculate size at
*
* Gets the map source's tile size at the given zoom level.
*
* At integer zoom levels, tiles are the exact size returned by
* shumate_map_source_get_tile_size(). When the map is zoomed in, the tiles
* scale up to twice their normal size until the next integer zoom level is
* reached and the next layer of tiles is loaded. Thus, this function calculates
* the size of a tile based on the fractional part of the @zoom.
*
* Returns: the tile's size
*/
guint
shumate_map_source_get_tile_size_at_zoom (ShumateMapSource *self, double zoom)
{
g_return_val_if_fail (SHUMATE_IS_MAP_SOURCE (self), 0);
return shumate_map_source_get_tile_size (self) * (fmod (zoom, 1.0) + 1.0);
}
/**
* shumate_map_source_get_projection:
* @map_source: a #ShumateMapSource
......@@ -210,12 +238,15 @@ shumate_map_source_get_x (ShumateMapSource *map_source,
double zoom_level,
double longitude)
{
double map_size;
g_return_val_if_fail (SHUMATE_IS_MAP_SOURCE (map_source), 0.0);
longitude = CLAMP (longitude, SHUMATE_MIN_LONGITUDE, SHUMATE_MAX_LONGITUDE);
/* FIXME: support other projections */
return ((longitude + 180.0) / 360.0) * shumate_map_source_get_tile_size (map_source) * pow (2.0, zoom_level);
map_size = shumate_map_source_get_tile_size_at_zoom (map_source, zoom_level) * shumate_map_source_get_row_count (map_source, zoom_level);
return ((longitude + 180.0) / 360.0) * map_size;
}
......@@ -235,14 +266,14 @@ shumate_map_source_get_y (ShumateMapSource *map_source,
double zoom_level,
double latitude)
{
double sin_latitude;
double sin_latitude, map_size;
g_return_val_if_fail (SHUMATE_IS_MAP_SOURCE (map_source), 0.0);
latitude = CLAMP (latitude, SHUMATE_MIN_LATITUDE, SHUMATE_MAX_LATITUDE);
/* FIXME: support other projections */
sin_latitude = sin (latitude * G_PI / 180.0);
return (0.5 - log ((1.0 + sin_latitude) / (1.0 - sin_latitude)) / (4.0 * G_PI)) * shumate_map_source_get_tile_size (map_source) * pow (2.0, zoom_level);
sin_latitude = sin (latitude * G_PI / 180.0);map_size = shumate_map_source_get_tile_size_at_zoom (map_source, zoom_level) * shumate_map_source_get_row_count (map_source, zoom_level);
return (0.5 - log ((1.0 + sin_latitude) / (1.0 - sin_latitude)) / (4.0 * G_PI)) * map_size;
}
......@@ -262,12 +293,12 @@ shumate_map_source_get_longitude (ShumateMapSource *map_source,
double zoom_level,
double x)
{
double longitude;
double longitude, map_size;
g_return_val_if_fail (SHUMATE_IS_MAP_SOURCE (map_source), 0.0);
/* FIXME: support other projections */
double dx = x / (double) shumate_map_source_get_tile_size (map_source);
longitude = dx / pow (2.0, zoom_level) * 360.0 - 180.0;
map_size = shumate_map_source_get_tile_size_at_zoom (map_source, zoom_level) * shumate_map_source_get_row_count (map_source, zoom_level);
longitude = (x / map_size) * 360.0 - 180.0;
return CLAMP (longitude, SHUMATE_MIN_LONGITUDE, SHUMATE_MAX_LONGITUDE);
}
......@@ -293,7 +324,7 @@ shumate_map_source_get_latitude (ShumateMapSource *map_source,
g_return_val_if_fail (SHUMATE_IS_MAP_SOURCE (map_source), 0.0);
/* FIXME: support other projections */
map_size = shumate_map_source_get_tile_size (map_source) * shumate_map_source_get_row_count (map_source, zoom_level);
map_size = shumate_map_source_get_tile_size_at_zoom (map_source, zoom_level) * shumate_map_source_get_row_count (map_source, zoom_level);
dy = 0.5 - y / map_size;
latitude = 90.0 - 360.0 / G_PI * atan (exp (-dy * 2.0 * G_PI));
......@@ -368,7 +399,7 @@ shumate_map_source_get_meters_per_pixel (ShumateMapSource *map_source,
* radius_at_latitude = 2pi * k * sin (pi/2-theta)
*/
double map_size = shumate_map_source_get_tile_size (map_source) * shumate_map_source_get_row_count (map_source, zoom_level);
double map_size = shumate_map_source_get_tile_size_at_zoom (map_source, zoom_level) * shumate_map_source_get_row_count (map_source, zoom_level);
/* FIXME: support other projections */
return 2.0 * G_PI * EARTH_RADIUS * sin (G_PI / 2.0 - G_PI / 180.0 * latitude) / map_size;
}
......
......@@ -76,6 +76,7 @@ const char *shumate_map_source_get_license_uri (ShumateMapSource *map_source);
guint shumate_map_source_get_min_zoom_level (ShumateMapSource *map_source);
guint shumate_map_source_get_max_zoom_level (ShumateMapSource *map_source);
guint shumate_map_source_get_tile_size (ShumateMapSource *map_source);
guint shumate_map_source_get_tile_size_at_zoom (ShumateMapSource *map_source, double zoom);
ShumateMapProjection shumate_map_source_get_projection (ShumateMapSource *map_source);
double shumate_map_source_get_x (ShumateMapSource *map_source,
......
......@@ -91,7 +91,7 @@ shumate_scale_compute_length (ShumateScale *self,
gboolean *out_is_small_unit)
{
ShumateMapSource *map_source;
int zoom_level;
double zoom_level;
double lat, lon;
float scale_width;
float base;
......
......@@ -78,8 +78,7 @@ shumate_tile_snapshot (GtkWidget *widget,
texture,
&GRAPHENE_RECT_INIT(
0, 0,
gdk_texture_get_width (texture),
gdk_texture_get_height (texture)
priv->size, priv->size
));
}
}
......
......@@ -248,7 +248,7 @@ move_viewport_from_pixel_offset (ShumateView *self,
ShumateMapSource *map_source;
double x, y;
double lat, lon;
guint zoom_level;
double zoom_level;
guint tile_size, max_x, max_y;
g_assert (SHUMATE_IS_VIEW (self));
......@@ -261,7 +261,7 @@ move_viewport_from_pixel_offset (ShumateView *self,
x = shumate_map_source_get_x (map_source, zoom_level, longitude) - offset_x;
y = shumate_map_source_get_y (map_source, zoom_level, latitude) - offset_y;
tile_size = shumate_map_source_get_tile_size (map_source);
tile_size = shumate_map_source_get_tile_size_at_zoom (map_source, zoom_level);
max_x = shumate_map_source_get_column_count (map_source, zoom_level) * tile_size;
max_y = shumate_map_source_get_row_count (map_source, zoom_level) * tile_size;
......@@ -544,7 +544,7 @@ on_scroll_controller_scroll (ShumateView *self,
double scroll_map_x, scroll_map_y;
double view_center_x, view_center_y;
double x_offset, y_offset;
guint zoom_level;
double zoom_level;
scroll_map_x = shumate_viewport_longitude_to_widget_x (priv->viewport, GTK_WIDGET (self), scroll_longitude);
scroll_map_y = shumate_viewport_latitude_to_widget_y (priv->viewport, GTK_WIDGET (self), scroll_latitude);
......
......@@ -417,7 +417,7 @@ void shumate_viewport_zoom_in (ShumateViewport *self)
{
g_return_if_fail (SHUMATE_IS_VIEWPORT (self));
shumate_viewport_set_zoom_level (self, self->zoom_level + 1);
shumate_viewport_set_zoom_level (self, self->zoom_level + 0.2);
}
/**
......@@ -433,7 +433,7 @@ void shumate_viewport_zoom_out (ShumateViewport *self)
if (self->zoom_level == 0)
return;
shumate_viewport_set_zoom_level (self, self->zoom_level - 1);
shumate_viewport_set_zoom_level (self, self->zoom_level - 0.2);
}
/**
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment