GRASS 8 Programmer's Manual 8.6.0dev(2026)-f6f2c534ea
Loading...
Searching...
No Matches
dangles.c
Go to the documentation of this file.
1/*!
2 \file lib/vector/Vlib/dangles.c
3
4 \brief Vector library - clean geometry (dangles)
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
20#define REMOVE_DANGLE 0
21#define CHTYPE_DANGLE 1
22#define SELECT_DANGLE 2
23
24static void dangles(struct Map_info *, int, int, double, struct Map_info *,
25 struct ilist *);
26
27/*!
28 \brief Remove dangles from vector map.
29
30 Remove dangles of given type shorter than maxlength from vector
31 map.
32
33 Line is considered to be a dangle if on at least one end node is no
34 other line of given type(s). If a dangle is formed by more lines,
35 such string of lines is taken as one dangle and either deleted are
36 all parts or nothing.
37
38 Optionally deleted dangles are written to error map.
39
40 Input map must be opened on level 2 for update.
41
42 \param Map input map where have to be deleted
43 \param type type of dangles (GV_LINES, GV_LINE or GV_BOUNDARY)
44 \param maxlength maxlength of dangles or -1 for all dangles
45 \param[out] Err vector map where deleted dangles are written or NULL
46
47 \return
48 */
49void Vect_remove_dangles(struct Map_info *Map, int type, double maxlength,
50 struct Map_info *Err)
51{
52 dangles(Map, type, REMOVE_DANGLE, maxlength, Err, NULL);
53}
54
55/*!
56 \brief Change boundary dangles to lines.
57
58 Change boundary dangles to lines.
59
60 Boundary is considered to be a dangle if on at least one end node
61 is no other boundary. If a dangle is formed by more boundaries,
62 such string of boundaries is taken as one dangle.
63
64 Optionally deleted dangles are written to error map.
65
66 Input map must be opened on level 2 for update at least on GV_BUILD_BASE.
67
68 \param Map input map where have to be deleted
69 \param maxlength maxlength of dangles or -1 for all dangles
70 \param[out] Err vector map where deleted dangles are written or NULL
71
72 \return
73 */
75 struct Map_info *Err)
76{
77 dangles(Map, 0, CHTYPE_DANGLE, maxlength, Err, NULL);
78}
79
80/*!
81 \brief Select dangles from vector map.
82
83 Remove dangles of given type shorter than maxlength from vector map.
84
85 Line is considered to be a dangle if on at least one end node is no
86 other line of given type(s). If a dangle is formed by more lines,
87 such string of lines is taken as one dangle.
88
89 Input map must be opened on level 2 for update.
90
91 \param Map input map where have to be deleted
92 \param type type of dangles (GV_LINES, GV_LINE or GV_BOUNDARY)
93 \param maxlength maxlength of dangles or -1 for all dangles
94 \param[out] List list of selected features
95
96 \return
97 */
98void Vect_select_dangles(struct Map_info *Map, int type, double maxlength,
99 struct ilist *List)
100{
101 dangles(Map, type, SELECT_DANGLE, maxlength, NULL, List);
102}
103
104/*
105 Line is considered to be a dangle if on at least one end node is no
106 other line of given type(s). If a dangle is formed by more lines,
107 such string of lines is taken as one dangle and either deleted are
108 all parts or nothing. Optionally, if chtype is set to 1, only
109 GV_BOUNDARY are checked for dangles, and if dangle is found lines
110 are not deleted but rewritten with type GVLINE. Optionally deleted
111 dangles are written to error map. Input map must be opened on level
112 2 for update at least on GV_BUILD_BASE.
113
114 Parameters:
115 Map input map where dangles have to be deleted
116 type type of dangles
117 option dangle option (REMOVE_DANGLE, CHTYPE_DANGLE, SELECT_DANGLE)
118 maxlength maxlength of dangles or -1 for all dangles
119 Err vector map where deleted dangles are written or NULL
120 List_dangle list of feature (selected dangles) ids
121 */
122static void dangles(struct Map_info *Map, int type, int option,
123 double maxlength, struct Map_info *Err,
124 struct ilist *List_dangle)
125{
126 struct line_pnts *Points;
127 struct line_cats *Cats;
128 int i, line, ltype, next_line = 0, nnodelines;
129 int nnodes, node, node1, node2, next_node;
130 int lcount, tmp_next_line = 0;
131 double length;
132 int dangles_removed; /* number of removed dangles */
133 int lines_removed; /* number of lines removed */
134 struct ilist *List; /* List of lines in chain */
135 char *lmsg;
136
137 next_line = tmp_next_line = 0;
138 dangles_removed = 0;
139 lines_removed = 0;
140
141 type &= GV_LINES; /* to work only with lines and boundaries */
142
143 if (option == CHTYPE_DANGLE) {
144 type = GV_BOUNDARY; /* process boundaries only */
145 lmsg = _("Changed");
146 }
147 else if (option == REMOVE_DANGLE) {
148 lmsg = _("Removed");
149 }
150 else {
151 lmsg = _("Selected");
152 }
153
154 if (List_dangle)
156
157 Points = Vect_new_line_struct();
160
162 G_debug(2, "nnodes = %d", nnodes);
163
164 for (node = 1; node <= nnodes; node++) {
165 G_percent(node, nnodes, 1);
166 G_debug(3, "node = %d", node);
167 if (!Vect_node_alive(Map, node))
168 continue;
169
171
172 lcount = 0; /* number of lines of given type */
173 for (i = 0; i < nnodelines; i++) {
174 line = Vect_get_node_line(Map, node, i);
175 G_debug(3, " node line %d = %d", i, line);
176
177 ltype = Vect_read_line(Map, NULL, NULL, abs(line));
178
179 if (ltype & type) {
180 lcount++;
181 next_line = line;
182 }
183 }
184
186 if (lcount == 1) {
187 G_debug(3, " node %d is dangle -> follow the line %d", node,
188 next_line);
189
190 while (next_line != 0) {
191 Vect_list_append(List, abs(next_line));
192
193 /* Look at the next end of the line if just one another line of
194 * the type is connected */
195 Vect_get_line_nodes(Map, abs(next_line), &node1, &node2);
196 next_node = next_line > 0 ? node2 : node1;
197
198 G_debug(3, " next_node = %d", next_node);
199
201
202 lcount = 0; /* number of lines of given type (except current
203 next_line) */
204 for (i = 0; i < nnodelines; i++) {
205 line = Vect_get_node_line(Map, next_node, i);
206 G_debug(3, " node line %d = %d", i, line);
207
208 ltype = Vect_read_line(Map, NULL, NULL, abs(line));
209
210 if (ltype & type && abs(line) != abs(next_line)) {
211 lcount++;
212 tmp_next_line = line;
213 }
214 }
215 if (lcount == 1)
216 next_line = tmp_next_line;
217 else
218 next_line = 0;
219 }
220
221 /* Length of the chain */
222 length = 0;
223 for (i = 0; i < List->n_values; i++) {
224 G_debug(3, " chain line %d = %d", i, List->value[i]);
225 ltype = Vect_read_line(Map, Points, NULL, List->value[i]);
226 length += Vect_line_length(Points);
227 }
228
229 if (maxlength < 0 || length < maxlength) { /* delete the chain */
230 G_debug(3, " delete the chain (length=%g)", length);
231
232 for (i = 0; i < List->n_values; i++) {
233 ltype = Vect_read_line(Map, Points, Cats, List->value[i]);
234
235 /* Write to Err deleted dangle */
236 if (Err) {
237 Vect_write_line(Err, ltype, Points, Cats);
238 }
239
240 if (option == REMOVE_DANGLE) {
241 Vect_delete_line(Map, List->value[i]);
242 }
243 else if (option == CHTYPE_DANGLE) {
244 G_debug(3, " rewrite line %d", List->value[i]);
245 Vect_rewrite_line(Map, List->value[i], GV_LINE, Points,
246 Cats);
247 }
248 else {
249 if (List_dangle) {
251 }
252 }
254 }
256 } /* delete the chain */
257 } /* lcount == 1 */
258 } /* node <= nnodes */
259 G_verbose_message(_("%s lines: %d"), lmsg, lines_removed);
260 G_verbose_message(_("%s dangles: %d"), lmsg, dangles_removed);
264}
#define NULL
Definition ccmath.h:32
void Vect_remove_dangles(struct Map_info *Map, int type, double maxlength, struct Map_info *Err)
Remove dangles from vector map.
Definition dangles.c:49
#define REMOVE_DANGLE
Definition dangles.c:20
#define CHTYPE_DANGLE
Definition dangles.c:21
#define SELECT_DANGLE
Definition dangles.c:22
void Vect_chtype_dangles(struct Map_info *Map, double maxlength, struct Map_info *Err)
Change boundary dangles to lines.
Definition dangles.c:74
void Vect_select_dangles(struct Map_info *Map, int type, double maxlength, struct ilist *List)
Select dangles from vector map.
Definition dangles.c:98
void G_percent(long, long, int)
Print percent complete messages.
Definition percent.c:61
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_get_line_nodes(struct Map_info *, int, int *, int *)
Get line nodes.
Definition level_two.c:304
double Vect_line_length(const struct line_pnts *)
Calculate line length, 3D-length in case of 3D vector line.
Definition line.c:575
void Vect_destroy_list(struct ilist *)
Frees all memory associated with a struct ilist, 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_list_append(struct ilist *, int)
Append new item to the end of list if not yet present.
int Vect_read_line(struct Map_info *, struct line_pnts *, struct line_cats *, int)
Read vector feature (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.
struct ilist * Vect_new_list(void)
Creates and initializes a struct ilist.
off_t Vect_write_line(struct Map_info *, int, const struct line_pnts *, const struct line_cats *)
Writes a new feature.
int Vect_get_node_n_lines(struct Map_info *, int)
Get number of lines for node.
Definition level_two.c:381
plus_t Vect_get_num_nodes(struct Map_info *)
Get number of nodes in vector map.
Definition level_two.c:34
int Vect_node_alive(struct Map_info *, int)
Check if node is alive or dead (topological level required)
int Vect_get_node_line(struct Map_info *, int, int)
Get line id for node line index.
Definition level_two.c:397
struct line_pnts * Vect_new_line_struct(void)
Creates and initializes a line_pnts structure.
Definition line.c:45
int Vect_reset_list(struct ilist *)
Reset ilist structure.
#define GV_LINE
#define GV_LINES
#define GV_BOUNDARY
#define _(str)
Definition glocale.h:10
Vector map info.
List of integers.
Definition gis.h:715
Feature category info.
Feature geometry info - coordinates.