~ubuntu-branches/ubuntu/vivid/grass/vivid-proposed

« back to all changes in this revision

Viewing changes to lib/gis/cats.c

  • Committer: Package Import Robot
  • Author(s): Bas Couwenberg
  • Date: 2015-02-20 23:12:08 UTC
  • mfrom: (8.2.6 experimental)
  • Revision ID: package-import@ubuntu.com-20150220231208-1u6qvqm84v430b10
Tags: 7.0.0-1~exp1
* New upstream release.
* Update python-ctypes-ternary.patch to use if/else instead of and/or.
* Drop check4dev patch, rely on upstream check.
* Add build dependency on libpq-dev to grass-dev for libpq-fe.h.
* Drop patches applied upstream, refresh remaining patches.
* Update symlinks for images switched from jpg to png.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
 
2
 
/**********************************************************************
3
 
 *
4
 
 * Code in this file works with category files.  There are two formats:
5
 
 * Pre 3.0 direct category encoding form:
6
 
 * 
7
 
 *    2 categories
8
 
 *    Map Title
9
 
 *    Elevation: 1000.00 to 1005.00 feet
10
 
 *    Elevation: 1005.00 to 1010.00 feet
11
 
 *    Elevation: 1010.00 to 1015.00 feet
12
 
 *
13
 
 * 3.0 format
14
 
 * 
15
 
 *    # 2 categories
16
 
 *    Map Title
17
 
 *    Elevation: $1.2 to $2.2 feet       ## Format Statement
18
 
 *    5.0 1000 5.0 1005                  ## Coefficients
19
 
 *
20
 
 * The coefficient line can be followed by explicit category labels
21
 
 * which override the format label generation.
22
 
 *    0:no data
23
 
 *    2:   .
24
 
 *    5:   .                             ## explicit category labels
25
 
 *    7:   .
26
 
 * explicit labels can be also of the form:
27
 
 *    5.5:5:9 label description
28
 
 *    or
29
 
 *    15:30  label description
30
 
 *
31
 
 * In the format line
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)
34
 
 *
35
 
 *   $1.2 will print $1 with 2 decimal places.
36
 
 *
37
 
 * Also, the form $?xxx$yyy$ translates into yyy if the category is 1, xxx 
38
 
 * otherwise. The $yyy$ is optional. Thus
39
 
 *
40
 
 *   $1 meter$?s
41
 
 *
42
 
 * will become: 1 meter (for category 1)
43
 
 *              2 meters (for category 2), etc.
44
 
 *
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":
48
 
 *
49
 
 *   sprintf(buff,"Elevation: %.2f to %.2f feet", num*5.0+1000, num*5.0*1005)
50
 
 *
51
 
 * Note: while both the format and coefficent lins must be present
52
 
 *       a blank line for the fmt will effectively suppress automatic
53
 
 *       label generation
54
 
 *
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
60
 
 * 
61
 
 **********************************************************************
62
 
 *
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
67
 
 *
68
 
 *  Reads the category information associated with cell file "name"
69
 
 *  in mapset "mapset" into the structure "pcats".
70
 
 *
71
 
 *  returns:    0  if successful
72
 
 *             -1  on fail
73
 
 *
74
 
 *  note:   a warning message is printed if the file is
75
 
 *          "missing" or "invalid".
76
 
 **********************************************************************
77
 
 *
78
 
 *  G_copy_raster_cats (pcats_to, pcats_from)
79
 
 *      struct Categories *pcats_to
80
 
 *      const struct Categories *pcats_from
81
 
 *
82
 
 *  Allocates NEW space for quant rules and labels and copies
83
 
 *  all info from "from" cats to "to" cats
84
 
 *
85
 
 *  returns:    0  if successful
86
 
 *             -1  on fail
87
 
 *
88
 
 **********************************************************************
89
 
 *
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
94
 
 *
95
 
 *
96
 
 *  returns:    0  if successful
97
 
 *             -1  on fail
98
 
 *
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
 
 **********************************************************************
104
 
 *
105
 
 *  G_number_of_cats(name, mapset)
106
 
 *  returns the largest category number in the map.
107
 
 *  -1 on error
108
 
 *  WARING: do not use for fp maps!
109
 
 **********************************************************************
110
 
 *
111
 
 * char *
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
115
 
 *
116
 
 * Returns pointer to a string describing category.
117
 
 *
118
 
 **********************************************************************
119
 
 *
120
 
 * char *
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
125
 
 *
126
 
 * Returns pointer to a string describing category.
127
 
 *
128
 
 **********************************************************************
129
 
 *
130
 
 * char *
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
134
 
 *
135
 
 * Returns pointer to a string describing category.
136
 
 *
137
 
 **********************************************************************
138
 
 *
139
 
 * int
140
 
 * G_number_of_raster_cats (pcats)
141
 
 *      struct Categories *pcats     structure to hold category info
142
 
 *
143
 
 * Returns pcats->ncats number of labels
144
 
 *
145
 
 **********************************************************************
146
 
 *
147
 
 * char *
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
152
 
 *
153
 
 * Returns pointer to a string describing category.
154
 
 *
155
 
 **********************************************************************
156
 
 *
157
 
 * char *
158
 
 * G_get_[raster]_cats_title (pcats)
159
 
 *      struct Categories *pcats     structure to hold category info
160
 
 *
161
 
 * Returns pointer to a string with title
162
 
 *
163
 
 **********************************************************************
164
 
 *
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
169
 
 *
170
 
 * Initializes the cats structure for subsequent calls to G_set_cat()
171
 
 **********************************************************************
172
 
 *
173
 
 * G_unmark_raster_cats (pcats)
174
 
 *      struct Categories *pcats     structure to hold category info
175
 
 *
176
 
 * initialize cats.marks: the statistics of how many values of map
177
 
 * have each label
178
 
 *
179
 
 **********************************************************************
180
 
 *
181
 
 * G_rewind_raster_cats (pcats)
182
 
 *      struct Categories *pcats     structure to hold category info
183
 
 *
184
 
 * after calll to this function G_get_next_marked_raster_cat() returns
185
 
 * rhe first marked cat label.
186
 
 *
187
 
 **********************************************************************
188
 
 *
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
192
 
 *    long *stats;
193
 
 *    RASTER_MAP_TYPE  data_type
194
 
 *
195
 
 *    returns the next marked label.
196
 
 *    NULL if none found
197
 
 *
198
 
 **********************************************************************
199
 
 *
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
203
 
 *    long *stats;
204
 
 *
205
 
 *    returns the next marked label.
206
 
 *    NULL if none found
207
 
 *
208
 
 **********************************************************************
209
 
 *
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 
217
 
 * marking is done.
218
 
 *
219
 
 **********************************************************************
220
 
 *
221
 
 * G_mark_c/d/f_raster_cats (rast_row, ncols, pcats)
222
 
 *      int ncols;
223
 
 *      [D?F]CELL *raster_row;            raster row to update stats
224
 
 *      struct Categories *pcats     structure to hold category info
225
 
 *
226
 
 * Finds the index of label for each raster cell in a row, and
227
 
 * increases pcats->marks[index]
228
 
 *
229
 
 **********************************************************************
230
 
 *
231
 
 * G_init_raster_cats (title, pcats)
232
 
 *      char *title                  cell title
233
 
 *      struct Categories *pcats     structure to hold category info
234
 
 *
235
 
 * Initializes the cats structure for subsequent calls to G_set_cat()
236
 
 *
237
 
 **********************************************************************
238
 
 *
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
243
 
 *
244
 
 * configures the cats structure for the equation. Must be called
245
 
 * after G_init_cats().
246
 
 *
247
 
 **********************************************************************
248
 
 *
249
 
 * G_set_[raster]_cats_title (title, pcats)
250
 
 *      char *title                  cell file title
251
 
 *      struct Categories *pcats     structure holding category info
252
 
 *
253
 
 * Store title as cell file in cats structure
254
 
 * Returns nothing.
255
 
 *
256
 
 **********************************************************************
257
 
 *
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
262
 
 *
263
 
 * Adds the string buff to represent category "num" in category structure
264
 
 * pcats.
265
 
 *
266
 
 * Returns: 0 is cat is null value -1 too many cats, 1 ok.
267
 
 *
268
 
 **********************************************************************
269
 
 *
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
274
 
 *
275
 
 * Adds the label for range val1 through val2 in category structure
276
 
 * pcats.
277
 
 *
278
 
 * Returns: 0 if cat is null value -1 too many cats, 1 ok.
279
 
 *
280
 
 **********************************************************************
281
 
 *
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
287
 
 *
288
 
 * Adds the label for range val1 through val2 in category structure
289
 
 * pcats.
290
 
 *
291
 
 * Returns: 0 if cat is null value -1 too many cats, 1 ok.
292
 
 *
293
 
 **********************************************************************
294
 
 *
295
 
 *  G_write_[raster]_cats (name, pcats)
296
 
 *      char *name                   name of cell file
297
 
 *      struct Categories *pcats     structure holding category info
298
 
 *
299
 
 *  Writes the category information associated with cell file "name"
300
 
 *  into current mapset from the structure "pcats".
301
 
 *
302
 
 *   returns:    1  if successful
303
 
 *              -1  on fail
304
 
 **********************************************************************
305
 
 *
306
 
 *  G_write_vector_cats (name, pcats)
307
 
 *      char *name                   name of vector map
308
 
 *      struct Categories *pcats     structure holding category info
309
 
 *
310
 
 *  Writes the category information associated with vector map "name"
311
 
 *  into current mapset from the structure "pcats".
312
 
 *
313
 
 *   returns:    1  if successful
314
 
 *              -1  on fail
315
 
 **********************************************************************
316
 
 *
317
 
 * G_free_[raster]_cats (pcats)
318
 
 *      struct Categories *pcats     structure holding category info
319
 
 *
320
 
 * Releases memory allocated for the cats structure
321
 
 **********************************************************************/
322
 
 
323
 
#include <stdlib.h>
324
 
#include <string.h>
325
 
#include <grass/gis.h>
326
 
#include <grass/glocale.h>
327
 
 
328
 
static int get_cond(char **, char *, DCELL);
329
 
static int get_fmt(char **, char *, int *);
330
 
static int cmp(const void *, const void *);
331
 
 
332
 
 
333
 
/*!
334
 
 * \brief read raster category file
335
 
 *
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.
340
 
 *
341
 
 *  \param name
342
 
 *  \param mapset
343
 
 *  \param cats
344
 
 *  \return int
345
 
 */
346
 
 
347
 
int G_read_cats(const char *name,
348
 
                const char *mapset, struct Categories *pcats)
349
 
{
350
 
    return G_read_raster_cats(name, mapset, pcats);
351
 
}
352
 
 
353
 
 
354
 
/*!
355
 
 * \brief 
356
 
 *
357
 
 * Is the same as existing G_read_cats()
358
 
 *
359
 
 *  \param name
360
 
 *  \param mapset
361
 
 *  \param pcats
362
 
 *  \return int
363
 
 */
364
 
 
365
 
int G_read_raster_cats(const char *name,
366
 
                       const char *mapset, struct Categories *pcats)
367
 
{
368
 
    char *type;
369
 
 
370
 
    switch (G__read_cats("cats", name, mapset, pcats, 1)) {
371
 
    case -2:
372
 
        type = "missing";
373
 
        break;
374
 
    case -1:
375
 
        type = "invalid";
376
 
        break;
377
 
    default:
378
 
        return 0;
379
 
    }
380
 
 
381
 
    G_warning(_("category support for [%s] in mapset [%s] %s"),
382
 
              name, mapset, type);
383
 
    return -1;
384
 
}
385
 
 
386
 
 
387
 
/*!
388
 
 * \brief read vector category file
389
 
 *
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.
394
 
 *
395
 
 *  \param name
396
 
 *  \param mapset
397
 
 *  \param cats
398
 
 *  \return int
399
 
 */
400
 
 
401
 
int G_read_vector_cats(const char *name,
402
 
                       const char *mapset, struct Categories *pcats)
403
 
{
404
 
    char *type;
405
 
 
406
 
    switch (G__read_cats("dig_cats", name, mapset, pcats, 1)) {
407
 
    case -2:
408
 
        type = "missing";
409
 
        break;
410
 
    case -1:
411
 
        type = "invalid";
412
 
        break;
413
 
    default:
414
 
        return 0;
415
 
    }
416
 
 
417
 
    G_warning(_("category support for vector map [%s] in mapset [%s] %s"),
418
 
              name, mapset, type);
419
 
    return -1;
420
 
}
421
 
 
422
 
CELL G_number_of_cats(const char *name, const char *mapset)
423
 
{
424
 
    struct Range range;
425
 
    CELL min, max;
426
 
 
427
 
    /* return the max category number */
428
 
    if (G_read_range(name, mapset, &range) < 0)
429
 
        return -1;
430
 
    G_get_range_min_max(&range, &min, &max);
431
 
    if (G_is_c_null_value(&max))
432
 
        max = 0;
433
 
    return max;
434
 
}
435
 
 
436
 
CELL G__read_cats(const char *element,
437
 
                  const char *name,
438
 
                  const char *mapset, struct Categories * pcats, int full)
439
 
{
440
 
    FILE *fd;
441
 
    char buff[1024];
442
 
    CELL cat;
443
 
    DCELL val1, val2;
444
 
    int old = 0, fp_map;
445
 
    long num = -1;
446
 
 
447
 
 
448
 
    if (strncmp(element, "dig", 3) == 0)
449
 
        fp_map = 0;
450
 
    else
451
 
        fp_map = G_raster_map_is_fp(name, mapset);
452
 
 
453
 
    if (!(fd = G_fopen_old(element, name, mapset)))
454
 
        return -2;
455
 
 
456
 
    /* Read the number of categories */
457
 
    if (G_getl(buff, sizeof buff, fd) == 0)
458
 
        goto error;
459
 
 
460
 
    if (sscanf(buff, "# %ld", &num) == 1)
461
 
        old = 0;
462
 
    else if (sscanf(buff, "%ld", &num) == 1)
463
 
        old = 1;
464
 
 
465
 
    if (!full) {
466
 
        fclose(fd);
467
 
        if (num < 0)
468
 
            return 0;           /* coorect */
469
 
        return (CELL) num;
470
 
    }
471
 
 
472
 
    /* Read the title for the file */
473
 
    if (G_getl(buff, sizeof buff, fd) == 0)
474
 
        goto error;
475
 
    G_strip(buff);
476
 
    /*    G_ascii_check(buff) ; */
477
 
 
478
 
    G_init_raster_cats(buff, pcats);
479
 
    if (num >= 0)
480
 
        pcats->num = num;
481
 
 
482
 
    if (!old) {
483
 
        char fmt[256];
484
 
        float m1, a1, m2, a2;
485
 
 
486
 
        if (G_getl(fmt, sizeof fmt, fd) == 0)
487
 
            goto error;
488
 
        /* next line contains equation coefficients */
489
 
        if (G_getl(buff, sizeof buff, fd) == 0)
490
 
            goto error;
491
 
        if (sscanf(buff, "%f %f %f %f", &m1, &a1, &m2, &a2) != 4)
492
 
            goto error;
493
 
        G_set_raster_cats_fmt(fmt, m1, a1, m2, a2, pcats);
494
 
    }
495
 
 
496
 
    /* Read all category names */
497
 
    for (cat = 0;; cat++) {
498
 
        char label[1024];
499
 
 
500
 
        if (G_getl(buff, sizeof buff, fd) == 0)
501
 
            break;
502
 
        if (old)
503
 
            G_set_cat(cat, buff, pcats);
504
 
        else {
505
 
            *label = 0;
506
 
            if (sscanf(buff, "%1s", label) != 1)
507
 
                continue;
508
 
            if (*label == '#')
509
 
                continue;
510
 
            *label = 0;
511
 
            /* for fp maps try to read a range of data */
512
 
            if (fp_map
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);
519
 
            else
520
 
                goto error;
521
 
        }
522
 
    }
523
 
 
524
 
    fclose(fd);
525
 
    return 0;
526
 
  error:
527
 
    fclose(fd);
528
 
    return -1;
529
 
}
530
 
 
531
 
 
532
 
/*!
533
 
 * \brief  get title from category structure struct
534
 
 *
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
539
 
 * returned.
540
 
 *
541
 
 *  \param cats
542
 
 *  \return char * 
543
 
 */
544
 
 
545
 
char *G_get_cats_title(const struct Categories *pcats)
546
 
{
547
 
    return G_get_raster_cats_title(pcats);
548
 
}
549
 
 
550
 
 
551
 
/*!
552
 
 * \brief get raster cats title
553
 
 *
554
 
 * Returns pointer to a string with title.
555
 
 *
556
 
 *  \param pcats
557
 
 *  \return char * 
558
 
 */
559
 
 
560
 
char *G_get_raster_cats_title(const struct Categories *pcats)
561
 
{
562
 
    static char *none = "";
563
 
 
564
 
    return pcats->title ? pcats->title : none;
565
 
}
566
 
 
567
 
 
568
 
/*!
569
 
 * \brief get a category label
570
 
 *
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.
577
 
 *
578
 
 *  \param n
579
 
 *  \param cats
580
 
 *  \return char * 
581
 
 */
582
 
 
583
 
char *G_get_cat(CELL num, struct Categories *pcats)
584
 
{
585
 
    return G_get_c_raster_cat(&num, pcats);
586
 
}
587
 
 
588
 
 
589
 
/*!
590
 
 * \brief 
591
 
 *
592
 
 * given a CELL value <em>val</em> Returns pointer to a string describing
593
 
 * category.
594
 
 *
595
 
 *  \param val
596
 
 *  \param pcats
597
 
 *  \return char * 
598
 
 */
599
 
 
600
 
char *G_get_c_raster_cat(CELL * rast, struct Categories *pcats)
601
 
{
602
 
    return G_get_raster_cat(rast, pcats, CELL_TYPE);
603
 
}
604
 
 
605
 
 
606
 
/*!
607
 
 * \brief 
608
 
 *
609
 
 * given a FCELL value <em>val</em> Returns pointer to a string
610
 
 * describing category.
611
 
 *
612
 
 *  \param val
613
 
 *  \param pcats
614
 
 *  \return char * 
615
 
 */
616
 
 
617
 
char *G_get_f_raster_cat(FCELL * rast, struct Categories *pcats)
618
 
{
619
 
    return G_get_raster_cat(rast, pcats, FCELL_TYPE);
620
 
}
621
 
 
622
 
 
623
 
/*!
624
 
 * \brief 
625
 
 *
626
 
 * given a DCELL value <em>val</em> Returns pointer to a string
627
 
 * describing category.
628
 
 *
629
 
 *  \param val
630
 
 *  \param pcats
631
 
 *  \return char * 
632
 
 */
633
 
 
634
 
char *G_get_d_raster_cat(DCELL * rast, struct Categories *pcats)
635
 
{
636
 
    return G_get_raster_cat(rast, pcats, DCELL_TYPE);
637
 
}
638
 
 
639
 
 
640
 
/*!
641
 
 * \brief 
642
 
 *
643
 
 *  given a raster value <em>val</em> of type <em>data_type</em> Returns pointer to a string
644
 
 *  describing category.
645
 
 *
646
 
 *  \param val
647
 
 *  \param pcats
648
 
 *  \param data_type
649
 
 *  \return char * 
650
 
 */
651
 
 
652
 
char *G_get_raster_cat(void *rast,
653
 
                       struct Categories *pcats, RASTER_MAP_TYPE data_type)
654
 
{
655
 
    static char label[1024];
656
 
    char *f, *l, *v;
657
 
    CELL i;
658
 
    DCELL val;
659
 
    float a[2];
660
 
    char fmt[30], value_str[30];
661
 
 
662
 
    if (G_is_null_value(rast, data_type)) {
663
 
        sprintf(label, "no data");
664
 
        return label;
665
 
    }
666
 
 
667
 
    /* first search the list of labels */
668
 
    *label = 0;
669
 
    val = G_get_raster_value_d(rast, data_type);
670
 
    i = G_quant_get_cell_value(&pcats->q, val);
671
 
 
672
 
    G_debug(5, "G_get_raster_cat(): val %lf found i %d", val, i);
673
 
 
674
 
    if (!G_is_c_null_value(&i) && i < pcats->ncats) {
675
 
        if (pcats->labels[i] != NULL)
676
 
            return pcats->labels[i];
677
 
        return label;
678
 
    }
679
 
 
680
 
    /* generate the label */
681
 
    if ((f = pcats->fmt) == NULL)
682
 
        return label;
683
 
 
684
 
    a[0] = (float)val *pcats->m1 + pcats->a1;
685
 
    a[1] = (float)val *pcats->m2 + pcats->a2;
686
 
 
687
 
    l = label;
688
 
    while (*f) {
689
 
        if (*f == '$') {
690
 
            f++;
691
 
            if (*f == '$')
692
 
                *l++ = *f++;
693
 
            else if (*f == '?') {
694
 
                f++;
695
 
                get_cond(&f, v = value_str, val);
696
 
                while (*v)
697
 
                    *l++ = *v++;
698
 
            }
699
 
            else if (get_fmt(&f, fmt, &i)) {
700
 
                sprintf(v = value_str, fmt, a[i]);
701
 
                while (*v)
702
 
                    *l++ = *v++;
703
 
            }
704
 
            else
705
 
                *l++ = '$';
706
 
        }
707
 
        else {
708
 
            *l++ = *f++;
709
 
        }
710
 
    }
711
 
    *l = 0;
712
 
    return label;
713
 
}
714
 
 
715
 
 
716
 
/*!
717
 
 * \brief 
718
 
 *
719
 
 * Sets marks
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.
726
 
 *
727
 
 *  \param pcats
728
 
 *  \return int
729
 
 */
730
 
 
731
 
int G_unmark_raster_cats(struct Categories *pcats)
732
 
{                               /* structure to hold category info */
733
 
    register int i;
734
 
 
735
 
    for (i = 0; i < pcats->ncats; i++)
736
 
        pcats->marks[i] = 0;
737
 
    return 0;
738
 
}
739
 
 
740
 
 
741
 
/*!
742
 
 * \brief 
743
 
 *
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.
748
 
 *
749
 
 *  \param rast_row
750
 
 *  \param ncols
751
 
 *  \param pcats
752
 
 *  \return int
753
 
 */
754
 
 
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);
759
 
    return 0;
760
 
}
761
 
 
762
 
 
763
 
/*!
764
 
 * \brief 
765
 
 *
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.
770
 
 *
771
 
 *  \param rast_row
772
 
 *  \param ncols
773
 
 *  \param pcats
774
 
 *  \return int
775
 
 */
776
 
 
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);
781
 
    return 0;
782
 
}
783
 
 
784
 
 
785
 
/*!
786
 
 * \brief 
787
 
 *
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.
792
 
 *
793
 
 *  \param rast_row
794
 
 *  \param ncols
795
 
 *  \param pcats
796
 
 *  \return int
797
 
 */
798
 
 
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);
803
 
    return 0;
804
 
}
805
 
 
806
 
 
807
 
/*!
808
 
 * \brief 
809
 
 *
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.
815
 
 *
816
 
 *  \param rast_row
817
 
 *  \param ncols
818
 
 *  \param pcats
819
 
 *  \param data_type
820
 
 *  \return int
821
 
 */
822
 
 
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)
826
 
{
827
 
    CELL i;
828
 
 
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))
833
 
            continue;
834
 
        if (i > pcats->ncats)
835
 
            return -1;
836
 
        pcats->marks[i]++;
837
 
        rast_row = G_incr_void_ptr(rast_row, G_raster_size(data_type));
838
 
    }
839
 
    return 1;
840
 
}
841
 
 
842
 
 
843
 
/*!
844
 
 * \brief 
845
 
 *
846
 
 * after call to
847
 
 * this function G_get_next_marked_raster_cat() returns the first marked
848
 
 * cat label.
849
 
 *
850
 
 *  \param pcats
851
 
 *  \return int
852
 
 */
853
 
 
854
 
int G_rewind_raster_cats(struct Categories *pcats)
855
 
{
856
 
    pcats->last_marked_rule = -1;
857
 
    return 0;
858
 
}
859
 
 
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 */
862
 
                                     long *count)
863
 
{
864
 
    char *descr = NULL;
865
 
    int found, i;
866
 
 
867
 
    found = 0;
868
 
    /* pcats->ncats should be == G_quant_nof_rules(&pcats->q) */
869
 
    /* DEBUG
870
 
       fprintf (stderr, "last marked %d nrules %d\n", pcats->last_marked_rule, G_quant_nof_rules(&pcats->q));
871
 
     */
872
 
    for (i = pcats->last_marked_rule + 1; i < G_quant_nof_rules(&pcats->q);
873
 
         i++) {
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]) {
877
 
            found = 1;
878
 
            break;
879
 
        }
880
 
    }
881
 
 
882
 
    if (!found)
883
 
        return NULL;
884
 
 
885
 
    *count = pcats->marks[i];
886
 
    pcats->last_marked_rule = i;
887
 
    return descr;
888
 
}
889
 
 
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 */
892
 
                                     long *count)
893
 
{
894
 
    return G_get_next_marked_raster_cat(pcats, rast1, rast2, count,
895
 
                                        CELL_TYPE);
896
 
}
897
 
 
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 */
900
 
                                     long *count)
901
 
{
902
 
    return G_get_next_marked_raster_cat(pcats, rast1, rast2, count,
903
 
                                        FCELL_TYPE);
904
 
}
905
 
 
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)
909
 
{
910
 
    DCELL val1, val2;
911
 
    char *lab;
912
 
 
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);
916
 
    return lab;
917
 
}
918
 
 
919
 
static int get_fmt(char **f, char *fmt, int *i)
920
 
{
921
 
    char *ff;
922
 
 
923
 
    ff = *f;
924
 
    if (*ff == 0)
925
 
        return 0;
926
 
    if (*ff == '$') {
927
 
        *f = ff + 1;
928
 
        return 0;
929
 
    }
930
 
    switch (*ff++) {
931
 
    case '1':
932
 
        *i = 0;
933
 
        break;
934
 
    case '2':
935
 
        *i = 1;
936
 
        break;
937
 
    default:
938
 
        return 0;
939
 
    }
940
 
    *fmt++ = '%';
941
 
    *fmt++ = '.';
942
 
    if (*ff++ != '.') {
943
 
        *f = ff - 1;
944
 
        *fmt++ = '0';
945
 
        *fmt++ = 'f';
946
 
        *fmt = 0;
947
 
        return 1;
948
 
    }
949
 
    *fmt = '0';
950
 
    while (*ff >= '0' && *ff <= '9')
951
 
        *fmt++ = *ff++;
952
 
    *fmt++ = 'f';
953
 
    *fmt = 0;
954
 
    *f = ff;
955
 
    return 1;
956
 
}
957
 
 
958
 
static int get_cond(char **f, char *value, DCELL val)
959
 
{
960
 
    char *ff;
961
 
 
962
 
    ff = *f;
963
 
    if (val == 1.) {
964
 
        while (*ff)
965
 
            if (*ff++ == '$')
966
 
                break;
967
 
    }
968
 
 
969
 
    while (*ff)
970
 
        if (*ff == '$') {
971
 
            ff++;
972
 
            break;
973
 
        }
974
 
        else
975
 
            *value++ = *ff++;
976
 
 
977
 
    if (val != 1.) {
978
 
        while (*ff)
979
 
            if (*ff++ == '$')
980
 
                break;
981
 
    }
982
 
    *value = 0;
983
 
    *f = ff;
984
 
 
985
 
    return 0;
986
 
}
987
 
 
988
 
 
989
 
/*!
990
 
 * \brief set a category label
991
 
 *
992
 
 * The <b>label</b> is copied into the <b>cats</b> structure
993
 
 * for category <b>n.</b>
994
 
 *
995
 
 *  \param n
996
 
 *  \param label
997
 
 *  \param cats
998
 
 *  \return int
999
 
 */
1000
 
 
1001
 
int G_set_cat(CELL num, char *label, struct Categories *pcats)
1002
 
{
1003
 
    CELL tmp = num;
1004
 
 
1005
 
    return G_set_c_raster_cat(&tmp, &tmp, label, pcats);
1006
 
}
1007
 
 
1008
 
 
1009
 
/*!
1010
 
 * \brief 
1011
 
 *
1012
 
 * Adds the label for range <em>rast1</em> through <em>rast2</em> in
1013
 
 * category structure <em>pcats</em>.
1014
 
 *
1015
 
 *  \param rast1
1016
 
 *  \param rast2
1017
 
 *  \param pcats
1018
 
 *  \return int
1019
 
 */
1020
 
 
1021
 
int G_set_c_raster_cat(CELL * rast1, CELL * rast2,
1022
 
                       char *label, struct Categories *pcats)
1023
 
{
1024
 
    return G_set_raster_cat(rast1, rast2, label, pcats, CELL_TYPE);
1025
 
}
1026
 
 
1027
 
 
1028
 
/*!
1029
 
 * \brief 
1030
 
 *
1031
 
 * Adds the label for range <em>rast1</em> through <em>rast2</em>
1032
 
 * in category structure <em>pcats</em>.
1033
 
 *
1034
 
 *  \param rast1
1035
 
 *  \param rast2
1036
 
 *  \param pcats
1037
 
 *  \return int
1038
 
 */
1039
 
 
1040
 
int G_set_f_raster_cat(FCELL * rast1, FCELL * rast2,
1041
 
                       char *label, struct Categories *pcats)
1042
 
{
1043
 
    return G_set_raster_cat(rast1, rast2, label, pcats, FCELL_TYPE);
1044
 
}
1045
 
 
1046
 
 
1047
 
/*!
1048
 
 * \brief 
1049
 
 *
1050
 
 * Adds the label for range <em>rast1</em> through <em>rast2</em>
1051
 
 * in category structure <em>pcats</em>.
1052
 
 *
1053
 
 *  \param rast1
1054
 
 *  \param rast2
1055
 
 *  \param pcats
1056
 
 *  \return int
1057
 
 */
1058
 
 
1059
 
int G_set_d_raster_cat(DCELL * rast1, DCELL * rast2,
1060
 
                       char *label, struct Categories *pcats)
1061
 
{
1062
 
    long len;
1063
 
    DCELL dtmp1, dtmp2;
1064
 
    int i;
1065
 
    char *descr;
1066
 
 
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))
1070
 
        return 0;
1071
 
    if (G_is_d_null_value(rast2))
1072
 
        return 0;
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 */
1081
 
 
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]);
1091
 
            return 1;
1092
 
        }
1093
 
    }
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);
1097
 
    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 */
1103
 
            pcats->ncats--;
1104
 
            return -1;
1105
 
        }
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); */
1109
 
            pcats->labels =
1110
 
                (char **)G_realloc((char *)pcats->labels, (int)len);
1111
 
        }
1112
 
        else {
1113
 
            /* DEBUG fprintf(stderr,"G_set_d_raster_cat(): alloc-ing new labels pointer array\n"); */
1114
 
            pcats->labels = (char **)G_malloc((int)len);
1115
 
        }
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 */
1120
 
            pcats->ncats--;
1121
 
            return -1;
1122
 
        }
1123
 
        if (pcats->nalloc)
1124
 
            pcats->marks = (int *)G_realloc((char *)pcats->marks, (int)len);
1125
 
        else
1126
 
            pcats->marks = (int *)G_malloc((int)len);
1127
 
        pcats->nalloc += 256;
1128
 
    }
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]);
1133
 
    /* DEBUG
1134
 
       fprintf (stderr, "%d %s\n", pcats->ncats - 1, pcats->labels[pcats->ncats - 1]);
1135
 
     */
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); */
1144
 
    return 1;
1145
 
}
1146
 
 
1147
 
 
1148
 
/*!
1149
 
 * \brief 
1150
 
 *
1151
 
 * Adds the label for range <em>rast1</em> through <em>rast2</em> in category structure <em>pcats</em>.
1152
 
 *
1153
 
 *  \param rast1
1154
 
 *  \param rast2
1155
 
 *  \param pcats
1156
 
 *  \param data_type
1157
 
 *  \return int
1158
 
 */
1159
 
 
1160
 
int G_set_raster_cat(void *rast1, void *rast2,
1161
 
                     char *label,
1162
 
                     struct Categories *pcats, RASTER_MAP_TYPE data_type)
1163
 
{
1164
 
    DCELL val1, val2;
1165
 
 
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);
1169
 
}
1170
 
 
1171
 
 
1172
 
/*!
1173
 
 * \brief write raster category file
1174
 
 *
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
1178
 
 * printed).
1179
 
 *
1180
 
 *  \param name
1181
 
 *  \param cats
1182
 
 *  \return int
1183
 
 */
1184
 
 
1185
 
int G_write_cats(char *name, struct Categories *cats)
1186
 
{
1187
 
    return G__write_cats("cats", name, cats);
1188
 
}
1189
 
 
1190
 
 
1191
 
/*!
1192
 
 * \brief 
1193
 
 *
1194
 
 * Same as existing G_write_cats()
1195
 
 *
1196
 
 *  \param name
1197
 
 *  \param pcats
1198
 
 *  \return int
1199
 
 */
1200
 
 
1201
 
int G_write_raster_cats(char *name, struct Categories *cats)
1202
 
{
1203
 
    return G__write_cats("cats", name, cats);
1204
 
}
1205
 
 
1206
 
 
1207
 
/*!
1208
 
 * \brief write
1209
 
 *       vector category file
1210
 
 *
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 
1214
 
 * printed).
1215
 
 *
1216
 
 *  \param name
1217
 
 *  \param cats
1218
 
 *  \return int
1219
 
 */
1220
 
 
1221
 
int G_write_vector_cats(char *name, struct Categories *cats)
1222
 
{
1223
 
    return G__write_cats("dig_cats", name, cats);
1224
 
}
1225
 
 
1226
 
int G__write_cats(char *element, char *name, struct Categories *cats)
1227
 
{
1228
 
    FILE *fd;
1229
 
    int i, fp_map;
1230
 
    char *descr;
1231
 
    DCELL val1, val2;
1232
 
    char str1[100], str2[100];
1233
 
 
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)))
1236
 
        return -1;
1237
 
 
1238
 
    /* write # cats - note # indicate 3.0 or later */
1239
 
    fprintf(fd, "# %ld categories\n", (long)cats->num);
1240
 
 
1241
 
    /* title */
1242
 
    fprintf(fd, "%s\n", cats->title != NULL ? cats->title : "");
1243
 
 
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);
1248
 
 
1249
 
    /* if the map is integer or if this is a vector map, sort labels */
1250
 
    if (strncmp(element, "dig", 3) == 0)
1251
 
        fp_map = 0;
1252
 
    else
1253
 
        fp_map = G_raster_map_is_fp(name, G_mapset());
1254
 
    /* DEBUG fprintf(stderr,"G__write_cats(): fp_map = %d\n",fp_map); */
1255
 
    if (!fp_map)
1256
 
        G_sort_cats(cats);
1257
 
 
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])) {
1263
 
            if (val1 == val2) {
1264
 
                sprintf(str1, "%.10f", val1);
1265
 
                G_trim_decimal(str1);
1266
 
                fprintf(fd, "%s:%s\n", str1, descr != NULL ? descr : "");
1267
 
            }
1268
 
            else {
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 : "");
1275
 
            }
1276
 
        }
1277
 
    }
1278
 
    fclose(fd);
1279
 
    /* DEBUG fprintf(stderr,"G__write_cats(): done\n"); */
1280
 
    return (1);
1281
 
}
1282
 
 
1283
 
 
1284
 
/*!
1285
 
 * \brief 
1286
 
 *
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>.
1290
 
 *
1291
 
 *  \param pcats
1292
 
 *  \param i
1293
 
 *  \param rast1
1294
 
 *  \param rast2
1295
 
 *  \return char * 
1296
 
 */
1297
 
 
1298
 
char *G_get_ith_d_raster_cat(const struct Categories *pcats,
1299
 
                             int i, DCELL * rast1, DCELL * rast2)
1300
 
{
1301
 
    int index;
1302
 
 
1303
 
    if (i > pcats->ncats) {
1304
 
        G_set_d_null_value(rast1, 1);
1305
 
        G_set_d_null_value(rast2, 1);
1306
 
        return "";
1307
 
    }
1308
 
    G_quant_get_ith_rule(&pcats->q, i, rast1, rast2, &index, &index);
1309
 
    return pcats->labels[index];
1310
 
}
1311
 
 
1312
 
 
1313
 
/*!
1314
 
 * \brief 
1315
 
 *
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>.
1319
 
 *
1320
 
 *  \param pcats
1321
 
 *  \param i
1322
 
 *  \param rast1
1323
 
 *  \param rast2
1324
 
 *  \return char * 
1325
 
 */
1326
 
 
1327
 
char *G_get_ith_f_raster_cat(const struct Categories *pcats,
1328
 
                             int i, void *rast1, void *rast2)
1329
 
{
1330
 
    RASTER_MAP_TYPE data_type = FCELL_TYPE;
1331
 
    char *tmp;
1332
 
    DCELL val1, val2;
1333
 
 
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);
1337
 
    return tmp;
1338
 
}
1339
 
 
1340
 
 
1341
 
/*!
1342
 
 * \brief 
1343
 
 *
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>.
1347
 
 *
1348
 
 *  \param pcats
1349
 
 *  \param i
1350
 
 *  \param rast1
1351
 
 *  \param rast2
1352
 
 *  \return char * 
1353
 
 */
1354
 
 
1355
 
char *G_get_ith_c_raster_cat(const struct Categories *pcats,
1356
 
                             int i, void *rast1, void *rast2)
1357
 
{
1358
 
    RASTER_MAP_TYPE data_type = CELL_TYPE;
1359
 
    char *tmp;
1360
 
    DCELL val1, val2;
1361
 
 
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);
1365
 
    return tmp;
1366
 
}
1367
 
 
1368
 
 
1369
 
/*!
1370
 
 * \brief 
1371
 
 *
1372
 
 * Returns i-th
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>.
1376
 
 *
1377
 
 *  \param pcats
1378
 
 *  \param i
1379
 
 *  \param rast1
1380
 
 *  \param rast2
1381
 
 *  \param data_type
1382
 
 *  \return char * 
1383
 
 */
1384
 
 
1385
 
char *G_get_ith_raster_cat(const struct Categories *pcats, int i, void *rast1,
1386
 
                           void *rast2, RASTER_MAP_TYPE data_type)
1387
 
{
1388
 
    char *tmp;
1389
 
    DCELL val1, val2;
1390
 
 
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);
1394
 
    return tmp;
1395
 
}
1396
 
 
1397
 
 
1398
 
/*!
1399
 
 * \brief initialize category structure
1400
 
 *
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>
1405
 
 * For example:
1406
 
 \code
1407
 
 struct Categories cats;
1408
 
 G_init_cats ( (CELL)0, "", &cats);
1409
 
 \endcode
1410
 
 *
1411
 
 *  \param n
1412
 
 *  \param title
1413
 
 *  \param cats
1414
 
 *  \return int
1415
 
 */
1416
 
 
1417
 
int G_init_cats(CELL num, const char *title, struct Categories *pcats)
1418
 
{
1419
 
    G_init_raster_cats(title, pcats);
1420
 
    pcats->num = num;
1421
 
    return 0;
1422
 
}
1423
 
 
1424
 
 
1425
 
/*!
1426
 
 * \brief 
1427
 
 *
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.
1431
 
 *
1432
 
 *  \param title
1433
 
 *  \param pcats
1434
 
 *  \return int
1435
 
 */
1436
 
 
1437
 
int G_init_raster_cats(const char *title, struct Categories *pcats)
1438
 
{
1439
 
    G_set_raster_cats_title(title, pcats);
1440
 
    pcats->labels = NULL;
1441
 
    pcats->nalloc = 0;
1442
 
    pcats->ncats = 0;
1443
 
    pcats->num = 0;
1444
 
    pcats->fmt = NULL;
1445
 
    pcats->m1 = 0.0;
1446
 
    pcats->a1 = 0.0;
1447
 
    pcats->m2 = 0.0;
1448
 
    pcats->a2 = 0.0;
1449
 
    pcats->last_marked_rule = -1;
1450
 
    G_quant_init(&pcats->q);
1451
 
    return 0;
1452
 
}
1453
 
 
1454
 
 
1455
 
/*!
1456
 
 * \brief set title in category structure
1457
 
 *
1458
 
 * The <b>title</b> is copied into the
1459
 
 * <b>cats</b> structure.
1460
 
 *
1461
 
 *  \param title
1462
 
 *  \param cats
1463
 
 *  \return int
1464
 
 */
1465
 
 
1466
 
int G_set_cats_title(const char *title, struct Categories *pcats)
1467
 
{
1468
 
    G_set_raster_cats_title(title, pcats);
1469
 
    return 0;
1470
 
}
1471
 
 
1472
 
 
1473
 
/*!
1474
 
 * \brief 
1475
 
 *
1476
 
 * Same as existing G_set_cats_title()
1477
 
 *
1478
 
 *  \param title
1479
 
 *  \param pcats
1480
 
 *  \return int
1481
 
 */
1482
 
 
1483
 
int G_set_raster_cats_title(const char *title, struct Categories *pcats)
1484
 
{
1485
 
    if (title == NULL)
1486
 
        title = "";
1487
 
    pcats->title = G_store(title);
1488
 
    G_newlines_to_spaces(pcats->title);
1489
 
    G_strip(pcats->title);
1490
 
    return 0;
1491
 
}
1492
 
 
1493
 
int G_set_cats_fmt(const char *fmt, double m1, double a1, double m2,
1494
 
                   double a2, struct Categories *pcats)
1495
 
{
1496
 
    G_set_raster_cats_fmt(fmt, m1, a1, m2, a2, pcats);
1497
 
    return 0;
1498
 
}
1499
 
 
1500
 
 
1501
 
/*!
1502
 
 * \brief 
1503
 
 *
1504
 
 * Same as existing G_set_cats_fmt()
1505
 
 *
1506
 
 *  \param fmt
1507
 
 *  \param m1
1508
 
 *  \param a1
1509
 
 *  \param m2
1510
 
 *  \param a2
1511
 
 *  \param pcats
1512
 
 *  \return int
1513
 
 */
1514
 
 
1515
 
int G_set_raster_cats_fmt(const char *fmt, double m1, double a1, double m2,
1516
 
                          double a2, struct Categories *pcats)
1517
 
{
1518
 
    pcats->m1 = m1;
1519
 
    pcats->a1 = a1;
1520
 
    pcats->m2 = m2;
1521
 
    pcats->a2 = a2;
1522
 
 
1523
 
    pcats->fmt = G_store(fmt);
1524
 
    G_newlines_to_spaces(pcats->fmt);
1525
 
    G_strip(pcats->fmt);
1526
 
    return 0;
1527
 
}
1528
 
 
1529
 
 
1530
 
/*!
1531
 
 * \brief free category structure memory
1532
 
 *
1533
 
 * Frees memory allocated by<i>G_read_cats, G_init_cats</i>
1534
 
 * and<i>G_set_cat.</i>
1535
 
 *
1536
 
 *  \param cats
1537
 
 *  \return int
1538
 
 */
1539
 
 
1540
 
int G_free_cats(struct Categories *pcats)
1541
 
{
1542
 
    G_free_raster_cats(pcats);
1543
 
    return 0;
1544
 
}
1545
 
 
1546
 
 
1547
 
/*!
1548
 
 * \brief 
1549
 
 *
1550
 
 * Same as existing G_free_cats()
1551
 
 *
1552
 
 *  \param pcats
1553
 
 *  \return int
1554
 
 */
1555
 
 
1556
 
int G_free_raster_cats(struct Categories *pcats)
1557
 
{
1558
 
    int i;
1559
 
 
1560
 
    if (pcats->title != NULL) {
1561
 
        G_free(pcats->title);
1562
 
        pcats->title = NULL;
1563
 
    }
1564
 
    if (pcats->fmt != NULL) {
1565
 
        G_free(pcats->fmt);
1566
 
        pcats->fmt = NULL;
1567
 
    }
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;
1575
 
    }
1576
 
    G_quant_free(&pcats->q);
1577
 
    pcats->ncats = 0;
1578
 
    pcats->nalloc = 0;
1579
 
    return 0;
1580
 
}
1581
 
 
1582
 
 
1583
 
/*!
1584
 
 * \brief 
1585
 
 *
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.
1588
 
 * returns:
1589
 
 * 0 if successful
1590
 
 * -1 on fail
1591
 
 *
1592
 
 *  \param pcats_to
1593
 
 *  \param pcats_from
1594
 
 *  \return int
1595
 
 */
1596
 
 
1597
 
int
1598
 
G_copy_raster_cats(struct Categories *pcats_to,
1599
 
                   const struct Categories *pcats_from)
1600
 
{
1601
 
    int i;
1602
 
    char *descr;
1603
 
    DCELL d1, d2;
1604
 
 
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);
1609
 
    }
1610
 
    return 0;
1611
 
}
1612
 
 
1613
 
int G_number_of_raster_cats(struct Categories *pcats)
1614
 
{
1615
 
    return pcats->ncats;
1616
 
}
1617
 
 
1618
 
static struct Categories save_cats;
1619
 
 
1620
 
int G_sort_cats(struct Categories *pcats)
1621
 
{
1622
 
    int *indexes, i, ncats;
1623
 
    char *descr;
1624
 
    DCELL d1, d2;
1625
 
 
1626
 
    if (pcats->ncats <= 1)
1627
 
        return -1;
1628
 
 
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);
1633
 
 
1634
 
    indexes = (int *)G_malloc(sizeof(int) * ncats);
1635
 
    for (i = 0; i < ncats; i++)
1636
 
        indexes[i] = i;
1637
 
 
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); */
1645
 
    }
1646
 
    G_free_raster_cats(&save_cats);
1647
 
    /* DEBUG fprintf(stderr,"G_sort_cats(): Done\n"); */
1648
 
    /* fflush(stderr); */
1649
 
 
1650
 
    return 0;
1651
 
}
1652
 
 
1653
 
static int cmp(const void *aa, const void *bb)
1654
 
{
1655
 
    const int *a = aa, *b = bb;
1656
 
    DCELL min_rast1, min_rast2, max_rast1, max_rast2;
1657
 
    CELL index;
1658
 
 
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)
1664
 
        return -1;
1665
 
    if (min_rast1 > min_rast2)
1666
 
        return 1;
1667
 
    return 0;
1668
 
}