GRASS 8 Programmer's Manual 8.6.0dev(2026)-5f4f7ad06c
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 (C) 2001-2009 by the GRASS Development Team
9
10 This program is free software under the GNU General Public License
11 (>=v2). Read the file COPYING that comes with GRASS for details.
12
13 \author Radim Blazek
14 */
15
16#include <stdlib.h>
17#include <grass/vector.h>
18#include <grass/glocale.h>
19
20static int cmp_int(const void *a, const void *b)
21{
22 return (*(int *)a - *(int *)b);
23}
24
25static int boxlist_add_sorted(struct boxlist *list, int id)
26{
27 int i;
28
29 if (list->n_values > 0) {
30 if (bsearch(&id, list->id, list->n_values, sizeof(int), cmp_int))
31 return 0;
32 }
33
34 if (list->n_values == list->alloc_values) {
35 size_t size = (list->n_values + 100) * sizeof(int);
36
37 list->id = (int *)G_realloc((void *)list->id, size);
38 list->alloc_values = list->n_values + 100;
39 }
40
41 i = 0;
42 if (list->n_values > 0) {
43 for (i = list->n_values; i > 0; i--) {
44 if (list->id[i - 1] < id)
45 break;
46 list->id[i] = list->id[i - 1];
47 }
48 }
49 list->id[i] = id;
50 list->n_values++;
51
52 return 1;
53}
54
55/*!
56 \brief Remove duplicate features from vector map.
57
58 Remove duplicate lines of given types from vector map. Duplicate
59 lines may be optionally written to error map. Input map must be
60 opened on level 2 for update. Categories are merged.
61 GV_BUILD_BASE is sufficient.
62
63 \param[in,out] Map vector map where duplicate lines will be deleted
64 \param type type of line to be delete
65 \param[out] Err vector map where duplicate lines will be written or NULL
66
67 \return void
68 */
69void Vect_remove_duplicates(struct Map_info *Map, int type,
70 struct Map_info *Err)
71{
72 struct line_pnts *APoints, *BPoints;
73 struct line_cats *ACats, *BCats;
74 int i, c, atype, aline, bline;
75 int nlines, nacats_orig, npoints;
76 int na1, na2, nb1, nb2, nodelines, nline;
77 struct bound_box ABox;
78 struct boxlist *List;
79 int ndupl, is_dupl;
80
86
87 nlines = Vect_get_num_lines(Map);
88
89 G_debug(1, "nlines = %d", nlines);
90 /* Go through all lines in vector, for each line select lines which
91 * overlap with the first vertex of this line and check if a
92 * selected line is identical. If yes, remove the selected line.
93 * If the line vertices are identical with those of any other line,
94 * merge categories and rewrite the current line.
95 */
96
97 ndupl = 0;
98
99 for (aline = 1; aline <= nlines; aline++) {
100 G_percent(aline, nlines, 1);
102 continue;
103
105 if (!(atype & type))
106 continue;
107
108 npoints = APoints->n_points;
110
111 if (npoints != APoints->n_points) {
112 G_debug(3, "Line %d pruned, %d vertices removed", aline,
113 npoints - APoints->n_points);
115 nlines = Vect_get_num_lines(Map);
116 continue;
117 }
118
119 na1 = na2 = -1;
120 if (atype & GV_LINES) {
121 /* faster than Vect_select_lines_by_box() */
125
126 for (i = 0; i < nodelines; i++) {
128
129 if (nline == aline)
130 continue;
132 continue;
133
134 boxlist_add_sorted(List, nline);
135 }
136 }
137 else {
138 /* select potential duplicates */
139 ABox.E = ABox.W = APoints->x[0];
140 ABox.N = ABox.S = APoints->y[0];
141 ABox.T = ABox.B = APoints->z[0];
143 G_debug(3, " %d lines selected by box", List->n_values);
144 }
145
146 is_dupl = 0;
147
148 for (i = 0; i < List->n_values; i++) {
149 bline = List->id[i];
150 G_debug(3, " j = %d bline = %d", i, bline);
151
152 /* compare aline and bline only once */
153 if (aline <= bline)
154 continue;
155
156 nb1 = nb2 = -1;
157
158 if (atype & GV_LINES) {
160 if ((na1 == nb1 && na2 != nb2) || (na1 == nb2 && na2 != nb1))
161 continue;
162 }
163
166
167 /* check for duplicate */
169 continue;
170
171 /* bline is identical to aline */
172 if (!is_dupl) {
173 if (Err) {
175 }
176 is_dupl = 1;
177 }
179
180 /* merge categories */
181 nacats_orig = ACats->n_cats;
182
183 for (c = 0; c < BCats->n_cats; c++)
184 Vect_cat_set(ACats, BCats->field[c], BCats->cat[c]);
185
186 if (ACats->n_cats > nacats_orig) {
187 G_debug(4, "cats merged: n_cats %d -> %d", nacats_orig,
188 ACats->n_cats);
189 }
190
191 ndupl++;
192 }
193 if (is_dupl) {
195 nlines = Vect_get_num_lines(Map);
196 G_debug(3, "nlines = %d\n", nlines);
197 }
198 }
199 G_verbose_message(_("Removed duplicates: %d"), ndupl);
205}
206
207/*!
208 \brief Check for duplicate lines
209
210 Note that lines must be pruned with Vect_line_prune() before passed
211 to Vect_line_check_duplicate(), as done by Vect_remove_duplicates()
212
213 \param APoints first line geometry
214 \param BPoints second line geometry
215
216 \return 1 duplicate
217 \return 0 not duplicate
218 */
220 const struct line_pnts *BPoints, int with_z)
221{
222 int k;
223 int npoints;
224 int forw, backw;
225
226 if (APoints->n_points != BPoints->n_points)
227 return 0;
228
229 npoints = APoints->n_points;
230
231 /* Forward */
232 forw = 1;
233 for (k = 0; k < APoints->n_points; k++) {
234 if (APoints->x[k] != BPoints->x[k] || APoints->y[k] != BPoints->y[k] ||
235 (with_z && APoints->z[k] != BPoints->z[k])) {
236 forw = 0;
237 break;
238 }
239 }
240
241 /* Backward */
242 backw = 1;
243 for (k = 0; k < APoints->n_points; k++) {
244 if (APoints->x[k] != BPoints->x[npoints - k - 1] ||
245 APoints->y[k] != BPoints->y[npoints - k - 1] ||
246 (with_z && APoints->z[k] != BPoints->z[npoints - k - 1])) {
247 backw = 0;
248 break;
249 }
250 }
251
252 if (!forw && !backw)
253 return 0;
254
255 return 1;
256}
void G_percent(long, long, int)
Print percent complete messages.
Definition percent.c:61
#define G_realloc(p, n)
Definition defs/gis.h:141
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:77
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:304
plus_t Vect_get_num_lines(struct Map_info *)
Fetch number of features (points, lines, boundaries, centroids) in vector map.
Definition level_two.c:75
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:254
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:32
int Vect_get_node_n_lines(struct Map_info *, int)
Get number of lines for node.
Definition level_two.c:381
int Vect_get_node_line(struct Map_info *, int, int)
Get line id for node line index.
Definition level_two.c:397
int Vect_line_prune(struct line_pnts *)
Remove duplicate points, i.e. zero length segments.
Definition line.c:279
struct line_pnts * Vect_new_line_struct(void)
Creates and initializes a line_pnts structure.
Definition line.c:45
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:39
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