}
gtk_widget_destroy ( msgbox );
}
+
+gboolean a_dialog_map_n_zoom(GtkWindow *parent, gchar *mapnames[], gint default_map, gchar *zoom_list[], gint default_zoom, gint *selected_map, gint *selected_zoom)
+{
+ gchar **s;
+
+ GtkWidget *dialog = gtk_dialog_new_with_buttons ( "Download along track", parent, 0, GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT, NULL );
+
+ GtkWidget *map_label = gtk_label_new("Map type:");
+ GtkWidget *map_combo = GTK_COMBO_BOX(gtk_combo_box_new_text());
+ for (s = mapnames; *s; s++)
+ gtk_combo_box_append_text(map_combo, *s);
+ gtk_combo_box_set_active (map_combo, default_map);
+ GtkWidget *zoom_label = gtk_label_new("Zoom level:");
+ GtkWidget *zoom_combo = GTK_COMBO_BOX(gtk_combo_box_new_text());
+ for (s = zoom_list; *s; s++)
+ gtk_combo_box_append_text(zoom_combo, *s);
+ gtk_combo_box_set_active (zoom_combo, default_zoom);
+
+ GtkTable *box = GTK_TABLE(gtk_table_new(2, 2, FALSE));
+ gtk_table_attach_defaults(box, GTK_WIDGET(map_label), 0, 1, 0, 1);
+ gtk_table_attach_defaults(box, GTK_WIDGET(map_combo), 1, 2, 0, 1);
+ gtk_table_attach_defaults(box, GTK_WIDGET(zoom_label), 0, 1, 1, 2);
+ gtk_table_attach_defaults(box, GTK_WIDGET(zoom_combo), 1, 2, 1, 2);
+
+ gtk_box_pack_start ( GTK_BOX(GTK_DIALOG(dialog)->vbox), GTK_WIDGET(box), FALSE, FALSE, 5 );
+
+ gtk_widget_show_all ( dialog );
+ if ( gtk_dialog_run ( GTK_DIALOG(dialog) ) != GTK_RESPONSE_ACCEPT ) {
+ gtk_widget_destroy(dialog);
+ return FALSE;
+ }
+
+ *selected_map = gtk_combo_box_get_active(map_combo);
+ *selected_zoom = gtk_combo_box_get_active(zoom_combo);
+
+ gtk_widget_destroy(dialog);
+ return TRUE;
+}
void a_dialog_choose_dir ( GtkWidget *entry );
+gboolean a_dialog_map_n_zoom(GtkWindow *parent, gchar *mapnames[], gint default_map, gchar *zoom_list[], gint default_zoom, gint *selected_map, gint *selected_zoom);
#endif
return NULL;
}
+GList *vik_aggregate_layer_get_all_layers_of_type(VikAggregateLayer *val, GList *layers, gint type)
+{
+ GList *l = layers;
+ GList *children = val->children;
+ if (!children)
+ return layers;
+ while (children) {
+ if (VIK_LAYER(children->data)->type == VIK_LAYER_AGGREGATE)
+ l = vik_aggregate_layer_get_all_layers_of_type(VIK_LAYER(children->data), l, type);
+ else if (VIK_LAYER(children->data)->type == type)
+ l = g_list_prepend(l, children->data); /* now in top down order */
+ children = children->next;
+ }
+ return l;
+}
+
void vik_aggregate_layer_realize ( VikAggregateLayer *val, VikTreeview *vt, GtkTreeIter *layer_iter )
{
GList *i = val->children;
gboolean vik_aggregate_layer_is_empty ( VikAggregateLayer *val );
const GList *vik_aggregate_layer_get_children ( VikAggregateLayer *val );
+GList *vik_aggregate_layer_get_all_layers_of_type(VikAggregateLayer *val, GList *layers, gint type);
#endif
else /* VIK_COORD_UTM */
return coord1->utm_zone == coord2->utm_zone && coord1->north_south == coord2->north_south && coord1->east_west == coord2->east_west;
}
+
+static void get_north_west(struct LatLon *center, struct LatLon *dist, struct LatLon *nw)
+{
+ nw->lat = center->lat + dist->lat;
+ nw->lon = center->lon - dist->lon;
+ if (nw->lon < -180)
+ nw->lon += 360.0;
+ if (nw->lat > 90.0) { /* over north pole */
+ nw->lat = 180 - nw->lat;
+ nw->lon = nw->lon - 180;
+ }
+}
+
+static void get_south_east(struct LatLon *center, struct LatLon *dist, struct LatLon *se)
+{
+ se->lat = center->lat - dist->lat;
+ se->lon = center->lon + dist->lon;
+ if (se->lon > 180.0)
+ se->lon -= 360.0;
+ if (se->lat < -90.0) { /* over south pole */
+ se->lat += 180;
+ se->lon = se->lon - 180;
+ }
+}
+
+void vik_coord_set_area(const VikCoord *coord, const struct LatLon *wh, VikCoord *tl, VikCoord *br)
+{
+ struct LatLon center, nw, se;
+ struct LatLon dist;
+
+ dist.lat = wh->lat/2;
+ dist.lon = wh->lon/2;
+
+ vik_coord_to_latlon(coord, ¢er);
+ get_north_west(¢er, &dist, &nw);
+ get_south_east(¢er, &dist, &se);
+
+ tl->mode = br->mode = VIK_COORD_LATLON;
+ *((struct LatLon *)tl) = nw;
+ *((struct LatLon *)br) = se;
+}
+
+gboolean vik_coord_inside(const VikCoord *coord, const VikCoord *tl, const VikCoord *br)
+{
+ struct LatLon ll, tl_ll, br_ll;
+
+ vik_coord_to_latlon(coord, &ll);
+ vik_coord_to_latlon(tl, &tl_ll);
+ vik_coord_to_latlon(br, &br_ll);
+
+#ifdef DEBUG
+ fprintf(stderr, "DEBUG: %s() ll=%f, %f tl=%f, %f br=%f, %f\n",
+ __PRETTY_FUNCTION__, ll.lat, ll.lon, tl_ll.lat, tl_ll.lon, br_ll.lat, br_ll.lon);
+#endif
+
+ if ((ll.lat > tl_ll.lat) || (ll.lon < tl_ll.lon))
+ return FALSE;
+ if ((ll.lat < br_ll.lat) || (ll.lon > br_ll.lon))
+ return FALSE;
+ return TRUE;
+}
gboolean vik_coord_equals ( const VikCoord *coord1, const VikCoord *coord2 );
+void vik_coord_set_area(const VikCoord *coord, const struct LatLon *wh, VikCoord *tl, VikCoord *br);
+gboolean vik_coord_inside(const VikCoord *coord, const VikCoord *tl, const VikCoord *br);
/* all coord operations MUST BE ABSTRACTED!!! */
#endif
return rv;
}
+GList *vik_layers_panel_get_all_layers_of_type(VikLayersPanel *vlp, gint type)
+{
+ GList *layers = NULL;
+
+ return (vik_aggregate_layer_get_all_layers_of_type ( vlp->toplayer, layers, type ));
+}
+
VikAggregateLayer *vik_layers_panel_get_top_layer ( VikLayersPanel *vlp )
{
return vlp->toplayer;
void vik_layers_panel_clear ( VikLayersPanel *vlp );
VikAggregateLayer *vik_layers_panel_get_top_layer ( VikLayersPanel *vlp );
void vik_layers_panel_change_coord_mode ( VikLayersPanel *vlp, VikCoordMode mode );
+GList *vik_layers_panel_get_all_layers_of_type(VikLayersPanel *vlp, gint type);
G_END_DECLS
#define MAPS_LAYER_NTH_ID(n) ((guint)g_list_nth_data(params_maptypes_ids, (n)))
#define MAPS_LAYER_NTH_TYPE(n) ((VikMapsLayer_MapType*)g_list_nth_data(__map_types, (n)))
+gint vik_maps_layer_get_map_type(VikMapsLayer *vml)
+{
+ return(vml->maptype);
+}
+
+gchar *vik_maps_layer_get_map_label(VikMapsLayer *vml)
+{
+ return(g_strdup(MAPS_LAYER_NTH_LABEL(vml->maptype)));
+}
+
/****************************************/
/******** CACHE DIR STUFF ***************/
/****************************************/
gint maxlen;
gint mapstoget;
gint redownload;
+ gboolean refresh_display;
VikMapsLayer *vml;
VikViewport *vvp;
gboolean map_layer_alive;
g_mutex_lock(mdi->mutex);
if (remove_mem_cache)
a_mapcache_remove_all_shrinkfactors ( x, y, mdi->mapcoord.z, MAPS_LAYER_NTH_TYPE(mdi->maptype)->uniq_id, mdi->mapcoord.scale );
- if (mdi->map_layer_alive) {
+ if (mdi->refresh_display && mdi->map_layer_alive) {
/* TODO: check if it's on visible area */
vik_layer_emit_update ( VIK_LAYER(mdi->vml) );
}
mdi->vvp = vvp;
mdi->map_layer_alive = TRUE;
mdi->mutex = g_mutex_new();
+ mdi->refresh_display = TRUE;
/* cache_dir and buffer for dest filename */
mdi->cache_dir = g_strdup ( vml->cache_dir );
}
}
+void maps_layer_download_section_without_redraw( VikMapsLayer *vml, VikViewport *vvp, VikCoord *ul, VikCoord *br, gdouble zoom)
+{
+ fprintf(stderr, "DEBUG: downloading ul= %f , %f br= %f , %f\n",
+ ul->north_south, ul->east_west, br->north_south, br->east_west);
+ MapCoord ulm, brm;
+ VikMapsLayer_MapType *map_type = MAPS_LAYER_NTH_TYPE(vml->maptype);
+
+ if (!map_type->coord_to_mapcoord(ul, zoom, zoom, &ulm)
+ || !map_type->coord_to_mapcoord(br, zoom, zoom, &brm)) {
+ fprintf(stderr, "%s() coord_to_mapcoord() failed\n", __PRETTY_FUNCTION__);
+ return;
+ }
+
+ MapDownloadInfo *mdi = g_malloc(sizeof(MapDownloadInfo));
+ gint i, j;
+
+ mdi->vml = vml;
+ mdi->vvp = vvp;
+ mdi->map_layer_alive = TRUE;
+ mdi->mutex = g_mutex_new();
+ mdi->refresh_display = FALSE;
+
+ mdi->cache_dir = g_strdup ( vml->cache_dir );
+ mdi->maxlen = strlen ( vml->cache_dir ) + 40;
+ mdi->filename_buf = g_malloc ( mdi->maxlen * sizeof(gchar) );
+ mdi->maptype = vml->maptype;
+
+ mdi->mapcoord = ulm;
+
+ mdi->redownload = REDOWNLOAD_NONE;
+
+ mdi->x0 = MIN(ulm.x, brm.x);
+ mdi->xf = MAX(ulm.x, brm.x);
+ mdi->y0 = MIN(ulm.y, brm.y);
+ mdi->yf = MAX(ulm.y, brm.y);
+
+ mdi->mapstoget = 0;
+
+ for (i = mdi->x0; i <= mdi->xf; i++) {
+ for (j = mdi->y0; j <= mdi->yf; j++) {
+ g_snprintf ( mdi->filename_buf, mdi->maxlen, DIRSTRUCTURE,
+ vml->cache_dir, map_type->uniq_id, ulm.scale,
+ ulm.z, i, j );
+ if ( access ( mdi->filename_buf, F_OK ) != 0)
+ mdi->mapstoget++;
+ }
+ }
+
+ mdi->mapcoord.x = mdi->mapcoord.y = 0; /* for cleanup -- no current map */
+
+ if (mdi->mapstoget) {
+ gchar *tmp = g_strdup_printf ( "%s %d %s %s...", "Downloading", mdi->mapstoget, MAPS_LAYER_NTH_LABEL(vml->maptype), (mdi->mapstoget == 1) ? "map" : "maps" );
+
+ g_object_weak_ref(G_OBJECT(mdi->vml), weak_ref_cb, mdi);
+ /* launch the thread */
+ a_background_thread ( VIK_GTK_WINDOW_FROM_LAYER(vml), /* parent window */
+ tmp, /* description string */
+ (vik_thr_func) map_download_thread, /* function to call within thread */
+ mdi, /* pass along data */
+ (vik_thr_free_func) mdi_free, /* function to free pass along data */
+ (vik_thr_free_func) mdi_cancel_cleanup,
+ mdi->mapstoget );
+ g_free ( tmp );
+ }
+ else
+ mdi_free ( mdi );
+}
+
static void maps_layer_redownload_bad ( VikMapsLayer *vml )
{
start_download_thread ( vml, vml->redownload_vvp, &(vml->redownload_ul), &(vml->redownload_br), REDOWNLOAD_BAD );
} VikMapsLayer_MapType;
void maps_layer_register_type ( const char *label, guint id, VikMapsLayer_MapType *map_type );
+void maps_layer_download_section_without_redraw ( VikMapsLayer *vml, VikViewport *vvp, VikCoord *ul, VikCoord *br, gdouble zoom);
+gint vik_maps_layer_get_map_type(VikMapsLayer *vml);
+gchar *vik_maps_layer_get_map_label(VikMapsLayer *vml);
#endif
/* viktrwlayer.c -- 2200 lines can make a difference in the state of things */
#include "viking.h"
+#include "vikmapslayer.h"
#include "viktrwlayer_pixmap.h"
#include "viktrwlayer_tpwin.h"
#include "viktrwlayer_propwin.h"
static void trw_layer_goto_track_endpoint ( gpointer pass_along[6] );
static void trw_layer_merge_by_timestamp ( gpointer pass_along[6] );
static void trw_layer_split_by_timestamp ( gpointer pass_along[6] );
+static void trw_layer_download_map_along_track_cb(gpointer pass_along[6]);
static void trw_layer_centerize ( gpointer layer_and_vlp[2] );
static void trw_layer_export ( gpointer layer_and_vlp[2], guint file_type );
static void trw_layer_goto_wp ( gpointer layer_and_vlp[2] );
g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_split_by_timestamp), pass_along );
gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
gtk_widget_show ( item );
+
+ item = gtk_menu_item_new_with_label ( "Download maps along track..." );
+ g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_download_map_along_track_cb), pass_along );
+ gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
+ gtk_widget_show ( item );
}
if ( vlp && (subtype == VIK_TRW_LAYER_SUBLAYER_WAYPOINTS || subtype == VIK_TRW_LAYER_SUBLAYER_WAYPOINT) )
return(vtl->menu_selection);
}
+/* ----------- Downloading maps along tracks --------------- */
+
+static int get_download_area_width(VikViewport *vvp, gdouble zoom_level, struct LatLon *wh)
+{
+ /* TODO: calculating based on current size of viewport */
+ const gdouble w_at_zoom_0_125 = 0.0013;
+ const gdouble h_at_zoom_0_125 = 0.0011;
+ gdouble zoom_factor = zoom_level/0.125;
+
+ wh->lat = h_at_zoom_0_125 * zoom_factor;
+ wh->lon = w_at_zoom_0_125 * zoom_factor;
+
+ return 0; /* all OK */
+}
+
+void vik_track_download_map(VikTrack *tr, VikMapsLayer *vml, VikViewport *vvp, gdouble zoom_level)
+{
+ typedef struct _Rect {
+ VikCoord tl;
+ VikCoord br;
+ } Rect;
+
+ struct LatLon wh;
+ GList *rect_to_download = NULL;
+ GList *rect_iter;
+
+ if (get_download_area_width(vvp, zoom_level, &wh))
+ return;
+
+ GList *iter = tr->trackpoints;
+
+ gboolean new_map = TRUE;
+ VikCoord *cur_coord, tl, br;
+ Rect *rect;
+ /* TODO: handle cases when trackpoints are far apart */
+ while (iter) {
+ cur_coord = &(VIK_TRACKPOINT(iter->data))->coord;
+ if (new_map) {
+ vik_coord_set_area(cur_coord, &wh, &tl, &br);
+ rect = g_malloc(sizeof(Rect));
+ rect->tl = tl;
+ rect->br = br;
+ rect_to_download = g_list_prepend(rect_to_download, rect);
+ new_map = FALSE;
+ iter = iter->next;
+ continue;
+ }
+ gboolean found = FALSE;
+ for (rect_iter = rect_to_download; rect_iter; rect_iter = rect_iter->next) {
+ if (vik_coord_inside(cur_coord, &(((Rect *)(rect_iter->data))->tl), &(((Rect *)(rect_iter->data))->br))) {
+ found = TRUE;
+ break;
+ }
+ }
+ if (found)
+ iter = iter->next;
+ else
+ new_map = TRUE;
+ }
+ for (rect_iter = rect_to_download; rect_iter; rect_iter = rect_iter->next) {
+ maps_layer_download_section_without_redraw(vml, vvp, &(((Rect *)(rect_iter->data))->tl), &(((Rect *)(rect_iter->data))->br), zoom_level);
+ }
+
+ for (rect_iter = rect_to_download; rect_iter; rect_iter = rect_iter->next)
+ g_free(rect_iter->data);
+ g_list_free(rect_to_download);
+}
+
+
+static void trw_layer_download_map_along_track_cb(gpointer pass_along[6])
+{
+ VikMapsLayer *vml;
+ gint selected_map, default_map;
+ gchar *zoomlist[] = {"0.125", "0.25", "0.5", "1", "2", "4", "8", "16", "32", "64", "128", "256", "512", "1024", NULL };
+ gdouble zoom_vals[] = {0.125, 0.25, 0.5, 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024};
+ gint selected_zoom, default_zoom;
+ int i,j;
+
+
+ VikTrwLayer *vtl = pass_along[0];
+ VikLayersPanel *vlp = pass_along[1];
+ VikTrack *tr = (VikTrack *) g_hash_table_lookup ( VIK_TRW_LAYER(pass_along[0])->tracks, pass_along[3] );
+ VikViewport *vvp = vik_window_viewport((VikWindow *)(VIK_GTK_WINDOW_FROM_LAYER(vtl)));
+
+ GList *vmls = vik_layers_panel_get_all_layers_of_type(vlp, VIK_LAYER_MAPS);
+ int num_maps = g_list_length(vmls);
+
+ if (!num_maps) {
+ a_dialog_msg(VIK_GTK_WINDOW_FROM_LAYER(vtl), GTK_MESSAGE_ERROR,"No map layer in use. Create one first", NULL);
+ return;
+ }
+
+ gchar **map_names = g_malloc(1 + num_maps * sizeof(gpointer));
+ VikMapsLayer **map_layers = g_malloc(1 + num_maps * sizeof(gpointer));
+
+ gchar **np = map_names;
+ VikMapsLayer **lp = map_layers;
+ for (i = 0; i < num_maps; i++) {
+ gboolean dup = FALSE;
+ vml = (VikMapsLayer *)(vmls->data);
+ for (j = 0; j < i; j++) { /* no duplicate allowed */
+ if (vik_maps_layer_get_map_type(vml) == vik_maps_layer_get_map_type(map_layers[j])) {
+ dup = TRUE;
+ break;
+ }
+ }
+ if (!dup) {
+ *lp++ = vml;
+ *np++ = vik_maps_layer_get_map_label(vml);
+ }
+ vmls = vmls->next;
+ }
+ *lp = NULL;
+ *np = NULL;
+ num_maps = lp - map_layers;
+
+ for (default_map = 0; default_map < num_maps; default_map++) {
+ /* TODO: check for parent layer's visibility */
+ if (VIK_LAYER(map_layers[default_map])->visible)
+ break;
+ }
+ default_map = (default_map == num_maps) ? 0 : default_map;
+
+ gdouble cur_zoom = vik_viewport_get_zoom(vvp);
+ for (default_zoom = 0; default_zoom < sizeof(zoom_vals)/sizeof(gdouble); default_zoom++) {
+ if (cur_zoom == zoom_vals[default_zoom])
+ break;
+ }
+ default_zoom = (default_zoom == sizeof(zoom_vals)/sizeof(gdouble)) ? sizeof(zoom_vals)/sizeof(gdouble) - 1 : default_zoom;
+
+ if (!a_dialog_map_n_zoom(VIK_GTK_WINDOW_FROM_LAYER(vtl), map_names, default_map, zoomlist, default_zoom, &selected_map, &selected_zoom))
+ goto done;
+
+ vik_track_download_map(tr, map_layers[selected_map], vvp, zoom_vals[selected_zoom]);
+
+done:
+ for (i = 0; i < num_maps; i++)
+ g_free(map_names[i]);
+ g_free(map_names);
+ g_free(map_layers);
+
+ g_list_free(vmls);
+
+}