diff options
author | Robert C. Helling <helling@atdotde.de> | 2013-01-22 21:06:31 -0800 |
---|---|---|
committer | Dirk Hohndel <dirk@hohndel.org> | 2013-01-27 15:48:25 -0800 |
commit | ae64abfbca2eb2c28a3875b1cb8ec098e660729a (patch) | |
tree | d07bd291ad6bc45d00de06a67b7202477f484d09 /gps.c | |
parent | 546fecd850a6e7342a41925b895c1e4275dc7aca (diff) | |
download | subsurface-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>
Diffstat (limited to 'gps.c')
-rw-r--r-- | gps.c | 47 |
1 files changed, 45 insertions, 2 deletions
@@ -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, <x, <y); + 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; } |