From: Kaj-Michael Lang Date: Sat, 17 May 2008 15:56:05 +0000 (+0300) Subject: MapWidget: X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=257af7c233dfe38e0692daa832365b1bb10f83f9;p=mapper MapWidget: - Move latlon2unit + unit2latlon here - Fix tile and latlon calculations - Add more methods --- diff --git a/src/gtkmap.c b/src/gtkmap.c index e4d9c10..67e576f 100644 --- a/src/gtkmap.c +++ b/src/gtkmap.c @@ -227,14 +227,14 @@ struct _GtkMapPriv #define GTK_MAP_TILE_SIZE_PIXELS (256) #define GTK_MAP_TILE_SIZE_P2 (8) +#define MAX_ZOOM (16) -/* #define GTK_MAP_WORLD_SIZE_UNITS(max_zoom) (2 << (max_zoom + GTK_MAP_TILE_SIZE_P2)) */ - -#define GTK_MAP_WORLD_SIZE_UNITS (2<<26) +#define GTK_MAP_WORLD_SIZE_UNITS (2 << (MAX_ZOOM + GTK_MAP_TILE_SIZE_P2)) #define WORLD_SIZE_UNITS GTK_MAP_WORLD_SIZE_UNITS -/* Pans are done two "grids" at a time, or 64 pixels. */ -#define GTK_MAP_PAN_UNITS (grid2unit(2)) +#define GTK_MAP_PAN_UNITS_SLOW (grid2unit(1)) +#define GTK_MAP_PAN_UNITS_FAST (grid2unit(2)) +#define GTK_MAP_PAN_UNITS GTK_MAP_PAN_UNITS_FAST #define BOUND(x, a, b) { \ if((x) < (a)) \ @@ -287,6 +287,27 @@ enum { static guint gtk_map_signals[LAST_SIGNAL] = { 0 }; +#define MERCATOR_SPAN (-6.28318377773622f) +#define MERCATOR_TOP (3.14159188886811f) + +void +latlon2unit(gdouble lat, gdouble lon, guint *unitx, guint *unity) +{ +gdouble tmp; + +*unitx=lrint((lon + 180.f) * (GTK_MAP_WORLD_SIZE_UNITS / 360.f)); +tmp=sin(lat * (M_PIl / 180.f)); +*unity=lrint((GTK_MAP_WORLD_SIZE_UNITS / MERCATOR_SPAN) * (log((1.f + tmp) / (1.f - tmp)) * 0.5f - MERCATOR_TOP)); +} + +void +unit2latlon(guint unitx, guint unity, gdouble *lat, gdouble *lon) +{ +*lon=(unitx * (360.f / GTK_MAP_WORLD_SIZE_UNITS)) - 180.f; +*lat=(360.f * (atan(exp(((unity) * (MERCATOR_SPAN / GTK_MAP_WORLD_SIZE_UNITS)) + MERCATOR_TOP)))) * (1.f / M_PIl) - 90.f; +} + + static void gtk_map_class_init(GtkMapClass *class) { @@ -341,15 +362,20 @@ switch(priv->center_mode) { } } -static inline void +static void gtk_map_recalc_offset(GtkMapPriv *priv) { g_return_if_fail(priv); +#if 0 priv->offsetx = grid2pixel(unit2grid(priv->center.unitx) - priv->screen_grids_halfwidth - tile2grid(priv->base_tilex)); priv->offsety = grid2pixel(unit2grid(priv->center.unity) - priv->screen_grids_halfheight - tile2grid(priv->base_tiley)); +#else +priv->offsetx = unit2pixel(priv->center.unitx) - priv->screen_width_pixels/2 - tile2pixel(priv->base_tilex); +priv->offsety = unit2pixel(priv->center.unity) - priv->screen_height_pixels/2 - tile2pixel(priv->base_tiley); +#endif } -static inline void +static void gtk_map_recalc_focus_base(GtkMapPriv *priv) { g_return_if_fail(priv); @@ -357,7 +383,7 @@ priv->focus.unitx = x2unit(priv->screen_width_pixels * priv->center_ratio / 20); priv->focus.unity = y2unit(priv->screen_height_pixels * priv->center_ratio / 20); } -static inline void +static void gtk_map_recalc_focus_size(GtkMapPriv *priv) { g_return_if_fail(priv); @@ -703,24 +729,39 @@ if (!priv->buffer) return g_debug("GTKMAP: expose (%d, %d)-(%d, %d)", event->area.x, event->area.y, event->area.width, event->area.height); -g_debug("GTKMAP: expose (%d, %d)", event->area.x + priv->offsetx, event->area.y + priv->offsety); -g_debug("GTKMAP: expose (%d, %d)", unit2x(priv->center.unitx), unit2y(priv->center.unity)); +g_debug("GTKMAP: offset (%d, %d)", event->area.x + priv->offsetx, event->area.y + priv->offsety); +g_debug("GTKMAP: x,y (%d, %d)", unit2x(priv->center.unitx), unit2y(priv->center.unity)); -#ifdef WITH_CAIROa +#ifdef WITH_CAIRO cairo_save(priv->ct); cairo_rectangle(priv->ct, event->area.x, event->area.y, event->area.width, event->area.height); cairo_clip(priv->ct); -#if 0 if (priv->rotate_view) { - cairo_translate(priv->ct, (gdouble)-unit2x(priv->center.unitx), (gdouble)-unit2y(priv->center.unity) ); - cairo_rotate(priv->ct, (gdouble)priv->rotate_angle); - cairo_translate(priv->ct, (gdouble)unit2x(priv->center.unitx), (gdouble)unit2y(priv->center.unity) ); -} + cairo_matrix_t r; + + g_debug("ROTATE: %f", priv->rotate_angle); + +#if 0 + cairo_matrix_init_translate(&r, -(unit2x(priv->center.unitx)+priv->offsetx), -(unit2y(priv->center.unity)+priv->offsety)); + cairo_matrix_rotate(&r, priv->rotate_angle); + cairo_matrix_translate(&r, (unit2x(priv->center.unitx)+priv->offsetx), (unit2y(priv->center.unity)+priv->offsety)); +#else + cairo_matrix_init_translate(&r, -(priv->offsetx), -(priv->offsety)); + cairo_matrix_rotate(&r, priv->rotate_angle); + cairo_matrix_translate(&r, priv->offsetx, priv->offsety); #endif -cairo_translate(priv->ct, -(event->area.x+priv->offsetx), -(event->area.y+priv->offsety)); -gdk_cairo_set_source_pixmap(priv->ct, priv->buffer, event->area.x, event->area.y); -cairo_set_operator (priv->ct, CAIRO_OPERATOR_SOURCE); -cairo_paint(priv->ct); + + cairo_set_matrix(priv->ct, &r); + gdk_cairo_set_source_pixmap(priv->ct, priv->buffer, 0, 0); + cairo_set_operator (priv->ct, CAIRO_OPERATOR_SOURCE); + cairo_paint(priv->ct); + cairo_identity_matrix(priv->ct); +} else { + cairo_translate(priv->ct, -(event->area.x+priv->offsetx), -(event->area.y+priv->offsety)); + gdk_cairo_set_source_pixmap(priv->ct, priv->buffer, event->area.x, event->area.y); + cairo_set_operator (priv->ct, CAIRO_OPERATOR_SOURCE); + cairo_paint(priv->ct); +} cairo_restore(priv->ct); #else gdk_draw_drawable(widget->window, widget->style->fg_gc[GTK_STATE_NORMAL], priv->buffer, @@ -856,6 +897,18 @@ if (path->type==PATH_TYPE_ROUTE) #endif } +void +gtk_map_set_path_display(GtkWidget *widget, gint path_mask) +{ +GtkMap *map; +GtkMapPriv *priv; + +map=GTK_MAP(widget); +priv=GTK_MAP_GET_PRIVATE(map); + +priv->show_paths=path_mask; +} + static void gtk_map_render_paths(GtkWidget *widget, GdkEventExpose *event) { @@ -896,6 +949,7 @@ priv=GTK_MAP_GET_PRIVATE(map); /* Don't allow duplicates */ if (g_slist_find(priv->paths, path)!=NULL) return FALSE; +g_object_ref(path); priv->paths=g_slist_append(priv->paths, path); return TRUE; } @@ -911,7 +965,11 @@ g_return_val_if_fail(path, FALSE); map=GTK_MAP(widget); priv=GTK_MAP_GET_PRIVATE(map); + +if (g_slist_find(priv->paths, path)==NULL) + return FALSE; priv->paths=g_slist_remove(priv->paths, path); +g_object_unref(path); return TRUE; } @@ -1006,8 +1064,8 @@ if (!gdk_rectangle_intersect(&event->area, &priv->scale_rect, NULL)) return; /* Now calculate and draw the distance. */ -unit2latlon(priv->center.unitx - pixel2unit(SCALE_WIDTH / 2 - SCALE_PADDING), priv->center.unity, lat1, lon1); -unit2latlon(priv->center.unitx + pixel2unit(SCALE_WIDTH / 2 - SCALE_PADDING), priv->center.unity, lat2, lon2); +unit2latlon(priv->center.unitx - pixel2unit(SCALE_WIDTH / 2 - SCALE_PADDING), priv->center.unity, &lat1, &lon1); +unit2latlon(priv->center.unitx + pixel2unit(SCALE_WIDTH / 2 - SCALE_PADDING), priv->center.unity, &lat2, &lon2); distance=calculate_distance(lat1, lon1, lat2, lon2) * priv->units_conv; if (distance < 1.f) @@ -1428,6 +1486,31 @@ priv=GTK_MAP_GET_PRIVATE(map); gtk_map_set_center(widget, priv->center.unitx + delta_x*GTK_MAP_PAN_UNITS, priv->center.unity + delta_y*GTK_MAP_PAN_UNITS); } +gboolean +gtk_map_rotate(GtkWidget *widget, gfloat angle) +{ +#ifdef WITH_CAIRO +GtkMap *map; +GtkMapPriv *priv; + +g_return_if_fail(GTK_IS_MAP(widget)); +map=GTK_MAP(widget); +priv=GTK_MAP_GET_PRIVATE(map); + +if (angle==0.0 || angle==NAN) { + priv->rotate_view=FALSE; +} else { + priv->rotate_view=TRUE; + priv->rotate_angle=angle*(M_PIl / 180.f); +} +gtk_widget_queue_draw(widget); +return TRUE; +#else +return FALSE; +#endif +} + + void gtk_map_refresh(GtkWidget *widget) { @@ -1460,6 +1543,16 @@ priv=GTK_MAP_GET_PRIVATE(map); return priv->zoom; } +gboolean +gtk_map_set_autozoom(GtkWidget *widget, gboolean az) +{ +GtkMap *map; +GtkMapPriv *priv; + +/* Check that we have a track set */ +return TRUE; +} + gboolean gtk_map_set_zoom(GtkWidget *widget, gint new_zoom) { @@ -1596,9 +1689,9 @@ priv=GTK_MAP_GET_PRIVATE(map); priv->mouse_x=(gint)event->x; priv->mouse_y=(gint)event->y; -unit2latlon(x2unit((gint) (event->x+0.5)), y2unit((gint) (event->y+0.5)), priv->mouse_lat, priv->mouse_lon); +unit2latlon(x2unit(priv->mouse_x), y2unit(priv->mouse_y), &priv->mouse_lat, &priv->mouse_lon); -g_debug("MOUSE: %d,%d (%f,%f)", priv->mouse_x, priv->mouse_y, priv->mouse_lat, priv->mouse_lon); +g_debug("MOUSE(%d): %d,%d (%f,%f)", priv->button_down, priv->mouse_x, priv->mouse_y, priv->mouse_lat, priv->mouse_lon); return FALSE; } diff --git a/src/gtkmap.h b/src/gtkmap.h index b9729a2..f4c0c07 100644 --- a/src/gtkmap.h +++ b/src/gtkmap.h @@ -60,6 +60,9 @@ struct _GtkMapClass { G_BEGIN_DECLS +void latlon2unit(gdouble lat, gdouble lon, guint *unitx, guint *unity); +void unit2latlon(guint unitx, guint unity, gdouble *lat, gdouble *lon); + GType gtk_map_get_type(void); GtkWidget* gtk_map_new(void); @@ -77,6 +80,8 @@ gboolean gtk_map_add_path(GtkWidget *map, Path *path); gboolean gtk_map_remove_path(GtkWidget *map, Path *path); gboolean gtk_map_remove_path_by_id(GtkWidget *map, gint path_id); +void gtk_map_set_path_display(GtkWidget *widget, gint path_mask); + /* Get copy of map buffer */ GdkPixmap *gtk_map_pixmap_get(GtkWidget *map); @@ -85,17 +90,25 @@ void gtk_map_set_cache_size(GtkWidget *widget, guint cache_size); /* Location functions */ void gtk_map_set_center(GtkWidget *map, guint unitx, guint unity); +void gtk_map_get_center(GtkWidget *map, guint *unitx, guint *unity); + void gtk_map_set_center_latlon(GtkWidget *map, gdouble lat, gdouble lon); -void gtk_map_get_center_latlon(GtkWidget *map); +void gtk_map_get_center_latlon(GtkWidget *map, gdouble *lat, gdouble *lon); + void gtk_map_pan(GtkWidget *map, gint delta_unitx, gint delta_unity); +/* Map rotation */ +gboolean gtk_map_rotate(GtkWidget *map, gfloat angle); + /* Zoom functions */ gint gtk_map_get_zoom(GtkWidget *map); gint gtk_map_set_zoom(GtkWidget *map, gint zoom); gint gtk_map_zoom(GtkWidget *map, gint zdir); gboolean gtk_map_zoom_out(GtkWidget *map); gboolean gtk_map_zoom_in(GtkWidget *map); -void gtk_map_set_autozoom(GtkWidget *map, gboolean az, gfloat speed); +gboolean gtk_map_set_autozoom(GtkWidget *map, gboolean az); + +void gtk_map_get_menu_latlon(GtkWidget *map, gdouble *lat, gdouble *lon); G_END_DECLS