GRASS GIS 8 Programmer's Manual  8.5.0dev(2024)-d6dec75dd4
gsd_legend.c
Go to the documentation of this file.
1 /*!
2  \file lib/ogsf/gsd_legend.c
3 
4  \brief OGSF library - legend creation
5 
6  GRASS OpenGL gsurf OGSF Library
7 
8  Converted code from legend.c in SG3d
9  routines to set viewport, close viewport, and make legend
10 
11  (C) 1999-2008 by the GRASS Development Team
12 
13  This program is free software under the
14  GNU General Public License (>=v2).
15  Read the file COPYING that comes with GRASS
16  for details.
17 
18  \author Bill Brown USACERL
19  \author Doxygenized by Martin Landa <landa.martin gmail.com> (May 2008)
20  */
21 
22 #include <stdlib.h>
23 
24 #include <grass/config.h>
25 
26 #if defined(OPENGL_X11) || defined(OPENGL_WINDOWS)
27 #include <GL/gl.h>
28 #include <GL/glu.h>
29 #elif defined(OPENGL_AQUA)
30 #include <OpenGL/gl.h>
31 #include <OpenGL/glu.h>
32 #endif
33 
34 #include <grass/gis.h>
35 #include <grass/raster.h>
36 #include <grass/glocale.h>
37 #include <grass/ogsf.h>
38 
39 #include "rgbpack.h"
40 
41 static float *Listcats;
42 static int Listnum = 0;
43 
44 /**** TODO
45 static int bigger(float *f1, float *f2)
46 {
47  return (*f1 < *f2 ? -1 : (*f1 > *f2));
48 }
49 *****/
50 
51 #define MAX_LEGEND 256
52 
53 /*!
54  \brief ADD
55 
56  \param wl
57  \param wb
58  \param wr
59  \param wt
60  */
61 void gsd_bgn_legend_viewport(GLint wl, GLint wb, GLint wr, GLint wt)
62 {
63  /* sets the viewport for the legend and the model matrix */
64 
66  glPushAttrib(GL_VIEWPORT);
67 
68  glMatrixMode(GL_PROJECTION);
69 
72  GS_ready_draw();
73 
74  gsd_linewidth(1);
75 
76  gsd_popmatrix();
77 
78  glViewport(wl, wb, (wr - wl), (wt - wb));
79  glLoadIdentity();
80  gluOrtho2D(-0.5, (wr - wl) + 0.5, -0.5, (wt - wb) + 0.5);
81  glMatrixMode(GL_MODELVIEW);
82  glPushMatrix();
83  glLoadIdentity();
84 
85  return;
86 }
87 
88 /*!
89  \brief ADD
90  */
92 {
93  /* closes the legend viewport and resets matrix and buffers */
94 
95  gsd_popmatrix();
96  glMatrixMode(GL_PROJECTION);
97  gsd_popmatrix();
98 
99  glPopAttrib();
100  glMatrixMode(GL_MODELVIEW);
101  gsd_popmatrix();
102 
103  GS_done_draw();
105 
106  return;
107 }
108 
109 /*!
110  \brief ADD
111 
112  \param lownum
113  \param highnum
114  \param numvals
115  \param vals
116 
117  \return 0 on failure
118  \return range value
119  */
120 int gsd_get_nice_range(float lownum, float highnum, int numvals, float *vals)
121 {
122  /* get a nice range for displaying legend */
123 
124  int num = 0;
125  float curnum, step, start;
126 
127  if (!numvals)
128  return (0);
129 
130  step = (highnum - lownum) / (float)numvals;
131  gsd_make_nice_number(&step);
132 
133  /* get a starting point */
134  start = step * (int)(1 + lownum / step);
135  if (start - lownum < .65 * step)
136  start += step;
137 
138  for (curnum = start; curnum < (highnum - .65 * step); curnum += step) {
139  vals[num++] = curnum;
140  }
141 
142  return (num);
143 }
144 
145 /*!
146  \brief ADD
147 
148  \param num
149 
150  \return 0 on error
151  \return 1 on success
152  */
153 int gsd_make_nice_number(float *num)
154 {
155  float newnum, nextnum;
156 
157  if (*num < 0)
158  return (0);
159 
160  if (*num < 1) {
161  newnum = 1.;
162  while (.5 * newnum > *num) {
163  nextnum = newnum / 10.;
164  newnum /= 2.;
165  if (.5 * newnum > *num)
166  newnum /= 2.;
167  if (.5 * newnum > *num)
168  newnum = nextnum;
169  }
170  }
171  else {
172  newnum = 1.;
173  while (2 * newnum <= *num) {
174  nextnum = newnum * 10.;
175  newnum *= 2.5;
176  if (2 * newnum <= *num)
177  newnum *= 2.;
178  if (2 * newnum <= *num)
179  newnum = nextnum;
180  }
181  if (newnum == 2.5)
182  newnum = 3;
183  /* 2.5 isn't nice, but .25, 25, 250 ... are */
184  }
185  *num = newnum;
186  return (1);
187 }
188 
189 /*!
190  \brief Put legend
191 
192  \param name
193  \param fontbase font-base
194  \param size
195  \param flags
196  \param rangef
197  \param pt
198 
199  \return
200  */
201 GLuint gsd_put_legend(const char *name, GLuint fontbase, int size, int *flags,
202  float *rangef, int *pt)
203 {
204  GLint sl, sr, sb, st;
205  GLuint legend_list;
206  int cat_labs = 0, cat_vals = 0, do_invert = 0, discrete = 0;
207  int is_fp, fprec, iprec;
208  struct Categories cats;
209  struct Range range;
210  struct FPRange fp_range;
211  const char *mapset;
212  struct Colors colors;
213  CELL min, max;
214  DCELL fmin, fmax;
215  float labvals[12];
216 
217  legend_list = gsd_makelist();
218  gsd_bgnlist(legend_list, 1);
219 
220  /* set coords from pt */
221  sl = pt[0];
222  sr = pt[1];
223  sb = pt[2];
224  st = pt[3];
225 
226  /* set legend flags */
227  if (flags[0])
228  cat_vals = 1;
229  if (flags[1])
230  cat_labs = 1;
231  if (flags[3])
232  discrete = 1;
233  if (flags[2])
234  do_invert = 1;
235 
236  mapset = G_find_raster2(name, "");
237  if (mapset == NULL) {
238  G_warning(_("Raster map <%s> not found"), name);
239  return (-1);
240  }
241 
242  is_fp = Rast_map_is_fp(name, mapset);
243 
244  if (Rast_read_colors(name, mapset, &colors) == -1) {
245  G_warning(_("Unable to read color file of raster map <%s>"), name);
246  return (-1);
247  }
248 
249  if (cat_labs)
250  if (Rast_read_cats(name, mapset, &cats) == -1) {
251  G_warning(_("Unable to read category file of raster map <%s>"),
252  name);
253  cat_labs = 0;
254  }
255 
256  if (flags[4] && rangef[0] != -9999. && rangef[1] != -9999.) {
257  fmin = rangef[0];
258  fmax = rangef[1];
259  if (!is_fp) {
260  min = (int)fmin;
261  max = (int)fmax;
262  }
263  }
264  else {
265  if (is_fp) {
266  if (Rast_read_fp_range(name, mapset, &fp_range) != 1) {
267  G_warning(_("Unable to read fp range of raster map <%s>"),
268  name);
269  return (-1);
270  }
271  Rast_get_fp_range_min_max(&fp_range, &fmin, &fmax);
272  if (flags[4] && rangef[0] != -9999.)
273  fmin = rangef[0];
274  if (flags[4] && rangef[1] != -9999.)
275  fmax = rangef[1];
276  }
277  else {
278  if (Rast_read_range(name, mapset, &range) == -1) {
279  G_warning(_("Unable to read range of raster map <%s>"), name);
280  return (-1);
281  }
282  Rast_get_range_min_max(&range, &min, &max);
283  if (flags[4] && rangef[0] != -9999.)
284  min = rangef[0];
285  if (flags[4] && rangef[1] != -9999.)
286  max = rangef[1];
287  fmin = min;
288  fmax = max;
289  }
290  }
291 
292  if (fmin == fmax)
293  G_warning(_("Range request error for legend"));
294 
295  /* set a reasonable precision */
296  if (is_fp) {
297  float df;
298 
299  df = fmax - fmin;
300  if (df < .1)
301  fprec = 6;
302  else if (df < 1)
303  fprec = 4;
304  else if (df < 10)
305  fprec = 3;
306  else if (df < 100)
307  fprec = 2;
308  else
309  fprec = 1;
310  }
311  else {
312  int tmp, p1, p2;
313 
314  iprec = p1 = p2 = 1;
315  if (max > 0)
316  for (tmp = 1; tmp < max; tmp *= 10, p1++)
317  ;
318  if (min < 0)
319  for (tmp = -1; tmp > min; tmp *= 10, p2++)
320  ;
321 
322  iprec = (p1 > p2 ? p1 : p2);
323  }
324 
325  /*********
326  * TODO incorp lists
327 
328  if(list && (legend_type & LT_LIST)){
329  Listcats = list;
330  Listnum = nlist;
331  qsort(Listcats, Listnum, sizeof(float), bigger);
332  discrete = 1;
333  }
334  else
335  Listnum = 0;
336 
337  *********/
338 
339  /* how many labels? */
340  /*
341  numlabs can't be = max - min + 1 any more because of floating point
342  maybe shouldn't allow discrete legend for floating point maps (unless
343  list) or else check number of different values in floating point map and
344  use each if "reasonable" gs_get_values_in_range(gs, att, low, high,
345  values, &nvals) the nvals sent has a max number to return, nvals returned
346  is the actual number set in values, return val is 1 on success, -1 if >
347  max vals found
348 
349  might need to think about doing histograms first & use same routines here
350  could also have a LT_MOST that would limit # to some N most frequent
351  */
352 
353  /*!
354  ???
355  */
356  {
357  int i, k, lleg, horiz;
358  int red, green, blue;
359  CELL tcell;
360  DCELL tdcell, pdcell;
361  float vert1[2], vert2[2], vert3[2], vert4[2];
362  float *dv1, *dv2; /* changing vertex coord */
363  float *sv1, *sv2; /* stable vertex coord */
364  float stab1, stab2;
365  unsigned long colr;
366  float *dividers;
367  int labw, maxlabw, numlabs;
368  float labpos, labpt[3];
369  const char *cstr;
370  char buff[80];
371  GLint wt, wb, wl, wr; /* Whole legend area, not just box */
372  int xoff, yoff;
373  int incr; /* for do_invert */
374 
375  horiz = (sr - sl > st - sb);
376  dividers = NULL;
377 
378  if (discrete) {
379  numlabs = Listnum ? Listnum : max - min + 1;
380  /* watch out for trying to display mega cats */
381  if (is_fp && !Listnum) {
382  discrete = 0; /* maybe later do stats & allow if few #s */
383  G_warning(_("Unable to show discrete FP range (use list)"));
384  return (-1);
385  }
386  if (numlabs < MAX_LEGEND)
387  dividers = (float *)G_malloc(numlabs * sizeof(float));
388  }
389  else {
390  numlabs = gsd_get_nice_range(fmin, fmax, 4, labvals + 1);
391  labvals[0] = fmin;
392  labvals[numlabs + 1] = fmax;
393  numlabs += 2;
394  }
395 
396  /* find longest string, reset viewport & saveunder */
397  maxlabw = 0;
398 
399  if (cat_labs || cat_vals) {
400  for (k = 0; k < numlabs; k++) {
401  if (is_fp) {
402  tdcell = discrete ? Listcats[k] : labvals[k];
403  if (cat_labs) {
404  cstr = Rast_get_d_cat(&tdcell, &cats);
405  }
406  if (cat_labs && !cat_vals) {
407  sprintf(buff, "%s", cstr);
408  }
409  else {
410  if (cat_labs && cat_vals) {
411  if (cstr)
412  sprintf(buff, "%.*lf) %s", fprec, tdcell, cstr);
413  else
414  sprintf(buff, "%.*lf", fprec, tdcell);
415  }
416  else if (cat_vals)
417  sprintf(buff, "%.*lf", fprec, tdcell);
418  }
419  }
420  else {
421  tcell =
422  discrete ? Listnum ? Listcats[k] : min + k : labvals[k];
423  if (cat_labs && !cat_vals)
424  sprintf(buff, "%s", Rast_get_c_cat(&tcell, &cats));
425  else {
426  if (cat_labs && cat_vals) {
427  cstr = Rast_get_c_cat(&tcell, &cats);
428  if (cstr[0])
429  sprintf(buff, "%*d) %s", iprec, tcell, cstr);
430  else
431  sprintf(buff, "%d", tcell);
432  }
433  else if (cat_vals)
434  sprintf(buff, "%d", tcell);
435  }
436  }
437  labw = gsd_get_txtwidth(buff, size);
438  if (labw > maxlabw) {
439  maxlabw = labw;
440  }
441  }
442  }
443 
444  if (horiz) {
445  xoff = maxlabw / 2 + get_txtxoffset();
446  wl = sl - xoff;
447  wr = sr + xoff;
448  yoff = 0;
449  wb = sb;
450  /*
451  wt = st + gsd_get_txtheight() + get_txtdescender() +3;
452  */
453  wt = st + gsd_get_txtheight(size) * 2 + 3;
454  }
455  else {
456  xoff = 0;
457  wl = sl;
458  wr = sr + maxlabw + get_txtxoffset() + 3;
459  /*
460  yoff = gsd_get_txtheight()/2 + get_txtdescender();
461  */
462  yoff = gsd_get_txtheight(size);
463  wb = sb - yoff;
464  wt = st + yoff;
465  }
466 
467  /* initialize viewport */
468  gsd_bgn_legend_viewport(wl, wb, wr, wt);
469 
470  vert1[X] = vert2[X] = xoff;
471  vert1[Y] = vert2[Y] = yoff;
472  if (horiz) {
473  lleg = sr - sl;
474  dv1 = vert1 + X;
475  dv2 = vert2 + X;
476  sv1 = vert1 + Y;
477  sv2 = vert2 + Y;
478  stab2 = vert2[Y] = st - sb + yoff;
479  stab1 = vert1[Y] = yoff;
480  if (do_invert)
481  vert1[X] = vert2[X] = sr - sl + xoff;
482  }
483  else {
484  lleg = st - sb;
485  dv1 = vert1 + Y;
486  dv2 = vert2 + Y;
487  sv1 = vert1 + X;
488  sv2 = vert2 + X;
489  stab2 = vert2[X] = sr - sl + xoff;
490  stab1 = vert1[X] = xoff;
491  if (do_invert)
492  vert1[Y] = vert2[Y] = st - sb + yoff;
493  }
494 
495  if (discrete) {
496  if (numlabs > lleg / 5)
497  G_warning(_("Too many categories to show as discrete!"));
498  else if (numlabs > 1.2 * lleg / gsd_get_txtheight(size))
499  G_warning(_("Try using smaller font!"));
500  }
501 
502  incr = do_invert ? -1 : 1;
503  for (k = 0, i = 0; k < lleg; k++) {
504  if (discrete && Listnum)
505  tdcell = Listcats[(int)((float)k * numlabs / lleg)];
506  else {
507  tcell = min + k * (max - min + 1) / lleg;
508  tdcell = fmin + k * (fmax - fmin) / lleg;
509  if (!is_fp)
510  tdcell = tcell;
511  }
512  if (k == 0 || tdcell != pdcell) {
513  if (is_fp)
514  Rast_get_d_color(&tdcell, &red, &green, &blue, &colors);
515  else
516  Rast_get_c_color((CELL *)&tdcell, &red, &green, &blue,
517  &colors);
518 
519  RGB_TO_INT(red, green, blue, colr);
520  if (discrete) { /* draw black-white-black separator */
521  if (k > 0) {
522  *dv1 -= 2. * incr;
523  *dv2 -= 2. * incr;
524  gsd_color_func(0x0);
525  gsd_bgnline();
526  glVertex2fv(vert1);
527  glVertex2fv(vert2);
528  gsd_endline();
529 
530  *dv1 += 1. * incr;
531  *dv2 += 1. * incr;
532  if (dividers)
533  dividers[i++] = *dv1;
534 
535  *dv1 += 1. * incr;
536  *dv2 += 1. * incr;
537  gsd_color_func(0x0);
538  gsd_bgnline();
539  glVertex2fv(vert1);
540  glVertex2fv(vert2);
541  gsd_endline();
542 
543  *dv1 += 1. * incr;
544  *dv2 += 1. * incr;
545  pdcell = tdcell;
546  continue;
547  }
548  }
549  }
550 
551  gsd_color_func(colr);
552  gsd_bgnline();
553  glVertex2fv(vert1);
554  glVertex2fv(vert2);
555  gsd_endline();
556  glFlush();
557  *dv1 += 1. * incr;
558  *dv2 += 1. * incr;
559  pdcell = tdcell;
560  }
561 
562  /* Black box */
563  vert1[X] = vert2[X] = 1. + xoff;
564  vert1[Y] = vert4[Y] = 1. + yoff;
565  vert3[X] = vert4[X] = sr - sl - 1. + xoff;
566  vert3[Y] = vert2[Y] = st - sb - 1. + yoff;
567 
568  gsd_color_func(0x000000);
569  gsd_bgnline();
570  glVertex2fv(vert1);
571  glVertex2fv(vert2);
572  glVertex2fv(vert3);
573  glVertex2fv(vert4);
574  glVertex2fv(vert1);
575  gsd_endline();
576 
577  /* White box */
578  vert1[X] = vert2[X] = xoff;
579  vert1[Y] = vert4[Y] = yoff;
580  vert3[X] = vert4[X] = sr - sl + xoff;
581  vert3[Y] = vert2[Y] = st - sb + yoff;
582 
583  gsd_color_func(0xFFFFFF);
584  gsd_bgnline();
585  glVertex2fv(vert1);
586  glVertex2fv(vert2);
587  glVertex2fv(vert3);
588  glVertex2fv(vert4);
589  glVertex2fv(vert1);
590  gsd_endline();
591 
592  /* draw discrete dividers */
593  if (dividers) {
594  gsd_color_func(0xFFFFFFFF);
595  *sv1 = stab1;
596  *sv2 = stab2;
597  for (k = 0; k < i; k++) {
598  *dv1 = *dv2 = dividers[k];
599  gsd_bgnline();
600  glVertex2fv(vert1);
601  glVertex2fv(vert2);
602  gsd_endline();
603  }
604  }
605 
606  if (cat_labs || cat_vals) {
607  labpt[Z] = 0;
608  for (k = 0; k < numlabs; k++) {
609  if (is_fp) {
610  if (discrete && Listnum) {
611  tdcell = Listcats[k];
612  labpos = (k + .5) / numlabs;
613  }
614  else {
615  /* show_all not supported unless Listnum */
616  tdcell = labvals[k];
617  labpos = (tdcell - fmin) / (fmax - fmin);
618  }
619  }
620  else {
621  if (discrete && Listnum) {
622  tcell = Listcats[k];
623  labpos = (k + .5) / numlabs;
624  }
625  else {
626  tcell = discrete ? min + k : labvals[k];
627  labpos = (tcell - min + .5) / (max - min + 1);
628  }
629  }
630  if (do_invert)
631  labpos = 1. - labpos;
632  if (cat_labs) {
633  if (!is_fp)
634  cstr = Rast_get_c_cat(&tcell, &cats);
635  else
636  cstr = Rast_get_d_cat(&tdcell, &cats);
637  }
638  if (cat_labs && !cat_vals)
639  sprintf(buff, "%s", cstr);
640  else {
641  if (cat_labs && cat_vals) {
642  if (cstr)
643  if (is_fp)
644  sprintf(buff, "%.*lf) %s", fprec, tdcell, cstr);
645  else
646  sprintf(buff, "%*d) %s", iprec, tcell, cstr);
647  else if (is_fp)
648  sprintf(buff, "%.*lf", fprec, tdcell);
649  else
650  sprintf(buff, "%d", tcell);
651  }
652  else if (cat_vals) {
653  if (is_fp)
654  sprintf(buff, "%.*lf", fprec, tdcell);
655  else
656  sprintf(buff, "%d", tcell);
657  }
658  }
659  if (horiz) {
660  labpt[X] = labpos * (sr - sl) + xoff -
661  gsd_get_txtwidth(buff, size) / 2 -
662  get_txtxoffset();
663  labpt[Y] = st - sb + yoff + 3 + gsd_get_txtheight(size) / 2;
664  }
665  else {
666  labpt[X] = sr - sl + xoff + get_txtxoffset() + 3;
667  /*
668  labpt[Y] = labpos * (st - sb) + yoff -
669  gsd_get_txtheight()/2 + get_txtdescender();
670  */
671  labpt[Y] =
672  labpos * (st - sb) + yoff - gsd_get_txtheight(size);
673  }
674  /* set color for black text -- maybe add option for color
675  * supplied with font ??
676  */
677  gsd_color_func(0x000000);
678  do_label_display(fontbase, labpt, buff);
679  }
680  }
681 
682  if (discrete)
683  G_free(dividers);
684  }
685 
686  if (cat_labs)
687  Rast_free_cats(&cats);
688 
689  Rast_free_colors(&colors);
690 
692 
693  /*
694  gsd_unset_font(fontbase);
695  */
696 
697  gsd_endlist();
698 
699  return (legend_list);
700 }
#define NULL
Definition: ccmath.h:32
void G_free(void *)
Free allocated memory.
Definition: gis/alloc.c:150
void G_warning(const char *,...) __attribute__((format(printf
#define G_malloc(n)
Definition: defs/gis.h:94
const char * G_find_raster2(const char *, const char *)
Find a raster map (look but don't touch)
Definition: find_rast.c:76
void gsd_endlist(void)
End list.
Definition: gsd_prim.c:1140
void gsd_pushmatrix(void)
Push the current matrix stack.
Definition: gsd_prim.c:511
void GS_set_draw(int)
Sets which buffer to draw to.
Definition: gs2.c:2459
void do_label_display(GLuint, float *, const char *)
Display label.
Definition: gsd_fonts.c:97
void gsd_bgnlist(int, int)
ADD.
Definition: gsd_prim.c:1125
int gsd_makelist(void)
ADD.
Definition: gsd_prim.c:1094
int gsd_get_txtwidth(const char *, int)
Get text width.
Definition: gsd_fonts.c:36
int gsd_get_txtheight(int size)
Get text height.
Definition: gsd_fonts.c:53
void gsd_color_func(unsigned int)
Set current color.
Definition: gsd_prim.c:698
void GS_ready_draw(void)
Definition: gs2.c:2485
void gsd_popmatrix(void)
Pop the current matrix stack.
Definition: gsd_prim.c:501
int get_txtxoffset(void)
Get text offset.
Definition: gsd_fonts.c:85
void gsd_linewidth(short)
Set width of rasterized lines.
Definition: gsd_prim.c:267
void gsd_endline(void)
End line.
Definition: gsd_prim.c:407
void gsd_colormode(int)
Set color mode.
Definition: gsd_prim.c:98
void gsd_bgnline(void)
Begin line.
Definition: gsd_prim.c:397
void GS_done_draw(void)
Draw done, swap buffers.
Definition: gs2.c:2498
void Rast_free_cats(struct Categories *)
Free category structure memory.
Definition: raster/cats.c:1213
int Rast_get_c_color(const CELL *, int *, int *, int *, struct Colors *)
Gets color from raster map (CELL)
Definition: color_get.c:67
int Rast_read_colors(const char *, const char *, struct Colors *)
Read color table of raster map.
int Rast_read_cats(const char *, const char *, struct Categories *)
Read raster category file.
Definition: raster/cats.c:104
int Rast_read_fp_range(const char *, const char *, struct FPRange *)
Read floating-point range.
Definition: raster/range.c:71
void Rast_free_colors(struct Colors *)
Free color structure memory.
Definition: color_free.c:30
void Rast_get_fp_range_min_max(const struct FPRange *, DCELL *, DCELL *)
Get minimum and maximum value from fp range.
Definition: raster/range.c:768
void Rast_get_range_min_max(const struct Range *, CELL *, CELL *)
Get range min and max.
Definition: raster/range.c:718
int Rast_read_range(const char *, const char *, struct Range *)
Read raster range (CELL)
Definition: raster/range.c:160
char * Rast_get_c_cat(CELL *, struct Categories *)
Get a raster category label (CELL)
Definition: raster/cats.c:321
char * Rast_get_d_cat(DCELL *, struct Categories *)
Get a raster category label (DCELL)
Definition: raster/cats.c:369
int Rast_map_is_fp(const char *, const char *)
Check if raster map is floating-point.
Definition: raster/open.c:861
int Rast_get_d_color(const DCELL *, int *, int *, int *, struct Colors *)
Gets color from raster map (DCELL)
Definition: color_get.c:109
#define min(x, y)
Definition: draw2.c:29
#define max(x, y)
Definition: draw2.c:30
double DCELL
Definition: gis.h:629
int CELL
Definition: gis.h:628
#define _(str)
Definition: glocale.h:10
int gsd_make_nice_number(float *num)
ADD.
Definition: gsd_legend.c:153
GLuint gsd_put_legend(const char *name, GLuint fontbase, int size, int *flags, float *rangef, int *pt)
Put legend.
Definition: gsd_legend.c:201
int gsd_get_nice_range(float lownum, float highnum, int numvals, float *vals)
ADD.
Definition: gsd_legend.c:120
void gsd_end_legend_viewport(void)
ADD.
Definition: gsd_legend.c:91
void gsd_bgn_legend_viewport(GLint wl, GLint wb, GLint wr, GLint wt)
ADD.
Definition: gsd_legend.c:61
#define MAX_LEGEND
Definition: gsd_legend.c:51
const char * name
Definition: named_colr.c:6
#define X
Definition: ogsf.h:140
#define Z
Definition: ogsf.h:142
#define GSD_FRONT
Definition: ogsf.h:104
#define Y
Definition: ogsf.h:141
#define CM_COLOR
Definition: ogsf.h:148
#define GSD_BACK
Definition: ogsf.h:105
struct state * st
Definition: parser.c:104
#define RGB_TO_INT(r, g, b, i)
Definition: rgbpack.h:12
Definition: gis.h:686
Definition: raster.h:211