+/**************************************************************
+ **** SOURCES & DOWNLOADING
+ **************************************************************/
+typedef struct {
+ gchar *dest;
+ gdouble lat, lon;
+
+ GMutex *mutex;
+ VikDEMLayer *vdl; /* NULL if not alive */
+
+ guint source;
+} DEMDownloadParams;
+
+
+/**************************************************
+ * SOURCE: SRTM *
+ **************************************************/
+
+static void srtm_dem_download_thread ( DEMDownloadParams *p, gpointer threaddata )
+{
+ gint intlat, intlon;
+ const gchar *continent_dir;
+
+ intlat = (int)floor(p->lat);
+ intlon = (int)floor(p->lon);
+ continent_dir = srtm_continent_dir(intlat, intlon);
+
+ if (!continent_dir) {
+ g_warning(N_("No SRTM data available for %f, %f"), p->lat, p->lon);
+ return;
+ }
+
+ gchar *src_fn = g_strdup_printf("%s%s/%c%02d%c%03d.hgt.zip",
+ SRTM_HTTP_URI,
+ continent_dir,
+ (intlat >= 0) ? 'N' : 'S',
+ ABS(intlat),
+ (intlon >= 0) ? 'E' : 'W',
+ ABS(intlon) );
+
+ static DownloadOptions options = { 0, NULL, 0, a_check_map_file };
+ a_http_download_get_url ( SRTM_HTTP_SITE, src_fn, p->dest, &options, NULL );
+ g_free ( src_fn );
+}
+
+static gchar *srtm_lat_lon_to_dest_fn ( gdouble lat, gdouble lon )
+{
+ gint intlat, intlon;
+ const gchar *continent_dir;
+
+ intlat = (int)floor(lat);
+ intlon = (int)floor(lon);
+ continent_dir = srtm_continent_dir(intlat, intlon);
+
+ if (!continent_dir)
+ continent_dir = "nowhere";
+
+ return g_strdup_printf("srtm3-%s%s%c%02d%c%03d.hgt.zip",
+ continent_dir,
+ G_DIR_SEPARATOR_S,
+ (intlat >= 0) ? 'N' : 'S',
+ ABS(intlat),
+ (intlon >= 0) ? 'E' : 'W',
+ ABS(intlon) );
+
+}
+
+/* TODO: generalize */
+static void srtm_draw_existence ( VikViewport *vp )
+{
+ gdouble max_lat, max_lon, min_lat, min_lon;
+ gchar buf[strlen(MAPS_CACHE_DIR)+strlen(SRTM_CACHE_TEMPLATE)+30];
+ gint i, j;
+
+ vik_viewport_get_min_max_lat_lon ( vp, &min_lat, &max_lat, &min_lon, &max_lon );
+
+ for (i = floor(min_lat); i <= floor(max_lat); i++) {
+ for (j = floor(min_lon); j <= floor(max_lon); j++) {
+ const gchar *continent_dir;
+ if ((continent_dir = srtm_continent_dir(i, j)) == NULL)
+ continue;
+ g_snprintf(buf, sizeof(buf), SRTM_CACHE_TEMPLATE,
+ MAPS_CACHE_DIR,
+ continent_dir,
+ G_DIR_SEPARATOR_S,
+ (i >= 0) ? 'N' : 'S',
+ ABS(i),
+ (j >= 0) ? 'E' : 'W',
+ ABS(j) );
+ if ( g_file_test(buf, G_FILE_TEST_EXISTS ) == TRUE ) {
+ VikCoord ne, sw;
+ gint x1, y1, x2, y2;
+ sw.north_south = i;
+ sw.east_west = j;
+ sw.mode = VIK_COORD_LATLON;
+ ne.north_south = i+1;
+ ne.east_west = j+1;
+ ne.mode = VIK_COORD_LATLON;
+ vik_viewport_coord_to_screen ( vp, &sw, &x1, &y1 );
+ vik_viewport_coord_to_screen ( vp, &ne, &x2, &y2 );
+ if ( x1 < 0 ) x1 = 0;
+ if ( y2 < 0 ) y2 = 0;
+ vik_viewport_draw_rectangle ( vp, GTK_WIDGET(vp)->style->black_gc,
+ FALSE, x1, y2, x2-x1, y1-y2 );
+ }
+ }
+ }
+}
+
+
+/**************************************************
+ * SOURCE: USGS 24K *
+ **************************************************/
+
+#ifdef VIK_CONFIG_DEM24K
+
+static void dem24k_dem_download_thread ( DEMDownloadParams *p, gpointer threaddata )
+{
+ /* TODO: dest dir */
+ gchar *cmdline = g_strdup_printf("%s %.03f %.03f",
+ DEM24K_DOWNLOAD_SCRIPT,
+ floor(p->lat*8)/8,
+ ceil(p->lon*8)/8 );
+ /* FIX: don't use system, use execv or something. check for existence */
+ system(cmdline);
+}
+
+static gchar *dem24k_lat_lon_to_dest_fn ( gdouble lat, gdouble lon )
+{
+ return g_strdup_printf("dem24k/%d/%d/%.03f,%.03f.dem",
+ (gint) lat,
+ (gint) lon,
+ floor(lat*8)/8,
+ ceil(lon*8)/8);
+}
+
+/* TODO: generalize */
+static void dem24k_draw_existence ( VikViewport *vp )
+{
+ gdouble max_lat, max_lon, min_lat, min_lon;
+ gchar buf[strlen(MAPS_CACHE_DIR)+40];
+ gdouble i, j;
+
+ vik_viewport_get_min_max_lat_lon ( vp, &min_lat, &max_lat, &min_lon, &max_lon );
+
+ for (i = floor(min_lat*8)/8; i <= floor(max_lat*8)/8; i+=0.125) {
+ /* check lat dir first -- faster */
+ g_snprintf(buf, sizeof(buf), "%sdem24k/%d/",
+ MAPS_CACHE_DIR,
+ (gint) i );
+ if ( g_file_test(buf, G_FILE_TEST_EXISTS) == FALSE )
+ continue;
+ for (j = floor(min_lon*8)/8; j <= floor(max_lon*8)/8; j+=0.125) {
+ /* check lon dir first -- faster */
+ g_snprintf(buf, sizeof(buf), "%sdem24k/%d/%d/",
+ MAPS_CACHE_DIR,
+ (gint) i,
+ (gint) j );
+ if ( g_file_test(buf, G_FILE_TEST_EXISTS) == FALSE )
+ continue;
+ g_snprintf(buf, sizeof(buf), "%sdem24k/%d/%d/%.03f,%.03f.dem",
+ MAPS_CACHE_DIR,
+ (gint) i,
+ (gint) j,
+ floor(i*8)/8,
+ floor(j*8)/8 );
+ if ( g_file_test(buf, G_FILE_TEST_EXISTS ) == TRUE ) {
+ VikCoord ne, sw;
+ gint x1, y1, x2, y2;
+ sw.north_south = i;
+ sw.east_west = j-0.125;
+ sw.mode = VIK_COORD_LATLON;
+ ne.north_south = i+0.125;
+ ne.east_west = j;
+ ne.mode = VIK_COORD_LATLON;
+ vik_viewport_coord_to_screen ( vp, &sw, &x1, &y1 );
+ vik_viewport_coord_to_screen ( vp, &ne, &x2, &y2 );
+ if ( x1 < 0 ) x1 = 0;
+ if ( y2 < 0 ) y2 = 0;
+ vik_viewport_draw_rectangle ( vp, GTK_WIDGET(vp)->style->black_gc,
+ FALSE, x1, y2, x2-x1, y1-y2 );
+ }
+ }
+ }
+}
+#endif
+
+/**************************************************
+ * SOURCES -- DOWNLOADING & IMPORTING TOOL *
+ **************************************************
+ */
+
+static void weak_ref_cb ( gpointer ptr, GObject * dead_vdl )
+{
+ DEMDownloadParams *p = ptr;
+ g_mutex_lock ( p->mutex );
+ p->vdl = NULL;
+ g_mutex_unlock ( p->mutex );
+}
+
+/* Try to add file full_path.
+ * full_path will be copied.
+ * returns FALSE if file does not exists, TRUE otherwise.
+ */
+static gboolean dem_layer_add_file ( VikDEMLayer *vdl, const gchar *full_path )
+{
+ if ( g_file_test(full_path, G_FILE_TEST_EXISTS ) == TRUE ) {
+ /* only load if file size is not 0 (not in progress) */
+ struct stat sb;
+ stat (full_path, &sb);
+ if ( sb.st_size ) {
+ gchar *duped_path = g_strdup(full_path);
+ vdl->files = g_list_prepend ( vdl->files, duped_path );
+ a_dems_load ( duped_path );
+ g_debug("%s: %s", __FUNCTION__, duped_path);
+ vik_layer_emit_update ( VIK_LAYER(vdl) );
+ }
+ return TRUE;
+ } else
+ return FALSE;
+}
+
+static void dem_download_thread ( DEMDownloadParams *p, gpointer threaddata )
+{
+ if ( p->source == DEM_SOURCE_SRTM )
+ srtm_dem_download_thread ( p, threaddata );
+#ifdef VIK_CONFIG_DEM24K
+ else if ( p->source == DEM_SOURCE_DEM24K )
+ dem24k_dem_download_thread ( p, threaddata );
+#endif
+
+ gdk_threads_enter();
+ g_mutex_lock ( p->mutex );
+ if ( p->vdl ) {
+ g_object_weak_unref ( G_OBJECT(p->vdl), weak_ref_cb, p );
+
+ if ( dem_layer_add_file ( p->vdl, p->dest ) )
+ vik_layer_emit_update ( VIK_LAYER(p->vdl) );
+ }
+ g_mutex_unlock ( p->mutex );
+ gdk_threads_leave();
+}
+
+
+static void free_dem_download_params ( DEMDownloadParams *p )
+{
+ g_mutex_free ( p->mutex );
+ g_free ( p->dest );
+ g_free ( p );
+}
+
+static gpointer dem_layer_download_create ( VikWindow *vw, VikViewport *vvp)
+{
+ return vvp;
+}
+
+
+static gboolean dem_layer_download_release ( VikDEMLayer *vdl, GdkEventButton *event, VikViewport *vvp )
+{
+ VikCoord coord;
+ struct LatLon ll;
+
+ gchar *full_path;
+ gchar *dem_file = NULL;
+
+ if ( vdl->source == DEM_SOURCE_NONE )
+ a_dialog_error_msg ( VIK_GTK_WINDOW_FROM_LAYER(vdl), _("No download source selected. Edit layer properties.") );
+
+ vik_viewport_screen_to_coord ( vvp, event->x, event->y, &coord );
+ vik_coord_to_latlon ( &coord, &ll );
+
+
+ if ( vdl->source == DEM_SOURCE_SRTM )
+ dem_file = srtm_lat_lon_to_dest_fn ( ll.lat, ll.lon );
+#ifdef VIK_CONFIG_DEM24K
+ else if ( vdl->source == DEM_SOURCE_DEM24K )
+ dem_file = dem24k_lat_lon_to_dest_fn ( ll.lat, ll.lon );
+#endif
+
+ if ( ! dem_file )
+ return TRUE;
+
+ full_path = g_strdup_printf("%s%s", MAPS_CACHE_DIR, dem_file );
+
+ g_debug("%s: %s", __FUNCTION__, full_path);
+
+ // TODO: check if already in filelist
+
+ if ( ! dem_layer_add_file(vdl, full_path) ) {
+ gchar *tmp = g_strdup_printf ( _("Downloading DEM %s"), dem_file );
+ DEMDownloadParams *p = g_malloc(sizeof(DEMDownloadParams));
+ p->dest = g_strdup(full_path);
+ p->lat = ll.lat;
+ p->lon = ll.lon;
+ p->vdl = vdl;
+ p->mutex = g_mutex_new();
+ p->source = vdl->source;
+ g_object_weak_ref(G_OBJECT(p->vdl), weak_ref_cb, p );
+
+ a_background_thread ( VIK_GTK_WINDOW_FROM_LAYER(vdl), tmp,
+ (vik_thr_func) dem_download_thread, p,
+ (vik_thr_free_func) free_dem_download_params, NULL, 1 );
+ }
+
+ g_free ( dem_file );
+ g_free ( full_path );
+
+ return TRUE;
+}
+
+static gboolean dem_layer_download_click ( VikDEMLayer *vdl, GdkEventButton *event, VikViewport *vvp )
+{
+/* choose & keep track of cache dir
+ * download in background thread
+ * download over area */
+ return TRUE;
+}
+