GRASS 8 Programmer's Manual 8.6.0dev(2026)-1d1e47ad9d
Loading...
Searching...
No Matches
clean_nodes.c
Go to the documentation of this file.
1/*!
2 \file lib/vector/Vlib/clean_nodes.c
3
4 \brief Vector library - Clean boundaries at nodes
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/*!
21 \brief Clean small angles at nodes.
22
23 It may happen that even if the angle between 2 boundaries at node
24 is very small, the calculated angle is 0 because of representation
25 error. The map must be built at least on level GV_BUILD_BASE
26
27 \param Map input map
28 \param otype feature type
29 \param[out] Err vector map where error line segments are written
30
31 \return number of line modifications
32 */
34 struct Map_info *Err)
35{
36 int node, nnodes;
37 int nmodif = 0;
38 struct line_pnts *Points;
39 struct line_cats *SCats, *LCats, *OCats;
40
41 Points = Vect_new_line_struct();
45
47 for (node = 1; node <= Vect_get_num_nodes(Map); node++) {
48 int i, nlines;
49
50 if (node <= nnodes)
51 G_percent(node, nnodes, 1);
52 G_debug(3, "node = %d", node);
53 if (!Vect_node_alive(Map, node))
54 continue;
55
56 while (1) {
57 float angle1 = -100;
58 int line1 = -999; /* value not important, just for debug */
59 int clean = 1;
60
61 nlines = Vect_get_node_n_lines(Map, node);
62 G_debug(3, "nlines = %d", nlines);
63
64 for (i = 0; i < nlines; i++) {
65 struct P_line *Line;
66 int line2;
67 float angle2;
68
69 line2 = Vect_get_node_line(Map, node, i);
70 Line = Map->plus.Line[abs(line2)];
71 if (!Line)
72 continue;
73 G_debug(4, " type = %d", Line->type);
74 if (!(Line->type & (otype & GV_LINES)))
75 continue;
76
78 if (angle2 == -9.0)
79 continue; /* Degenerated line */
80
81 G_debug(4, " line1 = %d angle1 = %e line2 = %d angle2 = %e",
83
84 if (angle2 == angle1) {
85 int j;
86 double length1, length2;
87 int short_line; /* line with shorter end segment */
88 int long_line; /* line with longer end segment */
89 int new_short_line =
90 0; /* line number of short line after rewrite */
92 double x, y, z, nx, ny, nz;
93
94 G_debug(4, " identical angles -> clean");
95
96 /* Length of end segments for both lines */
97 Vect_read_line(Map, Points, NULL, abs(line1));
98 if (line1 > 0) {
100 Points->x[0], Points->y[0], 0.0, Points->x[1],
101 Points->y[1], 0.0, 0);
102 }
103 else {
104 int np;
105
106 np = Points->n_points;
108 Points->x[np - 1], Points->y[np - 1], 0.0,
109 Points->x[np - 2], Points->y[np - 2], 0.0, 0);
110 }
111
112 Vect_read_line(Map, Points, NULL, abs(line2));
113 if (line2 > 0) {
115 Points->x[0], Points->y[0], 0.0, Points->x[1],
116 Points->y[1], 0.0, 0);
117 }
118 else {
119 int np;
120
121 np = Points->n_points;
123 Points->x[np - 1], Points->y[np - 1], 0.0,
124 Points->x[np - 2], Points->y[np - 2], 0.0, 0);
125 }
126
127 G_debug(4, " length1 = %f length2 = %f", length1, length2);
128
129 if (length1 < length2) {
132 }
133 else {
136 }
137
138 /* Remove end segment from short_line */
139 short_type =
141
142 if (short_line > 0) {
143 x = Points->x[1];
144 y = Points->y[1];
145 z = Points->z[1];
146 Vect_line_delete_point(Points, 0); /* first */
147 }
148 else {
149 x = Points->x[Points->n_points - 2];
150 y = Points->y[Points->n_points - 2];
151 z = Points->z[Points->n_points - 2];
153 Points->n_points - 1); /* last */
154 }
155
156 /* It may happen that it is one line: node could be deleted,
157 * in that case we have to read the node coords first */
158 Vect_get_node_coor(Map, node, &nx, &ny, &nz);
159
160 if (Points->n_points > 1) {
162 Map, abs(short_line), short_type, Points, SCats);
163 }
164 else {
166 }
167
168 /* It may happen that it is one line, in that case we have
169 * to take the new short line as long line, orientation is
170 * not changed */
171 if (abs(line1) == abs(line2)) {
172 if (long_line > 0)
174 else
176 }
177
178 /* Add new line (must be before rewrite of long_line
179 * otherwise node could be deleted) */
180 long_type =
182
184 for (j = 0; j < SCats->n_cats; j++) {
185 Vect_cat_set(OCats, SCats->field[j], SCats->cat[j]);
186 }
187 for (j = 0; j < LCats->n_cats; j++) {
188 Vect_cat_set(OCats, LCats->field[j], LCats->cat[j]);
189 }
190
193 }
194 else {
195 type = GV_LINE;
196 }
197
198 Vect_reset_line(Points);
199 Vect_append_point(Points, nx, ny, nz);
200 Vect_append_point(Points, x, y, z);
201 Vect_write_line(Map, type, Points, OCats);
202
203 if (Err) {
204 Vect_write_line(Err, type, Points, OCats);
205 }
206
207 /* Snap long_line to the new short_line end */
208 long_type =
210 if (long_line > 0) {
211 Points->x[0] = x;
212 Points->y[0] = y;
213 Points->z[0] = z;
214 }
215 else {
216 Points->x[Points->n_points - 1] = x;
217 Points->y[Points->n_points - 1] = y;
218 Points->z[Points->n_points - 1] = z;
219 }
220 Vect_line_prune(Points);
221 if (Points->n_points > 1) {
223 Points, LCats);
224 }
225 else {
227 }
228
229 nmodif += 3;
230 clean = 0;
231
232 break;
233 }
234
235 line1 = line2;
236 angle1 = angle2;
237 }
238
239 if (clean || !Vect_node_alive(Map, node))
240 break;
241 }
242 }
243 G_verbose_message(_("Modifications: %d"), nmodif);
248
249 return (nmodif);
250}
#define NULL
Definition ccmath.h:32
int Vect_clean_small_angles_at_nodes(struct Map_info *Map, int otype, struct Map_info *Err)
Clean small angles at nodes.
Definition clean_nodes.c:33
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_node_coor(struct Map_info *, int, double *, double *, double *)
Get node coordinates.
Definition level_two.c:274
int Vect_reset_cats(struct line_cats *)
Reset category structure to make sure cats structure is clean to be re-used.
float Vect_get_node_line_angle(struct Map_info *, int, int)
Angle of segment of the line connected to the node.
Definition level_two.c:413
int Vect_cat_set(struct line_cats *, int, int)
Add new field/cat to category structure if doesn't exist yet.
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)
double Vect_points_distance(double, double, double, double, double, double, int)
Calculate distance of 2 points.
Definition line.c:866
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_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_line_delete_point(struct line_pnts *, int)
Delete point at given index and move all points above down.
Definition line.c:210
int Vect_node_alive(struct Map_info *, int)
Check if node is alive or dead (topological level required)
void Vect_reset_line(struct line_pnts *)
Reset line.
Definition line.c:129
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_append_point(struct line_pnts *, double, double, double)
Appends one point to the end of a line.
Definition line.c:148
#define GV_LINE
#define GV_LINES
#define GV_BOUNDARY
#define _(str)
Definition glocale.h:10
Vector map info.
Vector geometry.
char type
Line type.
Feature category info.
Feature geometry info - coordinates.
double * y
Array of Y coordinates.
double * x
Array of X coordinates.
int n_points
Number of points.
double * z
Array of Z coordinates.
#define x