GRASS Programmer's Manual
6.4.2(2012)
|
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 }