[GRASS-SVN] r68671 - grass/trunk/display/d.legend
svn_grass at osgeo.org
svn_grass at osgeo.org
Sun Jun 12 12:09:50 PDT 2016
Author: annakrat
Date: 2016-06-12 12:09:49 -0700 (Sun, 12 Jun 2016)
New Revision: 68671
Modified:
grass/trunk/display/d.legend/main.c
Log:
d.legend: improvements by Adam Laza: ticks, new options for labels, title, see #3014, #3015
Modified: grass/trunk/display/d.legend/main.c
===================================================================
--- grass/trunk/display/d.legend/main.c 2016-06-11 20:35:06 UTC (rev 68670)
+++ grass/trunk/display/d.legend/main.c 2016-06-12 19:09:49 UTC (rev 68671)
@@ -15,6 +15,8 @@
* Markus Neteler
* Late 2002: Rewrite of much of the code:
* Hamish Bowman, Otago University, New Zealand
+ * Improvements (ticks, more label options, title):
+ * Adam Laza (part of GSoC 2016)
*
* COPYRIGHT: (c) 2002-2014 by The GRASS Development Team
*
@@ -48,8 +50,9 @@
int i, j, k;
int thin, lines, steps;
int fp;
+ int label_indent;
double t, b, l, r;
- int hide_catnum, hide_catstr, hide_nodata, do_smooth;
+ int hide_catnum, hide_catstr, show_ticks, hide_nodata, do_smooth;
char *cstr;
double x_box[5], y_box[5];
struct Categories cats;
@@ -57,8 +60,10 @@
struct GModule *module;
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, *histo;
+ *opt_font, *opt_path, *opt_charset, *opt_fontsize, *opt_title,
+ *opt_ticks, *opt_tstep;
+ struct Flag *hidestr, *hidenum, *hidenodata, *smooth, *flipit, *histo,
+ *showtick;
struct Range range;
struct FPRange fprange, render_range;
CELL min_ind, max_ind;
@@ -73,11 +78,13 @@
int flip, horiz, UserRange;
double UserRangeMin, UserRangeMax, UserRangeTemp;
double *catlist, maxCat;
- int catlistCount, use_catlist;
+ int catlistCount, use_catlist, ticksCount;
double fontsize;
char *units;
+ char *title;
+ double *tick_values;
+ double t_start, t_step;
-
/* Initialize the GIS calls */
G_gisinit(argv[0]);
@@ -99,6 +106,12 @@
opt_rast3d->required = NO;
opt_rast3d->guisection = _("Input");
+ opt_title = G_define_option();
+ opt_title->key = "title";
+ opt_title->type = TYPE_STRING;
+ opt_title->required = NO;
+ opt_title->description = _("Legend title");
+
opt_lines = G_define_option();
opt_lines->key = "lines";
opt_lines->type = TYPE_INTEGER;
@@ -127,6 +140,26 @@
_("Number of text labels for smooth gradient legend");
opt_labelnum->guisection = _("Gradient");
+ opt_ticks = G_define_option();
+ opt_ticks->key = "label_values";
+ opt_ticks->type = TYPE_DOUBLE;
+ opt_ticks->required = NO;
+ opt_ticks->description =
+ _("Specific values of text labels");
+ opt_ticks->required = NO;
+ opt_ticks->multiple = YES;
+ opt_ticks->guisection = _("Gradient");
+
+ opt_tstep = G_define_option();
+ opt_tstep->key = "label_step";
+ opt_tstep->type = TYPE_DOUBLE;
+ opt_tstep->required = NO;
+ opt_tstep->description =
+ _("Display label every step");
+ opt_tstep->required = NO;
+ opt_tstep->guisection = _("Gradient");
+
+
opt_at = G_define_option();
opt_at->key = "at";
opt_at->key_desc = "bottom,top,left,right";
@@ -202,6 +235,11 @@
hidenum->description = _("Do not show category numbers");
hidenum->guisection = _("Advanced");
+ showtick = G_define_flag();
+ showtick->key = 't';
+ showtick->description = _("Draw legend ticks for labels");
+ showtick->guisection = _("Gradient");
+
hidenodata = G_define_flag();
hidenodata->key = 'n';
hidenodata->description = _("Skip categories with no label");
@@ -222,16 +260,15 @@
histo->description = _("Add histogram to smoothed legend");
histo->guisection = _("Gradient");
+ G_option_required(opt_rast2d, opt_rast3d, NULL);
+ G_option_exclusive(opt_rast2d, opt_rast3d, NULL);
+ G_option_exclusive(hidenum, opt_ticks, NULL);
+ G_option_exclusive(hidenum, opt_tstep, NULL);
/* 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."));
-
if (opt_rast2d->answer) {
map_name = opt_rast2d->answer;
maptype = MAP_TYPE_RASTER2D;
@@ -241,12 +278,23 @@
maptype = MAP_TYPE_RASTER3D;
}
+ if (opt_title->answer)
+ title = opt_title->answer;
+
hide_catstr = hidestr->answer; /* note hide_catstr gets changed and re-read below */
hide_catnum = hidenum->answer;
+ show_ticks = showtick->answer;
hide_nodata = hidenodata->answer;
do_smooth = smooth->answer;
flip = flipit->answer;
+ if (showtick->answer){
+ show_ticks = showtick->answer;
+ label_indent = 12;
+ }
+ else
+ label_indent = 6;
+
color = D_parse_color(opt_color->answer, TRUE);
if (opt_lines->answer != NULL)
@@ -261,6 +309,24 @@
if (opt_labelnum->answer != NULL)
sscanf(opt_labelnum->answer, "%d", &steps);
+ if ((opt_tstep->answer) || (opt_ticks->answer))
+ steps = 0;
+
+ if (opt_tstep->answer != NULL)
+ t_step = atof(opt_tstep->answer);
+
+ ticksCount = 0;
+ if (opt_ticks->answer != NULL) {
+ tick_values = (double *)G_calloc(100+1, sizeof(double));
+ for (i = 0; i < 100; i++) /* fill with dummy values */
+ tick_values[i] = 1.0 * (i + 1);
+ tick_values[i] = 0;
+
+ for (i = 0; (opt_ticks->answers[i] != NULL) && i < 100; i++)
+ tick_values[i] = atof(opt_ticks->answers[i]);
+ ticksCount = i;
+ }
+
catlistCount = 0;
if (opt_use->answer != NULL) { /* should this be answerS ? */
use_catlist = TRUE;
@@ -317,8 +383,8 @@
D_open_driver();
- white = D_translate_color(DEFAULT_FG_COLOR);
- black = D_translate_color(DEFAULT_BG_COLOR);
+ black = D_translate_color(DEFAULT_FG_COLOR);
+ white = D_translate_color(DEFAULT_BG_COLOR);
if (opt_font->answer)
D_font(opt_font->answer);
@@ -621,8 +687,8 @@
if (do_smooth) {
int wleg, lleg, dx, dy;
- double txsiz;
- int ppl;
+ double txsiz, coef;
+ double ppl;
int tcell;
float ScaleFactor = 1.0;
@@ -671,23 +737,49 @@
if (!fp) { /* cut down labelnum so they don't repeat */
if (do_cats < steps)
steps = do_cats;
- if (1 == steps)
+ if ((steps < 2))
steps = 2; /* ward off the ppl floating point exception */
}
+
+ if (strlen(buff) > MaxLabelLen)
+ MaxLabelLen = strlen(buff);
+
+ /* Draw text and ticks */
+ if (!horiz)
+ txsiz = (y1 - y0) / 20;
+ else
+ txsiz = (x1 - x0) / 20;
+
+ /* scale text to fit in window if position not manually set */
+ /* usually not needed, except when frame is really narrow */
+ if (opt_at->answer == NULL) { /* ie default scaling */
+ ScaleFactor = ((r - x1) / ((MaxLabelLen + 1) * txsiz * 0.81)); /* ?? txsiz*.81=actual text width. */
+ if (ScaleFactor < 1.0) {
+ txsiz = txsiz * ScaleFactor;
+ }
+ }
+
+ if (opt_fontsize->answer != NULL)
+ txsiz = fontsize;
+
+ if (txsiz < 0)
+ txsiz = 0; /* keep it sane */
+
+ D_text_size(txsiz, txsiz);
+ D_use_color(color);
+
+
+ if (steps >= 2) {
for (k = 0; k < steps; k++) {
if (!fp) {
if (!flip)
tcell =
- min_ind + k * (double)(max_ind - min_ind) / (steps -
- 1);
+ min_ind + k * (double)(max_ind - min_ind) / (steps - 1);
else
tcell =
- max_ind - k * (double)(max_ind - min_ind) / (steps -
- 1);
+ max_ind - k * (double)(max_ind - min_ind) / (steps - 1);
- cstr = Rast_get_c_cat(&tcell, &cats);
-
if (!cstr[0]) /* no cats found, disable str output */
hide_catstr = 1;
else
@@ -716,91 +808,172 @@
}
}
- /* 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);
+ ppl = (lleg) / (steps * 1.0 - 1);
- /* Draw text */
- if (!horiz)
- txsiz = (y1 - y0) / 20;
- else
- txsiz = (x1 - x0) / 20;
+ if (!hide_catnum) {
+ if (!horiz) {
+ D_pos_abs(x1 + label_indent, y0 + ppl * k + txsiz / 2);
+ if (show_ticks)
+ D_line_abs(x1, y0 + ppl * k, x1 + 6, y0 + ppl * k);
+ }
+ else {
+ /* 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 */
+ D_pos_abs(x0 + ppl * k - (strlen(buff) * txsiz * .81 / 2),
+ y1 + label_indent + txsiz);
+ if (show_ticks)
+ D_line_abs(x0 + ppl * k, y1, x0 + ppl * k, y1 + 6);
+ }
- /* scale text to fit in window if position not manually set */
- /* usually not needed, except when frame is really narrow */
- if (opt_at->answer == NULL) { /* ie default scaling */
- ScaleFactor = ((r - x1) / ((MaxLabelLen + 1) * txsiz * 0.81)); /* ?? txsiz*.81=actual text width. */
- if (ScaleFactor < 1.0) {
- txsiz = txsiz * ScaleFactor;
+ if (color)
+ D_text(buff);
}
+
+ } /* for */
}
- if (opt_fontsize->answer != NULL)
- txsiz = fontsize;
+ lleg = y1 - y0;
+ wleg = x1 - x0;
- if (txsiz < 0)
- txsiz = 0; /* keep it sane */
+ /* draw tick_values labels and ticks */
+ if (ticksCount > 0) {
+ for (i = 0; i < ticksCount; i++) {
+ if ((tick_values[i] < dmin) || (tick_values[i] > dmax)) {
+ G_fatal_error(_("tick_value=%s out of range [%.3f, %.3f]"),
+ opt_ticks->answers[i], dmin, dmax);
+ }
+ coef = (tick_values[i] - dmin) / ((dmax - dmin) * 1.0);
+ sprintf(buff, DispFormat, tick_values[i]);
+ if (!flip){
+ if (!horiz) {
+ if (show_ticks)
+ D_line_abs(x1, y0 + coef * lleg,
+ x1 + 6, y0 + coef * lleg);
+ D_pos_abs(x1 + label_indent, y0 + coef * lleg + txsiz/2);}
+ else {
+ if (show_ticks)
+ D_line_abs(x0 + coef * wleg, y1,
+ x0 + coef * wleg, y1 + 6);
+ D_pos_abs(x0 + coef * wleg - (strlen(buff) * txsiz * .81 / 2),
+ y1 + label_indent + txsiz);}
+ }
+ else{
+ if (!horiz) {
+ if (show_ticks)
+ D_line_abs(x1, y1 - coef * lleg,
+ x1 + 6, y1 - coef * lleg);
+ D_pos_abs(x1 + label_indent, y1 - coef * lleg + txsiz/2);}
+ else {
+ if (show_ticks)
+ D_line_abs(x1 - coef * wleg, y1,
+ x1 - coef * wleg, y1 + 6);
+ D_pos_abs(x1 - coef * wleg - (strlen(buff) * txsiz * .81 / 2),
+ y1 + label_indent + txsiz);}
+ }
+ D_text(buff);
+ }
+ }
- D_text_size(txsiz, txsiz);
- D_use_color(color);
+ /* draw tick_step */
+ if (opt_tstep->answer) {
+ t_start = ceil(dmin/t_step) * t_step;
+ if (t_start == -0)
+ t_start = 0;
- ppl = (lleg) / (steps - 1);
+ if (!flip){
+ if (!horiz)
+ while (t_start<dmax) {
+ sprintf(buff, DispFormat, t_start);
+ coef = (t_start - dmin) / ((dmax - dmin) * 1.0);
+ if (show_ticks)
+ D_line_abs(x1, y0 + coef * lleg,
+ x1 + 6, y0 + coef * lleg);
+ D_pos_abs(x1 + label_indent, y0 + coef * lleg + txsiz/2);
+ D_text(buff);
- if (!horiz) {
- if (!k) /* first */
- D_pos_abs(x1 + 4, y0 + txsiz);
- else if (k == steps - 1) /* last */
- D_pos_abs(x1 + 4, y1);
+ t_start += t_step;}
else
- D_pos_abs(x1 + 4, y0 + ppl * k + txsiz / 2);
+ while (t_start<dmax) {
+ sprintf(buff, DispFormat, t_start);
+ coef = (t_start - dmin) / ((dmax - dmin) * 1.0);
+ if (show_ticks)
+ D_line_abs(x0 + coef * wleg,y1,
+ x0 + coef * wleg, y1 + 6);
+ D_pos_abs(x0 + coef * wleg - (strlen(buff) * txsiz * .81 / 2),
+ y1 + label_indent + txsiz);
+ D_text(buff);
+
+ t_start += t_step;}
}
else {
- /* 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);
- else if (k == steps - 1) /* last */
- D_pos_abs(x1 - (strlen(buff) * txsiz * .81 / 2),
- y1 + 4 + txsiz);
+ if (!horiz)
+ while (t_start<dmax) {
+ sprintf(buff, DispFormat, t_start);
+ coef = (t_start - dmin) / ((dmax - dmin) * 1.0);
+ if (show_ticks)
+ D_line_abs(x1, y1 - coef * lleg,
+ x1 + 6, y1 - coef * lleg);
+ D_pos_abs(x1 + label_indent, y1 - coef * lleg + txsiz/2);
+ D_text(buff);
+
+ t_start += t_step;}
else
- D_pos_abs(x0 + ppl * k -
- (strlen(buff) * txsiz * .81 / 2),
- y1 + 4 + txsiz);
- }
-
- if (color)
+ while (t_start<dmax) {
+ sprintf(buff, DispFormat, t_start);
+ coef = (t_start - dmin) / ((dmax - dmin) * 1.0);
+ if (show_ticks)
+ D_line_abs(x1 - coef * wleg, y1,
+ x1 - coef * wleg, y1 + 6);
+ D_pos_abs(x1 - coef * wleg - (strlen(buff) * txsiz * .81 / 2),
+ y1 + label_indent + txsiz);
D_text(buff);
- } /* for */
+ t_start += t_step;}
+ }
+ }
- lleg = y1 - y0;
- wleg = x1 - x0;
+ /* White box */
+ D_use_color(white);
+ D_begin();
+ D_move_abs(x0 + 1, y0 + 1);
+ D_cont_rel(0, lleg - 2);
+ D_cont_rel(wleg - 2, 0);
+ D_cont_rel(0, -lleg + 2);
+ D_close();
+ D_end();
+ D_stroke();
+
+ /* Black box */
+ D_use_color(black);
+ D_begin();
+ D_move_abs(x0, y0 );
+ D_cont_rel(0, lleg);
+ D_cont_rel(wleg, 0);
+ D_cont_rel(0, -lleg);
+ D_close();
+ D_end();
+ D_stroke();
+
+ if(opt_title->answer){
+ /* Display title */
+ double x_tit, y_tit;
- /* Black box */
- D_use_color(black);
- D_begin();
- D_move_abs(x0 + 1, y0 + 1);
- D_cont_rel(0, lleg - 2);
- D_cont_rel(wleg - 2, 0);
- D_cont_rel(0, 2 - lleg);
- D_close();
- D_end();
- D_stroke();
+ D_use_color(color);
- /* White box */
- D_use_color(white);
- D_begin();
- D_move_abs(x0, y0);
- D_cont_rel(0, lleg);
- D_cont_rel(wleg, 0);
- D_cont_rel(0, -lleg);
- D_close();
- D_end();
- D_stroke();
+ if (horiz){
+ x_tit = (x0 + x1)/2. - (strlen(title) * txsiz * 0.81)/2;
+ y_tit = y0 - (txsiz);
+ }
+ else{
+ x_tit = x0;
+ y_tit = y0 - (txsiz);
+ }
-
+ D_pos_abs(x_tit, y_tit);
+ D_text(title);
+ }
+ else{
+ /* Display units label */
/* print units label, if present */
if (maptype == MAP_TYPE_RASTER2D)
units = Rast_read_units(map_name, "");
@@ -821,10 +994,10 @@
if (horiz) {
x_pos = (x0 + x1)/2. - (strlen(units) * txsiz * 0.81)/2;
- y_pos = y1 + (txsiz * 3);
+ y_pos = y1 + (txsiz * 2.75);
}
else {
- x_pos = x1 - 4;
+ x_pos = x0;
if (default_pos)
y_pos = y0 - (txsiz * 1.75);
else
@@ -834,6 +1007,7 @@
D_pos_abs(x_pos, y_pos);
D_text(units);
}
+ }
/* display sidebar histogram, if requested */
@@ -938,9 +1112,9 @@
k++; /* count of actual boxes drawn (hide_nodata option invaidates using j-1) */
- /* White box */
+ /* Black box */
cur_dot_row += dots_per_line;
- D_use_color(white);
+ D_use_color(black);
D_begin();
D_move_abs(l + 2, (cur_dot_row - 1));
D_cont_rel(0, (3 - dots_per_line));
@@ -950,8 +1124,8 @@
D_end();
D_stroke();
- /* Black box */
- D_use_color(black);
+ /* White box */
+ D_use_color(white);
D_begin();
D_move_abs(l + 3, (cur_dot_row - 2));
D_cont_rel(0, (5 - dots_per_line));
More information about the grass-commit
mailing list