+2007-07-06
+Evan Battaglia <gtoevan@gmx.net>:
+ * Merge DEM Branch
+
2007-07-04
Quy Tonthat <qtonthat@gmail.com>:
* Bug fix: View Mode displayed wrong setting on start up
* Fixed bugs that caused draw_scale and draw_centermark status not being
consistent among View menu, viewport and loaded files.
+2007-07-02
+Evan Battaglia <gtoevan@gmx.net>
+ * DEM Branch: Trying to fix/cleanup various DEM things
+ * DEM Branch: Support for SRTM 3 arcsecond _global_ DEM data from http://www2.jpl.nasa.gov/srtm/
+
2007-07-02
Quy Tonthat <qtonthat@gmail.com>:
* Fixed bugs that caused crashes during GPS upload/download.
* Disable prompt for save before exit.
* Add "Save and Exit" to File menu.
+2007-05-20
+Evan Battaglia <gtoevan@gmx.net>
+ * DEM Branch
+
2007-05-20
Quy Tonthat <qtonthat@gmail.com>:
* Stop autodownload from running forever on map downloading errors.
datasource_google.c \
datasource_gc.c \
datasources.h \
- googlesearch.c googlesearch.h
+ googlesearch.c googlesearch.h \
+ datasources.h \
+ dem.c dem.h \
+ vikdemlayer.h vikdemlayer.c \
+ vikfilelist.c vikfilelist.h \
+ dems.c dems.h
if LIBCURL
viking_SOURCES += \
--- /dev/null
+#include <stdio.h>
+#include <string.h>
+#include <glib.h>
+#include <math.h>
+#include <stdlib.h>
+
+#include "dem.h"
+#include "file.h"
+
+#define DEM_BLOCK_SIZE 1024
+#define GET_COLUMN(dem,n) ((VikDEMColumn *)g_ptr_array_index( (dem)->columns, (n) ))
+
+static gboolean get_double_and_continue ( gchar **buffer, gdouble *tmp, gboolean warn )
+{
+ gchar *endptr;
+ *tmp = g_strtod(*buffer, &endptr);
+ if ( endptr == NULL|| endptr == *buffer ) {
+ if ( warn )
+ g_warning("Invalid DEM");
+ return FALSE;
+ }
+ *buffer=endptr;
+ return TRUE;
+}
+
+
+static gboolean get_int_and_continue ( gchar **buffer, gint *tmp, gboolean warn )
+{
+ gchar *endptr;
+ *tmp = strtol(*buffer, &endptr, 10);
+ if ( endptr == NULL|| endptr == *buffer ) {
+ if ( warn )
+ g_warning("Invalid DEM");
+ return FALSE;
+ }
+ *buffer=endptr;
+ return TRUE;
+}
+
+static gboolean dem_parse_header ( gchar *buffer, VikDEM *dem )
+{
+ gdouble val;
+ gint int_val;
+ guint i;
+ gchar *tmp = buffer;
+
+ /* incomplete header */
+ if ( strlen(buffer) != 1024 )
+ return FALSE;
+
+ /* fix Fortran-style exponentiation 1.0D5 -> 1.0E5 */
+ while (*tmp) {
+ if ( *tmp=='D')
+ *tmp='E';
+ tmp++;
+ }
+
+ /* skip name */
+ buffer += 149;
+
+ /* "DEM level code, pattern code, palaimetric reference system code" -- skip */
+ get_int_and_continue(&buffer, &int_val, TRUE);
+ get_int_and_continue(&buffer, &int_val, TRUE);
+ get_int_and_continue(&buffer, &int_val, TRUE);
+
+ /* zone */
+ get_int_and_continue(&buffer, &int_val, TRUE);
+ dem->utm_zone = int_val;
+ /* TODO -- southern or northern hemisphere?! */
+ dem->utm_letter = 'N';
+
+ /* skip numbers 5-19 */
+ for ( i = 0; i < 15; i++ ) {
+ if ( ! get_double_and_continue(&buffer, &val, FALSE) ) {
+ g_warning ("Invalid DEM header");
+ return FALSE;
+ }
+ }
+
+ /* number 20 -- horizontal unit code (utm/ll) */
+ get_double_and_continue(&buffer, &val, TRUE);
+ dem->horiz_units = val;
+ get_double_and_continue(&buffer, &val, TRUE);
+ dem->vert_units = val;
+
+ /* TODO: do this for real. these are only for 1:24k and 1:250k USGS */
+ if ( dem->horiz_units == VIK_DEM_HORIZ_UTM_METERS ) {
+ dem->east_scale = 10.0; /* meters */
+ dem->north_scale = 10.0;
+ } else {
+ dem->east_scale = 3.0; /* arcseconds */
+ dem->north_scale = 3.0;
+ }
+
+ /* skip next */
+ get_double_and_continue(&buffer, &val, TRUE);
+
+ /* now we get the four corner points. record the min and max. */
+ get_double_and_continue(&buffer, &val, TRUE);
+ dem->min_east = dem->max_east = val;
+ get_double_and_continue(&buffer, &val, TRUE);
+ dem->min_north = dem->max_north = val;
+
+ for ( i = 0; i < 3; i++ ) {
+ get_double_and_continue(&buffer, &val, TRUE);
+ if ( val < dem->min_east ) dem->min_east = val;
+ if ( val > dem->max_east ) dem->max_east = val;
+ get_double_and_continue(&buffer, &val, TRUE);
+ if ( val < dem->min_north ) dem->min_north = val;
+ if ( val > dem->max_north ) dem->max_north = val;
+ }
+
+ return TRUE;
+}
+
+static void dem_parse_block_as_cont ( gchar *buffer, VikDEM *dem, gint *cur_column, gint *cur_row )
+{
+ gint tmp;
+ while ( *cur_row < GET_COLUMN(dem, *cur_column)->n_points ) {
+ if ( get_int_and_continue(&buffer, &tmp,FALSE) )
+ GET_COLUMN(dem, *cur_column)->points[*cur_row] = (gint16) tmp;
+ else
+ return;
+ (*cur_row)++;
+ }
+ *cur_row = -1; /* expecting new column */
+}
+
+static void dem_parse_block_as_header ( gchar *buffer, VikDEM *dem, gint *cur_column, gint *cur_row )
+{
+ guint n_rows;
+ gint i;
+ gdouble east_west, south;
+ gdouble tmp;
+
+ /* 1 x n_rows 1 east_west south x x x DATA */
+
+ if ( (!get_double_and_continue(&buffer, &tmp, TRUE)) || tmp != 1 ) {
+ g_warning("Incorrect DEM Class B record: expected 1");
+ return;
+ }
+
+ /* don't need this */
+ if ( !get_double_and_continue(&buffer, &tmp, TRUE ) ) return;
+
+ /* n_rows */
+ if ( !get_double_and_continue(&buffer, &tmp, TRUE ) )
+ return;
+ n_rows = (guint) tmp;
+
+ if ( (!get_double_and_continue(&buffer, &tmp, TRUE)) || tmp != 1 ) {
+ g_warning("Incorrect DEM Class B record: expected 1");
+ return;
+ }
+
+ if ( !get_double_and_continue(&buffer, &east_west, TRUE) )
+ return;
+ if ( !get_double_and_continue(&buffer, &south, TRUE) )
+ return;
+
+ /* next three things we don't need */
+ if ( !get_double_and_continue(&buffer, &tmp, TRUE)) return;
+ if ( !get_double_and_continue(&buffer, &tmp, TRUE)) return;
+ if ( !get_double_and_continue(&buffer, &tmp, TRUE)) return;
+
+
+ dem->n_columns ++;
+ (*cur_column) ++;
+
+ /* empty spaces for things before that were skipped */
+ (*cur_row) = (south - dem->min_north) / dem->north_scale;
+ if ( south > dem->max_north || (*cur_row) < 0 )
+ (*cur_row) = 0;
+
+ n_rows += *cur_row;
+
+ g_ptr_array_add ( dem->columns, g_malloc(sizeof(VikDEMColumn)) );
+ GET_COLUMN(dem,*cur_column)->east_west = east_west;
+ GET_COLUMN(dem,*cur_column)->south = south;
+ GET_COLUMN(dem,*cur_column)->n_points = n_rows;
+ GET_COLUMN(dem,*cur_column)->points = g_malloc(sizeof(gint16)*n_rows);
+
+ /* no information for things before that */
+ for ( i = 0; i < (*cur_row); i++ )
+ GET_COLUMN(dem,*cur_column)->points[i] = VIK_DEM_INVALID_ELEVATION;
+
+ /* now just continue */
+ dem_parse_block_as_cont ( buffer, dem, cur_column, cur_row );
+
+
+}
+
+static void dem_parse_block ( gchar *buffer, VikDEM *dem, gint *cur_column, gint *cur_row )
+{
+ /* if haven't read anything or have read all items in a columns and are expecting a new column */
+ if ( *cur_column == -1 || *cur_row == -1 ) {
+ dem_parse_block_as_header(buffer, dem, cur_column, cur_row);
+ } else {
+ dem_parse_block_as_cont(buffer, dem, cur_column, cur_row);
+ }
+}
+
+static VikDEM *vik_dem_read_srtm_hgt(FILE *f, const gchar *basename)
+{
+ gint16 elev;
+ gint i, j;
+ VikDEM *dem;
+
+
+ dem = g_malloc(sizeof(VikDEM));
+
+ dem->horiz_units = VIK_DEM_HORIZ_LL_ARCSECONDS;
+ dem->vert_units = VIK_DEM_VERT_DECIMETERS;
+ dem->east_scale = dem->north_scale = 3;
+
+ /* TODO */
+ dem->min_north = atoi(basename+1) * 3600;
+ dem->min_east = atoi(basename+4) * 3600;
+ if ( basename[0] == 'S' )
+ dem->min_north = - dem->min_north;
+ if ( basename[3] == 'W' )
+ dem->min_east = - dem->min_east;
+
+ dem->max_north = 3600 + dem->min_north;
+ dem->max_east = 3600 + dem->min_east;
+
+ dem->columns = g_ptr_array_new();
+ dem->n_columns = 0;
+
+ for ( i = 0; i < 1201; i++ ) {
+ dem->n_columns++;
+ g_ptr_array_add ( dem->columns, g_malloc(sizeof(VikDEMColumn)) );
+ GET_COLUMN(dem,i)->east_west = dem->min_east + 3*i;
+ GET_COLUMN(dem,i)->south = dem->min_north;
+ GET_COLUMN(dem,i)->n_points = 1201;
+ GET_COLUMN(dem,i)->points = g_malloc(sizeof(gint16)*1201);
+ }
+
+ for ( i = 1200; i >= 0; i-- ) {
+ for ( j = 0; j < 1201; j++ ) {
+ if ( feof(f) ) {
+ g_warning("Incorrect SRTM file: unexpected EOF");
+ g_print("%d %d\n", i, j);
+ return dem;
+ }
+ fread(&elev, sizeof(elev), 1, f);
+ gchar *x = (gchar *) &elev;
+ gchar tmp;
+ tmp=x[0];
+ x[0]=x[1];
+ x[1]=tmp;
+ GET_COLUMN(dem,j)->points[i] = elev;
+ }
+
+ }
+
+ return dem;
+}
+
+#define IS_SRTM_HGT(fn) (strlen((fn))==11 && (fn)[7]=='.' && (fn)[8]=='h' && (fn)[9]=='g' && (fn)[10]=='t' && ((fn)[0]=='N' || (fn)[0]=='S') && ((fn)[3]=='E' || (fn)[3]=='W'))
+
+VikDEM *vik_dem_new_from_file(const gchar *file)
+{
+ FILE *f;
+ VikDEM *rv;
+ gchar buffer[DEM_BLOCK_SIZE+1];
+
+ /* use to record state for dem_parse_block */
+ gint cur_column = -1;
+ gint cur_row = -1;
+ const gchar *basename = a_file_basename(file);
+
+ /* FILE IO */
+ f = fopen(file, "r");
+ if ( !f )
+ return NULL;
+
+ if ( strlen(basename)==11 && basename[7]=='.' && basename[8]=='h' && basename[9]=='g' && basename[10]=='t' &&
+ (basename[0] == 'N' || basename[0] == 'S') && (basename[3] == 'E' || basename[3] =='W'))
+ return vik_dem_read_srtm_hgt(f, basename);
+
+ /* Create Structure */
+ rv = g_malloc(sizeof(VikDEM));
+
+ /* Header */
+ buffer[fread(buffer, 1, DEM_BLOCK_SIZE, f)] = '\0';
+ if ( ! dem_parse_header ( buffer, rv ) ) {
+ g_free ( rv );
+ return NULL;
+ }
+ /* TODO: actually use header -- i.e. GET # OF COLUMNS EXPECTED */
+
+ rv->columns = g_ptr_array_new();
+ rv->n_columns = 0;
+
+ /* Column -- Data */
+ while (! feof(f) ) {
+ gchar *tmp;
+
+ /* read block */
+ buffer[fread(buffer, 1, DEM_BLOCK_SIZE, f)] = '\0';
+
+ /* Fix Fortran-style exponentiation */
+ tmp = buffer;
+ while (*tmp) {
+ if ( *tmp=='D')
+ *tmp='E';
+ tmp++;
+ }
+
+ dem_parse_block(buffer, rv, &cur_column, &cur_row);
+ }
+
+ /* TODO - class C records (right now says 'Invalid' and dies) */
+
+ fclose(f);
+
+ /* 24k scale */
+ if ( rv->horiz_units == VIK_DEM_HORIZ_UTM_METERS && rv->n_columns >= 2 )
+ rv->north_scale = rv->east_scale = GET_COLUMN(rv, 1)->east_west - GET_COLUMN(rv,0)->east_west;
+
+ /* FIXME bug in 10m DEM's */
+ if ( rv->horiz_units == VIK_DEM_HORIZ_UTM_METERS && rv->north_scale == 10 ) {
+ rv->min_east -= 100;
+ rv->min_north += 200;
+ }
+
+
+ return rv;
+}
+
+void vik_dem_free ( VikDEM *dem )
+{
+ guint i;
+ for ( i = 0; i < dem->n_columns; i++)
+ g_free ( GET_COLUMN(dem, i)->points );
+ g_ptr_array_free ( dem->columns, TRUE );
+ g_free ( dem );
+}
+
+gint16 vik_dem_get_xy ( VikDEM *dem, guint col, guint row )
+{
+ if ( col < dem->n_columns )
+ if ( row < GET_COLUMN(dem, col)->n_points )
+ return GET_COLUMN(dem, col)->points[row];
+ return VIK_DEM_INVALID_ELEVATION;
+}
+
+gint16 vik_dem_get_east_north ( VikDEM *dem, gdouble east, gdouble north )
+{
+ gint col, row;
+
+ if ( east > dem->max_east || east < dem->min_east ||
+ north > dem->max_north || north < dem->min_north )
+ return VIK_DEM_INVALID_ELEVATION;
+
+ col = (gint) floor((east - dem->min_east) / dem->east_scale);
+ row = (gint) floor((north - dem->min_north) / dem->north_scale);
+
+ return vik_dem_get_xy ( dem, col, row );
+}
+
+void vik_dem_east_north_to_xy ( VikDEM *dem, gdouble east, gdouble north, guint *col, guint *row )
+{
+ *col = (gint) floor((east - dem->min_east) / dem->east_scale);
+ *row = (gint) floor((north - dem->min_north) / dem->north_scale);
+ if ( *col < 0 ) *col = 0;
+ if ( *row < 0 ) *row = 0;
+}
+
--- /dev/null
+#ifndef __VIKING_DEM_H
+#define __VIKING_DEM_H
+
+#define VIK_DEM_INVALID_ELEVATION -32767
+
+/* unit codes */
+#define VIK_DEM_HORIZ_UTM_METERS 2
+#define VIK_DEM_HORIZ_LL_ARCSECONDS 3
+
+#define VIK_DEM_VERT_DECIMETERS 2
+
+typedef struct {
+ guint n_columns;
+ GPtrArray *columns;
+
+ guint16 horiz_units, vert_units;
+ gdouble east_scale; /* gap between samples */
+ gdouble north_scale;
+
+ gdouble min_east, min_north, max_east, max_north;
+
+ guint8 utm_zone;
+ gchar utm_letter;
+} VikDEM;
+
+typedef struct {
+ /* east-west coordinate for ALL items in the column */
+ gdouble east_west;
+
+ /* coordinate of northern and southern boundaries */
+ gdouble south;
+// gdouble north;
+
+ guint n_points;
+ gint16 *points;
+} VikDEMColumn;
+
+
+VikDEM *vik_dem_new_from_file(const gchar *file);
+void vik_dem_free ( VikDEM *dem );
+gint16 vik_dem_get_xy ( VikDEM *dem, guint x, guint y );
+
+gint16 vik_dem_get_east_north ( VikDEM *dem, gdouble east, gdouble north );
+
+void vik_dem_east_north_to_xy ( VikDEM *dem, gdouble east, gdouble north, guint *col, guint *row );
+
+#endif
--- /dev/null
+#include <glib.h>
+
+#include "dems.h"
+
+typedef struct {
+ VikDEM *dem;
+ guint ref_count;
+} LoadedDEM;
+
+GHashTable *loaded_dems = NULL;
+/* filename -> DEM */
+
+static void loaded_dem_free ( LoadedDEM *ldem )
+{
+ vik_dem_free ( ldem->dem );
+ g_free ( ldem );
+}
+
+void a_dems_uninit ()
+{
+ if ( loaded_dems )
+ g_hash_table_destroy ( loaded_dems );
+}
+
+/* To load a dem. if it was already loaded, will simply
+ * reference the one already loaded and return it.
+ */
+VikDEM *a_dems_load(const gchar *filename)
+{
+ LoadedDEM *ldem;
+
+ /* dems init hash table */
+ if ( ! loaded_dems )
+ loaded_dems = g_hash_table_new_full ( g_str_hash, g_str_equal, g_free, (GDestroyNotify) loaded_dem_free );
+
+ ldem = (LoadedDEM *) g_hash_table_lookup ( loaded_dems, filename );
+ if ( ldem ) {
+ ldem->ref_count++;
+ return ldem->dem;
+ } else {
+ VikDEM *dem = vik_dem_new_from_file ( filename );
+ if ( ! dem )
+ return NULL;
+ ldem = g_malloc ( sizeof(LoadedDEM) );
+ ldem->ref_count = 1;
+ ldem->dem = dem;
+ g_hash_table_insert ( loaded_dems, g_strdup(filename), ldem );
+ return dem;
+ }
+}
+
+void a_dems_unref(const gchar *filename)
+{
+ LoadedDEM *ldem = (LoadedDEM *) g_hash_table_lookup ( loaded_dems, filename );
+ g_assert ( ldem );
+ ldem->ref_count --;
+ if ( ldem->ref_count == 0 )
+ g_hash_table_remove ( loaded_dems, filename );
+}
+
+/* to get a DEM that was already loaded.
+ * assumes that its in there already,
+ * although it could not be if earlier load failed.
+ */
+VikDEM *a_dems_get(const gchar *filename)
+{
+ LoadedDEM *ldem = g_hash_table_lookup ( loaded_dems, filename );
+ if ( ldem )
+ return ldem->dem;
+ return NULL;
+}
+
+
+/* Load a string list (GList of strings) of dems. You have to use get to at them later.
+ * When updating a list as a parameter, this should be bfore freeing the list so
+ * the same DEMs won't be loaded & unloaded.
+ * Modifies the list to remove DEMs which did not load.
+ */
+
+/* TODO: don't delete them when they don't exist.
+ * we need to warn the user, but we should keep them in the GList.
+ * we need to know that they weren't referenced though when we
+ * do the a_dems_list_free().
+ */
+void a_dems_load_list ( GList **dems )
+{
+ GList *iter = *dems;
+ while ( iter ) {
+ if ( ! a_dems_load((const gchar *) (iter->data)) ) {
+ GList *iter_temp = iter->next;
+ g_free ( iter->data );
+ (*dems) = g_list_remove_link ( (*dems), iter );
+ iter = iter_temp;
+ } else {
+ iter = iter->next;
+ }
+ }
+}
+
+/* Takes a string list (GList of strings) of dems (filenames).
+ * Unrefs all the dems (i.e. "unloads" them), then frees the
+ * strings, the frees the list.
+ */
+void a_dems_list_free ( GList *dems )
+{
+ GList *iter = dems;
+ while ( iter ) {
+ a_dems_unref ((const gchar *)iter->data);
+ g_free ( iter->data );
+ iter = iter->next;
+ }
+ g_list_free ( dems );
+}
+
+GList *a_dems_list_copy ( GList *dems )
+{
+ GList *rv = g_list_copy ( dems );
+ GList *iter = rv;
+ while ( iter ) {
+ if ( ! a_dems_load((const gchar *) (iter->data)) ) {
+ GList *iter_temp = iter->next; /* delete link, don't bother strdup'ing and free'ing string */
+ rv = g_list_remove_link ( rv, iter );
+ iter = iter_temp;
+ } else {
+ iter->data = g_strdup((gchar *)iter->data); /* copy the string too. */
+ iter = iter->next;
+ }
+ }
+ return rv;
+}
+
+gint16 a_dems_list_get_elev_by_coord ( GList *dems, const VikCoord *coord )
+{
+ static struct UTM utm_tmp;
+ static struct LatLon ll_tmp;
+ GList *iter = dems;
+ VikDEM *dem;
+ gint elev;
+
+ while ( iter ) {
+ dem = a_dems_get ( (gchar *) iter->data );
+ if ( dem ) {
+ if ( dem->horiz_units == VIK_DEM_HORIZ_LL_ARCSECONDS ) {
+ vik_coord_to_latlon ( coord, &ll_tmp );
+ ll_tmp.lat *= 3600;
+ ll_tmp.lon *= 3600;
+ elev = vik_dem_get_east_north(dem, ll_tmp.lon, ll_tmp.lat);
+ if ( elev != VIK_DEM_INVALID_ELEVATION )
+ return elev;
+ } else if ( dem->horiz_units == VIK_DEM_HORIZ_UTM_METERS ) {
+ vik_coord_to_utm ( coord, &utm_tmp );
+ if ( utm_tmp.zone == dem->utm_zone &&
+ (elev = vik_dem_get_east_north(dem, utm_tmp.easting, utm_tmp.northing)) != VIK_DEM_INVALID_ELEVATION )
+ return elev;
+ }
+ }
+ iter = iter->next;
+ }
+ return VIK_DEM_INVALID_ELEVATION;
+}
--- /dev/null
+#ifndef __VIKING_DEMS_H
+#define __VIKING_DEMS_H
+
+#include "dem.h"
+#include "vikcoord.h"
+
+void a_dems_uninit ();
+VikDEM *a_dems_load(const gchar *filename);
+void a_dems_unref(const gchar *filename);
+VikDEM *a_dems_get(const gchar *filename);
+void a_dems_load_list ( GList **dems );
+void a_dems_list_free ( GList *dems );
+GList *a_dems_list_copy ( GList *dems );
+gint16 a_dems_list_get_elev_by_coord ( GList *dems, const VikCoord *coord );
+
+#endif
+#include <glib.h>
+
for ( i = 0; i < params_count; i++ )
{
data = get_param(l,i);
- fprintf ( f, "%s=", params[i].name );
- switch ( params[i].type )
- {
- case VIK_LAYER_PARAM_DOUBLE: {
-// char buf[15]; /* locale independent */
-// fprintf ( f, "%s\n", (char *) g_dtostr (data.d, buf, sizeof (buf)) ); break;
- fprintf ( f, "%f\n", data.d );
- break;
- }
- case VIK_LAYER_PARAM_UINT: fprintf ( f, "%d\n", data.u ); break;
- case VIK_LAYER_PARAM_INT: fprintf ( f, "%d\n", data.i ); break;
- case VIK_LAYER_PARAM_BOOLEAN: fprintf ( f, "%c\n", data.b ? 't' : 'f' ); break;
- case VIK_LAYER_PARAM_STRING: fprintf ( f, "%s\n", data.s ); break;
- case VIK_LAYER_PARAM_COLOR: fprintf ( f, "#%.2x%.2x%.2x\n", (int)(data.c.red/256),(int)(data.c.green/256),(int)(data.c.blue/256)); break;
+
+ /* string lists are handled differently. We get a GList (that shouldn't
+ * be freed) back for get_param and if it is null we shouldn't write
+ * anything at all (otherwise we'd read in a list with an empty string,
+ Â * not an empty string list.
+ */
+ if ( params[i].type == VIK_LAYER_PARAM_STRING_LIST ) {
+ if ( data.sl ) {
+ GList *iter = (GList *)data.sl;
+ while ( iter ) {
+ fprintf ( f, "%s=", params[i].name );
+ fprintf ( f, "%s\n", (gchar *)(iter->data) );
+ iter = iter->next;
+ }
+ }
+ } else {
+ fprintf ( f, "%s=", params[i].name );
+ switch ( params[i].type )
+ {
+ case VIK_LAYER_PARAM_DOUBLE: {
+ // char buf[15]; /* locale independent */
+ // fprintf ( f, "%s\n", (char *) g_dtostr (data.d, buf, sizeof (buf)) ); break;
+ fprintf ( f, "%f\n", data.d );
+ break;
+ }
+ case VIK_LAYER_PARAM_UINT: fprintf ( f, "%d\n", data.u ); break;
+ case VIK_LAYER_PARAM_INT: fprintf ( f, "%d\n", data.i ); break;
+ case VIK_LAYER_PARAM_BOOLEAN: fprintf ( f, "%c\n", data.b ? 't' : 'f' ); break;
+ case VIK_LAYER_PARAM_STRING: fprintf ( f, "%s\n", data.s ); break;
+ case VIK_LAYER_PARAM_COLOR: fprintf ( f, "#%.2x%.2x%.2x\n", (int)(data.c.red/256),(int)(data.c.green/256),(int)(data.c.blue/256)); break;
+ }
}
}
}
*/
}
+static void string_list_delete ( gpointer key, gpointer l, gpointer user_data )
+{
+ GList *iter = (GList *) iter;
+ while ( iter ) {
+ g_free ( iter->data );
+ iter = iter->next;
+ }
+ g_list_free ( (GList *) iter );
+}
+
+static void string_list_set_param (gint i, GList *list, gpointer *layer_and_vp)
+{
+ VikLayerParamData x;
+ x.sl = list;
+ vik_layer_set_param ( VIK_LAYER(layer_and_vp[0]), i, x, layer_and_vp[1] );
+}
+
static void file_read ( VikAggregateLayer *top, FILE *f, gpointer vp )
{
Stack *stack;
VikLayerParam *params = NULL; /* for current layer, so we don't have to keep on looking up interface */
guint8 params_count = 0;
+ GHashTable *string_lists = g_hash_table_new(g_direct_hash,g_direct_equal);
+
push(&stack);
stack->under = NULL;
stack->data = (gpointer) top;
g_warning ( "Line %ld: Mismatched ~EndLayer command", line_num );
else
{
+ /* add any string lists we've accumulated */
+ gpointer layer_and_vp[2];
+ layer_and_vp[0] = stack->data;
+ layer_and_vp[1] = vp;
+ g_hash_table_foreach ( string_lists, (GHFunc) string_list_set_param, layer_and_vp );
+ g_hash_table_remove_all ( string_lists );
+
if ( stack->data && stack->under->data )
{
if (VIK_LAYER(stack->under->data)->type == VIK_LAYER_AGGREGATE) {
else if ( eq_pos != -1 && stack->under )
{
gboolean found_match = FALSE;
+
/* go thru layer params. if len == eq_pos && starts_with jazz, set it. */
/* also got to check for name and visible. */
{
VikLayerParamData x;
line += eq_pos+1;
- switch ( params[i].type )
- {
- case VIK_LAYER_PARAM_DOUBLE: x.d = strtod(line, NULL); break;
- case VIK_LAYER_PARAM_UINT: x.u = strtoul(line, NULL, 10); break;
- case VIK_LAYER_PARAM_INT: x.i = strtol(line, NULL, 10); break;
- case VIK_LAYER_PARAM_BOOLEAN: x.b = TEST_BOOLEAN(line); break;
- case VIK_LAYER_PARAM_COLOR: memset(&(x.c), 0, sizeof(x.c)); /* default: black */
+ if ( params[i].type == VIK_LAYER_PARAM_STRING_LIST ) {
+ GList *l = g_list_append ( g_hash_table_lookup ( string_lists, (gpointer) ((gint) i) ), g_strdup(line) );
+ g_hash_table_replace ( string_lists, (gpointer) ((gint)i), l );
+ /* add the value to a list, possibly making a new list.
+ * this will be passed to the layer when we read an ~EndLayer */
+ } else {
+ switch ( params[i].type )
+ {
+ case VIK_LAYER_PARAM_DOUBLE: x.d = strtod(line, NULL); break;
+ case VIK_LAYER_PARAM_UINT: x.u = strtoul(line, NULL, 10); break;
+ case VIK_LAYER_PARAM_INT: x.i = strtol(line, NULL, 10); break;
+ case VIK_LAYER_PARAM_BOOLEAN: x.b = TEST_BOOLEAN(line); break;
+ case VIK_LAYER_PARAM_COLOR: memset(&(x.c), 0, sizeof(x.c)); /* default: black */
gdk_color_parse ( line, &(x.c) ); break;
- default: x.s = line;
+ /* STRING or STRING_LIST -- if STRING_LIST, just set param to add a STRING */
+ default: x.s = line;
+ }
+ vik_layer_set_param ( VIK_LAYER(stack->data), i, x, vp );
}
- vik_layer_set_param ( VIK_LAYER(stack->data), i, x, vp );
found_match = TRUE;
break;
}
if ( ( ! VIK_LAYER(top)->visible ) && VIK_LAYER(top)->realized )
vik_treeview_item_set_visible ( VIK_LAYER(top)->vt, &(VIK_LAYER(top)->iter), FALSE );
+
+ /* delete anything we've forgotten about -- should only happen when file ends before an EndLayer */
+ g_hash_table_foreach ( string_lists, string_list_delete, NULL );
+ g_hash_table_destroy ( string_lists );
}
/*
#include "icons/viking_icon.png_h"
#include "mapcache.h"
#include "background.h"
+#include "dems.h"
#include "curl_download.h"
#include <string.h>
gdk_threads_leave ();
a_mapcache_uninit ();
+ a_dems_uninit ();
return 0;
}
static void coord_layer_update_gc ( VikCoordLayer *vcl, VikViewport *vp, const gchar *color );
static void coord_layer_post_read ( VikCoordLayer *vcl, VikViewport *vp );
-VikLayerParamScale param_scales[] = {
+static VikLayerParamScale param_scales[] = {
{ 0.05, 60.0, 0.25, 10 },
{ 1, 10, 1, 0 },
};
-VikLayerParam coord_layer_params[] = {
+static VikLayerParam coord_layer_params[] = {
{ "color", VIK_LAYER_PARAM_STRING, VIK_LAYER_GROUP_NONE, "Color:", VIK_LAYER_WIDGET_ENTRY },
{ "min_inc", VIK_LAYER_PARAM_DOUBLE, VIK_LAYER_GROUP_NONE, "Minutes Width:", VIK_LAYER_WIDGET_SPINBUTTON, param_scales + 0 },
{ "line_thickness", VIK_LAYER_PARAM_UINT, VIK_LAYER_GROUP_NONE, "Line Thickness:", VIK_LAYER_WIDGET_SPINBUTTON, param_scales + 1 },
--- /dev/null
+/*
+ * viking -- GPS Data and Topo Analyzer, Explorer, and Manager
+ *
+ * Copyright (C) 2003-2005, Evan Battaglia <gtoevan@gmx.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+#include <math.h>
+
+#include "globals.h"
+#include "coords.h"
+#include "vikcoord.h"
+#include "download.h"
+#include "vikwaypoint.h"
+#include "viktrack.h"
+#include "vikviewport.h"
+#include "viktreeview.h"
+#include "viklayer.h"
+#include "vikaggregatelayer.h"
+#include "viklayerspanel.h"
+#include "vikdemlayer.h"
+#include "vikdemlayer_pixmap.h"
+
+#include "dem.h"
+#include "dems.h"
+
+static VikDEMLayer *dem_layer_copy ( VikDEMLayer *vdl, gpointer vp );
+static void dem_layer_marshall( VikDEMLayer *vdl, guint8 **data, gint *len );
+static VikDEMLayer *dem_layer_unmarshall( guint8 *data, gint len, VikViewport *vvp );
+static gboolean dem_layer_set_param ( VikDEMLayer *vdl, guint16 id, VikLayerParamData data, VikViewport *vp );
+static VikLayerParamData dem_layer_get_param ( VikDEMLayer *vdl, guint16 id );
+static void dem_layer_update_gc ( VikDEMLayer *vdl, VikViewport *vp, const gchar *color );
+static void dem_layer_post_read ( VikDEMLayer *vdl, VikViewport *vp );
+
+static VikLayerParamScale param_scales[] = {
+ { 1, 10000, 10, 1 },
+ { 1, 10, 1, 0 },
+};
+
+static VikLayerParam dem_layer_params[] = {
+ { "files", VIK_LAYER_PARAM_STRING_LIST, VIK_LAYER_GROUP_NONE, "DEM Files:", VIK_LAYER_WIDGET_FILELIST },
+ { "color", VIK_LAYER_PARAM_STRING, VIK_LAYER_GROUP_NONE, "Color:", VIK_LAYER_WIDGET_ENTRY },
+ { "max_elev", VIK_LAYER_PARAM_DOUBLE, VIK_LAYER_GROUP_NONE, "Max Elev:", VIK_LAYER_WIDGET_SPINBUTTON, param_scales + 0 },
+ { "line_thickness", VIK_LAYER_PARAM_UINT, VIK_LAYER_GROUP_NONE, "Line Thickness:", VIK_LAYER_WIDGET_SPINBUTTON, param_scales + 1 },
+};
+
+/*
+*/
+
+
+static gchar *dem_colors[] = {
+"#0000FF",
+"#9b793c",
+"#9c7d40",
+"#9d8144",
+"#9e8549",
+"#9f894d",
+"#a08d51",
+"#a29156",
+"#a3955a",
+"#a4995e",
+"#a69d63",
+"#a89f65",
+"#aaa267",
+"#ada569",
+"#afa76b",
+"#b1aa6d",
+"#b4ad6f",
+"#b6b071",
+"#b9b373",
+"#bcb676",
+"#beb978",
+"#c0bc7a",
+"#c2c07d",
+"#c4c37f",
+"#c6c681",
+"#c8ca84",
+"#cacd86",
+"#ccd188",
+"#cfd58b",
+"#c2ce84",
+"#b5c87e",
+"#a9c278",
+"#9cbb71",
+"#8fb56b",
+"#83af65",
+"#76a95e",
+"#6aa358",
+"#5e9d52",
+"#63a055",
+"#69a458",
+"#6fa85c",
+"#74ac5f",
+"#7ab063",
+"#80b467",
+"#86b86a",
+"#8cbc6e",
+"#92c072",
+"#94c175",
+"#97c278",
+"#9ac47c",
+"#9cc57f",
+"#9fc682",
+"#a2c886",
+"#a4c989",
+"#a7cb8d",
+"#aacd91",
+"#afce99",
+"#b5d0a1",
+"#bbd2aa",
+"#c0d3b2",
+"#c6d5ba",
+"#ccd7c3",
+"#d1d9cb",
+"#d7dbd4",
+"#DDDDDD",
+"#e0e0e0",
+"#e4e4e4",
+"#e8e8e8",
+"#ebebeb",
+"#efefef",
+"#f3f3f3",
+"#f7f7f7",
+"#fbfbfb",
+"#ffffff"
+};
+
+/*
+"#9b793c",
+"#9e8549",
+"#a29156",
+"#a69d63",
+"#ada569",
+"#b4ad6f",
+"#bcb676",
+"#c2c07d",
+"#c8ca84",
+"#cfd58b",
+"#a9c278",
+"#83af65",
+"#5e9d52",
+"#6fa85c",
+"#80b467",
+"#92c072",
+"#9ac47c",
+"#a2c886",
+"#aacd91",
+"#bbd2aa",
+"#ccd7c3",
+"#DDDDDD",
+"#e8e8e8",
+"#f3f3f3",
+"#FFFFFF"
+};
+*/
+
+static const guint dem_n_colors = sizeof(dem_colors)/sizeof(dem_colors[0]);
+
+enum { PARAM_FILES=0, PARAM_COLOR, PARAM_MAX_ELEV, PARAM_LINE_THICKNESS, NUM_PARAMS };
+
+VikLayerInterface vik_dem_layer_interface = {
+ "DEM",
+ &demlayer_pixbuf,
+
+ NULL,
+ 0,
+
+ dem_layer_params,
+ NUM_PARAMS,
+ NULL,
+ 0,
+
+ VIK_MENU_ITEM_ALL,
+
+ (VikLayerFuncCreate) vik_dem_layer_create,
+ (VikLayerFuncRealize) NULL,
+ (VikLayerFuncPostRead) dem_layer_post_read,
+ (VikLayerFuncFree) vik_dem_layer_free,
+
+ (VikLayerFuncProperties) NULL,
+ (VikLayerFuncDraw) vik_dem_layer_draw,
+ (VikLayerFuncChangeCoordMode) NULL,
+
+ (VikLayerFuncSetMenuItemsSelection) NULL,
+ (VikLayerFuncGetMenuItemsSelection) NULL,
+
+ (VikLayerFuncAddMenuItems) NULL,
+ (VikLayerFuncSublayerAddMenuItems) NULL,
+
+ (VikLayerFuncSublayerRenameRequest) NULL,
+ (VikLayerFuncSublayerToggleVisible) NULL,
+
+ (VikLayerFuncCopy) dem_layer_copy,
+ (VikLayerFuncMarshall) dem_layer_marshall,
+ (VikLayerFuncUnmarshall) dem_layer_unmarshall,
+
+ (VikLayerFuncSetParam) dem_layer_set_param,
+ (VikLayerFuncGetParam) dem_layer_get_param,
+
+ (VikLayerFuncReadFileData) NULL,
+ (VikLayerFuncWriteFileData) NULL,
+
+ (VikLayerFuncDeleteItem) NULL,
+ (VikLayerFuncCopyItem) NULL,
+ (VikLayerFuncPasteItem) NULL,
+ (VikLayerFuncFreeCopiedItem) NULL,
+ (VikLayerFuncDragDropRequest) NULL,
+};
+
+struct _VikDEMLayer {
+ VikLayer vl;
+ GdkGC *gc;
+ GdkGC **gcs;
+ GList *files;
+ gdouble max_elev;
+ guint8 line_thickness;
+ gchar *color;
+};
+
+GType vik_dem_layer_get_type ()
+{
+ static GType vdl_type = 0;
+
+ if (!vdl_type)
+ {
+ static const GTypeInfo vdl_info =
+ {
+ sizeof (VikDEMLayerClass),
+ NULL, /* base_init */
+ NULL, /* base_finalize */
+ NULL, /* class init */
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ sizeof (VikDEMLayer),
+ 0,
+ NULL /* instance init */
+ };
+ vdl_type = g_type_register_static ( VIK_LAYER_TYPE, "VikDEMLayer", &vdl_info, 0 );
+ }
+
+ return vdl_type;
+}
+
+static VikDEMLayer *dem_layer_copy ( VikDEMLayer *vdl, gpointer vp )
+{
+ VikDEMLayer *rv = vik_dem_layer_new ( );
+
+
+ /* TODO -- FIX for files */
+
+ rv->color = g_strdup ( vdl->color );
+ rv->max_elev = vdl->max_elev;
+ rv->line_thickness = vdl->line_thickness;
+ rv->gc = vdl->gc;
+ g_object_ref ( rv->gc );
+ return rv;
+}
+
+static void dem_layer_marshall( VikDEMLayer *vdl, guint8 **data, gint *len )
+{
+ vik_layer_marshall_params ( VIK_LAYER(vdl), data, len );
+}
+
+static VikDEMLayer *dem_layer_unmarshall( guint8 *data, gint len, VikViewport *vvp )
+{
+ VikDEMLayer *rv = vik_dem_layer_new ( vvp );
+ vik_layer_unmarshall_params ( VIK_LAYER(rv), data, len, vvp );
+ return rv;
+}
+
+gboolean dem_layer_set_param ( VikDEMLayer *vdl, guint16 id, VikLayerParamData data, VikViewport *vp )
+{
+ switch ( id )
+ {
+ case PARAM_COLOR: if ( vdl->color ) g_free ( vdl->color ); vdl->color = g_strdup ( data.s ); break;
+ case PARAM_MAX_ELEV: vdl->max_elev = data.d; break;
+ case PARAM_LINE_THICKNESS: if ( data.u >= 1 && data.u <= 15 ) vdl->line_thickness = data.u; break;
+ case PARAM_FILES: a_dems_load_list ( &(data.sl) ); a_dems_list_free ( vdl->files ); vdl->files = data.sl; break;
+ }
+ return TRUE;
+}
+
+static VikLayerParamData dem_layer_get_param ( VikDEMLayer *vdl, guint16 id )
+{
+ VikLayerParamData rv;
+ switch ( id )
+ {
+ case PARAM_FILES: rv.sl = vdl->files; break;
+ case PARAM_COLOR: rv.s = vdl->color ? vdl->color : ""; break;
+ case PARAM_MAX_ELEV: rv.d = vdl->max_elev; break;
+ case PARAM_LINE_THICKNESS: rv.i = vdl->line_thickness; break;
+ }
+ return rv;
+}
+
+static void dem_layer_post_read ( VikDEMLayer *vdl, VikViewport *vp )
+{
+ if ( vdl->gc )
+ g_object_unref ( G_OBJECT(vdl->gc) );
+
+ vdl->gc = vik_viewport_new_gc ( vp, vdl->color, vdl->line_thickness );
+}
+
+VikDEMLayer *vik_dem_layer_new ( )
+{
+ VikDEMLayer *vdl = VIK_DEM_LAYER ( g_object_new ( VIK_DEM_LAYER_TYPE, NULL ) );
+ vik_layer_init ( VIK_LAYER(vdl), VIK_LAYER_DEM );
+
+ vdl->files = NULL;
+
+
+ vdl->gc = NULL;
+
+ vdl->gcs = g_malloc(sizeof(GdkGC *)*dem_n_colors);
+
+ vdl->max_elev = 1000.0;
+ vdl->line_thickness = 3;
+ vdl->color = NULL;
+ return vdl;
+}
+
+
+static void vik_dem_layer_draw_dem ( VikDEMLayer *vdl, VikViewport *vp, VikDEM *dem )
+{
+ VikCoord tleft, tright, bleft, bright;
+ VikDEMColumn *column;
+
+ struct LatLon dem_northeast, dem_southwest;
+ gdouble max_lat, max_lon, min_lat, min_lon;
+
+
+ /**** Check if viewport and DEM data overlap ****/
+
+ /* get min, max lat/lon of viewport */
+ vik_viewport_screen_to_coord ( vp, 0, 0, &tleft );
+ vik_viewport_screen_to_coord ( vp, vik_viewport_get_width(vp), 0, &tright );
+ vik_viewport_screen_to_coord ( vp, 0, vik_viewport_get_height(vp), &bleft );
+ vik_viewport_screen_to_coord ( vp, vik_viewport_get_width(vp), vik_viewport_get_height(vp), &bright );
+
+ vik_coord_convert(&tleft, VIK_COORD_LATLON);
+ vik_coord_convert(&tright, VIK_COORD_LATLON);
+ vik_coord_convert(&bleft, VIK_COORD_LATLON);
+ vik_coord_convert(&bright, VIK_COORD_LATLON);
+
+ max_lat = MAX(tleft.north_south, tright.north_south);
+ min_lat = MIN(bleft.north_south, bright.north_south);
+ max_lon = MAX(tright.east_west, bright.east_west);
+ min_lon = MIN(tleft.east_west, bleft.east_west);
+
+ /* get min, max lat/lon of DEM data */
+ if ( dem->horiz_units == VIK_DEM_HORIZ_LL_ARCSECONDS ) {
+ dem_northeast.lat = dem->max_north / 3600.0;
+ dem_northeast.lon = dem->max_east / 3600.0;
+ dem_southwest.lat = dem->min_north / 3600.0;
+ dem_southwest.lon = dem->min_east / 3600.0;
+ } else if ( dem->horiz_units == VIK_DEM_HORIZ_UTM_METERS ) {
+ struct UTM dem_northeast_utm, dem_southwest_utm;
+ dem_northeast_utm.northing = dem->max_north;
+ dem_northeast_utm.easting = dem->max_east;
+ dem_southwest_utm.northing = dem->min_north;
+ dem_southwest_utm.easting = dem->min_east;
+ dem_northeast_utm.zone = dem_southwest_utm.zone = dem->utm_zone;
+ dem_northeast_utm.letter = dem_southwest_utm.letter = dem->utm_letter;
+
+ a_coords_utm_to_latlon(&dem_northeast_utm, &dem_northeast);
+ a_coords_utm_to_latlon(&dem_southwest_utm, &dem_southwest);
+ }
+
+ if ( (max_lat > dem_northeast.lat && min_lat > dem_northeast.lat) ||
+ (max_lat < dem_southwest.lat && min_lat < dem_southwest.lat) )
+ return;
+ else if ( (max_lon > dem_northeast.lon && min_lon > dem_northeast.lon) ||
+ (max_lon < dem_southwest.lon && min_lon < dem_southwest.lon) )
+ return;
+ /* else they overlap */
+
+ /**** End Overlap Check ****/
+
+ if ( dem->horiz_units == VIK_DEM_HORIZ_LL_ARCSECONDS ) {
+ VikCoord tmp; /* TODO: don't use coord_load_from_latlon, especially if in latlon drawing mode */
+
+ gdouble max_lat_as, max_lon_as, min_lat_as, min_lon_as;
+ gdouble start_lat_as, end_lat_as, start_lon_as, end_lon_as;
+
+ gdouble start_lat, end_lat, start_lon, end_lon;
+
+ struct LatLon counter;
+
+ guint x, y, start_x, start_y;
+
+ gint16 elev;
+
+ guint skip_factor = ceil ( vik_viewport_get_xmpp(vp) / 40 ); /* todo: smarter calculation. */
+
+ gdouble nscale_deg = dem->north_scale / ((gdouble) 3600);
+ gdouble escale_deg = dem->east_scale / ((gdouble) 3600);
+
+ max_lat_as = max_lat * 3600;
+ min_lat_as = min_lat * 3600;
+ max_lon_as = max_lon * 3600;
+ min_lon_as = min_lon * 3600;
+
+ start_lat_as = MAX(min_lat_as, dem->min_north);
+ end_lat_as = MIN(max_lat_as, dem->max_north);
+ start_lon_as = MAX(min_lon_as, dem->min_east);
+ end_lon_as = MIN(max_lon_as, dem->max_east);
+
+ start_lat = floor(start_lat_as / dem->north_scale) * nscale_deg;
+ end_lat = ceil (end_lat_as / dem->north_scale) * nscale_deg;
+ start_lon = floor(start_lon_as / dem->east_scale) * escale_deg;
+ end_lon = ceil (end_lon_as / dem->east_scale) * escale_deg;
+
+ vik_dem_east_north_to_xy ( dem, start_lon_as, start_lat_as, &start_x, &start_y );
+
+ for ( x=start_x, counter.lon = start_lon; counter.lon <= end_lon; counter.lon += escale_deg * skip_factor, x += skip_factor ) {
+ if ( x > 0 && x < dem->n_columns ) {
+ column = g_ptr_array_index ( dem->columns, x );
+ for ( y=start_y, counter.lat = start_lat; counter.lat <= end_lat; counter.lat += nscale_deg * skip_factor, y += skip_factor ) {
+ if ( y > column->n_points )
+ break;
+ elev = column->points[y];
+ if ( elev > vdl->max_elev ) elev=vdl->max_elev;
+ {
+ gint a, b;
+
+ vik_coord_load_from_latlon(&tmp, vik_viewport_get_coord_mode(vp), &counter);
+ vik_viewport_coord_to_screen(vp, &tmp, &a, &b);
+ if ( elev == VIK_DEM_INVALID_ELEVATION )
+ ; /* don't draw it */
+ else if ( elev <= 0 )
+ vik_viewport_draw_rectangle(vp, vdl->gcs[0], TRUE, a-2, b-2, 4, 4 );
+ else
+ vik_viewport_draw_rectangle(vp, vdl->gcs[(gint)floor(elev/vdl->max_elev*(dem_n_colors-2))+1], TRUE, a-2, b-2, 4, 4 );
+ }
+ } /* for y= */
+ }
+ } /* for x= */
+ } else if ( dem->horiz_units == VIK_DEM_HORIZ_UTM_METERS ) {
+ gdouble max_nor, max_eas, min_nor, min_eas;
+ gdouble start_nor, start_eas, end_nor, end_eas;
+
+ gint16 elev;
+
+ guint x, y, start_x, start_y;
+
+ VikCoord tmp; /* TODO: don't use coord_load_from_latlon, especially if in latlon drawing mode */
+ struct UTM counter;
+
+ guint skip_factor = ceil ( vik_viewport_get_xmpp(vp) / 10 ); /* todo: smarter calculation. */
+
+ vik_coord_convert(&tleft, VIK_COORD_UTM);
+ vik_coord_convert(&tright, VIK_COORD_UTM);
+ vik_coord_convert(&bleft, VIK_COORD_UTM);
+ vik_coord_convert(&bright, VIK_COORD_UTM);
+
+ max_nor = MAX(tleft.north_south, tright.north_south);
+ min_nor = MIN(bleft.north_south, bright.north_south);
+ max_eas = MAX(bright.east_west, tright.east_west);
+ min_eas = MIN(bleft.east_west, tleft.east_west);
+
+ start_nor = MAX(min_nor, dem->min_north);
+ end_nor = MIN(max_nor, dem->max_north);
+ if ( tleft.utm_zone == dem->utm_zone && bleft.utm_zone == dem->utm_zone
+ && (tleft.utm_letter >= 'N') == (dem->utm_letter >= 'N')
+ && (bleft.utm_letter >= 'N') == (dem->utm_letter >= 'N') ) /* if the utm zones/hemispheres are different, min_eas will be bogus */
+ start_eas = MAX(min_eas, dem->min_east);
+ else
+ start_eas = dem->min_east;
+ if ( tright.utm_zone == dem->utm_zone && bright.utm_zone == dem->utm_zone
+ && (tright.utm_letter >= 'N') == (dem->utm_letter >= 'N')
+ && (bright.utm_letter >= 'N') == (dem->utm_letter >= 'N') ) /* if the utm zones/hemispheres are different, min_eas will be bogus */
+ end_eas = MIN(max_eas, dem->max_east);
+ else
+ end_eas = dem->max_east;
+
+ start_nor = floor(start_nor / dem->north_scale) * dem->north_scale;
+ end_nor = ceil (end_nor / dem->north_scale) * dem->north_scale;
+ start_eas = floor(start_eas / dem->east_scale) * dem->east_scale;
+ end_eas = ceil (end_eas / dem->east_scale) * dem->east_scale;
+
+ vik_dem_east_north_to_xy ( dem, start_eas, start_nor, &start_x, &start_y );
+
+ /* TODO: why start_x and start_y are -1 -- rounding error from above? */
+
+ counter.zone = dem->utm_zone;
+ counter.letter = dem->utm_letter;
+
+ for ( x=start_x, counter.easting = start_eas; counter.easting <= end_eas; counter.easting += dem->east_scale * skip_factor, x += skip_factor ) {
+ if ( x > 0 && x < dem->n_columns ) {
+ column = g_ptr_array_index ( dem->columns, x );
+ for ( y=start_y, counter.northing = start_nor; counter.northing <= end_nor; counter.northing += dem->north_scale * skip_factor, y += skip_factor ) {
+ if ( y > column->n_points )
+ continue;
+ elev = column->points[y];
+ if ( elev > vdl->max_elev ) elev=vdl->max_elev;
+ {
+ gint a, b;
+ vik_coord_load_from_utm(&tmp, vik_viewport_get_coord_mode(vp), &counter);
+ vik_viewport_coord_to_screen(vp, &tmp, &a, &b);
+ if ( elev == VIK_DEM_INVALID_ELEVATION )
+ ; /* don't draw it */
+ else if ( elev <= 0 )
+ vik_viewport_draw_rectangle(vp, vdl->gcs[0], TRUE, a-2, b-2, 4, 4 );
+ else
+ vik_viewport_draw_rectangle(vp, vdl->gcs[(gint)floor(elev/vdl->max_elev*(dem_n_colors-2))+1], TRUE, a-2, b-2, 4, 4 );
+ }
+ } /* for y= */
+ }
+ } /* for x= */
+ }
+}
+
+void vik_dem_layer_draw ( VikDEMLayer *vdl, gpointer data )
+{
+ VikViewport *vp = (VikViewport *) data;
+ GList *dems_iter = vdl->files;
+ VikDEM *dem;
+ while ( dems_iter ) {
+ dem = a_dems_get ( (const char *) (dems_iter->data) );
+ if ( dem )
+ vik_dem_layer_draw_dem ( vdl, vp, dem );
+ dems_iter = dems_iter->next;
+ }
+}
+
+void vik_dem_layer_free ( VikDEMLayer *vdl )
+{
+ if ( vdl->gc != NULL )
+ g_object_unref ( G_OBJECT(vdl->gc) );
+
+ if ( vdl->color != NULL )
+ g_free ( vdl->color );
+
+ a_dems_list_free ( vdl->files );
+}
+
+static void dem_layer_update_gc ( VikDEMLayer *vdl, VikViewport *vp, const gchar *color )
+{
+ guint i;
+
+ if ( vdl->color )
+ g_free ( vdl->color );
+
+ vdl->color = g_strdup ( color );
+
+ if ( vdl->gc )
+ g_object_unref ( G_OBJECT(vdl->gc) );
+
+ vdl->gc = vik_viewport_new_gc ( vp, vdl->color, vdl->line_thickness );
+
+ for ( i = 0 ; i < dem_n_colors; i++ )
+ vdl->gcs[i] = vik_viewport_new_gc ( vp, dem_colors[i], vdl->line_thickness );
+
+}
+
+VikDEMLayer *vik_dem_layer_create ( VikViewport *vp )
+{
+ VikDEMLayer *vdl = vik_dem_layer_new ();
+ dem_layer_update_gc ( vdl, vp, "red" );
+ return vdl;
+}
+
--- /dev/null
+/*
+ * viking -- GPS Data and Topo Analyzer, Explorer, and Manager
+ *
+ * Copyright (C) 2003-2005, Evan Battaglia <gtoevan@gmx.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#ifndef _VIKING_DEMLAYER_H
+#define _VIKING_DEMLAYER_H
+
+#include "viklayer.h"
+
+#define VIK_DEM_LAYER_TYPE (vik_dem_layer_get_type ())
+#define VIK_DEM_LAYER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), VIK_DEM_LAYER_TYPE, VikDEMLayer))
+#define VIK_DEM_LAYER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), VIK_DEM_LAYER_TYPE, VikDEMLayerClass))
+#define IS_VIK_DEM_LAYER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), VIK_DEM_LAYER_TYPE))
+#define IS_VIK_DEM_LAYER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), VIK_DEM_LAYER_TYPE))
+
+typedef struct _VikDEMLayerClass VikDEMLayerClass;
+struct _VikDEMLayerClass
+{
+ VikLayerClass object_class;
+};
+
+GType vik_dem_layer_get_type ();
+
+typedef struct _VikDEMLayer VikDEMLayer;
+
+/* TODO 0.0.8: yup, everything goes. */
+
+VikDEMLayer *vik_dem_layer_new ( );
+void vik_dem_layer_draw ( VikDEMLayer *vcl, gpointer data );
+void vik_dem_layer_free ( VikDEMLayer *vcl );
+
+VikDEMLayer *vik_dem_layer_create ( VikViewport *vp );
+gboolean vik_dem_layer_properties ( VikDEMLayer *vcl, gpointer vp );
+
+
+#endif
--- /dev/null
+/* GdkPixbuf RGB C-Source image dump 1-byte-run-length-encoded */
+
+static const GdkPixdata demlayer_pixbuf = {
+ 0x47646b50, /* Pixbuf magic: 'GdkP' */
+ 24 + 132, /* header length + pixel_data length */
+ 0x2010001, /* pixdata_type */
+ 48, /* rowstride */
+ 16, /* width */
+ 16, /* height */
+ /* pixel_data: */
+ "\233\377\377\377\1\307\353\361\217\377\377\377\202\201\322\341\215\377"
+ "\377\377\203m\306\377\214\377\377\377\205L*\340\207\377\377\377\1!\12"
+ "\203\203\377\377\377\205!\12\203\207\377\377\377\1\12T\203\202\377\377"
+ "\377\210\12T\203\204\377\377\377\203\12\203s\1\377\377\377\210\12\203"
+ "s\203\377\377\377\215\12\203\36\202\377\377\377\216)\265\33\202\377\377"
+ "\377\216Y\265\33\1\377\377\377\217\213\265\33\1\377\377\377\217\250\265"
+ "\33\220\265\226\33\220\313S\36\220\207\25\25",
+};
+
+
--- /dev/null
+/*
+ * viking -- GPS Data and Topo Analyzer, Explorer, and Manager
+ *
+ * Copyright (C) 2003-2005, Evan Battaglia <gtoevan@gmx.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <gtk/gtk.h>
+
+#include "vikfilelist.h"
+#include "vikfileentry.h"
+
+struct _VikFileList {
+ GtkVBox parent;
+ VikFileEntry *file_entry;
+ GtkWidget *treeview;
+ GtkTreeModel *model;
+};
+
+static void file_list_add ( VikFileList *vfl )
+{
+ GtkTreeIter iter;
+ gtk_list_store_append ( GTK_LIST_STORE(vfl->model), &iter );
+ gtk_list_store_set ( GTK_LIST_STORE(vfl->model), &iter, 0, vik_file_entry_get_filename(vfl->file_entry), -1 );
+}
+
+static void file_list_del ( VikFileList *vfl )
+{
+ GtkTreeSelection *ts = gtk_tree_view_get_selection (GTK_TREE_VIEW(vfl->treeview));
+ GtkTreeIter iter;
+ if ( gtk_tree_selection_get_selected(ts, NULL, &iter) )
+ gtk_list_store_remove(GTK_LIST_STORE(vfl->model), &iter);
+}
+
+GType vik_file_list_get_type (void)
+{
+ static GType vs_type = 0;
+
+ if (!vs_type)
+ {
+ static const GTypeInfo vs_info =
+ {
+ sizeof (VikFileListClass),
+ NULL, /* base_init */
+ NULL, /* base_finalize */
+ NULL, /* class init */
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ sizeof (VikFileList),
+ 0,
+ NULL /* instance init */
+ };
+ vs_type = g_type_register_static ( GTK_TYPE_VBOX, "VikFileList", &vs_info, 0 );
+ }
+
+ return vs_type;
+}
+
+GtkWidget *vik_file_list_new ( const gchar *title )
+{
+ GtkWidget *add_btn, *del_btn;
+ GtkWidget *hbox, *scrolledwindow;
+ VikFileList *vfl = VIK_FILE_LIST ( g_object_new ( VIK_FILE_LIST_TYPE, NULL ) );
+
+ GtkTreeViewColumn *column;
+
+ vfl->model = GTK_TREE_MODEL ( gtk_list_store_new(1, G_TYPE_STRING) );
+
+ vfl->treeview = gtk_tree_view_new ( );
+ gtk_tree_view_set_model ( GTK_TREE_VIEW(vfl->treeview), vfl->model );
+ column = gtk_tree_view_column_new_with_attributes ( title, gtk_cell_renderer_text_new (), "text", 0, NULL);
+ gtk_tree_view_append_column (GTK_TREE_VIEW (vfl->treeview), column);
+
+ gtk_widget_set_size_request ( vfl->treeview, 200, 100);
+
+ vfl->file_entry = VIK_FILE_ENTRY(vik_file_entry_new());
+ add_btn = gtk_button_new_with_label("Add");
+ del_btn = gtk_button_new_with_label("Delete");
+
+ g_signal_connect_swapped ( G_OBJECT(add_btn), "clicked", G_CALLBACK(file_list_add), vfl );
+ g_signal_connect_swapped ( G_OBJECT(del_btn), "clicked", G_CALLBACK(file_list_del), vfl );
+
+ hbox = gtk_hbox_new(FALSE, 2);
+
+ scrolledwindow = gtk_scrolled_window_new ( NULL, NULL );
+ gtk_scrolled_window_set_policy ( GTK_SCROLLED_WINDOW(scrolledwindow), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC );
+ gtk_container_add ( GTK_CONTAINER(scrolledwindow), GTK_WIDGET(vfl->treeview) );
+
+ gtk_box_pack_start ( GTK_BOX(vfl), scrolledwindow, TRUE, TRUE, 3 );
+
+
+ gtk_box_pack_start ( GTK_BOX(hbox), GTK_WIDGET(vfl->file_entry), TRUE, TRUE, 3 );
+ gtk_box_pack_start ( GTK_BOX(hbox), add_btn, TRUE, TRUE, 3 );
+ gtk_box_pack_start ( GTK_BOX(hbox), del_btn, TRUE, TRUE, 3 );
+ gtk_box_pack_start ( GTK_BOX(vfl), hbox, FALSE, FALSE, 3 );
+ gtk_widget_show_all(GTK_WIDGET(vfl));
+
+
+ return GTK_WIDGET(vfl);
+}
+
+static gboolean get_file_name(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, GList **list)
+{
+ gchar *str;
+ gtk_tree_model_get ( model, iter, 0, &str, -1 );
+ printf("%s\n\n\n", str);
+ (*list) = g_list_append((*list), g_strdup(str));
+ return FALSE;
+}
+
+GList *vik_file_list_get_files ( VikFileList *vfl )
+{
+ GList *list = NULL;
+ gtk_tree_model_foreach (vfl->model, (GtkTreeModelForeachFunc) get_file_name, &list);
+ return list;
+}
+
+void vik_file_list_set_files ( VikFileList *vfl, GList *files )
+{
+ while (files) {
+ GtkTreeIter iter;
+ gtk_list_store_append ( GTK_LIST_STORE(vfl->model), &iter );
+ gtk_list_store_set ( GTK_LIST_STORE(vfl->model), &iter, 0, files->data, -1 );
+ files = files->next;
+ }
+}
--- /dev/null
+/*
+ * viking -- GPS Data and Topo Analyzer, Explorer, and Manager
+ *
+ * Copyright (C) 2003-2005, Evan Battaglia <gtoevan@gmx.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#ifndef _VIKING_FILELIST_H
+#define _VIKING_FILELIST_H
+
+#include <glib.h>
+#include <glib-object.h>
+#include <gtk/gtkvbox.h>
+
+G_BEGIN_DECLS
+
+#define VIK_FILE_LIST_TYPE (vik_file_list_get_type ())
+#define VIK_FILE_LIST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), VIK_FILE_LIST_TYPE, VikFileList))
+#define VIK_FILE_LIST_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), VIK_FILE_LIST_TYPE, VikFileListClass))
+#define IS_VIK_FILE_LIST(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), VIK_FILE_LIST_TYPE))
+#define IS_VIK_FILE_LIST_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), VIK_FILE_LIST_TYPE))
+
+typedef struct _VikFileList VikFileList;
+typedef struct _VikFileListClass VikFileListClass;
+
+struct _VikFileListClass
+{
+ GtkVBoxClass vbox_class;
+};
+
+GType vik_file_list_get_type ();
+
+GtkWidget *vik_file_list_new ( const gchar *title );
+/* result must be freed */
+GList *vik_file_list_get_files ( VikFileList *vfl );
+void vik_file_list_set_files ( VikFileList *vfl, GList * );
+
+#endif
#include "viking.h"
#include "vikradiogroup.h"
+#include "vikfilelist.h"
#include <string.h>
/* functions common to all layers. */
extern VikLayerInterface vik_coord_layer_interface;
extern VikLayerInterface vik_georef_layer_interface;
extern VikLayerInterface vik_gps_layer_interface;
+extern VikLayerInterface vik_dem_layer_interface;
enum {
VL_UPDATE_SIGNAL,
&vik_georef_layer_interface,
&vik_gps_layer_interface,
&vik_maps_layer_interface,
+ &vik_dem_layer_interface,
};
VikLayerInterface *vik_layer_get_interface ( gint type )
}
break;
case VIK_LAYER_WIDGET_COMBOBOX:
+#ifndef GTK_2_2
if ( param->type == VIK_LAYER_PARAM_UINT && param->widget_data )
{
gchar **pstr = param->widget_data;
gtk_combo_box_set_active ( GTK_COMBO_BOX ( rv ), data.u );
}
break;
+#endif
case VIK_LAYER_WIDGET_RADIOGROUP:
/* widget_data and extra_widget_data are GList */
if ( param->type == VIK_LAYER_PARAM_UINT && param->widget_data )
vik_file_entry_set_filename ( VIK_FILE_ENTRY(rv), data.s );
}
break;
+ case VIK_LAYER_WIDGET_FILELIST:
+ if ( param->type == VIK_LAYER_PARAM_STRING_LIST )
+ {
+ rv = vik_file_list_new ( param->title );
+ vik_file_list_set_files ( VIK_FILE_LIST(rv), data.sl );
+ }
+ break;
case VIK_LAYER_WIDGET_HSCALE:
if ( (param->type == VIK_LAYER_PARAM_DOUBLE || param->type == VIK_LAYER_PARAM_UINT
|| param->type == VIK_LAYER_PARAM_INT) && param->widget_data )
rv.b = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
break;
case VIK_LAYER_WIDGET_COMBOBOX:
+#ifndef GTK_2_2
rv.i = gtk_combo_box_get_active ( GTK_COMBO_BOX(widget) );
if ( rv.i == -1 ) rv.i = 0;
rv.u = rv.i;
if ( param->extra_widget_data )
rv.u = ((guint *)param->extra_widget_data)[rv.u];
break;
+#endif
case VIK_LAYER_WIDGET_RADIOGROUP:
rv.u = vik_radio_group_get_selected(VIK_RADIO_GROUP(widget));
if ( param->extra_widget_data )
case VIK_LAYER_WIDGET_FILEENTRY:
rv.s = vik_file_entry_get_filename ( VIK_FILE_ENTRY(widget) );
break;
+ case VIK_LAYER_WIDGET_FILELIST:
+ rv.sl = vik_file_list_get_files ( VIK_FILE_LIST(widget) );
+ break;
case VIK_LAYER_WIDGET_HSCALE:
if ( param->type == VIK_LAYER_PARAM_UINT )
rv.u = (guint32) gtk_range_get_value ( GTK_RANGE(widget) );
VIK_LAYER_GEOREF,
VIK_LAYER_GPS,
VIK_LAYER_MAPS,
+ VIK_LAYER_DEM,
VIK_LAYER_NUM_TYPES
};
gboolean b;
const gchar *s;
GdkColor c;
+ GList *sl;
} VikLayerParamData;
typedef struct {
VIK_LAYER_WIDGET_HSCALE,
VIK_LAYER_WIDGET_COLOR,
VIK_LAYER_WIDGET_COMBOBOX,
+VIK_LAYER_WIDGET_FILELIST,
};
typedef struct {
VIK_LAYER_PARAM_STRING,
VIK_LAYER_PARAM_BOOLEAN,
VIK_LAYER_PARAM_COLOR,
+
+/* NOTE: string layer works auniquely: data.sl should NOT be free'd when
+ * the internals call get_param -- i.e. it should be managed w/in the layer.
+ * The value passed by the internals into set_param should also be managed
+ * by the layer -- i.e. free'd by the layer.
+ */
+
+VIK_LAYER_PARAM_STRING_LIST,
};
/* layer interface functions */
#include "vikcoord.h"
#include "viktrack.h"
#include "globals.h"
+#include "dems.h"
VikTrack *vik_track_new()
{
}
return new_tr;
}
+
+void vik_track_apply_dem_data ( VikTrack *tr, GList *dems )
+{
+ GList *tp_iter;
+ gint16 elev;
+ if ( ! dems )
+ return;
+ tp_iter = tr->trackpoints;
+ while ( tp_iter ) {
+ /* TODO: of the 4 possible choices we have for choosing an elevation
+ * (trackpoint in between samples), choose the one with the least elevation change
+ * as the last */
+ elev = a_dems_list_get_elev_by_coord ( dems, &(VIK_TRACKPOINT(tp_iter->data)->coord) );
+ if ( elev != VIK_DEM_INVALID_ELEVATION )
+ VIK_TRACKPOINT(tp_iter->data)->altitude = elev;
+ tp_iter = tp_iter->next;
+ }
+}
void vik_track_marshall ( VikTrack *tr, guint8 **data, guint *len);
VikTrack *vik_track_unmarshall (guint8 *data, guint datalen);
+void vik_track_apply_dem_data ( VikTrack *tr, GList *dems );
+
+
#endif
#include "background.h"
#include "gpx.h"
#include "babel.h"
+#include "dem.h"
+#include "dems.h"
+
#include <math.h>
#include <string.h>
gboolean has_verified_thumbnails;
+ /* DEM files */
+ GList *dems;
+
GtkMenu *wp_right_click_menu;
/* menu */
/****** PARAMETERS ******/
-static gchar *params_groups[] = { "Waypoints", "Tracks", "Waypoint Images" };
-enum { GROUP_WAYPOINTS, GROUP_TRACKS, GROUP_IMAGES };
+static gchar *params_groups[] = { "Waypoints", "Tracks", "Waypoint Images", "DEM Data" };
+enum { GROUP_WAYPOINTS, GROUP_TRACKS, GROUP_IMAGES, GROUP_DEM };
static gchar *params_drawmodes[] = { "Draw by Track", "Draw by Velocity", "All Tracks Black", 0 };
static gchar *params_wpsymbols[] = { "Filled Square", "Square", "Circle", "X", 0 };
{ "image_size", VIK_LAYER_PARAM_UINT, GROUP_IMAGES, "Image Size (pixels):", VIK_LAYER_WIDGET_HSCALE, params_scales + 3 },
{ "image_alpha", VIK_LAYER_PARAM_UINT, GROUP_IMAGES, "Image Alpha:", VIK_LAYER_WIDGET_HSCALE, params_scales + 4 },
{ "image_cache_size", VIK_LAYER_PARAM_UINT, GROUP_IMAGES, "Image Memory Cache Size:", VIK_LAYER_WIDGET_HSCALE, params_scales + 5 },
+
+ { "dems", VIK_LAYER_PARAM_STRING_LIST, GROUP_DEM, "DEM Files:", VIK_LAYER_WIDGET_FILELIST },
};
-enum { PARAM_TV, PARAM_WV, PARAM_DM, PARAM_DL, PARAM_DP, PARAM_DE, PARAM_EF, PARAM_DS, PARAM_SL, PARAM_LT, PARAM_BLT, PARAM_TBGC, PARAM_VMIN, PARAM_VMAX, PARAM_DLA, PARAM_WPC, PARAM_WPTC, PARAM_WPBC, PARAM_WPBA, PARAM_WPSYM, PARAM_WPSIZE, PARAM_WPSYMS, PARAM_DI, PARAM_IS, PARAM_IA, PARAM_ICS, NUM_PARAMS };
+enum { PARAM_TV, PARAM_WV, PARAM_DM, PARAM_DL, PARAM_DP, PARAM_DE, PARAM_EF, PARAM_DS, PARAM_SL, PARAM_LT, PARAM_BLT, PARAM_TBGC, PARAM_VMIN, PARAM_VMAX, PARAM_DLA, PARAM_WPC, PARAM_WPTC, PARAM_WPBC, PARAM_WPBA, PARAM_WPSYM, PARAM_WPSIZE, PARAM_WPSYMS, PARAM_DI, PARAM_IS, PARAM_IA, PARAM_ICS, PARAM_DEMS, NUM_PARAMS };
+
+/*** TO ADD A PARAM:
+ *** 1) Add to trw_layer_params and enumeration
+ *** 2) Handle in get_param & set_param (presumably adding on to VikTrwLayer struct)
+ *** 3) Add code to copy_layer, free, and new (try searching for ->dems)
+ ***/
/****** END PARAMETERS ******/
case PARAM_WPSYM: if ( data.u < WP_NUM_SYMBOLS ) vtl->wp_symbol = data.u; break;
case PARAM_WPSIZE: if ( data.u > 0 && data.u <= 64 ) vtl->wp_size = data.u; break;
case PARAM_WPSYMS: vtl->wp_draw_symbols = data.b; break;
+ case PARAM_DEMS: a_dems_load_list ( &(data.sl) ); a_dems_list_free ( vtl->dems ); vtl->dems = data.sl; break;
}
return TRUE;
}
case PARAM_WPSYM: rv.u = vtl->wp_symbol; break;
case PARAM_WPSIZE: rv.u = vtl->wp_size; break;
case PARAM_WPSYMS: rv.b = vtl->wp_draw_symbols; break;
+ case PARAM_DEMS: rv.sl = vtl->dems; break;
}
return rv;
}
g_hash_table_foreach ( vtl->waypoints, (GHFunc) waypoint_copy, rv->waypoints );
g_hash_table_foreach ( vtl->tracks, (GHFunc) track_copy, rv->tracks );
+ rv->dems = a_dems_list_copy ( vtl->dems );
+
return rv;
}
rv->tracks_iters = g_hash_table_new_full ( g_str_hash, g_str_equal, NULL, g_free );
rv->waypoints_iters = g_hash_table_new_full ( g_str_hash, g_str_equal, NULL, g_free );
+ rv->dems = NULL;
+
/* TODO: constants at top */
rv->waypoints_visible = rv->tracks_visible = TRUE;
rv->drawmode = drawmode;
g_hash_table_destroy(trwlayer->waypoints);
g_hash_table_destroy(trwlayer->tracks);
+ a_dems_list_free ( trwlayer->dems );
+
/* ODC: replace with GArray */
trw_layer_free_track_gcs ( trwlayer );
}
}
+static void trw_layer_apply_dem_data ( gpointer pass_along[6] )
+{
+ /* TODO: check & warn if no DEM data, or no applicable DEM data. */
+ /* Also warn if overwrite old elevation data */
+ VikTrack *track = (VikTrack *) g_hash_table_lookup ( VIK_TRW_LAYER(pass_along[0])->tracks, pass_along[3] );
+
+ vik_track_apply_dem_data ( track, VIK_TRW_LAYER(pass_along[0])->dems );
+}
+
+
static void trw_layer_goto_track_endpoint ( gpointer pass_along[6] )
{
GList *trps = ((VikTrack *) g_hash_table_lookup ( VIK_TRW_LAYER(pass_along[0])->tracks, pass_along[3] ))->trackpoints;
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 );
+
+ item = gtk_menu_item_new_with_label ( "Apply DEM Data" );
+ g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_apply_dem_data), 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) )