GRASS 8 Programmer's Manual 8.6.0dev(2026)-4bb960b182
Loading...
Searching...
No Matches
remove_duplicates.c
Go to the documentation of this file.
1/*!
2 \file lib/vector/Vlib/remove_duplicates.c
3
4 \brief Vector library - clean geometry (remove duplicates)
5
6 Higher level functions for reading/writing/manipulating vectors.
7
8 SPDX-FileCopyrightText: 2001-2009 GRASS Development Team
9 SPDX-License-Identifier: GPL-2.0-or-later
10
11 \author Radim Blazek
12 */
13
14#include <stdlib.h>
15#include <grass/vector.h>
16#include <grass/glocale.h>
17
18static int cmp_int(const void *a, const void *b)
19{
20 return (*(int *)a - *(int *)b);
21}
22
23static int boxlist_add_sorted(struct boxlist *list, int id)
24{
25 int i;
26
27 if (list->n_values > 0) {
28 if (bsearch(&id, list->id, list->n_values, sizeof(int), cmp_int))
29 return 0;
30 }
31
32 if (list->n_values == list->alloc_values) {
33 size_t size = (list->n_values + 100) * sizeof(int);
34
35 list->id = (int *)G_realloc((void *)list->id, size);
36 list->alloc_values = list->n_values + 100;
37 }
38
39 i = 0;
40 if (list->n_values > 0) {
41 for (i = list->n_values; i > 0; i--) {
42 if (list->id[i - 1] < id)
43 break;
44 list->id[i] = list->id[i - 1];
45 }
46 }
47 list->id[i] = id;
48 list->n_values++;
49
50 return 1;
51}
52
53/*!
54 \brief Remove duplicate features from vector map.
55
56 Remove duplicate lines of given types from vector map. Duplicate
57 lines may be optionally written to error map. Input map must be
58 opened on level 2 for update. Categories are merged.
59 GV_BUILD_BASE is sufficient.
60
61 \param[in,out] Map vector map where duplicate lines will be deleted
62 \param type type of line to be delete
63 \param[out] Err vector map where duplicate lines will be written or NULL
64
65 \return void
66 */
67void Vect_remove_duplicates(struct Map_info *Map, int type,
68 struct Map_info *Err)
69{
70 struct line_pnts *APoints, *BPoints;
71 struct line_cats *ACats, *BCats;
72 int i, c, atype, aline, bline;
73 int nlines, nacats_orig, npoints;
74 int na1, na2, nb1, nb2, nodelines, nline;
75 struct bound_box ABox;
76 struct boxlist *List;
77 int ndupl, is_dupl;
78
84
85 nlines = Vect_get_num_lines(Map);
86
87 G_debug(1, "nlines = %d", nlines);
88 /* Go through all lines in vector, for each line select lines which
89 * overlap with the first vertex of this line and check if a
90 * selected line is identical. If yes, remove the selected line.
91 * If the line vertices are identical with those of any other line,
92 * merge categories and rewrite the current line.
93 */
94
95 ndupl = 0;
96
97 for (aline = 1; aline <= nlines; aline++) {
98 G_percent(aline, nlines, 1);
100 continue;
101
103 if (!(atype & type))
104 continue;
105
106 npoints = APoints->n_points;
108
109 if (npoints != APoints->n_points) {
110 G_debug(3, "Line %d pruned, %d vertices removed", aline,
111 npoints - APoints->n_points);
113 nlines = Vect_get_num_lines(Map);
114 continue;
115 }
116
117 na1 = na2 = -1;
118 if (atype & GV_LINES) {
119 /* faster than Vect_select_lines_by_box() */
123
124 for (i = 0; i < nodelines; i++) {
126
127 if (nline == aline)
128 continue;
130 continue;
131
132 boxlist_add_sorted(List, nline);
133 }
134 }
135 else {
136 /* select potential duplicates */
137 ABox.E = ABox.W = APoints->x[0];
138 ABox.N = ABox.S = APoints->y[0];
139 ABox.T = ABox.B = APoints->z[0];
141 G_debug(3, " %d lines selected by box", List->n_values);
142 }
143
144 is_dupl = 0;
145
146 for (i = 0; i < List->n_values; i++) {
147 bline = List->id[i];
148 G_debug(3, " j = %d bline = %d", i, bline);
149
150 /* compare aline and bline only once */
151 if (aline <= bline)
152 continue;
153
154 nb1 = nb2 = -1;
155
156 if (atype & GV_LINES) {
158 if ((na1 == nb1 && na2 != nb2) || (na1 == nb2 && na2 != nb1))
159 continue;
160 }
161
164
165 /* check for duplicate */
167 continue;
168
169 /* bline is identical to aline */
170 if (!is_dupl) {
171 if (Err) {
173 }
174 is_dupl = 1;
175 }
177
178 /* merge categories */
179 nacats_orig = ACats->n_cats;
180
181 for (c = 0; c < BCats->n_cats; c++)
182 Vect_cat_set(ACats, BCats->field[c], BCats->cat[c]);
183
184 if (ACats->n_cats > nacats_orig) {
185 G_debug(4, "cats merged: n_cats %d -> %d", nacats_orig,
186 ACats->n_cats);
187 }
188
189 ndupl++;
190 }
191 if (is_dupl) {
193 nlines = Vect_get_num_lines(Map);
194 G_debug(3, "nlines = %d\n", nlines);
195 }
196 }
197 G_verbose_message(_("Removed duplicates: %d"), ndupl);
203}
204
205/*!
206 \brief Check for duplicate lines
207
208 Note that lines must be pruned with Vect_line_prune() before passed
209 to Vect_line_check_duplicate(), as done by Vect_remove_duplicates()
210
211 \param APoints first line geometry
212 \param BPoints second line geometry
213
214 \return 1 duplicate
215 \return 0 not duplicate
216 */
218 const struct line_pnts *BPoints, int with_z)
219{
220 int k;
221 int npoints;
222 int forw, backw;
223
224 if (APoints->n_points != BPoints->n_points)
225 return 0;
226
227 npoints = APoints->n_points;
228
229 /* Forward */
230 forw = 1;
231 for (k = 0; k < APoints->n_points; k++) {
232 if (APoints->x[k] != BPoints->x[k] || APoints->y[k] != BPoints->y[k] ||
233 (with_z && APoints->z[k] != BPoints->z[k])) {
234 forw = 0;
235 break;
236 }
237 }
238
239 /* Backward */
240 backw = 1;
241 for (k = 0; k < APoints->n_points; k++) {
242 if (APoints->x[k] != BPoints->x[npoints - k - 1] ||
243 APoints->y[k] != BPoints->y[npoints - k - 1] ||
244 (with_z && APoints->z[k] != BPoints->z[npoints - k - 1])) {
245 backw = 0;
246 break;
247 }
248 }
249
250 if (!forw && !backw)
251 return 0;
252
253 return 1;
254}
void G_percent(long, long, int)
Print percent complete messages.
Definition percent.c:59
#define G_realloc(p, n)
Definition defs/gis.h:138
void void G_verbose_message(const char *,...) __attribute__((format(printf
int G_debug(int, const char *,...) __attribute__((format(printf
void Vect_destroy_line_struct(struct line_pnts *)
Frees all memory associated with a line_pnts structure, including the structure itself.
Definition line.c:75
off_t Vect_rewrite_line(struct Map_info *, off_t, int, const struct line_pnts *, const struct line_cats *)
Rewrites existing feature (topological level required)
int Vect_reset_boxlist(struct boxlist *)
Reset boxlist structure.
int Vect_get_line_nodes(struct Map_info *, int, int *, int *)
Get line nodes.
Definition level_two.c:302
plus_t Vect_get_num_lines(struct Map_info *)
Fetch number of features (points, lines, boundaries, centroids) in vector map.
Definition level_two.c:73
int Vect_cat_set(struct line_cats *, int, int)
Add new field/cat to category structure if doesn't exist yet.
int Vect_get_line_type(struct Map_info *, int)
Get line type.
Definition level_two.c:252
struct boxlist * Vect_new_boxlist(int)
Creates and initializes a struct boxlist.
void Vect_destroy_boxlist(struct boxlist *)
Frees all memory associated with a struct boxlist, including the struct itself.
void Vect_destroy_cats_struct(struct line_cats *)
Frees all memory associated with line_cats structure, including the struct itself.
int Vect_read_line(struct Map_info *, struct line_pnts *, struct line_cats *, int)
Read vector feature (topological level required)
int Vect_line_alive(struct Map_info *, int)
Check if feature is alive or dead (topological level required)
int Vect_delete_line(struct Map_info *, off_t)
Delete existing feature (topological level required)
struct line_cats * Vect_new_cats_struct(void)
Creates and initializes line_cats structure.
off_t Vect_write_line(struct Map_info *, int, const struct line_pnts *, const struct line_cats *)
Writes a new feature.
int Vect_select_lines_by_box(struct Map_info *, const struct bound_box *, int, struct boxlist *)
Select lines with bounding boxes by box.
Definition sindex.c:30
int Vect_get_node_n_lines(struct Map_info *, int)
Get number of lines for node.
Definition level_two.c:379
int Vect_get_node_line(struct Map_info *, int, int)
Get line id for node line index.
Definition level_two.c:395
int Vect_line_prune(struct line_pnts *)
Remove duplicate points, i.e. zero length segments.
Definition line.c:277
struct line_pnts * Vect_new_line_struct(void)
Creates and initializes a line_pnts structure.
Definition line.c:43
int Vect_is_3d(struct Map_info *)
Check if vector map is 3D.
#define GV_LINES
#define _(str)
Definition glocale.h:10
double b
Definition r_raster.c:37
int Vect_line_check_duplicate(const struct line_pnts *APoints, const struct line_pnts *BPoints, int with_z)
Check for duplicate lines.
void Vect_remove_duplicates(struct Map_info *Map, int type, struct Map_info *Err)
Remove duplicate features from vector map.
Vector map info.
Bounding box.
Definition dig_structs.h:62
List of bounding boxes with id.
Feature category info.
Feature geometry info - coordinates.
Definition manage.h:4