[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