summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Robert C. Helling <helling@atdotde.de>2013-01-22 21:06:31 -0800
committerGravatar Dirk Hohndel <dirk@hohndel.org>2013-01-27 15:48:25 -0800
commitae64abfbca2eb2c28a3875b1cb8ec098e660729a (patch)
treed07bd291ad6bc45d00de06a67b7202477f484d09
parent546fecd850a6e7342a41925b895c1e4275dc7aca (diff)
downloadsubsurface-ae64abfbca2eb2c28a3875b1cb8ec098e660729a.tar.gz
Modify map zoom to keep the point under the mouse cursor constant
The idea is that while zooming the map the point under the mouse would stay as close to constant as possible (given that we use integer coordinates). This version uses some algebra to figure out the correct new parameters for the mercator projection used in osm-gps-map. Occasionally (and we haven't figured out what triggers it) zooming out suddenly resets your position to 0,0. [Dirk Hohndel: switched this to using the correct interface to get the object properties and did some serious whitespace cleanup] Signed-off-by: Robert C. Helling <helling@atdotde.de> Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
-rw-r--r--gps.c47
1 files changed, 45 insertions, 2 deletions
diff --git a/gps.c b/gps.c
index cc6eaa3a4..267b85084 100644
--- a/gps.c
+++ b/gps.c
@@ -30,10 +30,53 @@ static void on_close(GtkWidget *widget, gpointer user_data)
static gboolean scroll_cb(GtkWidget *widget, GdkEventScroll *event, gpointer data)
{
OsmGpsMap *map = (OsmGpsMap *)widget;
- if (event->direction == GDK_SCROLL_UP)
+ OsmGpsMapPoint *pt, *lt, *rb, *target;
+ float target_lat, target_lon;
+ gint ltx, lty, rbx, rby, target_x, target_y;
+ gint zoom, max_zoom, min_zoom;
+
+ g_object_get(widget, "max-zoom", &max_zoom, "zoom", &zoom, "min-zoom", &min_zoom, NULL);
+
+ pt = osm_gps_map_point_new_degrees(0.0, 0.0);
+ lt = osm_gps_map_point_new_degrees(0.0, 0.0);
+ rb = osm_gps_map_point_new_degrees(0.0, 0.0);
+ target = osm_gps_map_point_new_degrees(0.0, 0.0);
+
+ osm_gps_map_convert_screen_to_geographic(map, event->x, event->y, pt);
+
+ osm_gps_map_get_bbox(map, lt, rb);
+ osm_gps_map_convert_geographic_to_screen(map, lt, &ltx, &lty);
+ osm_gps_map_convert_geographic_to_screen(map, rb, &rbx, &rby);
+
+ if (event->direction == GDK_SCROLL_UP) {
+ if (zoom == max_zoom)
+ return TRUE;
+
+ target_x = event->x + ((ltx + rbx) / 2.0 - (gint)(event->x)) / 2;
+ target_y = event->y + ((lty + rby) / 2.0 - (gint)(event->y)) / 2;
+
+ osm_gps_map_convert_screen_to_geographic(map, target_x, target_y, target);
+ osm_gps_map_point_get_degrees(target, &target_lat, &target_lon);
+
osm_gps_map_zoom_in(map);
- else if (event->direction == GDK_SCROLL_DOWN)
+ } else if (event->direction == GDK_SCROLL_DOWN) {
+ if(zoom == min_zoom)
+ return TRUE;
+
+ target_x = event->x + ((ltx + rbx) / 2.0 - (gint)(event->x)) * 2;
+ target_y = event->y + ((lty + rby) / 2.0 - (gint)(event->y)) * 2;
+
+ osm_gps_map_convert_screen_to_geographic(map, target_x, target_y, target);
+ osm_gps_map_point_get_degrees(target, &target_lat, &target_lon);
+
osm_gps_map_zoom_out(map);
+ }
+
+ /* There is no OSM interface to do this afaik. Hack something together */
+ /* set_map_pt_at_xy(map, pt, event->x, event->y); */
+
+ osm_gps_map_set_center(map, target_lat, target_lon);
+
/* don't allow the insane default handler to get its hands on this event */
return TRUE;
}