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
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;
00138 int ltype;
00139 struct line_cats *Cats;
00140
00141 G_debug(4, "Vect_set_varray_from_cat_list(): field = %d", field);
00142
00143
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) {
00152 n = Vect_get_num_areas(Map);
00153
00154 if (n > varray->size) {
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;
00163
00164 Vect_read_line(Map, NULL, Cats, centr);
00165 if (!Vect_cat_get(Cats, field, &cat))
00166 continue;
00167
00168 if (Vect_cat_in_cat_list(cat, clist)) {
00169 varray->c[i] = value;
00170 ni++;
00171 }
00172 }
00173 }
00174 else {
00175 n = Vect_get_num_lines(Map);
00176
00177 if (n > varray->size) {
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;
00187
00188 if (!Vect_cat_get(Cats, field, &cat))
00189 continue;
00190
00191 if (Vect_cat_in_cat_list(cat, clist)) {
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
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
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;
00257 int ltype;
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
00266
00267
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
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) {
00300 n = Vect_get_num_areas(Map);
00301
00302
00303
00304
00305 if (n > varray->size) {
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;
00314
00315 Vect_read_line(Map, NULL, Cats, centr);
00316
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
00329
00330
00331
00332
00333 }
00334 }
00335 else {
00336 n = Vect_get_num_lines(Map);
00337
00338 if (n > varray->size) {
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;
00348
00349
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
00361
00362
00363
00364
00365 }
00366
00367 }
00368
00369 G_free(cats);
00370 Vect_destroy_cats_struct(Cats);
00371
00372 return ni;
00373 }