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