~ubuntu-branches/ubuntu/wily/grass/wily

« back to all changes in this revision

Viewing changes to lib/vector/Vlib/cats.c

Tags: 7.0.0~rc1+ds1-1~exp1
* New upstream release candidate.
* Repack upstream tarball, remove precompiled Python objects.
* Add upstream metadata.
* Update gbp.conf and Vcs-Git URL to use the experimental branch.
* Update watch file for GRASS 7.0.
* Drop build dependencies for Tcl/Tk, add build dependencies:
  python-numpy, libnetcdf-dev, netcdf-bin, libblas-dev, liblapack-dev
* Update Vcs-Browser URL to use cgit instead of gitweb.
* Update paths to use grass70.
* Add configure options: --with-netcdf, --with-blas, --with-lapack,
  remove --with-tcltk-includes.
* Update patches for GRASS 7.
* Update copyright file, changes:
  - Update copyright years
  - Group files by license
  - Remove unused license sections
* Add patches for various typos.
* Fix desktop file with patch instead of d/rules.
* Use minimal dh rules.
* Bump Standards-Version to 3.9.6, no changes.
* Use dpkg-maintscript-helper to replace directories with symlinks.
  (closes: #776349)
* Update my email to use @debian.org address.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*!
2
 
 * \file cats.c
 
2
 * \file lib/vector/Vlib/cats.c
3
3
 *
4
4
 * \brief Vector library - Category management
5
5
 *
6
6
 * Higher level functions for reading/writing/manipulating vectors.
7
7
 *
8
 
 * (C) 2001-2009 by the GRASS Development Team
9
 
 *
10
 
 * This program is free software under the 
11
 
 * GNU General Public License (>=v2). 
12
 
 * Read the file COPYING that comes with GRASS
13
 
 * for details.
14
 
 *
15
 
 * \author Original author CERL, probably Dave Gerdes or Mike
16
 
 * Higgins
 
8
 * (C) 2001-2012 by the GRASS Development Team
 
9
 *
 
10
 * This program is free software under the GNU General Public License
 
11
 * (>=v2).  Read the file COPYING that comes with GRASS for details.
 
12
 *
 
13
 * \author Original author CERL, probably Dave Gerdes or Mike Higgins
17
14
 * \author Update to GRASS 5.7 Radim Blazek and David D. Gray.
18
15
 * \author Various updates by Martin Landa <landa.martin gmail.com>
 
16
 * \author Various updates by Markus Metz
19
17
 */
20
18
 
21
19
#include <stdlib.h>
22
20
#include <string.h>
23
 
#include <grass/gis.h>
24
 
#include <grass/Vect.h>
 
21
#include <grass/vector.h>
 
22
#include <grass/dbmi.h>
25
23
#include <grass/glocale.h>
26
24
 
27
25
static int cmp(const void *pa, const void *pb);
28
 
struct line_cats *Vect__new_cats_struct(void);
 
26
static struct line_cats *Vect__new_cats_struct(void);
29
27
 
30
28
 
31
29
/*!
33
31
 
34
32
   This structure is used for reading and writing vector cats. The
35
33
   library routines handle all memory allocation.
 
34
   
 
35
   To free allocated memory call Vect_destroy_cats_struct().
36
36
 
37
37
   \return struct line_cats *
38
38
   \return NULL on error
55
55
 
56
56
   \return struct line_cats *
57
57
 */
58
 
struct line_cats *Vect__new_cats_struct()
 
58
static struct line_cats *Vect__new_cats_struct()
59
59
{
60
60
    struct line_cats *p;
61
61
 
72
72
}
73
73
 
74
74
/*!
75
 
   \brief Frees all memory associated with line_cats structure, including the struct itself.
 
75
   \brief Frees all memory associated with line_cats structure,
 
76
   including the struct itself.
76
77
 
77
78
   \param p line_cats structure
78
 
 
79
 
   \return 0
80
79
 */
81
 
int Vect_destroy_cats_struct(struct line_cats *p)
 
80
void Vect_destroy_cats_struct(struct line_cats *p)
82
81
{
83
82
    if (p) {                    /* probably a moot test */
84
83
        if (p->n_cats) {
87
86
        }
88
87
        G_free((void *)p);
89
88
    }
90
 
 
91
 
    return 0;
92
89
}
93
90
 
94
91
/*!
95
 
   \brief Add new field/cat to category structure if doesn't exist yet.
 
92
   \brief Add new field/cat to category structure if doesn't exist
 
93
   yet.
96
94
 
97
 
   \param[in] Cats line_cats structure
 
95
   \param[in,out] Cats line_cats structure
98
96
   \param[in] field layer number
99
97
   \param[in] cat category number
100
98
 
145
143
/*!
146
144
   \brief Get first found category of given field.
147
145
 
148
 
   'cat' is set to first category found or -1 if field was not found
149
 
 
150
 
   \param[in] Cats line_cats structure
151
 
   \param[in] field layer number
152
 
   \param[in] cat pointer to variable where cat will be written
153
 
 
154
 
   \return 1 found
 
146
   <em>cat</em> is set to first category found or -1 if field was not
 
147
   found
 
148
 
 
149
   \param Cats pointer line_cats structure
 
150
   \param field layer number
 
151
   \param[out] cat pointer to variable where cat will be written (can be NULL)
 
152
 
 
153
   \return number of found cats for given field (first reported)
155
154
   \return 0 layer does not exist
156
155
 */
157
 
int Vect_cat_get(struct line_cats *Cats, int field, int *cat)
 
156
int Vect_cat_get(const struct line_cats *Cats, int field, int *cat)
158
157
{
159
 
    register int n;
 
158
    int n, ret;
160
159
 
 
160
    /* field was not found */    
 
161
    ret = 0;
 
162
    if (cat)
 
163
        *cat = -1;
 
164
    
161
165
    /* check input value */
162
 
    /*
163
 
       if (field < 1 || field > GV_FIELD_MAX)
164
 
       return (0);
165
 
     */
166
 
 
167
 
    *cat = -1;
 
166
    if (field < 1 || field > GV_FIELD_MAX)
 
167
        return (0);
168
168
 
169
169
    /* go through cats and find if field exist */
170
170
    for (n = 0; n < Cats->n_cats; n++) {
171
171
        if (Cats->field[n] == field) {
172
 
            *cat = Cats->cat[n];
173
 
            return (1);
 
172
            if (cat && ret == 0) {
 
173
                *cat = Cats->cat[n];
 
174
            }
 
175
            ret++;
174
176
        }
175
177
    }
176
 
 
177
 
    /* field was not found */
178
 
    return (0);
 
178
    
 
179
    return ret;
179
180
}
180
181
 
181
182
/*!
188
189
   \return number of found categories
189
190
   \return -1 on invalid field
190
191
 */
191
 
int Vect_field_cat_get(struct line_cats *Cats, int field, struct ilist *cats)
 
192
int Vect_field_cat_get(const struct line_cats *Cats, int field, struct ilist *cats)
192
193
{
193
194
    int n;
194
195
    
201
202
    
202
203
    /* go through cats and find if field exist */
203
204
    for (n = 0; n < Cats->n_cats; n++) {
204
 
        if (Cats->field[n] != field)
205
 
            continue;
206
 
        Vect_list_append(cats, Cats->cat[n]);
 
205
        if (Cats->field[n] == field)
 
206
            Vect_list_append(cats, Cats->cat[n]);
207
207
    }
208
208
 
209
209
    return cats->n_values;
212
212
/*!
213
213
   \brief Delete all categories of given layer
214
214
 
215
 
   \param[in] Cats line_cats structure
216
 
   \param[in] field layer number
 
215
   \param[in,out] Cats line_cats structure
 
216
   \param field layer number
217
217
 
218
 
   \return 1 deleted
 
218
   \return number of categories deleted
219
219
   \return 0 layer does not exist
220
220
 */
221
221
int Vect_cat_del(struct line_cats *Cats, int field)
222
222
{
223
 
    int n, m, found = 0;
 
223
    int n, m, found;
224
224
 
225
225
    /* check input value */
226
226
    /*
229
229
     */
230
230
 
231
231
    /* go through cats and find if field exist */
 
232
    m = 0;
232
233
    for (n = 0; n < Cats->n_cats; n++) {
233
 
        if (Cats->field[n] == field) {
234
 
            for (m = n; m < Cats->n_cats - 1; m++) {
235
 
                Cats->field[m] = Cats->field[m + 1];
236
 
                Cats->cat[m] = Cats->cat[m + 1];
237
 
            }
238
 
            Cats->n_cats--;
239
 
            found = 1;
240
 
            n--;                /* check again this position */
 
234
        if (Cats->field[n] != field) {
 
235
            Cats->field[m] = Cats->field[n];
 
236
            Cats->cat[m] = Cats->cat[n];
 
237
            m++;
241
238
        }
242
239
    }
 
240
    found = Cats->n_cats - m;
 
241
    Cats->n_cats = m;
243
242
 
244
243
    return (found);
245
244
}
247
246
/*!
248
247
   \brief Delete field/cat from line_cats structure
249
248
 
250
 
   \param[in] Cats line_cats structure
251
 
   \param[in] field layer number
252
 
   \param[in] cat category to be deleted or -1 to delete all cats of given field
 
249
   \param[in,out] Cats line_cats structure
 
250
   \param field layer number
 
251
   \param cat category to be deleted or -1 to delete all cats of given field
253
252
 
254
 
   \return 1 deleted
 
253
   \return number of categories deleted
255
254
   \return 0 field/category number does not exist
256
255
 */
257
256
int Vect_field_cat_del(struct line_cats *Cats, int field, int cat)
258
257
{
259
 
    register int n, m, found = 0;
 
258
    register int n, m, found;
260
259
 
261
260
    /* check input value */
262
261
    /*
263
262
       if (field < 1 || field > GV_FIELD_MAX)
264
263
       return (0);
265
264
     */
 
265
     
 
266
    if (cat == -1)
 
267
        return Vect_cat_del(Cats, field);
266
268
 
267
269
    /* go through cats and find if field exist */
 
270
    m = 0;
268
271
    for (n = 0; n < Cats->n_cats; n++) {
269
 
        if (Cats->field[n] == field && (Cats->cat[n] == cat || cat == -1)) {
270
 
            for (m = n; m < Cats->n_cats - 1; m++) {
271
 
                Cats->field[m] = Cats->field[m + 1];
272
 
                Cats->cat[m] = Cats->cat[m + 1];
273
 
            }
274
 
            Cats->n_cats--;
275
 
            found = 1;
 
272
        if (Cats->field[n] != field || Cats->cat[n] != cat) {
 
273
            Cats->field[m] = Cats->field[n];
 
274
            Cats->cat[m] = Cats->cat[n];
 
275
            m++;
276
276
        }
277
277
    }
 
278
    found = Cats->n_cats - m;
 
279
    Cats->n_cats = m;
278
280
 
279
281
    return (found);
280
282
}
299
301
/*!
300
302
   \brief Allocate memory for cat_list structure.
301
303
 
302
 
   \return poiter to allocated structure
303
 
   \return NULL on out of memory
 
304
   \return pointer to allocated structure
 
305
   \return NULL if out of memory
304
306
 */
305
307
struct cat_list *Vect_new_cat_list()
306
308
{
309
311
    p = (struct cat_list *)G_malloc(sizeof(struct cat_list));
310
312
 
311
313
    /* n_ranges MUST be initialized to zero */
312
 
    if (p) {
313
 
        p->n_ranges = 0;
314
 
        p->alloc_ranges = 0;
315
 
        p->field = 0;
316
 
        p->min = NULL;
317
 
        p->max = NULL;
318
 
    }
319
 
 
 
314
    if (p)
 
315
        G_zero(p, sizeof(struct cat_list));
 
316
    
320
317
    return p;
321
318
}
322
319
 
324
321
/*!
325
322
   \brief Frees allocated cat_list memory.
326
323
 
327
 
   \param[in] p line_cats structure
328
 
 
329
 
   \return 0
 
324
   \param p pointer to line_cats structure
330
325
 */
331
 
int Vect_destroy_cat_list(struct cat_list *p)
 
326
void Vect_destroy_cat_list(struct cat_list *p)
332
327
{
333
328
    if (p) {                    /* probably a moot test */
334
329
        if (p->n_ranges) {
337
332
        }
338
333
        G_free((void *)p);
339
334
    }
340
 
 
341
 
    return 0;
342
335
}
343
336
 
344
337
 
345
338
/*!
346
 
   \brief Convert string of categories and cat ranges separated by commas to cat_list.
347
 
 
348
 
   Examples of string: 2,3,5-9,20. str - input string
349
 
 
350
 
   \param[in] str cat list string
351
 
   \param[out] list result cat_list structure
 
339
   \brief Converts string of categories and cat ranges separated by commas to cat_list.
 
340
 
 
341
   \par Examples of string:
 
342
   \verbatim
 
343
   5,6,7
 
344
   3-9
 
345
   2,3,5-9,20\endverbatim
 
346
   
 
347
   \par Example:
 
348
   \code
 
349
   ...
 
350
   str = "2,3,5-9,20"
 
351
   cat_list = Vect_new_cat_list()
 
352
 
 
353
   Vect_str_to_cat_list(str, cat_list)
 
354
   \endcode
 
355
   \verbatim
 
356
   cat_list->field = 0
 
357
   cat_list->n_ranges = 4
 
358
   cat_list->min = {2, 3, 5, 20}
 
359
   cat_list->max = {2, 3, 9, 20}
 
360
   \endverbatim
 
361
 
 
362
   \param str category list as a string
 
363
   \param[in,out] list pointer to cat_list structure
352
364
 
353
365
   \return number of errors in ranges
354
366
 */
423
435
/*!
424
436
   \brief Convert ordered array of integers to cat_list structure.
425
437
 
426
 
   \param[in] vals array of integers
427
 
   \param[in] nvals number of values
428
 
   \param[out] list result cat_list structure
 
438
   \param vals array of integers
 
439
   \param nvals number of values
 
440
   \param[in,out] list pointer to cat_list structure
429
441
 
430
442
   \return number of ranges
431
443
 */
432
 
int Vect_array_to_cat_list(int *vals, int nvals, struct cat_list *list)
 
444
int Vect_array_to_cat_list(const int *vals, int nvals, struct cat_list *list)
433
445
{
434
446
    int i, range;
435
447
 
461
473
}
462
474
 
463
475
/*!
 
476
   \brief Convert cat_list struct to ordered array of unique integers.
 
477
   
 
478
   Output array do not contain duplicate items.
 
479
 
 
480
   Allocated array should be freed by G_free().
 
481
   
 
482
   \param cat_list pointer to cat_list struct
 
483
   \param[out] vals array of integers
 
484
   \param[out] nvals number of values
 
485
 
 
486
   \return 0 on success
 
487
   \return -1 on failure
 
488
 */
 
489
int Vect_cat_list_to_array(const struct cat_list *list, int **vals, int *nvals)
 
490
{
 
491
    int i, j, k, n, n_cats, n_ucats, last_cat;
 
492
    int *cats, *ucats;
 
493
    
 
494
    G_debug(1, "Vect_cat_list_to_array()");
 
495
 
 
496
    *nvals = n_cats = 0;
 
497
    cats = NULL;
 
498
    for (i = 0; i < list->n_ranges; i++) {
 
499
        n = list->max[i] - list->min[i] + 1;
 
500
        if (n < 1)
 
501
            return -1;
 
502
        
 
503
        /* realloc array */
 
504
        cats = (int *) G_realloc(cats, sizeof(int) * (n_cats + n));
 
505
 
 
506
        for (j = n_cats, k = 0; j < n_cats + n; j++, k++) {
 
507
            cats[j] = list->min[i] + k;
 
508
        }
 
509
        n_cats += n;
 
510
    }
 
511
 
 
512
    /* sort array */
 
513
    qsort(cats, n_cats, sizeof(int), cmp);
 
514
 
 
515
    /* skip duplicated values */
 
516
    ucats = G_malloc(sizeof(int) * n_cats);
 
517
    last_cat = ucats[0] = cats[0];
 
518
    n_ucats = 1;
 
519
    for (i = 1; i < n_cats; i++) {
 
520
        if (last_cat == cats[i])
 
521
            continue;
 
522
        last_cat = ucats[n_ucats++] = cats[i];
 
523
    }
 
524
    G_free(cats);
 
525
    
 
526
    /* reallocate array for unique values */
 
527
    ucats = (int *) G_realloc(ucats, sizeof(int) * n_ucats);
 
528
    
 
529
    *nvals = n_ucats;
 
530
    *vals = ucats;
 
531
    
 
532
    return 0;
 
533
}
 
534
 
 
535
/*!
464
536
   \brief Check if category number is in list.
465
537
 
466
 
   \param[in] cat category number
467
 
   \param[in] list cat_list structure
 
538
   \param cat category number
 
539
   \param list cat_list structure
468
540
 
469
541
   \return TRUE if cat is in list
470
 
   \return FALSE if it is not
 
542
   \return FALSE if not
471
543
 */
472
 
int Vect_cat_in_cat_list(int cat, struct cat_list *list)
 
544
int Vect_cat_in_cat_list(int cat, const struct cat_list *list)
473
545
{
474
546
    int i;
475
547
 
481
553
}
482
554
 
483
555
/*!
 
556
   \brief Set category constraints using 'where' or 'cats' option and layer number.
 
557
 
 
558
   \param Map pointer to Map_info structure
 
559
   \param layer layer number
 
560
   \param where where statement
 
561
   \param catstr category list as string
 
562
 
 
563
   \return pointer to cat_list structure or NULL
 
564
 */
 
565
struct cat_list *Vect_cats_set_constraint(struct Map_info *Map, int layer,
 
566
                                         char *where, char *catstr)
 
567
{
 
568
    struct cat_list *list = NULL;
 
569
    int ret;
 
570
 
 
571
    if (layer < 1) {
 
572
        G_warning(_("Layer number must be > 0 for category constraints"));
 
573
        /* no valid constraints, all categories qualify */
 
574
        return list;
 
575
    }
 
576
 
 
577
    /* where has precedence over cats */
 
578
    if (where) {
 
579
        struct field_info *Fi = NULL;
 
580
        dbDriver *driver = NULL;
 
581
        int ncats, *cats = NULL;
 
582
        int i, j;
 
583
 
 
584
        if (catstr)
 
585
            G_warning(_("'%s' and '%s' parameters were supplied, cats will be ignored"), "where", "cats");
 
586
 
 
587
        Fi = Vect_get_field(Map, layer);
 
588
        if (!Fi) {
 
589
            G_fatal_error(_("Database connection not defined for layer %d"),
 
590
                          layer);
 
591
        }
 
592
 
 
593
        G_verbose_message(_("Loading categories from table <%s>..."), Fi->table);
 
594
 
 
595
        driver = db_start_driver_open_database(Fi->driver, Fi->database);
 
596
        if (driver == NULL)
 
597
            G_fatal_error(_("Unable to open database <%s> by driver <%s>"),
 
598
                          Fi->database, Fi->driver);
 
599
        
 
600
        ncats = db_select_int(driver, Fi->table, Fi->key, where,
 
601
                              &cats);
 
602
        if (ncats == -1)
 
603
                G_fatal_error(_("Unable select records from table <%s>"),
 
604
                              Fi->table);
 
605
        G_verbose_message(_n("One category loaded", "%d categories loaded", ncats), ncats);
 
606
            
 
607
        db_close_database_shutdown_driver(driver);
 
608
 
 
609
        /* sort */
 
610
        qsort(cats, ncats, sizeof(int), cmp);
 
611
        
 
612
        /* remove duplicates */
 
613
        j = 1;
 
614
        for (i = 1; i < ncats; i++) {
 
615
            if (cats[i] != cats[j - 1]) {
 
616
                cats[j] = cats[i];
 
617
                j++;
 
618
            }
 
619
        }
 
620
        ncats = j;
 
621
        
 
622
        /* convert to cat list */
 
623
        list = Vect_new_cat_list();
 
624
        
 
625
        ret = Vect_array_to_cat_list(cats, ncats, list);
 
626
        if (ret == 0)
 
627
            G_warning(_("No categories selected with '%s' option"), "where");
 
628
        
 
629
        if (cats)
 
630
            G_free(cats);
 
631
    }
 
632
    else if (catstr) {
 
633
        list = Vect_new_cat_list();
 
634
 
 
635
        ret = Vect_str_to_cat_list(catstr, list);
 
636
        if (ret > 0)
 
637
            G_warning(_("%d errors in '%s' option"), ret, "cats");
 
638
    }
 
639
    
 
640
    if (list) {
 
641
        if (list->n_ranges < 1) {
 
642
            Vect_destroy_cat_list(list);
 
643
            list = NULL;
 
644
        }
 
645
        else
 
646
            list->field = layer;
 
647
    }
 
648
        
 
649
    return list;
 
650
}
 
651
 
 
652
/*!
 
653
   \brief Check if categories match with category constraints.
 
654
 
 
655
   \param Cats line_cats structure
 
656
   \param layer layer number
 
657
   \param list cat_list structure
 
658
 
 
659
   \return 0 no match, categories are outside constraints
 
660
   \return 1 match, categories are inside constraints
 
661
 */
 
662
int Vect_cats_in_constraint(struct line_cats *Cats, int layer,
 
663
                              struct cat_list *list)
 
664
{
 
665
    int i;
 
666
 
 
667
    if (layer < 1) {
 
668
        G_warning(_("Layer number must be > 0 for category constraints"));
 
669
        /* no valid constraint, all categories qualify */
 
670
        return 1;
 
671
    }
 
672
 
 
673
    if (list) {
 
674
        for (i = 0; i < Cats->n_cats; i++) {
 
675
            if (Cats->field[i] == layer &&
 
676
                Vect_cat_in_cat_list(Cats->cat[i], list)) {
 
677
                return 1;
 
678
            }
 
679
        }
 
680
        return 0;
 
681
    }
 
682
 
 
683
    for (i = 0; i < Cats->n_cats; i++) {
 
684
        if (Cats->field[i] == layer)
 
685
            return 1;
 
686
    }
 
687
        
 
688
    return 0;
 
689
}
 
690
 
 
691
 
 
692
/*!
484
693
   \brief Check if category is in ordered array of integers.
485
694
 
486
 
   \param[in] cat category number
487
 
   \param[in] array ordered array of integers
488
 
   \param[in] ncats number of categories in array
 
695
   \param cat category number
 
696
   \param array ordered array of integers
 
697
   \param ncats number of categories in array
489
698
 
490
699
   \return TRUE if cat is in list
491
700
   \return FALSE if it is not
492
701
 */
493
 
int Vect_cat_in_array(int cat, int *array, int ncats)
 
702
int Vect_cat_in_array(int cat, const int *array, int ncats)
494
703
{
495
704
    int *i;
496
705
 
497
706
    i = bsearch((void *)&cat, (void *)array, (size_t) ncats,
498
707
                sizeof(int), cmp);
499
708
 
500
 
    if (i != NULL)
501
 
        return (TRUE);
502
 
 
503
 
    return (FALSE);
 
709
    return (i != NULL);
504
710
}
505
711
 
 
712
/* return -1 if *p1 < *p2
 
713
 * return  1 if *p1 > *p2
 
714
 * return  0 if *p1 == *p2 */
506
715
static int cmp(const void *pa, const void *pb)
507
716
{
508
717
    int *p1 = (int *)pa;
510
719
 
511
720
    if (*p1 < *p2)
512
721
        return -1;
513
 
    if (*p1 > *p2)
514
 
        return 1;
515
 
    return 0;
 
722
    return (*p1 > *p2);
516
723
}