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