[GRASS-SVN] r60379 - grass/branches/releasebranch_7_0/display/d.legend

svn_grass at osgeo.org svn_grass at osgeo.org
Tue May 20 19:24:08 PDT 2014


Author: hamish
Date: 2014-05-20 19:24:08 -0700 (Tue, 20 May 2014)
New Revision: 60379

Added:
   grass/branches/releasebranch_7_0/display/d.legend/get_stats.c
   grass/branches/releasebranch_7_0/display/d.legend/histogram.c
Modified:
   grass/branches/releasebranch_7_0/display/d.legend/
   grass/branches/releasebranch_7_0/display/d.legend/Makefile
   grass/branches/releasebranch_7_0/display/d.legend/d.legend.html
   grass/branches/releasebranch_7_0/display/d.legend/local_proto.h
   grass/branches/releasebranch_7_0/display/d.legend/main.c
Log:
add support for histogram sidebars (#1049); add support for 3D raster map legends (#2083, thanks Vaclav); display map data units, if known [merge from trunk]



Property changes on: grass/branches/releasebranch_7_0/display/d.legend
___________________________________________________________________
Modified: svn:ignore
   - OBJ.*

   + OBJ.*
*.tmp.html


Modified: grass/branches/releasebranch_7_0/display/d.legend/Makefile
===================================================================
--- grass/branches/releasebranch_7_0/display/d.legend/Makefile	2014-05-20 16:04:53 UTC (rev 60378)
+++ grass/branches/releasebranch_7_0/display/d.legend/Makefile	2014-05-21 02:24:08 UTC (rev 60379)
@@ -2,8 +2,8 @@
 
 PGM = d.legend
 
-LIBES = $(DISPLAYLIB) $(RASTERLIB) $(GISLIB) $(MATHLIB)
-DEPENDENCIES = $(DISPLAYDEP) $(RASTERDEP) $(GISDEP)
+LIBES = $(DISPLAYLIB) $(RASTERLIB) $(RASTER3DLIB) $(GISLIB) $(MATHLIB)
+DEPENDENCIES = $(DISPLAYDEP) $(RASTERDEP) $(RASTER3DDEP) $(GISDEP)
 
 include $(MODULE_TOPDIR)/include/Make/Module.make
 

Modified: grass/branches/releasebranch_7_0/display/d.legend/d.legend.html
===================================================================
--- grass/branches/releasebranch_7_0/display/d.legend/d.legend.html	2014-05-20 16:04:53 UTC (rev 60378)
+++ grass/branches/releasebranch_7_0/display/d.legend/d.legend.html	2014-05-21 02:24:08 UTC (rev 60379)
@@ -1,7 +1,7 @@
 <h2>DESCRIPTION</h2>
 
-<em>d.legend</em> displays a legend for a user-specified
-raster map layer in the active frame on the graphics monitor.  
+<em>d.legend</em> displays a legend for a user-specified raster map or
+3D raster map layer in the active frame on the graphics monitor.  
 <p>
 The legend's default size is based on the dimensions of the
 active frame, specifically its height.  <em>d.legend</em> will only
@@ -65,10 +65,14 @@
 output with a meaningful number of significant digits. For very small values,
 numbers will be expressed in scientific notation, e.g. "1.7e-9".
 <p>
-Note that old scripts which relied on setting <b>lines</b> greater than the
-number of categories to scale the legend may no longer produce the desired
-output, although the auto-scaling should still produce something that looks 
-good in this case.
+When the <b>-d</b> flag is used to display a histogram distribution along
+side the smoothed gradient legend, note that the statistics are calculated
+on the <i>current computational region</i> settings set by <em>g.region</em>.
+The default <b>range</b> however covers the entire natural bounds of the input map.
+If the histogram appears empty, check your region settings.
+<p>
+If the raster map's <i>units</i> metadata has been set with the
+<em>r.support</em> module then it will be displayed along side the legend.
 
 
 <h2>SEE ALSO</h2>
@@ -76,14 +80,15 @@
 <em>
 <a href="d.barscale.html">d.barscale</a>,
 <a href="d.colortable.html">d.colortable</a>,
-<a href="d.erase.html">d.erase</a>,
 <a href="d.font.html">d.font</a>,
 <a href="d.grid.html">d.grid</a>,
 <a href="d.rast.html">d.rast</a>,
 <a href="d.rast.leg.html">d.rast.leg</a>,
 <a href="d.text.html">d.text</a>,
 <a href="d.vect.thematic.html">d.vect.thematic</a>,
-<a href="r.reclass.html">r.reclass</a>
+<a href="r.reclass.html">r.reclass</a>,
+<a href="r.stats.html">r.stats</a>,
+<a href="r3.stats.html">r3.stats</a>
 </em>
 
 

Copied: grass/branches/releasebranch_7_0/display/d.legend/get_stats.c (from rev 60093, grass/trunk/display/d.legend/get_stats.c)
===================================================================
--- grass/branches/releasebranch_7_0/display/d.legend/get_stats.c	                        (rev 0)
+++ grass/branches/releasebranch_7_0/display/d.legend/get_stats.c	2014-05-21 02:24:08 UTC (rev 60379)
@@ -0,0 +1,149 @@
+#include <stdio.h>
+#include <unistd.h>
+#include <grass/gis.h>
+#include <grass/raster.h>
+#include <grass/spawn.h>
+#include "local_proto.h"
+
+
+void run_stats(const char *mapname, int nsteps, const char *tempfile,
+	       int map_type)
+{
+    char buf[32];
+    const char *argv[12];
+    int argc = 0;
+
+    if (map_type == MAP_TYPE_RASTER2D) {
+	argv[argc++] = "r.stats";
+	argv[argc++] = "-r";
+    }
+    else
+	argv[argc++] = "r3.stats";
+
+    argv[argc++] = "-c";
+    argv[argc++] = mapname;
+
+    sprintf(buf, "nsteps=%d", nsteps);
+    argv[argc++] = buf;
+
+    argv[argc++] = SF_REDIRECT_FILE;
+    argv[argc++] = SF_STDOUT;
+    argv[argc++] = SF_MODE_OUT;
+    argv[argc++] = tempfile;
+
+    argv[argc++] = NULL;
+
+    if (G_vspawn_ex(argv[0], argv) != 0)
+	G_fatal_error("error running r.stats");
+}
+
+/* linked list of stats */
+void get_stats(const char *mapname, struct stat_list *dist_stats, int nsteps,
+	       int map_type)
+{
+    char buf[1024];		/* input buffer for reading stats */
+    int done = FALSE;
+    char *tempfile;		/* temp file name */
+    FILE *fd;			/* temp file pointer */
+/*
+    int is_fp;
+    struct FPRange fp_range;
+*/
+    long int cat;		/* a category value */
+    long int stat;		/* a category stat value */
+    struct stat_node *ptr = NULL;
+    int first;
+
+    /* write stats to a temp file */
+    tempfile = G_tempfile();
+/*
+    is_fp = Rast_map_is_fp(mapname, "");
+    if (is_fp) {
+	if (Rast_read_fp_range(mapname, "", &fp_range) <= 0)
+	    G_fatal_error("Can't read frange file");
+    }
+*/
+    run_stats(mapname, nsteps, tempfile, map_type);
+
+    /* open temp file and read the stats into a linked list */
+    fd = fopen(tempfile, "r");
+    if (fd == NULL) {
+	perror("opening r.stats output file");
+	G_fatal_error("unable to continue.");
+    }
+    dist_stats->ptr = NULL;
+    dist_stats->count = 0;
+    dist_stats->sumstat = 0;
+
+    first = TRUE;
+
+    while (!done) {
+	if (fgets(buf, sizeof(buf), fd) != NULL) {
+	    /* WARNING!!!!!!
+	     * this will be very wrong if type!=COUNT
+	     * since the stat prodcued by r.stats will be a floating point value
+	     * possibly less than 1 (shapiro)
+	     */
+	    if (sscanf(buf, "* %ld", &stat) == 1) {
+		dist_stats->null_stat = stat;
+/*
+		if (stat > dist_stats->maxstat && nodata)
+		    dist_stats->maxstat = stat;
+		if (stat < dist_stats->minstat && nodata)
+		    dist_stats->minstat = stat;
+		if (nodata)
+		    dist_stats->sumstat += stat;
+*/
+	    }
+	    else if (sscanf(buf, "%ld %ld", &cat, &stat) == 2) {
+		/* count stats */
+		dist_stats->count++;
+
+		/* sum stats */
+		dist_stats->sumstat += stat;
+
+		/* a max or a min stat? */
+		if (first) {
+		    dist_stats->maxstat = stat;
+		    dist_stats->minstat = stat;
+		    dist_stats->maxcat = cat;
+		    dist_stats->mincat = cat;
+		    first = FALSE;
+		}
+		if (stat > dist_stats->maxstat)
+		    dist_stats->maxstat = stat;
+		if (stat < dist_stats->minstat)
+		    dist_stats->minstat = stat;
+
+		/* a max or a min cat? */
+		if (cat > dist_stats->maxcat)
+		    dist_stats->maxcat = cat;
+		if (cat < dist_stats->mincat)
+		    dist_stats->mincat = cat;
+
+		/* put it in the list */
+		if (dist_stats->ptr == NULL) {
+		    /* first in list */
+		    dist_stats->ptr = (struct stat_node *)
+			G_malloc(sizeof(struct stat_node));
+		    dist_stats->ptr->cat = cat;
+		    dist_stats->ptr->stat = stat;
+		    dist_stats->ptr->next = NULL;
+		    ptr = dist_stats->ptr;
+		}
+		else {
+		    ptr->next = (struct stat_node *)
+			G_malloc(sizeof(struct stat_node));
+		    ptr->next->cat = cat;
+		    ptr->next->stat = stat;
+		    ptr->next->next = NULL;	/* mod: shapiro */
+		    ptr = ptr->next;
+		}
+	    }
+	}
+	else
+	    done = TRUE;
+    }
+    fclose(fd);
+    unlink(tempfile);
+}

Copied: grass/branches/releasebranch_7_0/display/d.legend/histogram.c (from rev 60093, grass/trunk/display/d.legend/histogram.c)
===================================================================
--- grass/branches/releasebranch_7_0/display/d.legend/histogram.c	                        (rev 0)
+++ grass/branches/releasebranch_7_0/display/d.legend/histogram.c	2014-05-21 02:24:08 UTC (rev 60379)
@@ -0,0 +1,94 @@
+/* histogram.c:
+ *    Draws a histogram along the left side of a smooth gradient legend
+ *    (stats fetching code adapted from d.histogram)
+ *
+ *    Copyright (C) 2014 by Hamish Bowman, and the GRASS Development Team* 
+ *    This program is free software under the GPL (>=v2)
+ *    Read the COPYING file that comes with GRASS for details.
+ */
+
+#include <grass/gis.h>
+#include <grass/display.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 i, nsteps;
+    long cell_count;
+    double max_width, width_mult, dx;
+    struct stat_list dist_stats;
+    struct stat_node *ptr;
+
+    if (horiz) {
+	max_width = height * 1.75;
+	nsteps = width - 3;
+    }
+    else {
+	max_width = width * 1.75;
+	nsteps = height - 3;
+    }
+
+    /* get the distribution statistics */
+    get_stats(map_name, &dist_stats, nsteps, map_type);
+
+    width_mult = max_width / dist_stats.maxstat;
+
+    D_use_color(color);
+    D_begin();
+
+    ptr = dist_stats.ptr;
+
+    for (i = dist_stats.mincat; i <= dist_stats.maxcat; i++) {
+	if (!ptr)
+	    break;
+
+	if (ptr->cat == i) {       /* AH-HA!! found the stat */
+            cell_count = ptr->stat;
+
+            if (ptr->next != NULL)
+                ptr = ptr->next;
+        }
+        else {                  /* we have to look for the stat */
+
+            /* loop until we find it, or pass where it should be */
+            while (ptr->cat < i && ptr->next != NULL)
+                ptr = ptr->next;
+            if (ptr->cat == i) {        /* AH-HA!! found the stat */
+                cell_count = ptr->stat;
+
+                if (ptr->next != NULL)
+                    ptr = ptr->next;
+            }
+            else                /* stat cannot be found */
+		G_debug(4, "No matching stat found, i=%d", i);
+        }
+
+	if (!cell_count)
+	    continue;
+
+	dx = cell_count * width_mult;
+
+	if (horiz) {
+	    if (flip)
+		D_move_abs(x0 + width - i - 1, y0 - 1);
+	    else
+		D_move_abs(x0 + i + 1, y0 - 1);
+
+	    D_cont_rel(0, -dx);
+	}
+	else {  /* vertical */
+	    if (flip)
+		D_move_abs(x0 - 1, y0 - 1 + height - i);
+	    else
+		D_move_abs(x0 - 1, y0 + 1 + i);
+
+	    D_cont_rel(-dx, 0);
+	}
+    }
+
+    D_close();
+    D_end();
+    D_stroke();
+}

Modified: grass/branches/releasebranch_7_0/display/d.legend/local_proto.h
===================================================================
--- grass/branches/releasebranch_7_0/display/d.legend/local_proto.h	2014-05-20 16:04:53 UTC (rev 60378)
+++ grass/branches/releasebranch_7_0/display/d.legend/local_proto.h	2014-05-21 02:24:08 UTC (rev 60379)
@@ -1,5 +1,34 @@
-/* main.c */
-char *G_chop(char *s);
+#define MAP_TYPE_RASTER2D 1
+#define MAP_TYPE_RASTER3D 2
+/* possibles for the future:
+#define MAP_TYPE_VECTOR 3
+#define MAP_TYPE_RULES 4
+*/
 
-/* box.c */
-int get_legend_box(int *, int *, int *, int *);
+struct stat_node
+{
+    long int cat;               /* cell-file category value */
+    long int stat;              /* statistic: number of cells with that cat */
+    struct stat_node *next;     /* pointer to next stat_node in list */
+};
+
+struct stat_list
+{
+    struct stat_node *ptr;      /* pointer to first stat_node in list */
+    long int count,             /* number of stat_nodes in list 
+                                   (not counting null cells) */
+      null_stat,                /* stats for null cell */
+      maxstat,                  /* max. statistic in list */
+      minstat,                  /* min. statistic in list */
+      sumstat,                  /* sum of all statistics in list */
+      maxcat,                   /* max. cell-file category value in list */
+      mincat;                   /* min. cell-file category value in list */
+};
+
+
+/* histogram.c */
+void draw_histogram(const char *, int, int, int, int, int, int, int, int);
+
+/* get_stats.c */
+void get_stats(const char *, struct stat_list *, int, int);
+void run_stats(const char *, int, const char *, int);

Modified: grass/branches/releasebranch_7_0/display/d.legend/main.c
===================================================================
--- grass/branches/releasebranch_7_0/display/d.legend/main.c	2014-05-20 16:04:53 UTC (rev 60378)
+++ grass/branches/releasebranch_7_0/display/d.legend/main.c	2014-05-21 02:24:08 UTC (rev 60379)
@@ -29,6 +29,7 @@
 #include <math.h>
 #include <grass/gis.h>
 #include <grass/raster.h>
+#include <grass/raster3d.h>
 #include <grass/display.h>
 #include <grass/glocale.h>
 #include "local_proto.h"
@@ -38,32 +39,29 @@
 {
     char buff[512];
     char *map_name;
-    int black;
+    int maptype;
+    int black, white, color;
     int cats_num;
-    int color;
     int cur_dot_row;
     int do_cats;
     int dots_per_line;
-    int thin;
     int i, j, k;
-    int lines, steps;
+    int thin, lines, steps;
     int fp;
     double t, b, l, r;
     int hide_catnum, hide_catstr, hide_nodata, do_smooth;
     char *cstr;
-    int white;
-    double x_box[5];
-    double y_box[5];
+    double x_box[5], y_box[5];
     struct Categories cats;
     struct Colors colors;
     struct GModule *module;
-    struct Option *opt_input, *opt_color, *opt_lines, *opt_thin,
-		  *opt_labelnum, *opt_at, *opt_use, *opt_range,
+    struct Option *opt_rast2d, *opt_rast3d, *opt_color, *opt_lines,
+		  *opt_thin, *opt_labelnum, *opt_at, *opt_use, *opt_range,
 		  *opt_font, *opt_path, *opt_charset, *opt_fontsize;
-    struct Flag *hidestr, *hidenum, *hidenodata, *smooth, *flipit, *size;
+    struct Flag *hidestr, *hidenum, *hidenodata, *smooth, *flipit, *histo;
     struct Range range;
     struct FPRange fprange;
-    CELL min_ind, max_ind, null_cell;
+    CELL min_ind, max_ind;
     DCELL dmin, dmax, val;
     CELL min_colr, max_colr;
     DCELL min_dcolr, max_dcolr;
@@ -77,6 +75,7 @@
     double *catlist, maxCat;
     int catlistCount, use_catlist;
     double fontsize;
+    char *units;
 
 
     /* Initialize the GIS calls */
@@ -86,15 +85,18 @@
     G_add_keyword(_("display"));
     G_add_keyword(_("cartography"));
     module->description =
-	_("Displays a legend for a raster map in the active frame "
+	_("Displays a legend for a raster map (2 or 3D) in the active frame "
 	  "of the graphics monitor.");
 
-    opt_input = G_define_standard_option(G_OPT_R_MAP);
-    opt_input->description = _("Name of raster map");
+    opt_rast2d = G_define_standard_option(G_OPT_R_MAP);
+    opt_rast2d->key = "rast";
+    opt_rast2d->required = NO;
+    opt_rast2d->guisection = _("Input");
 
-    opt_color = G_define_standard_option(G_OPT_C_FG);
-    opt_color->label = _("Text color");
-    opt_color->guisection = _("Font settings");
+    opt_rast3d = G_define_standard_option(G_OPT_R3_MAP);
+    opt_rast3d->key = "rast3d";
+    opt_rast3d->required = NO;
+    opt_rast3d->guisection = _("Input");
 
     opt_lines = G_define_option();
     opt_lines->key = "lines";
@@ -111,7 +113,8 @@
     opt_thin->required = NO;
     opt_thin->answer = "1";
     opt_thin->options = "1-1000";
-    opt_thin->description = _("Thinning factor (thin=10 gives cats 0,10,20...)");
+    opt_thin->description =
+	_("Thinning factor (thin=10 gives cats 0,10,20...)");
     opt_thin->guisection = _("Advanced");
 
     opt_labelnum = G_define_option();
@@ -119,23 +122,25 @@
     opt_labelnum->type = TYPE_INTEGER;
     opt_labelnum->answer = "5";
     opt_labelnum->options = "2-100";
-    opt_labelnum->description = _("Number of text labels for smooth gradient legend");
+    opt_labelnum->description =
+	_("Number of text labels for smooth gradient legend");
     opt_labelnum->guisection = _("Gradient");
 
     opt_at = G_define_option();
     opt_at->key = "at";
     opt_at->key_desc = "bottom,top,left,right";
-    opt_at->type = TYPE_DOUBLE;	/* needs to be TYPE_DOUBLE to get past options check */
+    opt_at->type = TYPE_DOUBLE;  /* needs to be TYPE_DOUBLE to get past options check */
     opt_at->required = NO;
     opt_at->options = "0-100";
     opt_at->label =
-	_("Size and placement as percentage of screen coordinates (0,0 is lower left)");
+	_("Size and placement as percentage of screen coordinates "
+	  "(0,0 is lower left)");
     opt_at->description = opt_at->key_desc;
     opt_at->answer = NULL;
 
     opt_use = G_define_option();
     opt_use->key = "use";
-    opt_use->type = TYPE_DOUBLE;	/* string as it is fed through the parser? */
+    opt_use->type = TYPE_DOUBLE;  /* string as it is fed through the parser? */
     opt_use->required = NO;
     opt_use->description =
 	_("List of discrete category numbers/values for legend");
@@ -145,12 +150,16 @@
     opt_range = G_define_option();
     opt_range->key = "range";
     opt_range->key_desc = "min,max";
-    opt_range->type = TYPE_DOUBLE;	/* should it be type_double or _string ?? */
+    opt_range->type = TYPE_DOUBLE;  /* should it be type_double or _string ?? */
     opt_range->required = NO;
     opt_range->description =
 	_("Use a subset of the map range for the legend (min,max)");
     opt_range->guisection = _("Subset");
 
+    opt_color = G_define_standard_option(G_OPT_C_FG);
+    opt_color->label = _("Text color");
+    opt_color->guisection = _("Font settings");
+
     opt_font = G_define_option();
     opt_font->key = "font";
     opt_font->type = TYPE_STRING;
@@ -207,17 +216,29 @@
     flipit->description = _("Flip legend");
     flipit->guisection = _("Advanced");
 
-    size = G_define_flag();
-    size->key = 's';
-    size->description = _("Font size is height in pixels");
-    size->guisection = _("Font settings");
+    histo = G_define_flag();
+    histo->key = 'd';
+    histo->description = _("Add histogram to smoothed legend");
+    histo->guisection = _("Gradient");
 
+
     /* Check command line */
     if (G_parser(argc, argv))
 	exit(EXIT_FAILURE);
 
+    /* FIXME: add GUI launching logic to G_parser() call */
+    if ((opt_rast2d->answer && opt_rast3d->answer) ||
+        !(opt_rast2d->answer || opt_rast3d->answer))
+	G_fatal_error(_("Please specify a single map name. To launch GUI use d.legend --ui."));
 
-    map_name = opt_input->answer;
+    if (opt_rast2d->answer) {
+	map_name = opt_rast2d->answer;
+	maptype = MAP_TYPE_RASTER2D;
+    }
+    else {
+	map_name = opt_rast3d->answer;
+	maptype = MAP_TYPE_RASTER3D;
+    }
 
     hide_catstr = hidestr->answer;	/* note hide_catstr gets changed and re-read below */
     hide_catnum = hidenum->answer;
@@ -225,11 +246,6 @@
     do_smooth = smooth->answer;
     flip = flipit->answer;
 
-    if (opt_fontsize->answer != NULL)
-	fontsize = atof(opt_fontsize->answer);
-    else
-	fontsize = 12; /* dummy placeholder, should never be called */
-
     color = D_parse_color(opt_color->answer, TRUE);
 
     if (opt_lines->answer != NULL)
@@ -275,34 +291,46 @@
 	}
     }
 
+    if (maptype == MAP_TYPE_RASTER2D) {
+	if (Rast_read_colors(map_name, "", &colors) == -1)
+	    G_fatal_error(_("Color file for <%s> not available"), map_name);
 
-    if (Rast_read_colors(map_name, "", &colors) == -1)
-	G_fatal_error(_("Color file for <%s> not available"), map_name);
+	fp = Rast_map_is_fp(map_name, "");
+ 
+	Rast_read_cats(map_name, "", &cats);
+    }
+    else {
+	if (Rast3d_read_colors(map_name, "", &colors) == -1)
+	    G_fatal_error(_("Color file for <%s> not available"), map_name);
 
-    fp = Rast_map_is_fp(map_name, "");
+	fp = TRUE;  /* currently raster 3D is always floating point */
+
+	Rast3d_read_cats(map_name, "", &cats);
+    }
+
     if (fp && !use_catlist) {
 	do_smooth = TRUE;
 	/* fprintf(stderr, "FP map found - switching gradient legend on\n"); */
 	flip = !flip;
     }
 
-    if (Rast_read_cats(map_name, "", &cats) == -1)
-	G_warning(_("Category file for <%s> not available"), map_name);
-
-    Rast_set_c_null_value(&null_cell, 1);
-
     if (D_open_driver() != 0)
-      	G_fatal_error(_("No graphics device selected. "
+	G_fatal_error(_("No graphics device selected. "
 			"Use d.mon to select graphics device."));
-    
+
     white = D_translate_color(DEFAULT_FG_COLOR);
     black = D_translate_color(DEFAULT_BG_COLOR);
-    
+
     if (opt_font->answer)
 	D_font(opt_font->answer);
     else if (opt_path->answer)
 	D_font(opt_path->answer);
 
+    if (opt_fontsize->answer != NULL)
+	fontsize = atof(opt_fontsize->answer);
+    else
+	fontsize = 12; /* dummy placeholder, should never be called */
+
     if (opt_charset->answer)
 	D_encoding(opt_charset->answer);
 
@@ -321,11 +349,16 @@
 	Y0 = 88;
 	X0 = 3;
 	X1 = 7;
+
+	if (histo->answer) {
+	    X0 += 5;
+	    X1 += 5;
+	}
     }
 
     x0 = l + (int)((r - l) * X0 / 100.);
     x1 = l + (int)((r - l) * X1 / 100.);
-    y0 = t + (int)((b - t) * (100. - Y0) / 100.);	/* make lower left the origin */
+    y0 = t + (int)((b - t) * (100. - Y0) / 100.);  /* make lower left the origin */
     y1 = t + (int)((b - t) * (100. - Y1) / 100.);
 
     if (y0 > y1) {		/* allow for variety in order of corner */
@@ -523,13 +556,19 @@
 		sprintf(DispFormat, "%%2d");
 	}
     }
-    else {			/* is fp */
-	if (Rast_read_fp_range(map_name, "", &fprange) == -1)
-	    G_fatal_error(_("Range information for <%s> not available"),
-			  map_name);
+    else {	/* is fp */
+	if (maptype == MAP_TYPE_RASTER2D) {
+	    if (Rast_read_fp_range(map_name, "", &fprange) == -1)
+		G_fatal_error(_("Range information for <%s> not available"),
+				map_name);
+	}
+	else {
+	    if (Rast3d_read_range(map_name, "", &fprange) == -1)
+		G_fatal_error(_("Range information for <%s> not available"),
+				map_name);
+	}
 
 	Rast_get_fp_range_min_max(&fprange, &dmin, &dmax);
-
 	Rast_get_d_color_range(&min_dcolr, &max_dcolr, &colors);
 
 	if (UserRange) {
@@ -648,6 +687,7 @@
 								     1);
 
 		cstr = Rast_get_c_cat(&tcell, &cats);
+
 		if (!cstr[0])	/* no cats found, disable str output */
 		    hide_catstr = 1;
 		else
@@ -676,7 +716,7 @@
 		}
 	    }
 
-	    /* this probably shouldn't happen mid-loop as text sizes 
+	    /* this probably shouldn't happen mid-loop as text sizes
 	       might not end up being uniform, but it's a start */
 	    if (strlen(buff) > MaxLabelLen)
 		MaxLabelLen = strlen(buff);
@@ -716,24 +756,24 @@
 		    D_pos_abs(x1 + 4, y0 + ppl * k + txsiz / 2);
 	    }
 	    else {
-		/* text width is 0.81 of text height? so even though we set width 
+		/* text width is 0.81 of text height? so even though we set width
 		   to txsiz with D_text_size(), we still have to reduce.. hmmm */
 		if (!k)		/* first  */
 		    D_pos_abs(x0 - (strlen(buff) * txsiz * .81 / 2),
-			       y1 + 4 + txsiz);
+			      y1 + 4 + txsiz);
 		else if (k == steps - 1)	/* last */
 		    D_pos_abs(x1 - (strlen(buff) * txsiz * .81 / 2),
-			       y1 + 4 + txsiz);
+			      y1 + 4 + txsiz);
 		else
 		    D_pos_abs(x0 + ppl * k -
-			       (strlen(buff) * txsiz * .81 / 2),
-			       y1 + 4 + txsiz);
+			      (strlen(buff) * txsiz * .81 / 2),
+			      y1 + 4 + txsiz);
 	    }
 
-	    if(color)
+	    if (color)
 		D_text(buff);
 
-	}			/*for */
+	}	/* for */
 
 	lleg = y1 - y0;
 	wleg = x1 - x0;
@@ -760,8 +800,42 @@
 	D_end();
 	D_stroke();
 
+
+	/* print units label, if present */
+	if (maptype == MAP_TYPE_RASTER2D)
+	    units = Rast_read_units(map_name, "");
+	else
+	    units = "";
+/* FIXME: does the raster3d really need to be opened to read the units?
+	    units = Rast3d_get_unit(map_fid); */
+
+	if (!units)
+	    units = "";
+
+	if(strlen(units)) {
+	    D_use_color(color);
+	    /* D_text_size() should be already set */
+	    if (horiz)
+		D_pos_abs((x0 + x1)/2. - (strlen(units) * txsiz * 0.81)/2,
+			  y1 + (txsiz * 3));
+	    else
+		D_pos_abs(x1 - 4, y0 - (txsiz * 1.75));
+
+	    D_text(units);
+	}
+
+
+	/* 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);
+	}
+
     }
-    else {			/* non FP, no smoothing */
+    else {	/* non FP, no smoothing */
 
 	int true_l, true_r;
 	double txsiz;
@@ -908,11 +982,11 @@
 	    }
 	    else {		/* is fp */
 		if (!flip) {
-		    if(use_catlist)
+		    if (use_catlist)
 			/* pass through format exactly as given by the user in
 			   the use= command line parameter (helps with log scale) */
 			sprintf(buff, "%s", opt_use->answers[i]);
-		    else 
+		    else
 			/* automatically generated/tuned decimal precision format */
 			sprintf(buff, DispFormat, catlist[i]);
 		}
@@ -926,7 +1000,7 @@
 
 	    D_pos_abs((l + 3 + dots_per_line), (cur_dot_row) - 3);
 
-	    if(color)
+	    if (color)
 		D_text(buff);
 	}
 
@@ -953,13 +1027,13 @@
 	    }
 	    D_use_color(white);
 	    D_pos_abs((l + 3 + dots_per_line), (cur_dot_row));
-	    if(color)
+	    if (color)
 		D_text(buff);
 	}
     }
 
     D_save_command(G_recreate_command());
     D_close_driver();
-    
+
     exit(EXIT_SUCCESS);
 }



More information about the grass-commit mailing list