GRASS Programmer's Manual  6.5.svn(2014)-r66266
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
Vlib/cindex.c
Go to the documentation of this file.
1 
17 #include <stdlib.h>
18 #include <string.h>
19 #include <sys/types.h>
20 #include <sys/stat.h>
21 #include <unistd.h>
22 #include <grass/gis.h>
23 #include <grass/Vect.h>
24 #include <grass/glocale.h>
25 
26 static int cmp_cat(const void *pa, const void *pb);
27 
28 static void check_status(struct Map_info *Map)
29 {
30  if (!Map->plus.cidx_up_to_date)
31  G_fatal_error(_("Category index is not up to date"));
32 }
33 
41 int Vect_cidx_get_num_fields(struct Map_info *Map)
42 {
43  check_status(Map);
44 
45  return (Map->plus.n_cidx);
46 }
47 
56 int Vect_cidx_get_field_number(struct Map_info *Map, int index)
57 {
58  check_status(Map);
59 
60  if (index >= Map->plus.n_cidx)
61  G_fatal_error(_("Invalid layer index (index >= number of layers)"));
62 
63  return (Map->plus.cidx[index].field);
64 }
65 
75 int Vect_cidx_get_field_index(struct Map_info *Map, int field)
76 {
77  int i;
78  struct Plus_head *Plus;
79 
80  G_debug(2, "Vect_cidx_get_field_index() field = %d", field);
81 
82  check_status(Map);
83  Plus = &(Map->plus);
84 
85  for (i = 0; i < Plus->n_cidx; i++) {
86  if (Plus->cidx[i].field == field)
87  return i;
88  }
89 
90  return (-1);
91 }
92 
102 int Vect_cidx_get_num_unique_cats_by_index(struct Map_info *Map, int index)
103 {
104  check_status(Map);
105 
106  if (index < 0 || index >= Map->plus.n_cidx)
107  G_fatal_error(_("Invalid layer index (index < 0 or index >= number of layers)"));
108 
109  return (Map->plus.cidx[index].n_ucats);
110 }
111 
121 int Vect_cidx_get_num_cats_by_index(struct Map_info *Map, int index)
122 {
123  check_status(Map);
124  if (index >= Map->plus.n_cidx)
125  G_fatal_error(_("Invalid layer index (index >= number of layers)"));
126 
127  return (Map->plus.cidx[index].n_cats);
128 }
129 
139 int Vect_cidx_get_num_types_by_index(struct Map_info *Map, int field_index)
140 {
141  check_status(Map);
142  if (field_index >= Map->plus.n_cidx)
143  G_fatal_error(_("Invalid layer index (index >= number of layers)"));
144 
145  return (Map->plus.cidx[field_index].n_types);
146 }
147 
160 int
161 Vect_cidx_get_type_count_by_index(struct Map_info *Map, int field_index,
162  int type_index, int *type, int *count)
163 {
164  check_status(Map);
165  if (field_index >= Map->plus.n_cidx)
166  G_fatal_error(_("Invalid layer index (index >= number of layers)"));
167 
168  *type = Map->plus.cidx[field_index].type[type_index][0];
169  *count = Map->plus.cidx[field_index].type[type_index][1];
170 
171  return (1);
172 }
173 
184 int Vect_cidx_get_type_count(struct Map_info *Map, int field, int type)
185 {
186  int i, fi, count = 0;
187 
188  G_debug(3, "Vect_cidx_get_type_count() field = %d, type = %d", field,
189  type);
190 
191  check_status(Map);
192 
193  if ((fi = Vect_cidx_get_field_index(Map, field)) < 0)
194  return 0; /* field not found */
195  G_debug(3, "field_index = %d", fi);
196 
197  G_debug(3, "ntypes = %d", Map->plus.cidx[fi].n_types);
198  for (i = 0; i < Map->plus.cidx[fi].n_types; i++) {
199  int tp, cnt;
200 
201  tp = Map->plus.cidx[fi].type[i][0];
202  cnt = Map->plus.cidx[fi].type[i][1];
203  if (tp & type)
204  count += cnt;
205  G_debug(3, "%d tp = %d, cnt= %d count = %d", i, tp, cnt, count);
206  }
207 
208  return (count);
209 }
210 
224 int
225 Vect_cidx_get_cat_by_index(struct Map_info *Map, int field_index,
226  int cat_index, int *cat, int *type, int *id)
227 {
228  check_status(Map); /* This check is slow ? */
229 
230  if (field_index >= Map->plus.n_cidx || field_index < 0 ||
231  cat_index >= Map->plus.cidx[field_index].n_cats)
232  G_fatal_error(_("Layer or category index out of range"));
233 
234  *cat = Map->plus.cidx[field_index].cat[cat_index][0];
235  *type = Map->plus.cidx[field_index].cat[cat_index][1];
236  *id = Map->plus.cidx[field_index].cat[cat_index][2];
237 
238  return 1;
239 }
240 
241 /* Compare by cat */
242 static int cmp_cat(const void *pa, const void *pb)
243 {
244  int *p1 = (int *)pa;
245  int *p2 = (int *)pb;
246 
247  if (*p1 < p2[0])
248  return -1;
249  if (*p1 > p2[0])
250  return 1;
251  return 0;
252 }
253 
268 int
269 Vect_cidx_find_next(struct Map_info *Map, int field_index, int cat,
270  int type_mask, int start_index, int *type, int *id)
271 {
272  int *catp, cat_index;
273  struct Cat_index *ci;
274 
275  G_debug(3,
276  "Vect_cidx_find_next() cat = %d, type_mask = %d, start_index = %d",
277  cat, type_mask, start_index);
278 
279  check_status(Map); /* This check is slow ? */
280  *type = *id = 0;
281 
282  if (field_index >= Map->plus.n_cidx)
283  G_fatal_error(_("Layer index out of range"));
284 
285  if (start_index < 0)
286  start_index = 0;
287  if (start_index >= Map->plus.cidx[field_index].n_cats)
288  return -1; /* outside range */
289 
290  /* pointer to beginning of searched part of category index */
291  ci = &(Map->plus.cidx[field_index]);
292 
293  /* calc with pointers is using sizeof(int) !!! */
294  catp = bsearch(&cat, (int *)ci->cat + start_index * 3,
295  (size_t) ci->n_cats - start_index,
296  3 * sizeof(int), cmp_cat);
297 
298  G_debug(3, "catp = %p", catp);
299  if (!catp)
300  return -1;
301 
302  /* get index from pointer, the difference between pointers is using sizeof(int) !!! */
303  cat_index = (catp - (int *)ci->cat) / 3;
304 
305  G_debug(4, "cat_index = %d", cat_index);
306 
307  /* Go down to the first if multiple */
308  while (cat_index > start_index) {
309  if (ci->cat[cat_index - 1][0] != cat) {
310  break;
311  }
312  cat_index--;
313  }
314  G_debug(4, "cat_index = %d", cat_index);
315 
316  do {
317  G_debug(3, " cat_index = %d", cat_index);
318  if (ci->cat[cat_index][0] == cat && ci->cat[cat_index][1] & type_mask) {
319  *type = ci->cat[cat_index][1];
320  *id = ci->cat[cat_index][2];
321  G_debug(3, " type match -> record found");
322  return cat_index;
323  }
324  cat_index++;
325  } while (cat_index < ci->n_cats);
326 
327  return -1;
328 }
329 
330 
342 void Vect_cidx_find_all(struct Map_info *Map, int layer, int type_mask,
343  int cat, struct ilist *lines)
344 {
345  int type, line;
346  struct Cat_index *ci;
347  int field_index, idx;
348 
349  Vect_reset_list(lines);
350  field_index = Vect_cidx_get_field_index(Map, layer);
351 
352  if (field_index == -1) {
353  /* not found */
354  return;
355  }
356  ci = &(Map->plus.cidx[field_index]);
357 
358  idx = Vect_cidx_find_next(Map, field_index, cat,
359  type_mask, 0, &type, &line);
360 
361  if (idx == -1) {
362  return;
363  }
364 
365  do {
366  if (ci->cat[idx][0] != cat) {
367  break;
368  }
369  if (ci->cat[idx][1] & type_mask) {
370  Vect_list_append(lines, ci->cat[idx][2]);
371  }
372  idx++;
373  } while (idx < ci->n_cats);
374  return;
375 }
376 
377 
378 #define SEP "------------------------------------------------------------------------------------------\n"
379 
389 int Vect_cidx_dump(struct Map_info *Map, FILE * out)
390 {
391  int i, field, nfields, ntypes;
392 
393  G_debug(2, "Vect_cidx_dump()");
394 
395  check_status(Map);
396 
397  nfields = Vect_cidx_get_num_fields(Map);
398  fprintf(out, "---------- CATEGORY INDEX DUMP: Number of layers: %d "
399  "--------------------------------------\n", nfields);
400 
401  for (i = 0; i < nfields; i++) {
402  int j, nucats, ncats;
403 
404  field = Vect_cidx_get_field_number(Map, i);
406  ncats = Vect_cidx_get_num_cats_by_index(Map, i);
407  ntypes = Vect_cidx_get_num_types_by_index(Map, i);
408 
409  fprintf(out,
410  "Layer %6d number of unique cats: %7d number of cats: %7d number of types: %d\n",
411  field, nucats, ncats, ntypes);
412  fprintf(out, SEP);
413 
414  fprintf(out, " type | count\n");
415  for (j = 0; j < ntypes; j++) {
416  int type, count;
417 
418  Vect_cidx_get_type_count_by_index(Map, i, j, &type, &count);
419  fprintf(out, " %5d | %9d\n", type, count);
420  }
421 
422  fprintf(out, " category | type | line/area\n");
423  for (j = 0; j < ncats; j++) {
424  int cat, type, id;
425 
426  Vect_cidx_get_cat_by_index(Map, i, j, &cat, &type, &id);
427  fprintf(out, "%9d | %4d | %9d\n", cat, type, id);
428  }
429 
430  fprintf(out, SEP);
431  }
432 
433  return 1;
434 }
435 
444 int Vect_cidx_save(struct Map_info *Map)
445 {
446  struct Plus_head *plus;
447  char fname[1024], buf[1024];
448  GVFILE fp;
449 
450  G_debug(2, "Vect_cidx_save()");
451  check_status(Map);
452 
453  plus = &(Map->plus);
454 
455  sprintf(buf, "%s/%s", GRASS_VECT_DIRECTORY, Map->name);
456  G__file_name(fname, buf, GV_CIDX_ELEMENT, Map->mapset);
457  G_debug(2, "Open cidx: %s", fname);
458  dig_file_init(&fp);
459  fp.file = fopen(fname, "w");
460  if (fp.file == NULL) {
461  G_warning(_("Unable to open cidx file <%s> for write"), fname);
462  return 1;
463  }
464 
465  /* set portable info */
466  dig_init_portable(&(plus->cidx_port), dig__byte_order_out());
467 
468  if (0 > dig_write_cidx(&fp, plus)) {
469  G_warning(_("Error writing out category index file <%s>"), fname);
470  return 1;
471  }
472 
473  fclose(fp.file);
474 
475  return 0;
476 }
477 
488 int Vect_cidx_open(struct Map_info *Map, int head_only)
489 {
490  int ret;
491  char buf[500], file_path[2000];
492  GVFILE fp;
493  struct Plus_head *Plus;
494  struct stat info;
495 
496  G_debug(2, "Vect_cidx_open(): name = %s mapset= %s", Map->name,
497  Map->mapset);
498 
499  Plus = &(Map->plus);
500 
501  sprintf(buf, "%s/%s", GRASS_VECT_DIRECTORY, Map->name);
502  G__file_name(file_path, buf, GV_CIDX_ELEMENT, Map->mapset);
503 
504  if (stat(file_path, &info) != 0) /* does not exist */
505  return 1;
506 
507 
508  dig_file_init(&fp);
509  fp.file = G_fopen_old(buf, GV_CIDX_ELEMENT, Map->mapset);
510 
511  if (fp.file == NULL) { /* category index file is not available */
512  G_warning(_("Unable to open category index file for vector map <%s@%s>"),
513  Map->name, Map->mapset);
514  return -1;
515  }
516 
517  /* load category index to memory */
518  dig_cidx_init(Plus);
519  ret = dig_read_cidx(&fp, Plus, head_only);
520 
521  fclose(fp.file);
522 
523  if (ret == 1) {
524  G_debug(3, "Cannot read cidx");
525  return -1;
526  }
527 
528  return 0;
529 }
sprintf(buf2,"%s", G3D_CATS_ELEMENT)
#define SEP
Definition: Vlib/cindex.c:378
int Vect_cidx_get_num_cats_by_index(struct Map_info *Map, int index)
Get number of categories for given layer index.
Definition: Vlib/cindex.c:121
int Vect_cidx_get_field_index(struct Map_info *Map, int field)
Get layer index for given layer number.
Definition: Vlib/cindex.c:75
int count
int Vect_cidx_dump(struct Map_info *Map, FILE *out)
Write category index in text form to file.
Definition: Vlib/cindex.c:389
void Vect_cidx_find_all(struct Map_info *Map, int layer, int type_mask, int cat, struct ilist *lines)
Gind all line/area id&#39;s for given category.
Definition: Vlib/cindex.c:342
int Vect_cidx_get_field_number(struct Map_info *Map, int index)
Get layer number for given index.
Definition: Vlib/cindex.c:56
void dig_init_portable(struct Port_info *port, int byte_order)
Definition: portable.c:568
int Vect_cidx_get_num_unique_cats_by_index(struct Map_info *Map, int index)
Get number of unique categories for given layer index.
Definition: Vlib/cindex.c:102
int Vect_cidx_get_cat_by_index(struct Map_info *Map, int field_index, int cat_index, int *cat, int *type, int *id)
Get number of categories for given field and category index.
Definition: Vlib/cindex.c:225
int stat
Definition: g3dcolor.c:369
char * G__file_name(char *path, const char *element, const char *name, const char *mapset)
Builds full path names to GIS data files.
Definition: file_name.c:33
tuple id
self.OnVectorSurface(event)
Definition: tools.py:3426
int Vect_cidx_get_type_count_by_index(struct Map_info *Map, int field_index, int type_index, int *type, int *count)
Get type count field index and type index.
Definition: Vlib/cindex.c:161
int Vect_cidx_get_type_count(struct Map_info *Map, int field, int type)
Get count of features of certain type by layer and type.
Definition: Vlib/cindex.c:184
int Vect_reset_list(struct ilist *list)
Reset ilist structure.
int Vect_list_append(struct ilist *list, int val)
Append new item to the end of list if not yet present.
char buf[GNAME_MAX+sizeof(G3D_DIRECTORY)+2]
Definition: g3drange.c:62
int dig_cidx_init(struct Plus_head *Plus)
Definition: diglib/cindex.c:29
int dig_read_cidx(GVFILE *fp, struct Plus_head *plus, int head_only)
Definition: cindex_rw.c:256
return NULL
Definition: dbfopen.c:1394
int Vect_cidx_get_num_fields(struct Map_info *Map)
Get number of layer in category index.
Definition: Vlib/cindex.c:41
G_warning("category support for [%s] in mapset [%s] %s", name, mapset, type)
tuple Map
Definition: render.py:1310
int G_debug(int level, const char *msg,...)
Print debugging message.
Definition: gis/debug.c:51
void dig_file_init(GVFILE *file)
Initialize GVFILE.
Definition: file.c:168
fclose(fd)
int Vect_cidx_find_next(struct Map_info *Map, int field_index, int cat, int type_mask, int start_index, int *type, int *id)
Find next line/area id for given category, start_index and type_mask.
Definition: Vlib/cindex.c:269
int dig_write_cidx(GVFILE *fp, struct Plus_head *plus)
Definition: cindex_rw.c:218
int Vect_cidx_save(struct Map_info *Map)
Save category index.
Definition: Vlib/cindex.c:444
int Vect_cidx_open(struct Map_info *Map, int head_only)
Read category index from file if exists.
Definition: Vlib/cindex.c:488
CELL cat
Definition: g3dcats.c:90
int dig__byte_order_out()
Definition: portable.c:646
FILE * G_fopen_old(const char *element, const char *name, const char *mapset)
Open a database file for reading.
Definition: gis/open.c:226
int G_fatal_error(const char *msg,...)
Print a fatal error message to stderr.
int Vect_cidx_get_num_types_by_index(struct Map_info *Map, int field_index)
Get number of types for given layer index.
Definition: Vlib/cindex.c:139