hi!

i'm rather new to viking. i stumbled over it while searching for
software to plan and track my bike routes. after downloading the
SRTM3-data, i found it pretty cool to play with the DEM layer, but what
i was somehow missing is a DEM height-gradient layer.

so i improvised one :)

attached is a patch to the current git that will do the following:

* fix SRTM3 downloading patch

* add a switch to DEM layers: either `absolute height' or
  `height gradient'

for my purposes (bike), a (min, max) elev of (1, 100) is optimal in
gradient mode.



this is far from perfect, but i'd like to hear your opinion on this. is
it worth more effort? are you interested in putting this into the main
branch?




david


diff --git a/src/vikdemlayer.c b/src/vikdemlayer.c
index 3c48f74..db72c82 100644
--- a/src/vikdemlayer.c
+++ b/src/vikdemlayer.c
@@ -63,7 +63,7 @@
 
 #define SRTM_CACHE_TEMPLATE "%ssrtm3-%s%s%c%02d%c%03d.hgt.zip"
 #define SRTM_HTTP_SITE "dds.cr.usgs.gov"
-#define SRTM_HTTP_URI  "/srtm/version2_1/SRTM3/OLD/"
+#define SRTM_HTTP_URI  "/srtm/version2_1/SRTM3/"
 
 #ifdef VIK_CONFIG_DEM24K
 #define DEM24K_DOWNLOAD_SCRIPT "dem24k.pl"
@@ -97,6 +97,12 @@ static gchar *params_source[] = {
        NULL
        };
 
+static gchar *params_type[] = {
+       "Absolute height",
+       "Height gradient",
+       NULL
+};
+
 enum { DEM_SOURCE_SRTM,
 #ifdef VIK_CONFIG_DEM24K
        DEM_SOURCE_DEM24K,
@@ -104,17 +110,23 @@ enum { DEM_SOURCE_SRTM,
        DEM_SOURCE_NONE,
      };
 
+enum { DEM_TYPE_HEIGHT = 0,
+       DEM_TYPE_GRADIENT,
+       DEM_TYPE_NONE,
+};
+
 static VikLayerParam dem_layer_params[] = {
   { "files", VIK_LAYER_PARAM_STRING_LIST, VIK_LAYER_GROUP_NONE, N_("DEM 
Files:"), VIK_LAYER_WIDGET_FILELIST },
   { "source", VIK_LAYER_PARAM_UINT, VIK_LAYER_GROUP_NONE, N_("Download 
Source:"), VIK_LAYER_WIDGET_RADIOGROUP_STATIC, params_source, NULL },
   { "color", VIK_LAYER_PARAM_STRING, VIK_LAYER_GROUP_NONE, N_("Color:"), 
VIK_LAYER_WIDGET_ENTRY },
+  { "type", VIK_LAYER_PARAM_UINT, VIK_LAYER_GROUP_NONE, N_("Type:"), 
VIK_LAYER_WIDGET_RADIOGROUP_STATIC, params_type, NULL },
   { "min_elev", VIK_LAYER_PARAM_DOUBLE, VIK_LAYER_GROUP_NONE, N_("Min Elev:"), 
VIK_LAYER_WIDGET_SPINBUTTON, param_scales + 0 },
   { "max_elev", VIK_LAYER_PARAM_DOUBLE, VIK_LAYER_GROUP_NONE, N_("Max Elev:"), 
VIK_LAYER_WIDGET_SPINBUTTON, param_scales + 0 },
   { "line_thickness", VIK_LAYER_PARAM_UINT, VIK_LAYER_GROUP_NONE, N_("Line 
Thickness:"), VIK_LAYER_WIDGET_SPINBUTTON, param_scales + 1 },
 };
 
 
-enum { PARAM_FILES=0, PARAM_SOURCE, PARAM_COLOR, PARAM_MIN_ELEV, 
PARAM_MAX_ELEV, PARAM_LINE_THICKNESS, NUM_PARAMS };
+enum { PARAM_FILES=0, PARAM_SOURCE, PARAM_COLOR, PARAM_TYPE, PARAM_MIN_ELEV, 
PARAM_MAX_ELEV, PARAM_LINE_THICKNESS, NUM_PARAMS };
 
 static gpointer dem_layer_download_create ( VikWindow *vw, VikViewport *vvp);
 static gboolean dem_layer_download_release ( VikDEMLayer *vdl, GdkEventButton 
*event, VikViewport *vvp );
@@ -130,113 +142,42 @@ static VikToolInterface dem_tools[] = {
 /*
 */
 
-static gchar *dem_colors[] = {
+static gchar *dem_height_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", "#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"
 };
 
+static const guint DEM_N_HEIGHT_COLORS = 
sizeof(dem_height_colors)/sizeof(dem_height_colors[0]);
+
 /*
-"#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"
+"#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]);
+static gchar *dem_gradient_colors[] = {
+"#AAAAAA"
+"#000000", "#000011", "#000022", "#000033", "#000044", "#00004c", "#000055", 
"#00005d", "#000066", "#00006e",
+"#000077", "#00007f", "#000088", "#000090", "#000099", "#0000a1", "#0000aa", 
"#0000b2", "#0000bb", "#0000c3",
+"#0000cc", "#0000d4", "#0000dd", "#0000e5", "#0000ee", "#0000f6", "#0000ff", 
"#0008f7", "#0011ee", "#0019e6",
+"#0022dd", "#002ad5", "#0033cc", "#003bc4", "#0044bb", "#004cb3", "#0055aa", 
"#005da2", "#006699", "#006e91",
+"#007788", "#007f80", "#008877", "#00906f", "#009966", "#00a15e", "#00aa55", 
"#00b24d", "#00bb44", "#00c33c",
+"#00cc33", "#00d42b", "#00dd22", "#00e51a", "#00ee11", "#00f609", "#00ff00", 
"#08f700", "#11ee00", "#19e600",
+"#22dd00", "#2ad500", "#33cc00", "#3bc400", "#44bb00", "#4cb300", "#55aa00", 
"#5da200", "#669900", "#6e9100",
+"#778800", "#7f8000", "#887700", "#906f00", "#996600", "#a15e00", "#aa5500", 
"#b24d00", "#bb4400", "#c33c00",
+"#cc3300", "#d42b00", "#dd2200", "#e51a00", "#ee1100", "#f60900", "#ff0000",
+"#FFFFFF"
+};
+
+static const guint DEM_N_GRADIENT_COLORS = 
sizeof(dem_gradient_colors)/sizeof(dem_gradient_colors[0]);
 
 
 VikLayerInterface vik_dem_layer_interface = {
@@ -291,12 +232,14 @@ struct _VikDEMLayer {
   VikLayer vl;
   GdkGC *gc;
   GdkGC **gcs;
+  GdkGC **gcsgradient;
   GList *files;
   gdouble min_elev;
   gdouble max_elev;
   guint8 line_thickness;
   gchar *color;
   guint source;
+  guint type;
 };
 
 GType vik_dem_layer_get_type ()
@@ -334,8 +277,11 @@ static VikDEMLayer *dem_layer_unmarshall( guint8 *data, 
gint len, VikViewport *v
   gint i;
 
   /* TODO: share GCS between layers */
-  for ( i = 0; i < DEM_N_COLORS; i++ )
-    rv->gcs[i] = vik_viewport_new_gc ( vvp, dem_colors[i], rv->line_thickness 
);
+  for ( i = 0; i < DEM_N_HEIGHT_COLORS; i++ )
+    rv->gcs[i] = vik_viewport_new_gc ( vvp, dem_height_colors[i], 
rv->line_thickness );
+
+  for ( i = 0; i < DEM_N_GRADIENT_COLORS; i++ )
+    rv->gcsgradient[i] = vik_viewport_new_gc ( vvp, dem_gradient_colors[i], 
rv->line_thickness );
 
   vik_layer_unmarshall_params ( VIK_LAYER(rv), data, len, vvp );
   return rv;
@@ -347,6 +293,7 @@ gboolean dem_layer_set_param ( VikDEMLayer *vdl, guint16 
id, VikLayerParamData d
   {
     case PARAM_COLOR: if ( vdl->color ) g_free ( vdl->color ); vdl->color = 
g_strdup ( data.s ); break;
     case PARAM_SOURCE: vdl->source = data.u; break;
+    case PARAM_TYPE: vdl->type = data.u; break;
     case PARAM_MIN_ELEV: vdl->min_elev = data.d; 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;
@@ -362,6 +309,7 @@ static VikLayerParamData dem_layer_get_param ( VikDEMLayer 
*vdl, guint16 id )
   {
     case PARAM_FILES: rv.sl = vdl->files; break;
     case PARAM_SOURCE: rv.u = vdl->source; break;
+    case PARAM_TYPE: rv.u = vdl->type; break;
     case PARAM_COLOR: rv.s = vdl->color ? vdl->color : ""; break;
     case PARAM_MIN_ELEV: rv.d = vdl->min_elev; break;
     case PARAM_MAX_ELEV: rv.d = vdl->max_elev; break;
@@ -390,12 +338,14 @@ VikDEMLayer *vik_dem_layer_new ( )
 
   vdl->gc = NULL;
 
-  vdl->gcs = g_malloc(sizeof(GdkGC *)*DEM_N_COLORS);
+  vdl->gcs = g_malloc(sizeof(GdkGC *)*DEM_N_HEIGHT_COLORS);
+  vdl->gcsgradient = g_malloc(sizeof(GdkGC *)*DEM_N_GRADIENT_COLORS);
   /* make new gcs only if we need it (copy layer -> use old) */
 
   vdl->min_elev = 0.0;
   vdl->max_elev = 1000.0;
   vdl->source = DEM_SOURCE_SRTM;
+  vdl->type = DEM_TYPE_HEIGHT;
   vdl->line_thickness = 3;
   vdl->color = NULL;
   return vdl;
@@ -406,6 +356,7 @@ VikDEMLayer *vik_dem_layer_new ( )
 static void vik_dem_layer_draw_dem ( VikDEMLayer *vdl, VikViewport *vp, VikDEM 
*dem )
 {
   VikDEMColumn *column;
+  VikDEMColumn *nextcolumn;
 
   struct LatLon dem_northeast, dem_southwest;
   gdouble max_lat, max_lon, min_lat, min_lon;  
@@ -514,28 +465,88 @@ static void vik_dem_layer_draw_dem ( VikDEMLayer *vdl, 
VikViewport *vp, VikDEM *
     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 );
+       if(x+1 == dem->n_columns) {
+         nextcolumn = g_ptr_array_index ( dem->columns, x-1);
+       } else {
+         nextcolumn = g_ptr_array_index ( dem->columns, x+1);
+       }
+
         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 != VIK_DEM_INVALID_ELEVATION && elev < vdl->min_elev )
-            elev=vdl->min_elev;
-          if ( elev != VIK_DEM_INVALID_ELEVATION && elev > vdl->max_elev )
-            elev=vdl->max_elev;
-
+         if(vdl->type == DEM_TYPE_HEIGHT) {
+                 if ( elev != VIK_DEM_INVALID_ELEVATION && elev < 
vdl->min_elev )
+                   elev=vdl->min_elev;
+                 if ( elev != VIK_DEM_INVALID_ELEVATION && 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->min_elev)/(vdl->max_elev - vdl->min_elev)*(DEM_N_COLORS-2))+1], TRUE, a-2, 
b-2, 4, 4 );
+           if(vdl->type == DEM_TYPE_GRADIENT) {
+                   if( elev == VIK_DEM_INVALID_ELEVATION ) {
+                           /* don't draw it */
+                   } else {
+                           // calculate gradient, but only in two orthogonal 
directions.
+                           gint16 change = 0;
+                           gint16 newelev;
+
+                           // down
+                           if(y+1 == column->n_points)
+                                   newelev = column->points[y-1];
+                           else
+                                   newelev = column->points[y+1];
+                           if(newelev != VIK_DEM_INVALID_ELEVATION)
+                                   change += abs(newelev - elev);
+
+                           // down + right
+                           if(y+1 == nextcolumn->n_points)
+                                   newelev = nextcolumn->points[y-1];
+                           else
+                                   newelev = nextcolumn->points[y+1];
+                           if(newelev != VIK_DEM_INVALID_ELEVATION)
+                                   change += abs(newelev - elev);
+
+                           // right
+                           newelev = nextcolumn->points[y];
+                           if(newelev != VIK_DEM_INVALID_ELEVATION)
+                                   change += abs(newelev - elev);
+
+                           // up + right
+                           if(y <= 1)
+                                   newelev = nextcolumn->points[y+1];
+                           else
+                                   newelev = nextcolumn->points[y-1];
+                           if(newelev != VIK_DEM_INVALID_ELEVATION)
+                                   change += abs(newelev - elev);
+
+                           change = log(change) * log(change) * log(change);
+
+                           if(change < vdl->min_elev)
+                                   change = vdl->min_elev;
+
+                           if(change > vdl->max_elev)
+                                   change = vdl->max_elev;
+
+                           // void vik_viewport_draw_rectangle ( VikViewport 
*vvp, GdkGC *gc, gboolean filled, gint x1, gint y1, gint x2, gint y2 );
+                           vik_viewport_draw_rectangle(vp, 
vdl->gcsgradient[(gint)floor((change - vdl->min_elev)/(vdl->max_elev - 
vdl->min_elev)*(DEM_N_GRADIENT_COLORS-2))+1], TRUE, a-2, b-2, 4, 4 );
+                   }
+            } else {
+                   if(vdl->type == DEM_TYPE_HEIGHT) {
+                           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->min_elev)/(vdl->max_elev - 
vdl->min_elev)*(DEM_N_HEIGHT_COLORS-2))+1], TRUE, a-2, b-2, 4, 4 );
+                   }
+           }
+
           }
         } /* for y= */
       }
@@ -619,7 +630,7 @@ static void vik_dem_layer_draw_dem ( VikDEMLayer *vdl, 
VikViewport *vp, VikDEM *
             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->min_elev)/(vdl->max_elev - vdl->min_elev)*(DEM_N_COLORS-2))+1], TRUE, a-2, 
b-2, 4, 4 );
+              vik_viewport_draw_rectangle(vp, vdl->gcs[(gint)floor((elev - 
vdl->min_elev)/(vdl->max_elev - vdl->min_elev)*(DEM_N_HEIGHT_COLORS-2))+1], 
TRUE, a-2, b-2, 4, 4 );
           }
         } /* for y= */
       }
@@ -691,10 +702,15 @@ void vik_dem_layer_free ( VikDEMLayer *vdl )
     g_free ( vdl->color );
 
   if ( vdl->gcs )
-    for ( i = 0; i < DEM_N_COLORS; i++ )
+    for ( i = 0; i < DEM_N_HEIGHT_COLORS; i++ )
       g_object_unref ( vdl->gcs[i] );
   g_free ( vdl->gcs );
 
+  if ( vdl->gcsgradient )
+    for ( i = 0; i < DEM_N_GRADIENT_COLORS; i++ )
+      g_object_unref ( vdl->gcsgradient[i] );
+  g_free ( vdl->gcsgradient );
+
   a_dems_list_free ( vdl->files );
 }
 
@@ -717,8 +733,11 @@ VikDEMLayer *vik_dem_layer_create ( VikViewport *vp )
   gint i;
 
   /* TODO: share GCS between layers */
-  for ( i = 0; i < DEM_N_COLORS; i++ )
-    vdl->gcs[i] = vik_viewport_new_gc ( vp, dem_colors[i], vdl->line_thickness 
);
+  for ( i = 0; i < DEM_N_HEIGHT_COLORS; i++ )
+    vdl->gcs[i] = vik_viewport_new_gc ( vp, dem_height_colors[i], 
vdl->line_thickness );
+
+  for ( i = 0; i < DEM_N_GRADIENT_COLORS; i++ )
+    vdl->gcsgradient[i] = vik_viewport_new_gc ( vp, dem_gradient_colors[i], 
vdl->line_thickness );
 
   dem_layer_update_gc ( vdl, vp, "red" );
   return vdl;

Attachment: pgpisbwooSzbu.pgp
Description: PGP signature

------------------------------------------------------------------------------
Come build with us! The BlackBerry&reg; Developer Conference in SF, CA
is the only developer event you need to attend this year. Jumpstart your
developing skills, take BlackBerry mobile applications to market and stay 
ahead of the curve. Join us from November 9&#45;12, 2009. Register now&#33;
http://p.sf.net/sfu/devconf
_______________________________________________
Viking-devel mailing list
Viking-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/viking-devel
Viking home page: http://viking.sf.net/

Reply via email to