[GRASS-SVN] r60440 - grass/trunk/display/d.legend

svn_grass at osgeo.org svn_grass at osgeo.org
Fri May 23 01:39:16 PDT 2014


Author: hamish
Date: 2014-05-23 01:39:16 -0700 (Fri, 23 May 2014)
New Revision: 60440

Modified:
   grass/trunk/display/d.legend/histogram.c
   grass/trunk/display/d.legend/local_proto.h
   grass/trunk/display/d.legend/main.c
Log:
add support for histograms with constrained ranges (so far only FP maps)

Modified: grass/trunk/display/d.legend/histogram.c
===================================================================
--- grass/trunk/display/d.legend/histogram.c	2014-05-23 07:39:08 UTC (rev 60439)
+++ grass/trunk/display/d.legend/histogram.c	2014-05-23 08:39:16 UTC (rev 60440)
@@ -9,18 +9,26 @@
 
 #include <grass/gis.h>
 #include <grass/display.h>
+#include <grass/raster.h>
+#include <grass/glocale.h>
 #include "local_proto.h"
 
 void draw_histogram(const char *map_name, int x0, int y0, int width,
 		    int height, int color, int flip, int horiz,
-		    int map_type, int is_fp)
+		    int map_type, int is_fp, struct FPRange render_range)
 {
-    int i, nsteps;
-    long cell_count;
+    int i, nsteps, ystep;
+    long cell_count = 0;
     double max_width, width_mult, dx;
     double dy, y0_adjust;	/* only needed for CELL maps */
     struct stat_list dist_stats;
     struct stat_node *ptr;
+    struct Range range;
+    struct FPRange fprange;
+    CELL c_map_min, c_map_max;
+    DCELL d_map_min, d_map_max;
+    double map_min, map_max, map_range, user_range;
+    double crop_min_perc = 0.0, crop_max_perc = 1.0, pad_min_perc = 0.0;
 
     if (horiz) {
 	max_width = height * 1.75;
@@ -31,6 +39,78 @@
 	nsteps = height - 3;
     }
 
+
+    if (render_range.first_time) {
+	/* user specified range, can be either larger
+	    or smaller than actual map's range */
+
+	if (is_fp) {
+	    Rast_read_fp_range(map_name, "", &fprange);
+	    Rast_get_fp_range_min_max(&fprange, &d_map_min, &d_map_max);
+	    map_min = (double)d_map_min;
+	    map_max = (double)d_map_max;
+	}
+	else {
+	    Rast_read_range(map_name, "", &range);
+	    Rast_get_range_min_max(&range, &c_map_min, &c_map_max);
+	    map_min = (double)c_map_min;
+	    map_max = (double)c_map_max;
+	}
+
+	map_range = map_max - map_min;
+	user_range = render_range.max - render_range.min;
+
+	if (horiz)
+	    nsteps = (int)(0.5 + (map_range * (width - 3) / user_range));
+	else
+	    nsteps = (int)(0.5 + (map_range * (height - 3) / user_range));
+
+	G_debug(1, "number of steps for r.stats = %d, height-3=%d  width-3=%d",
+		nsteps, height - 3, width - 3);
+
+	/* need to know the % of the MAP range where user range starts and stops.
+	 *   note that MAP range can be fully inside user range, in which case
+	 *   keep 0-100% aka 0,nsteps, i.e. the step number in the nsteps range */
+
+	if (render_range.min > map_min) {
+	   crop_min_perc = (render_range.min - map_min) / map_range;
+	   G_debug(3, "min: %.02f vs. %.02f (%.02f) ... %.02f%%",
+	   	   render_range.min, map_min, map_range, 100 * crop_min_perc);
+	}
+
+	if (render_range.max > map_max) {
+	    crop_max_perc = 1.0 - ((render_range.max - map_max) / user_range);
+	    G_debug(3, "max: %.02f vs. %.02f (%.02f) ... %.02f%%",
+		    map_max, render_range.max, map_range, 100 * crop_max_perc);
+	}
+
+	if (render_range.min < map_min) {
+	   pad_min_perc = (map_min - render_range.min) / user_range;
+	   G_debug(3, "Min: %.02f vs. %.02f (%.02f) ... %.02f%%",
+	   	   map_min, render_range.min, user_range, 100 * pad_min_perc);
+	}
+
+#ifdef amplify_gain
+	/* proportion of nsteps to width, use as mult factor to boost the 1.75x
+	    when spread out over more nsteps than we are displaying */
+	G_debug(0, "max_width was: %.2f  (nsteps=%d)", max_width, nsteps);
+
+	if (nsteps > ((horiz ? width : height) - 3.0))
+	    max_width *= nsteps / ((horiz ? width : height) - 3.0);
+
+	G_debug(0, "max_width now: %.2f", max_width);
+#endif
+    }
+
+
+    /* TODO */
+    if (!is_fp && render_range.first_time) {
+	G_warning(_("Histogram constrained by range not yet implemented for "
+		  "categorical rasters"));
+	return;
+    }
+
+
     /* get the distribution statistics */
     get_stats(map_name, &dist_stats, nsteps, map_type);
 
@@ -56,10 +136,39 @@
 	    y0_adjust += 0.5;
     }
 
-    for (i = dist_stats.mincat; i <= dist_stats.maxcat; i++) {
+
+    G_debug(3, "mincat=%ld  maxcat=%ld", dist_stats.mincat, dist_stats.maxcat);
+
+    for (i = dist_stats.mincat, ystep = 0; i <= dist_stats.maxcat; i++) {
 	if (!ptr)
 	    break;
 
+	/* jump out if user range cuts things shorter than the map's native range */
+	if ((horiz && ystep > width - 4) || (!horiz && ystep > height - 4))
+	    break;
+
+	/* jump out if user range goes beyond max of map data */
+	if (((double)ystep / ((horiz ? width : height) - 3.0)) > crop_max_perc)
+	    break;
+/* TODO	if (!is_fp && i > render_range.max)
+	    break;
+*/
+	/* haven't made it to the min of the user range yet */
+	if (((double)i / nsteps) < crop_min_perc) {
+	    continue;
+	}
+
+	/* now it's ok advance the plotter position */
+	ystep++;
+
+	/* if user range is below the minimum real map value, we need to pad out the space */
+	if (render_range.first_time && render_range.min < map_min) {
+	    if ( ((double)ystep / ((horiz ? width : height) - 3.0)) < pad_min_perc) {
+		i--;
+		continue;
+	    }
+	}
+
 	if (ptr->cat == i) {	/* AH-HA!! found the stat */
 	    cell_count = ptr->stat;
 
@@ -78,9 +187,12 @@
 		    ptr = ptr->next;
 	    }
 	    else		/* stat cannot be found */
-		G_debug(4, "No matching stat found, i=%d", i);
+		G_debug(5, "No matching stat found, i=%d", i);
 	}
 
+	G_debug(5, "i=%d  ptr->cat=%ld  cell_count=%ld", i, ptr->cat, 
+		cell_count);
+
 	if (!cell_count)
 	    continue;
 
@@ -89,17 +201,17 @@
 	if (is_fp) {
 	    if (horiz) {
 		if (flip)
-		    D_move_abs(x0 + width - i - 1, y0 - 1);
+		    D_move_abs(x0 + width - ystep - 1, y0 - 1);
 		else
-		    D_move_abs(x0 + i + 1, y0 - 1);
+		    D_move_abs(x0 + ystep + 1, y0 - 1);
 
 		D_cont_rel(0, -dx);
 	    }
 	    else {  /* vertical */
 		if (flip)
-		    D_move_abs(x0 - 1, y0 - 1 + height - i);
+		    D_move_abs(x0 - 1, y0 - 1 + height - ystep);
 		else
-		    D_move_abs(x0 - 1, y0 + 1 + i);
+		    D_move_abs(x0 - 1, y0 + 1 + ystep);
 
 		D_cont_rel(-dx, 0);
 	    }

Modified: grass/trunk/display/d.legend/local_proto.h
===================================================================
--- grass/trunk/display/d.legend/local_proto.h	2014-05-23 07:39:08 UTC (rev 60439)
+++ grass/trunk/display/d.legend/local_proto.h	2014-05-23 08:39:16 UTC (rev 60440)
@@ -1,3 +1,5 @@
+#include <grass/raster.h>
+
 #define MAP_TYPE_RASTER2D 1
 #define MAP_TYPE_RASTER3D 2
 /* possibles for the future:
@@ -27,7 +29,8 @@
 
 
 /* histogram.c */
-void draw_histogram(const char *, int, int, int, int, int, int, int, int, int);
+void draw_histogram(const char *, int, int, int, int, int, int, int, int,
+		    int, struct FPRange);
 
 /* get_stats.c */
 void get_stats(const char *, struct stat_list *, int, int);

Modified: grass/trunk/display/d.legend/main.c
===================================================================
--- grass/trunk/display/d.legend/main.c	2014-05-23 07:39:08 UTC (rev 60439)
+++ grass/trunk/display/d.legend/main.c	2014-05-23 08:39:16 UTC (rev 60440)
@@ -16,7 +16,7 @@
  *      Late 2002: Rewrite of much of the code:
  *         Hamish Bowman, Otago University, New Zealand
  *
- * COPYRIGHT:   (c) 2006-2014 by The GRASS Development Team
+ * COPYRIGHT:   (c) 2002-2014 by The GRASS Development Team
  *
  *              This program is free software under the GNU General Public
  *              License (>=v2). Read the file COPYING that comes with GRASS
@@ -60,7 +60,7 @@
 		  *opt_font, *opt_path, *opt_charset, *opt_fontsize;
     struct Flag *hidestr, *hidenum, *hidenodata, *smooth, *flipit, *histo;
     struct Range range;
-    struct FPRange fprange;
+    struct FPRange fprange, render_range;
     CELL min_ind, max_ind;
     DCELL dmin, dmax, val;
     CELL min_colr, max_colr;
@@ -839,11 +839,14 @@
 
 	/* display sidebar histogram, if requested */
 	if (histo->answer) {
-	    if (opt_range->answer != NULL)
-		G_warning(_("Histogram constrained by range not yet implemented"));
-	    else
-		draw_histogram(map_name, x0, y0, wleg, lleg, color, flip,
-			       horiz, maptype, fp);
+
+	    render_range.min = (DCELL)(fp ? dmin : min_ind);
+	    render_range.max = (DCELL)(fp ? dmax : max_ind);
+	    /* reuse flag to indicate if user-specified or default ranging */
+	    render_range.first_time = opt_range->answer ? TRUE : FALSE;
+
+	    draw_histogram(map_name, x0, y0, wleg, lleg, color, flip, horiz,
+			   maptype, fp, render_range);
 	}
 
     }
@@ -853,6 +856,10 @@
 	double txsiz;
 	float ScaleFactor = 1.0;
 
+	if (histo->answer)
+	    G_warning(_("Histogram plotting not implemented for categorical legends. "
+			"Use the '-s' flag"));
+
 	/* set legend box bounds */
 	true_l = l;
 	true_r = r;	/* preserve window width */
@@ -906,15 +913,15 @@
 
 	/* Draw away */
 
-	/*              if(ScaleFactor < 1.0)   */
-	/*                  cur_dot_row = ((b-t) - (dots_per_line*lines))/2; *//* this will center the legend */
-	/*              else    */
+	/* if(ScaleFactor < 1.0)   */
+	/*    cur_dot_row = ((b-t) - (dots_per_line*lines))/2; *//* this will center the legend */
+	/* else    */
 	cur_dot_row = t + dots_per_line / 2;
 
 	/*  j = (do_cats == cats_num ? 1 : 2 ); */
 
 	for (i = 0, k = 0; i < catlistCount; i++)
-	    /*              for(i=min_ind, j=1, k=0; j<=do_cats && i<=max_ind; j++, i+=thin)        */
+	    /* for(i=min_ind, j=1, k=0; j<=do_cats && i<=max_ind; j++, i+=thin) */
 	{
 	    if (!flip)
 		cstr = Rast_get_d_cat(&catlist[i], &cats);
@@ -930,7 +937,7 @@
 	    else
 		hide_catstr = hidestr->answer;
 
-	    k++;		/* count of actual boxes drawn (hide_nodata option invaidates using j-1) */
+	    k++;  /* count of actual boxes drawn (hide_nodata option invaidates using j-1) */
 
 	    /* White box */
 	    cur_dot_row += dots_per_line;



More information about the grass-commit mailing list