#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)) \
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)
{
}
}
-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);
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);
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,
#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)
{
/* 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;
}
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;
}
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)
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)
{
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)
{
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;
}
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);
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);
/* 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