2
/**********************************************************************
4
* Code in this file works with category files. There are two formats:
5
* Pre 3.0 direct category encoding form:
9
* Elevation: 1000.00 to 1005.00 feet
10
* Elevation: 1005.00 to 1010.00 feet
11
* Elevation: 1010.00 to 1015.00 feet
17
* Elevation: $1.2 to $2.2 feet ## Format Statement
18
* 5.0 1000 5.0 1005 ## Coefficients
20
* The coefficient line can be followed by explicit category labels
21
* which override the format label generation.
24
* 5: . ## explicit category labels
26
* explicit labels can be also of the form:
27
* 5.5:5:9 label description
29
* 15:30 label description
32
* $1 refers to the value num*5.0+1000 (ie, using the first 2 coefficients)
33
* $2 refers to the value num*5.0+1005 (ie, using the last 2 coefficients)
35
* $1.2 will print $1 with 2 decimal places.
37
* Also, the form $?xxx$yyy$ translates into yyy if the category is 1, xxx
38
* otherwise. The $yyy$ is optional. Thus
42
* will become: 1 meter (for category 1)
43
* 2 meters (for category 2), etc.
45
* The format and coefficients above would be used to generate the
46
* following statement in creation of the format appropriate category
47
* string for category "num":
49
* sprintf(buff,"Elevation: %.2f to %.2f feet", num*5.0+1000, num*5.0*1005)
51
* Note: while both the format and coefficent lins must be present
52
* a blank line for the fmt will effectively suppress automatic
55
* Note: quant rules of Categories structures are heavily dependent
56
* on the fact that rules are stored in the same order they are entered.
57
* since i-th rule and i-th label are entered at the same time, we
58
* know that i-th rule maps fp range to i, thus we know for sure
59
* that cats.labels[i] corresponds to i-th quant rule
61
**********************************************************************
63
* G_read_[raster]_cats (name, mapset, pcats)
64
* char *name name of cell file
65
* char *mapset mapset that cell file belongs to
66
* struct Categories *pcats structure to hold category info
68
* Reads the category information associated with cell file "name"
69
* in mapset "mapset" into the structure "pcats".
71
* returns: 0 if successful
74
* note: a warning message is printed if the file is
75
* "missing" or "invalid".
76
**********************************************************************
78
* G_copy_raster_cats (pcats_to, pcats_from)
79
* struct Categories *pcats_to
80
* const struct Categories *pcats_from
82
* Allocates NEW space for quant rules and labels and copies
83
* all info from "from" cats to "to" cats
85
* returns: 0 if successful
88
**********************************************************************
90
* G_read_vector_cats (name, mapset, pcats)
91
* char *name name of vector map
92
* char *mapset mapset that vector map belongs to
93
* struct Categories *pcats structure to hold category info
96
* returns: 0 if successful
99
* note: a warning message is printed if the file is
100
* "missing" or "invalid".
101
**********************************************************************
102
* Returns pointer to a string describing category.
103
**********************************************************************
105
* G_number_of_cats(name, mapset)
106
* returns the largest category number in the map.
108
* WARING: do not use for fp maps!
109
**********************************************************************
112
* G_get_c/f/d_raster_cat (num, pcats)
113
* [F/D]CELL *val pointer to cell value
114
* struct Categories *pcats structure to hold category info
116
* Returns pointer to a string describing category.
118
**********************************************************************
121
* G_get_raster_cat (val, pcats, data_type)
122
* void *val pointer to cell value
123
* struct Categories *pcats structure to hold category info
124
* RASTER_MAP_TYPE data_type type of raster cell
126
* Returns pointer to a string describing category.
128
**********************************************************************
131
* G_get_ith_c/f/d_raster_cat (pcats, i, rast1, rast2)
132
* [F/D]CELL *rast1, *rast2 cat range
133
* struct Categories *pcats structure to hold category info
135
* Returns pointer to a string describing category.
137
**********************************************************************
140
* G_number_of_raster_cats (pcats)
141
* struct Categories *pcats structure to hold category info
143
* Returns pcats->ncats number of labels
145
**********************************************************************
148
* G_get_ith_raster_cat (pcats, i, rast1, rast2, data_type)
149
* void *rast1, *rast2 cat range
150
* struct Categories *pcats structure to hold category info
151
* RASTER_MAP_TYPE data_type type of raster cell
153
* Returns pointer to a string describing category.
155
**********************************************************************
158
* G_get_[raster]_cats_title (pcats)
159
* struct Categories *pcats structure to hold category info
161
* Returns pointer to a string with title
163
**********************************************************************
165
* G_init_cats (ncats, title, pcats)
166
* CELL ncats number of categories
167
* char *title cell title
168
* struct Categories *pcats structure to hold category info
170
* Initializes the cats structure for subsequent calls to G_set_cat()
171
**********************************************************************
173
* G_unmark_raster_cats (pcats)
174
* struct Categories *pcats structure to hold category info
176
* initialize cats.marks: the statistics of how many values of map
179
**********************************************************************
181
* G_rewind_raster_cats (pcats)
182
* struct Categories *pcats structure to hold category info
184
* after calll to this function G_get_next_marked_raster_cat() returns
185
* rhe first marked cat label.
187
**********************************************************************
189
* char* G_get_next_marked_raster_cat(pcats, rast1, rast2, stats, data_type)
190
* struct Categories *pcats structure to hold category info
191
* void *rast1, *rast2; pointers to raster range
193
* RASTER_MAP_TYPE data_type
195
* returns the next marked label.
198
**********************************************************************
200
* char* G_get_next_marked_f/d/craster_cat(pcats, rast1, rast2, stats)
201
* struct Categories *pcats structure to hold category info
202
* [D/F]CELL *rast1, *rast2; pointers to raster range
205
* returns the next marked label.
208
**********************************************************************
210
* G_mark_raster_cats (rast_row, ncols, pcats, data_type)
211
* void *raster_row; raster row to update stats
212
* struct Categories *pcats structure to hold category info
213
* RASTER_MAP_TYPE data_type;
214
* Finds the index of label for each raster cell in a row, and
215
* increases pcats->marks[index]
216
* Note: if there are no explicit cats: only rules for cats, no
219
**********************************************************************
221
* G_mark_c/d/f_raster_cats (rast_row, ncols, pcats)
223
* [D?F]CELL *raster_row; raster row to update stats
224
* struct Categories *pcats structure to hold category info
226
* Finds the index of label for each raster cell in a row, and
227
* increases pcats->marks[index]
229
**********************************************************************
231
* G_init_raster_cats (title, pcats)
232
* char *title cell title
233
* struct Categories *pcats structure to hold category info
235
* Initializes the cats structure for subsequent calls to G_set_cat()
237
**********************************************************************
239
* G_set_[raster]_cats_fmt (fmt, m1, a1, m2, a2, pcats)
240
* char *fmt user form of the equation format
241
* float m1,a1,m2,a2 coefficients
242
* struct Categories *pcats structure to hold category info
244
* configures the cats structure for the equation. Must be called
245
* after G_init_cats().
247
**********************************************************************
249
* G_set_[raster]_cats_title (title, pcats)
250
* char *title cell file title
251
* struct Categories *pcats structure holding category info
253
* Store title as cell file in cats structure
256
**********************************************************************
258
* G_set_cat (num, label, pcats)
259
* CELL num category number
260
* char *label category label
261
* struct Categories *pcats structure to hold category info
263
* Adds the string buff to represent category "num" in category structure
266
* Returns: 0 is cat is null value -1 too many cats, 1 ok.
268
**********************************************************************
270
* G_set_[f/d/c]_raster_cat (&val1, &val2, label, pcats)
271
* [D/F]CELL *val1, *val2; pointers to raster values
272
* char *label category label
273
* struct Categories *pcats structure to hold category info
275
* Adds the label for range val1 through val2 in category structure
278
* Returns: 0 if cat is null value -1 too many cats, 1 ok.
280
**********************************************************************
282
* G_set_raster_cat (val1, val2, label, pcats, data_type)
283
* void *val1, *val2; pointers to raster values
284
* char *label category label
285
* struct Categories *pcats structure to hold category info
286
* RASTER_MAP_TYPE data_type type of raster cell
288
* Adds the label for range val1 through val2 in category structure
291
* Returns: 0 if cat is null value -1 too many cats, 1 ok.
293
**********************************************************************
295
* G_write_[raster]_cats (name, pcats)
296
* char *name name of cell file
297
* struct Categories *pcats structure holding category info
299
* Writes the category information associated with cell file "name"
300
* into current mapset from the structure "pcats".
302
* returns: 1 if successful
304
**********************************************************************
306
* G_write_vector_cats (name, pcats)
307
* char *name name of vector map
308
* struct Categories *pcats structure holding category info
310
* Writes the category information associated with vector map "name"
311
* into current mapset from the structure "pcats".
313
* returns: 1 if successful
315
**********************************************************************
317
* G_free_[raster]_cats (pcats)
318
* struct Categories *pcats structure holding category info
320
* Releases memory allocated for the cats structure
321
**********************************************************************/
325
#include <grass/gis.h>
326
#include <grass/glocale.h>
328
static int get_cond(char **, char *, DCELL);
329
static int get_fmt(char **, char *, int *);
330
static int cmp(const void *, const void *);
334
* \brief read raster category file
336
* The category file for raster map
337
* <b>name</b> in <b>mapset</b> is read into the <b>cats</b> structure. If
338
* there is an error reading the category file, a diagnostic message is printed
339
* and -1 is returned. Otherwise, 0 is returned.
347
int G_read_cats(const char *name,
348
const char *mapset, struct Categories *pcats)
350
return G_read_raster_cats(name, mapset, pcats);
357
* Is the same as existing G_read_cats()
365
int G_read_raster_cats(const char *name,
366
const char *mapset, struct Categories *pcats)
370
switch (G__read_cats("cats", name, mapset, pcats, 1)) {
381
G_warning(_("category support for [%s] in mapset [%s] %s"),
388
* \brief read vector category file
390
* The category file for vector map
391
* <b>name</b> in <b>mapset</b> is read into the <b>cats</b> structure. If
392
* there is an error reading the category file, a diagnostic message is printed
393
* and -1 is returned. Otherwise, 0 is returned.
401
int G_read_vector_cats(const char *name,
402
const char *mapset, struct Categories *pcats)
406
switch (G__read_cats("dig_cats", name, mapset, pcats, 1)) {
417
G_warning(_("category support for vector map [%s] in mapset [%s] %s"),
422
CELL G_number_of_cats(const char *name, const char *mapset)
427
/* return the max category number */
428
if (G_read_range(name, mapset, &range) < 0)
430
G_get_range_min_max(&range, &min, &max);
431
if (G_is_c_null_value(&max))
436
CELL G__read_cats(const char *element,
438
const char *mapset, struct Categories * pcats, int full)
448
if (strncmp(element, "dig", 3) == 0)
451
fp_map = G_raster_map_is_fp(name, mapset);
453
if (!(fd = G_fopen_old(element, name, mapset)))
456
/* Read the number of categories */
457
if (G_getl(buff, sizeof buff, fd) == 0)
460
if (sscanf(buff, "# %ld", &num) == 1)
462
else if (sscanf(buff, "%ld", &num) == 1)
468
return 0; /* coorect */
472
/* Read the title for the file */
473
if (G_getl(buff, sizeof buff, fd) == 0)
476
/* G_ascii_check(buff) ; */
478
G_init_raster_cats(buff, pcats);
484
float m1, a1, m2, a2;
486
if (G_getl(fmt, sizeof fmt, fd) == 0)
488
/* next line contains equation coefficients */
489
if (G_getl(buff, sizeof buff, fd) == 0)
491
if (sscanf(buff, "%f %f %f %f", &m1, &a1, &m2, &a2) != 4)
493
G_set_raster_cats_fmt(fmt, m1, a1, m2, a2, pcats);
496
/* Read all category names */
497
for (cat = 0;; cat++) {
500
if (G_getl(buff, sizeof buff, fd) == 0)
503
G_set_cat(cat, buff, pcats);
506
if (sscanf(buff, "%1s", label) != 1)
511
/* for fp maps try to read a range of data */
513
&& sscanf(buff, "%lf:%lf:%[^\n]", &val1, &val2, label) == 3)
514
G_set_raster_cat(&val1, &val2, label, pcats, DCELL_TYPE);
515
else if (sscanf(buff, "%d:%[^\n]", &cat, label) >= 1)
516
G_set_raster_cat(&cat, &cat, label, pcats, CELL_TYPE);
517
else if (sscanf(buff, "%lf:%[^\n]", &val1, label) >= 1)
518
G_set_raster_cat(&val1, &val1, label, pcats, DCELL_TYPE);
533
* \brief get title from category structure struct
535
* Map layers store a one-line title in the category structure
536
* as well. This routine returns a pointer to the title contained in the
537
* <b>cats</b> structure. A legal pointer is always returned. If the map
538
* layer does not have a title, then a pointer to the empty string "" is
545
char *G_get_cats_title(const struct Categories *pcats)
547
return G_get_raster_cats_title(pcats);
552
* \brief get raster cats title
554
* Returns pointer to a string with title.
560
char *G_get_raster_cats_title(const struct Categories *pcats)
562
static char *none = "";
564
return pcats->title ? pcats->title : none;
569
* \brief get a category label
571
* This routine looks up category <b>n</b> in the <b>cats</b>
572
* structure and returns a pointer to a string which is the label for the
573
* category. A legal pointer is always returned. If the category does not exist
574
* in <b>cats,</b> then a pointer to the empty string "" is returned.
575
* <b>Warning.</b> The pointer that is returned points to a hidden static
576
* buffer. Successive calls to G_get_cat( ) overwrite this buffer.
583
char *G_get_cat(CELL num, struct Categories *pcats)
585
return G_get_c_raster_cat(&num, pcats);
592
* given a CELL value <em>val</em> Returns pointer to a string describing
600
char *G_get_c_raster_cat(CELL * rast, struct Categories *pcats)
602
return G_get_raster_cat(rast, pcats, CELL_TYPE);
609
* given a FCELL value <em>val</em> Returns pointer to a string
610
* describing category.
617
char *G_get_f_raster_cat(FCELL * rast, struct Categories *pcats)
619
return G_get_raster_cat(rast, pcats, FCELL_TYPE);
626
* given a DCELL value <em>val</em> Returns pointer to a string
627
* describing category.
634
char *G_get_d_raster_cat(DCELL * rast, struct Categories *pcats)
636
return G_get_raster_cat(rast, pcats, DCELL_TYPE);
643
* given a raster value <em>val</em> of type <em>data_type</em> Returns pointer to a string
644
* describing category.
652
char *G_get_raster_cat(void *rast,
653
struct Categories *pcats, RASTER_MAP_TYPE data_type)
655
static char label[1024];
660
char fmt[30], value_str[30];
662
if (G_is_null_value(rast, data_type)) {
663
sprintf(label, "no data");
667
/* first search the list of labels */
669
val = G_get_raster_value_d(rast, data_type);
670
i = G_quant_get_cell_value(&pcats->q, val);
672
G_debug(5, "G_get_raster_cat(): val %lf found i %d", val, i);
674
if (!G_is_c_null_value(&i) && i < pcats->ncats) {
675
if (pcats->labels[i] != NULL)
676
return pcats->labels[i];
680
/* generate the label */
681
if ((f = pcats->fmt) == NULL)
684
a[0] = (float)val *pcats->m1 + pcats->a1;
685
a[1] = (float)val *pcats->m2 + pcats->a2;
693
else if (*f == '?') {
695
get_cond(&f, v = value_str, val);
699
else if (get_fmt(&f, fmt, &i)) {
700
sprintf(v = value_str, fmt, a[i]);
720
* for all categories to 0. This initializes Categories structure for subsequest
721
* calls to G_mark_raster_cats (rast_row,...) for each row of data, where
722
* non-zero mark for i-th label means that some of the cells in rast_row are
723
* labeled with i-th label and fall into i-th data range.
724
* These marks help determine from the Categories structure which labels were
725
* used and which weren't.
731
int G_unmark_raster_cats(struct Categories *pcats)
732
{ /* structure to hold category info */
735
for (i = 0; i < pcats->ncats; i++)
744
* Looks up the category label for each raster value in
745
* the <em>rast_row</em> and updates the marks for labels found.
746
* NOTE: non-zero mark for i-th label stores the number of of raster cells read
747
* so far which are labeled with i-th label and fall into i-th data range.
755
int G_mark_c_raster_cats(CELL * rast_row, /* raster row to update stats */
756
int ncols, struct Categories *pcats)
757
{ /* structure to hold category info */
758
G_mark_raster_cats(rast_row, ncols, pcats, CELL_TYPE);
766
* Looks up the category label for each raster value in
767
* the <em>rast_row</em> and updates the marks for labels found.
768
* NOTE: non-zero mark for i-th label stores the number of of raster cells read
769
* so far which are labeled with i-th label and fall into i-th data range.
777
int G_mark_f_raster_cats(FCELL * rast_row, /* raster row to update stats */
778
int ncols, struct Categories *pcats)
779
{ /* structure to hold category info */
780
G_mark_raster_cats(rast_row, ncols, pcats, FCELL_TYPE);
788
* Looks up the category label for each raster value in
789
* the <em>rast_row</em> and updates the marks for labels found.
790
* NOTE: non-zero mark for i-th label stores the number of of raster cells read
791
* so far which are labeled with i-th label and fall into i-th data range.
799
int G_mark_d_raster_cats(DCELL * rast_row, /* raster row to update stats */
800
int ncols, struct Categories *pcats)
801
{ /* structure to hold category info */
802
G_mark_raster_cats(rast_row, ncols, pcats, DCELL_TYPE);
810
* Looks up the category
811
* label for each raster value in the <em>rast_row</em> (row of raster cell value)
812
* and updates the marks for labels found.
813
* NOTE: non-zero mark for i-th label stores the number of of raster cells read
814
* so far which are labeled with i-th label and fall into i-th data range.
823
int G_mark_raster_cats(void *rast_row, /* raster row to update stats */
824
int ncols, struct Categories *pcats, /* structure to hold category info */
825
RASTER_MAP_TYPE data_type)
829
while (ncols-- > 0) {
830
i = G_quant_get_cell_value(&pcats->q,
831
G_get_raster_value_d(rast_row, data_type));
832
if (G_is_c_null_value(&i))
834
if (i > pcats->ncats)
837
rast_row = G_incr_void_ptr(rast_row, G_raster_size(data_type));
847
* this function G_get_next_marked_raster_cat() returns the first marked
854
int G_rewind_raster_cats(struct Categories *pcats)
856
pcats->last_marked_rule = -1;
860
char *G_get_next_marked_d_raster_cat(struct Categories *pcats, /* structure to hold category info */
861
DCELL * rast1, DCELL * rast2, /* pointers to raster range */
868
/* pcats->ncats should be == G_quant_nof_rules(&pcats->q) */
870
fprintf (stderr, "last marked %d nrules %d\n", pcats->last_marked_rule, G_quant_nof_rules(&pcats->q));
872
for (i = pcats->last_marked_rule + 1; i < G_quant_nof_rules(&pcats->q);
874
descr = G_get_ith_d_raster_cat(pcats, i, rast1, rast2);
875
/* DEBUG fprintf (stderr, "%d %d\n", i, pcats->marks[i]); */
876
if (pcats->marks[i]) {
885
*count = pcats->marks[i];
886
pcats->last_marked_rule = i;
890
char *G_get_next_marked_c_raster_cat(struct Categories *pcats, /* structure to hold category info */
891
CELL * rast1, CELL * rast2, /* pointers to raster range */
894
return G_get_next_marked_raster_cat(pcats, rast1, rast2, count,
898
char *G_get_next_marked_f_raster_cat(struct Categories *pcats, /* structure to hold category info */
899
FCELL * rast1, FCELL * rast2, /* pointers to raster range */
902
return G_get_next_marked_raster_cat(pcats, rast1, rast2, count,
906
char *G_get_next_marked_raster_cat(struct Categories *pcats, /* structure to hold category info */
907
void *rast1, void *rast2, /* pointers to raster range */
908
long *count, RASTER_MAP_TYPE data_type)
913
lab = G_get_next_marked_d_raster_cat(pcats, &val1, &val2, count);
914
G_set_raster_value_d(rast1, val1, data_type);
915
G_set_raster_value_d(rast2, val2, data_type);
919
static int get_fmt(char **f, char *fmt, int *i)
950
while (*ff >= '0' && *ff <= '9')
958
static int get_cond(char **f, char *value, DCELL val)
990
* \brief set a category label
992
* The <b>label</b> is copied into the <b>cats</b> structure
993
* for category <b>n.</b>
1001
int G_set_cat(CELL num, char *label, struct Categories *pcats)
1005
return G_set_c_raster_cat(&tmp, &tmp, label, pcats);
1012
* Adds the label for range <em>rast1</em> through <em>rast2</em> in
1013
* category structure <em>pcats</em>.
1021
int G_set_c_raster_cat(CELL * rast1, CELL * rast2,
1022
char *label, struct Categories *pcats)
1024
return G_set_raster_cat(rast1, rast2, label, pcats, CELL_TYPE);
1031
* Adds the label for range <em>rast1</em> through <em>rast2</em>
1032
* in category structure <em>pcats</em>.
1040
int G_set_f_raster_cat(FCELL * rast1, FCELL * rast2,
1041
char *label, struct Categories *pcats)
1043
return G_set_raster_cat(rast1, rast2, label, pcats, FCELL_TYPE);
1050
* Adds the label for range <em>rast1</em> through <em>rast2</em>
1051
* in category structure <em>pcats</em>.
1059
int G_set_d_raster_cat(DCELL * rast1, DCELL * rast2,
1060
char *label, struct Categories *pcats)
1067
/* DEBUG fprintf(stderr,"G_set_d_raster_cat(rast1 = %p,rast2 = %p,label = '%s',pcats = %p)\n",
1068
rast1,rast2,label,pcats); */
1069
if (G_is_d_null_value(rast1))
1071
if (G_is_d_null_value(rast2))
1073
/* DEBUG fprintf (stderr, "G_set_d_raster_cat(): adding quant rule: %f %f %d %d\n", *rast1, *rast2, pcats->ncats, pcats->ncats); */
1074
/* the set_cat() functions are used in many places to reset the labels
1075
for the range (or cat) with existing label. In this case we don't
1076
want to store both rules with identical range even though the result
1077
of get_cat() will be correct, since it will use rule added later.
1078
we don't want to overuse memory and we don't want rules which are
1079
not used to be writen out in cats file. So we first look if
1080
the label for this range has been sen, and if it has, overwrite it */
1082
for (i = 0; i < pcats->ncats; i++) {
1083
descr = G_get_ith_d_raster_cat(pcats, i, &dtmp1, &dtmp2);
1084
if ((dtmp1 == *rast1 && dtmp2 == *rast2)
1085
|| (dtmp1 == *rast2 && dtmp2 == *rast1)) {
1086
if (pcats->labels[i] != NULL)
1087
G_free(pcats->labels[i]);
1088
pcats->labels[i] = G_store(label);
1089
G_newlines_to_spaces(pcats->labels[i]);
1090
G_strip(pcats->labels[i]);
1094
/* when rule for this range does not exist */
1095
/* DEBUG fprintf (stderr, "G_set_d_raster_cat(): New rule: adding %d %p\n", i, pcats->labels); */
1096
G_quant_add_rule(&pcats->q, *rast1, *rast2, pcats->ncats, pcats->ncats);
1098
if (pcats->nalloc < pcats->ncats) {
1099
/* DEBUG fprintf (stderr, "G_set_d_raster_cat(): need more space nalloc = %d ncats = %d\n", pcats->nalloc,pcats->ncats); */
1100
len = (pcats->nalloc + 256) * sizeof(char *);
1101
/* DEBUG fprintf (stderr, "G_set_d_raster_cat(): allocating %d labels(%d)\n", pcats->nalloc + 256,(int)len); */
1102
if (len != (int)len) { /* make sure len doesn't overflow int */
1106
/* DEBUG fprintf(stderr,"G_set_d_raster_cat(): pcats->nalloc = %d, pcats->labels = (%p), len = %d\n",pcats->nalloc,pcats->labels,(int)len); */
1107
if (pcats->nalloc) {
1108
/* DEBUG fprintf(stderr,"G_set_d_raster_cat(): Realloc-ing pcats->labels (%p)\n",pcats->labels); */
1110
(char **)G_realloc((char *)pcats->labels, (int)len);
1113
/* DEBUG fprintf(stderr,"G_set_d_raster_cat(): alloc-ing new labels pointer array\n"); */
1114
pcats->labels = (char **)G_malloc((int)len);
1116
/* fflush(stderr); */
1117
/* DEBUG fprintf (stderr, "G_set_d_raster_cats(): allocating %d marks(%d)\n", pcats->nalloc + 256,(int)len); */
1118
len = (pcats->nalloc + 256) * sizeof(int);
1119
if (len != (int)len) { /* make sure len doesn't overflow int */
1124
pcats->marks = (int *)G_realloc((char *)pcats->marks, (int)len);
1126
pcats->marks = (int *)G_malloc((int)len);
1127
pcats->nalloc += 256;
1129
/* DEBUG fprintf(stderr,"G_set_d_raster_cats(): store new label\n"); */
1130
pcats->labels[pcats->ncats - 1] = G_store(label);
1131
G_newlines_to_spaces(pcats->labels[pcats->ncats - 1]);
1132
G_strip(pcats->labels[pcats->ncats - 1]);
1134
fprintf (stderr, "%d %s\n", pcats->ncats - 1, pcats->labels[pcats->ncats - 1]);
1136
/* updates cats.num = max cat values. This is really just used in old
1137
raster programs, and I am doing it for backwards cmpatibility (Olga) */
1138
if ((CELL) * rast1 > pcats->num)
1139
pcats->num = (CELL) * rast1;
1140
if ((CELL) * rast2 > pcats->num)
1141
pcats->num = (CELL) * rast2;
1142
/* DEBUG fprintf(stderr,"G_set_d_raster_cat(): done\n"); */
1143
/* DEBUG fflush(stderr); */
1151
* Adds the label for range <em>rast1</em> through <em>rast2</em> in category structure <em>pcats</em>.
1160
int G_set_raster_cat(void *rast1, void *rast2,
1162
struct Categories *pcats, RASTER_MAP_TYPE data_type)
1166
val1 = G_get_raster_value_d(rast1, data_type);
1167
val2 = G_get_raster_value_d(rast2, data_type);
1168
return G_set_d_raster_cat(&val1, &val2, label, pcats);
1173
* \brief write raster category file
1175
* Writes the category file for the raster map <b>name</b> in
1176
* the current mapset from the <b>cats</b> structure.
1177
* Returns 1 if successful. Otherwise, -1 is returned (no diagnostic is
1185
int G_write_cats(char *name, struct Categories *cats)
1187
return G__write_cats("cats", name, cats);
1194
* Same as existing G_write_cats()
1201
int G_write_raster_cats(char *name, struct Categories *cats)
1203
return G__write_cats("cats", name, cats);
1209
* vector category file
1211
* Writes the category file for the vector map
1212
* <b>name</b> in the current mapset from the <b>cats</b> structure.
1213
* Returns 1 if successful. Otherwise, -1 is returned (no diagnostic is
1221
int G_write_vector_cats(char *name, struct Categories *cats)
1223
return G__write_cats("dig_cats", name, cats);
1226
int G__write_cats(char *element, char *name, struct Categories *cats)
1232
char str1[100], str2[100];
1234
/* DEBUG fprintf(stderr,"G__write_cats(*element = '%s', name = '%s', cats = %p\n",element,name,cats); */
1235
if (!(fd = G_fopen_new(element, name)))
1238
/* write # cats - note # indicate 3.0 or later */
1239
fprintf(fd, "# %ld categories\n", (long)cats->num);
1242
fprintf(fd, "%s\n", cats->title != NULL ? cats->title : "");
1244
/* write format and coefficients */
1245
fprintf(fd, "%s\n", cats->fmt != NULL ? cats->fmt : "");
1246
fprintf(fd, "%.2f %.2f %.2f %.2f\n",
1247
cats->m1, cats->a1, cats->m2, cats->a2);
1249
/* if the map is integer or if this is a vector map, sort labels */
1250
if (strncmp(element, "dig", 3) == 0)
1253
fp_map = G_raster_map_is_fp(name, G_mapset());
1254
/* DEBUG fprintf(stderr,"G__write_cats(): fp_map = %d\n",fp_map); */
1258
/* write the cat numbers:label */
1259
for (i = 0; i < G_quant_nof_rules(&cats->q); i++) {
1260
descr = G_get_ith_d_raster_cat(cats, i, &val1, &val2);
1261
if ((cats->fmt && cats->fmt[0])
1262
|| (descr && descr[0])) {
1264
sprintf(str1, "%.10f", val1);
1265
G_trim_decimal(str1);
1266
fprintf(fd, "%s:%s\n", str1, descr != NULL ? descr : "");
1269
sprintf(str1, "%.10f", val1);
1270
G_trim_decimal(str1);
1271
sprintf(str2, "%.10f", val2);
1272
G_trim_decimal(str2);
1273
fprintf(fd, "%s:%s:%s\n", str1, str2,
1274
descr != NULL ? descr : "");
1279
/* DEBUG fprintf(stderr,"G__write_cats(): done\n"); */
1287
* Returns i-th description and i-th data range
1288
* from the list of category descriptions with corresponding data ranges. end
1289
* points of data interval in <em>rast1</em> and <em>rast2</em>.
1298
char *G_get_ith_d_raster_cat(const struct Categories *pcats,
1299
int i, DCELL * rast1, DCELL * rast2)
1303
if (i > pcats->ncats) {
1304
G_set_d_null_value(rast1, 1);
1305
G_set_d_null_value(rast2, 1);
1308
G_quant_get_ith_rule(&pcats->q, i, rast1, rast2, &index, &index);
1309
return pcats->labels[index];
1316
* Returns i-th description and i-th data range
1317
* from the list of category descriptions with corresponding data ranges. end
1318
* points of data interval in <em>rast1</em> and <em>rast2</em>.
1327
char *G_get_ith_f_raster_cat(const struct Categories *pcats,
1328
int i, void *rast1, void *rast2)
1330
RASTER_MAP_TYPE data_type = FCELL_TYPE;
1334
tmp = G_get_ith_d_raster_cat(pcats, i, &val1, &val2);
1335
G_set_raster_value_d(rast1, val1, data_type);
1336
G_set_raster_value_d(rast2, val2, data_type);
1344
* Returns i-th description and i-th data range
1345
* from the list of category descriptions with corresponding data ranges. end
1346
* points of data interval in <em>rast1</em> and <em>rast2</em>.
1355
char *G_get_ith_c_raster_cat(const struct Categories *pcats,
1356
int i, void *rast1, void *rast2)
1358
RASTER_MAP_TYPE data_type = CELL_TYPE;
1362
tmp = G_get_ith_d_raster_cat(pcats, i, &val1, &val2);
1363
G_set_raster_value_d(rast1, val1, data_type);
1364
G_set_raster_value_d(rast2, val2, data_type);
1373
* description and i-th data range from the list of category descriptions with
1374
* corresponding data ranges. Stores end points of data interval in <em>rast1</em>
1375
* and <em>rast2</em> (after converting them to <em>data_type</em>.
1385
char *G_get_ith_raster_cat(const struct Categories *pcats, int i, void *rast1,
1386
void *rast2, RASTER_MAP_TYPE data_type)
1391
tmp = G_get_ith_d_raster_cat(pcats, i, &val1, &val2);
1392
G_set_raster_value_d(rast1, val1, data_type);
1393
G_set_raster_value_d(rast2, val2, data_type);
1399
* \brief initialize category structure
1401
* To construct a new category file, the
1402
* structure must first be initialized. This routine initializes the
1403
* <b>cats</b> structure, and copies the <b>title</b> into the structure.
1404
* The number of categories is set initially to <b>n.</b>
1407
struct Categories cats;
1408
G_init_cats ( (CELL)0, "", &cats);
1417
int G_init_cats(CELL num, const char *title, struct Categories *pcats)
1419
G_init_raster_cats(title, pcats);
1428
* Same as existing G_init_raster_cats() only ncats argument is
1429
* missign. ncats has no meaning in new Categories structure and only stores
1430
* (int) largets data value for backwards compatibility.
1437
int G_init_raster_cats(const char *title, struct Categories *pcats)
1439
G_set_raster_cats_title(title, pcats);
1440
pcats->labels = NULL;
1449
pcats->last_marked_rule = -1;
1450
G_quant_init(&pcats->q);
1456
* \brief set title in category structure
1458
* The <b>title</b> is copied into the
1459
* <b>cats</b> structure.
1466
int G_set_cats_title(const char *title, struct Categories *pcats)
1468
G_set_raster_cats_title(title, pcats);
1476
* Same as existing G_set_cats_title()
1483
int G_set_raster_cats_title(const char *title, struct Categories *pcats)
1487
pcats->title = G_store(title);
1488
G_newlines_to_spaces(pcats->title);
1489
G_strip(pcats->title);
1493
int G_set_cats_fmt(const char *fmt, double m1, double a1, double m2,
1494
double a2, struct Categories *pcats)
1496
G_set_raster_cats_fmt(fmt, m1, a1, m2, a2, pcats);
1504
* Same as existing G_set_cats_fmt()
1515
int G_set_raster_cats_fmt(const char *fmt, double m1, double a1, double m2,
1516
double a2, struct Categories *pcats)
1523
pcats->fmt = G_store(fmt);
1524
G_newlines_to_spaces(pcats->fmt);
1525
G_strip(pcats->fmt);
1531
* \brief free category structure memory
1533
* Frees memory allocated by<i>G_read_cats, G_init_cats</i>
1534
* and<i>G_set_cat.</i>
1540
int G_free_cats(struct Categories *pcats)
1542
G_free_raster_cats(pcats);
1550
* Same as existing G_free_cats()
1556
int G_free_raster_cats(struct Categories *pcats)
1560
if (pcats->title != NULL) {
1561
G_free(pcats->title);
1562
pcats->title = NULL;
1564
if (pcats->fmt != NULL) {
1568
if (pcats->ncats > 0) {
1569
for (i = 0; i < pcats->ncats; i++)
1570
if (pcats->labels[i] != NULL)
1571
G_free(pcats->labels[i]);
1572
G_free(pcats->labels);
1573
G_free(pcats->marks);
1574
pcats->labels = NULL;
1576
G_quant_free(&pcats->q);
1586
* Allocates NEW space for quant rules and labels n
1587
* <em>pcats_to</em> and copies all info from <em>pcats_from</em> cats to <em>pcats_to</em> cats.
1598
G_copy_raster_cats(struct Categories *pcats_to,
1599
const struct Categories *pcats_from)
1605
G_init_raster_cats(pcats_from->title, pcats_to);
1606
for (i = 0; i < pcats_from->ncats; i++) {
1607
descr = G_get_ith_d_raster_cat(pcats_from, i, &d1, &d2);
1608
G_set_d_raster_cat(&d1, &d2, descr, pcats_to);
1613
int G_number_of_raster_cats(struct Categories *pcats)
1615
return pcats->ncats;
1618
static struct Categories save_cats;
1620
int G_sort_cats(struct Categories *pcats)
1622
int *indexes, i, ncats;
1626
if (pcats->ncats <= 1)
1629
ncats = pcats->ncats;
1630
/* DEBUG fprintf(stderr,"G_sort_cats(): Copying to save cats buffer\n"); */
1631
G_copy_raster_cats(&save_cats, pcats);
1632
G_free_raster_cats(pcats);
1634
indexes = (int *)G_malloc(sizeof(int) * ncats);
1635
for (i = 0; i < ncats; i++)
1638
qsort(indexes, ncats, sizeof(int), cmp);
1639
G_init_raster_cats(save_cats.title, pcats);
1640
for (i = 0; i < ncats; i++) {
1641
descr = G_get_ith_d_raster_cat(&save_cats, indexes[i], &d1, &d2);
1642
/* DEBUG fprintf(stderr,"G_sort_cats(): Write sorted cats, pcats = %p pcats->labels = %p\n",pcats,pcats->labels); */
1643
G_set_d_raster_cat(&d1, &d2, descr, pcats);
1644
/* DEBUG fflush(stderr); */
1646
G_free_raster_cats(&save_cats);
1647
/* DEBUG fprintf(stderr,"G_sort_cats(): Done\n"); */
1648
/* fflush(stderr); */
1653
static int cmp(const void *aa, const void *bb)
1655
const int *a = aa, *b = bb;
1656
DCELL min_rast1, min_rast2, max_rast1, max_rast2;
1659
G_quant_get_ith_rule(&(save_cats.q), *a,
1660
&min_rast1, &max_rast1, &index, &index);
1661
G_quant_get_ith_rule(&(save_cats.q), *b,
1662
&min_rast2, &max_rast2, &index, &index);
1663
if (min_rast1 < min_rast2)
1665
if (min_rast1 > min_rast2)