GRASS Programmer's Manual  6.5.svn(2014)-r66266
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
diglib/cindex.c
Go to the documentation of this file.
1 
2 /*****************************************************************************
3 *
4 * MODULE: Vector library
5 *
6 * AUTHOR(S): Radim Blazek
7 *
8 * PURPOSE: Lower level functions for reading/writing/manipulating vectors.
9 *
10 * COPYRIGHT: (C) 2001 by the GRASS Development Team
11 *
12 * This program is free software under the GNU General Public
13 * License (>=v2). Read the file COPYING that comes with GRASS
14 * for details.
15 *
16 *****************************************************************************/
17 #include <stdlib.h>
18 #include <string.h>
19 #include <grass/gis.h>
20 #include <grass/Vect.h>
21 
22 /*
23  * dig_cidx_init ()
24  * initit cat index
25  *
26  * returns 1 OK
27  * 0 on error
28  */
29 int dig_cidx_init(struct Plus_head *Plus)
30 {
31  G_debug(3, "dig_cidx_init()");
32 
33  Plus->n_cidx = 0;
34  Plus->a_cidx = 5;
35  Plus->cidx =
36  (struct Cat_index *)G_malloc(Plus->a_cidx * sizeof(struct Cat_index));
37  if (!Plus->cidx)
38  return 0;
39  Plus->cidx_up_to_date = 0;
40  return 1;
41 }
42 
43 /* Free category index */
44 void dig_cidx_free(struct Plus_head *Plus)
45 {
46  int i;
47  struct Cat_index *ci;
48 
49  G_debug(2, "dig_cidx_free()");
50  for (i = 0; i < Plus->n_cidx; i++) {
51  ci = &(Plus->cidx[0]);
52  G_free(ci->cat);
53  ci->cat = NULL;
54  ci->field = ci->n_cats = ci->a_cats = ci->n_types = 0;
55  }
56  Plus->n_cidx = 0;
57  Plus->cidx_up_to_date = 0;
58 }
59 
60 /*
61  * dig_cidx_add_cat ()
62  * add new field - cat - line record, space is allocated if necessary
63  *
64  * returns 1 OK
65  * 0 on error
66  */
67 int
68 dig_cidx_add_cat(struct Plus_head *Plus, int field, int cat, int line,
69  int type)
70 {
71  int i, si, found;
72  struct Cat_index *ci;
73 
74  G_debug(3, "dig_cidx_add_cat(): field = %d cat = %d line = %d type = %d",
75  field, cat, line, type);
76 
77  /* Find field or add new */
78  si = -1;
79  for (i = 0; i < Plus->n_cidx; i++) {
80  if (Plus->cidx[i].field == field) {
81  si = i;
82  }
83  }
84  if (si == -1) { /* not found add new */
85  if (Plus->n_cidx == Plus->a_cidx) {
86  Plus->a_cidx += 10;
87  Plus->cidx =
88  (struct Cat_index *)G_realloc(Plus->cidx,
89  Plus->a_cidx *
90  sizeof(struct Cat_index));
91  if (!Plus->cidx)
92  return 0;
93  }
94  si = Plus->n_cidx;
95  ci = &(Plus->cidx[si]);
96  ci->field = field;
97  ci->n_cats = ci->a_cats = 0;
98  ci->cat = NULL;
99  ci->n_types = 0;
100  ci->offset = 0;
101  Plus->n_cidx++;
102  }
103 
104  /* Add new cat - line record */
105  ci = &(Plus->cidx[si]);
106  if (ci->n_cats == ci->a_cats) {
107  ci->a_cats += 5000;
108  ci->cat = G_realloc(ci->cat, ci->a_cats * 3 * sizeof(int));
109  }
110 
111  ci->cat[ci->n_cats][0] = cat;
112  ci->cat[ci->n_cats][1] = type;
113  ci->cat[ci->n_cats][2] = line;
114  ci->n_cats++;
115 
116  /* Add type */
117  found = 0;
118  for (i = 0; i < ci->n_types; i++) {
119  if (ci->type[i][0] == type) {
120  ci->type[i][1]++;
121  found = 1;
122  }
123  }
124  if (!found) {
125  ci->type[ci->n_types][0] = type;
126  ci->type[ci->n_types][1] = 1;
127  ci->n_types++;
128  }
129 
130  return 1;
131 }
132 
133 /* Compare by cat */
134 static int cmp_cat(const void *pa, const void *pb)
135 {
136  int *p1 = (int *)pa;
137  int *p2 = (int *)pb;
138 
139  if (p1[0] < p2[0])
140  return -1;
141  if (p1[0] > p2[0])
142  return 1;
143  return 0;
144 }
145 
146 /* Compare by field */
147 static int cmp_field(const void *pa, const void *pb)
148 {
149  struct Cat_index *p1 = (struct Cat_index *)pa;
150  struct Cat_index *p2 = (struct Cat_index *)pb;
151 
152  if (p1->field < p2->field)
153  return -1;
154  if (p1->field > p2->field)
155  return 1;
156  return 0;
157 }
158 
159 /*
160  * dig_cidx_add_cat_sorted ()
161  * add new field - cat - line record to sorted category index, space is allocated if necessary
162  *
163  * returns 1 OK
164  * 0 on error
165  */
166 int
167 dig_cidx_add_cat_sorted(struct Plus_head *Plus, int field, int cat, int line,
168  int type)
169 {
170  int i, si, found, position;
171  struct Cat_index *ci;
172 
173  G_debug(3,
174  "dig_cidx_add_cat_sorted(): field = %d cat = %d line = %d type = %d",
175  field, cat, line, type);
176 
177  /* Find field or add new */
178  si = -1;
179  for (i = 0; i < Plus->n_cidx; i++) {
180  if (Plus->cidx[i].field == field) {
181  si = i;
182  }
183  }
184  if (si == -1) { /* not found add new */
185  if (Plus->n_cidx == Plus->a_cidx) {
186  Plus->a_cidx += 10;
187  Plus->cidx =
188  (struct Cat_index *)G_realloc(Plus->cidx,
189  Plus->a_cidx *
190  sizeof(struct Cat_index));
191  if (!Plus->cidx)
192  return 0;
193  }
194  si = Plus->n_cidx;
195  ci = &(Plus->cidx[si]);
196  ci->field = field;
197  ci->n_cats = ci->a_cats = 0;
198  ci->cat = NULL;
199  ci->n_types = 0;
200  ci->offset = 0;
201  Plus->n_cidx++;
202  }
203 
204  /* Add new cat - line record */
205  ci = &(Plus->cidx[si]);
206  if (ci->n_cats == ci->a_cats) {
207  ci->a_cats += 5000;
208  ci->cat = G_realloc(ci->cat, ci->a_cats * 3 * sizeof(int));
209  }
210 
211  /* Find position */
212  for (position = 0; position < ci->n_cats; position++) {
213  if (ci->cat[position][0] >= cat) {
214  break;
215  }
216  }
217 
218  G_debug(4, "position = %d", position);
219 
220  /* Move */
221  for (i = ci->n_cats; i > position; i--) {
222  ci->cat[i][0] = ci->cat[i - 1][0];
223  ci->cat[i][1] = ci->cat[i - 1][1];
224  ci->cat[i][2] = ci->cat[i - 1][2];
225  }
226 
227  ci->cat[position][0] = cat;
228  ci->cat[position][1] = type;
229  ci->cat[position][2] = line;
230  ci->n_cats++;
231 
232  /* Add type */
233  found = 0;
234  for (i = 0; i < ci->n_types; i++) {
235  if (ci->type[i][0] == type) {
236  ci->type[i][1]++;
237  found = 1;
238  }
239  }
240  if (!found) {
241  ci->type[ci->n_types][0] = type;
242  ci->type[ci->n_types][1] = 1;
243  ci->n_types++;
244  }
245 
246  /* Sort by field */
247  qsort(Plus->cidx, Plus->n_cidx, sizeof(struct Cat_index), cmp_field);
248 
249  G_debug(3, "Added new category to index");
250 
251  return 1;
252 }
253 
254 /*
255  * dig_cidx_del_cat ()
256  * delete old field - cat - line record from _sorted_ category index
257  *
258  * returns 1 OK
259  * 0 on error
260  */
261 int
262 dig_cidx_del_cat(struct Plus_head *Plus, int field, int cat, int line,
263  int type)
264 {
265  int i, position;
266  struct Cat_index *ci;
267 
268  G_debug(3, "dig_cidx_del_cat(): field = %d cat = %d line = %d", field,
269  cat, line);
270 
271  /* Find field or add new */
272  ci = NULL;
273  for (i = 0; i < Plus->n_cidx; i++) {
274  if (Plus->cidx[i].field == field) {
275  ci = &(Plus->cidx[i]);
276  }
277  }
278  if (ci == NULL) { /* should not happen */
279  G_warning("BUG: Category index not found for field %d.", field);
280  return 0;
281  }
282 
283  /* Find position */
284  G_debug(3, "n_cats = %d", ci->n_cats);
285  for (position = 0; position < ci->n_cats; position++) {
286  if (ci->cat[position][0] == cat && ci->cat[position][1] == type &&
287  ci->cat[position][2] == line) {
288  break;
289  }
290  }
291 
292  G_debug(4, "position = %d", position);
293 
294  if (position == ci->n_cats) {
295  G_warning("BUG: Category not found in category index.");
296  return 0;
297  }
298 
299  /* Delete */
300  for (i = position; i < ci->n_cats - 1; i++) {
301  ci->cat[i][0] = ci->cat[i + 1][0];
302  ci->cat[i][1] = ci->cat[i + 1][1];
303  ci->cat[i][2] = ci->cat[i + 1][2];
304  }
305 
306  ci->n_cats--;
307 
308  for (i = 0; i < ci->n_types; i++) {
309  if (ci->type[i][0] == type) {
310  ci->type[i][1]--;
311  }
312  }
313 
314  G_debug(3, "Deleted from category index");
315  return 1;
316 }
317 
318 /*
319  * dig_cidx_sort ()
320  * sort all records in cat index
321  *
322  */
323 void dig_cidx_sort(struct Plus_head *Plus)
324 {
325  int f;
326  struct Cat_index *ci;
327 
328  G_debug(2, "dig_cidx_sort()");
329 
330  for (f = 0; f < Plus->n_cidx; f++) {
331  int c, nucats = 0;
332 
333  ci = &(Plus->cidx[f]);
334 
335  /* Sort by category */
336  qsort(ci->cat, ci->n_cats, 3 * sizeof(int), cmp_cat);
337 
338  /* Calculate number of unique cats */
339  if (ci->n_cats > 0)
340  nucats++;
341  for (c = 1; c < ci->n_cats; c++) {
342  if (ci->cat[c][0] != ci->cat[c - 1][0])
343  nucats++;
344  }
345  ci->n_ucats = nucats;
346  }
347 
348  /* Sort by field */
349  qsort(Plus->cidx, Plus->n_cidx, sizeof(struct Cat_index), cmp_field);
350 }
void G_free(void *buf)
Free allocated memory.
Definition: gis/alloc.c:142
int dig_cidx_add_cat_sorted(struct Plus_head *Plus, int field, int cat, int line, int type)
int dig_cidx_add_cat(struct Plus_head *Plus, int field, int cat, int line, int type)
Definition: diglib/cindex.c:68
void dig_cidx_sort(struct Plus_head *Plus)
void dig_cidx_free(struct Plus_head *Plus)
Definition: diglib/cindex.c:44
int dig_cidx_init(struct Plus_head *Plus)
Definition: diglib/cindex.c:29
return NULL
Definition: dbfopen.c:1394
G_warning("category support for [%s] in mapset [%s] %s", name, mapset, type)
int G_debug(int level, const char *msg,...)
Print debugging message.
Definition: gis/debug.c:51
CELL cat
Definition: g3dcats.c:90
int dig_cidx_del_cat(struct Plus_head *Plus, int field, int cat, int line, int type)