GRASS Programmer's Manual  6.4.2(2012)
array.c
Go to the documentation of this file.
00001 
00020 #include <stdlib.h>
00021 #include <grass/gis.h>
00022 #include <grass/dbmi.h>
00023 #include <grass/Vect.h>
00024 #include <grass/glocale.h>
00025 
00026 
00027 /* function prototypes */
00028 static int cmp(const void *pa, const void *pb);
00029 static int in_array(int *cats, size_t ncats, int cat);
00030 
00031 
00044 VARRAY *Vect_new_varray(int size)
00045 {
00046     VARRAY *p;
00047 
00048     p = (VARRAY *) G_malloc(sizeof(VARRAY));
00049 
00050     if (p == NULL)
00051         return NULL;
00052 
00053     p->size = size;
00054     p->c = (int *)G_calloc(sizeof(char) * size + 1, sizeof(int));
00055 
00056     if (p->c == NULL) {
00057         G_free(p);
00058         return NULL;
00059     }
00060 
00061     return p;
00062 }
00063 
00084 int
00085 Vect_set_varray_from_cat_string(struct Map_info *Map, int field,
00086                                 const char *cstring, int type, int value,
00087                                 VARRAY * varray)
00088 {
00089     int ret;
00090     struct cat_list *Clist;
00091 
00092     G_debug(4, "Vect_set_varray_from_cat_string(): cstring = '%s'", cstring);
00093 
00094     Clist = Vect_new_cat_list();
00095 
00096     ret = Vect_str_to_cat_list(cstring, Clist);
00097 
00098     if (ret > 0)
00099         G_warning(_("%d errors in category string."), ret);
00100 
00101     G_debug(4, "  %d ranges in clist", Clist->n_ranges);
00102 
00103     ret =
00104         Vect_set_varray_from_cat_list(Map, field, Clist, type, value, varray);
00105 
00106     Vect_destroy_cat_list(Clist);
00107 
00108     return ret;
00109 }
00110 
00131 int
00132 Vect_set_varray_from_cat_list(struct Map_info *Map, int field,
00133                               struct cat_list *clist, int type, int value,
00134                               VARRAY * varray)
00135 {
00136     int i, n, centr, cat;
00137     int ni = 0;                 /* number of items set */
00138     int ltype;                  /* line type */
00139     struct line_cats *Cats;
00140 
00141     G_debug(4, "Vect_set_varray_from_cat_list(): field = %d", field);
00142 
00143     /* Check type */
00144     if ((type & GV_AREA) && (type & (GV_POINTS | GV_LINES))) {
00145         G_warning(_("Mixed area and other type requested for vector array"));
00146         return 0;
00147     }
00148 
00149     Cats = Vect_new_cats_struct();
00150 
00151     if (type & GV_AREA) {       /* Areas */
00152         n = Vect_get_num_areas(Map);
00153 
00154         if (n > varray->size) { /* not enough space */
00155             G_warning(_("Not enough space in vector array"));
00156             return 0;
00157         }
00158 
00159         for (i = 1; i <= n; i++) {
00160             centr = Vect_get_area_centroid(Map, i);
00161             if (centr <= 0)
00162                 continue;       /* No centroid */
00163 
00164             Vect_read_line(Map, NULL, Cats, centr);
00165             if (!Vect_cat_get(Cats, field, &cat))
00166                 continue;       /* No such field */
00167 
00168             if (Vect_cat_in_cat_list(cat, clist)) {     /* cat is in list */
00169                 varray->c[i] = value;
00170                 ni++;
00171             }
00172         }
00173     }
00174     else {                      /* Lines */
00175         n = Vect_get_num_lines(Map);
00176 
00177         if (n > varray->size) { /* not enough space */
00178             G_warning(_("Not enough space in vector array"));
00179             return 0;
00180         }
00181 
00182         for (i = 1; i <= n; i++) {
00183             ltype = Vect_read_line(Map, NULL, Cats, i);
00184 
00185             if (!(ltype & type))
00186                 continue;       /* is not specified type */
00187 
00188             if (!Vect_cat_get(Cats, field, &cat))
00189                 continue;       /* No such field */
00190 
00191             if (Vect_cat_in_cat_list(cat, clist)) {     /* cat is in list */
00192                 varray->c[i] = value;
00193                 ni++;
00194             }
00195         }
00196 
00197     }
00198 
00199     Vect_destroy_cats_struct(Cats);
00200 
00201     return ni;
00202 }
00203 
00204 /* compare 2 integers in array */
00205 static int cmp(const void *pa, const void *pb)
00206 {
00207     int *p1 = (int *)pa;
00208     int *p2 = (int *)pb;
00209 
00210     if (*p1 < *p2)
00211         return -1;
00212     if (*p1 > *p2)
00213         return 1;
00214     return 0;
00215 }
00216 
00217 /* check if cat is in array */
00218 static int in_array(int *cats, size_t ncats, int cat)
00219 {
00220     int *p;
00221 
00222     p = (int *)bsearch((void *)&cat, cats, ncats, sizeof(int), cmp);
00223 
00224     if (p == NULL)
00225         return 0;
00226 
00227     return 1;
00228 }
00229 
00250 int
00251 Vect_set_varray_from_db(struct Map_info *Map, int field, const char *where,
00252                         int type, int value, VARRAY * varray)
00253 {
00254     int i, n, c, centr, cat, *cats;
00255     int ncats;
00256     int ni = 0;                 /* number of items set */
00257     int ltype;                  /* line type */
00258     struct line_cats *Cats;
00259     struct field_info *Fi;
00260     dbDriver *driver;
00261 
00262     G_debug(4, "Vect_set_varray_from_db(): field = %d where = '%s'", field,
00263             where);
00264 
00265     /* Note: use category index once available */
00266 
00267     /* Check type */
00268     if ((type & GV_AREA) && (type & (GV_POINTS | GV_LINES))) {
00269         G_warning(_("Mixed area and other type requested for vector array"));
00270         return 0;
00271     }
00272 
00273     Cats = Vect_new_cats_struct();
00274 
00275     /* Select categories from DB to array */
00276     Fi = Vect_get_field(Map, field);
00277     if (Fi == NULL) {
00278         G_warning(_("Database connection not defined for layer %d"), field);
00279         return -1;
00280     }
00281 
00282     driver = db_start_driver_open_database(Fi->driver, Fi->database);
00283     if (driver == NULL) {
00284         G_warning(_("Unable to open database <%s> by driver <%s>"),
00285                   Fi->database, Fi->driver);
00286         return -1;
00287     }
00288 
00289     ncats = db_select_int(driver, Fi->table, Fi->key, where, &cats);
00290 
00291     db_close_database_shutdown_driver(driver);
00292 
00293     if (ncats == -1) {
00294         G_warning(_("Unable to select record from table <%s> (key %s, where %s)"),
00295                   Fi->table, Fi->key, where);
00296         return -1;
00297     }
00298 
00299     if (type & GV_AREA) {       /* Areas */
00300         n = Vect_get_num_areas(Map);
00301 
00302         /* IMHO varray should be allocated only when it's required AND only as large as required
00303         as WHERE will create a small subset of all vector features and thus on large datasets
00304         it's waste of memory to allocate it for all features. */
00305         if (n > varray->size) { /* not enough space */
00306             G_warning(_("Not enough space in vector array"));
00307             return 0;
00308         }
00309 
00310         for (i = 1; i <= n; i++) {
00311             centr = Vect_get_area_centroid(Map, i);
00312             if (centr <= 0)
00313                 continue;       /* No centroid */
00314 
00315             Vect_read_line(Map, NULL, Cats, centr);
00316             /*if ( !Vect_cat_get(Cats, field, &cat) ) continue; No such field */
00317             for (c = 0; c < Cats->n_cats; c++) {
00318                 if (Cats->field[c] == field &&
00319                     in_array(cats, ncats, Cats->cat[c])) {
00320                     cat = Cats->cat[c];
00321                     varray->c[i] = value;
00322                     ni++;
00323                     break;
00324                 }
00325             }
00326 
00327             /*
00328                if ( in_array ( cats, ncats, cat ) ) {
00329                varray->c[i] = value;
00330                ni++;
00331                }
00332              */
00333         }
00334     }
00335     else {                      /* Lines */
00336         n = Vect_get_num_lines(Map);
00337 
00338         if (n > varray->size) { /* not enough space */
00339             G_warning(_("Not enough space in vector array"));
00340             return 0;
00341         }
00342 
00343         for (i = 1; i <= n; i++) {
00344             ltype = Vect_read_line(Map, NULL, Cats, i);
00345 
00346             if (!(ltype & type))
00347                 continue;       /* is not specified type */
00348 
00349             /* if ( !Vect_cat_get(Cats, field, &cat) ) continue;  No such field */
00350             for (c = 0; c < Cats->n_cats; c++) {
00351                 if (Cats->field[c] == field &&
00352                     in_array(cats, ncats, Cats->cat[c])) {
00353                     cat = Cats->cat[c];
00354                     varray->c[i] = value;
00355                     ni++;
00356                     break;
00357                 }
00358             }
00359             /*
00360                if ( in_array ( cats, ncats, cat ) ) {
00361                varray->c[i] = value;
00362                ni++;
00363                }
00364              */
00365         }
00366 
00367     }
00368 
00369     G_free(cats);
00370     Vect_destroy_cats_struct(Cats);
00371 
00372     return ni;
00373 }
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines