GRASS 8 Programmer's Manual 8.6.0dev(2026)-4bb960b182
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 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/*!
19 \brief Clean small angles at nodes.
20
21 It may happen that even if the angle between 2 boundaries at node
22 is very small, the calculated angle is 0 because of representation
23 error. The map must be built at least on level GV_BUILD_BASE
24
25 \param Map input map
26 \param otype feature type
27 \param[out] Err vector map where error line segments are written
28
29 \return number of line modifications
30 */
32 struct Map_info *Err)
33{
34 int node, nnodes;
35 int nmodif = 0;
36 struct line_pnts *Points;
37 struct line_cats *SCats, *LCats, *OCats;
38
39 Points = Vect_new_line_struct();
43
45 for (node = 1; node <= Vect_get_num_nodes(Map); node++) {
46 int i, nlines;
47
48 if (node <= nnodes)
49 G_percent(node, nnodes, 1);
50 G_debug(3, "node = %d", node);
51 if (!Vect_node_alive(Map, node))
52 continue;
53
54 while (1) {
55 float angle1 = -100;
56 int line1 = -999; /* value not important, just for debug */
57 int clean = 1;
58
59 nlines = Vect_get_node_n_lines(Map, node);
60 G_debug(3, "nlines = %d", nlines);
61
62 for (i = 0; i < nlines; i++) {
63 struct P_line *Line;
64 int line2;
65 float angle2;
66
67 line2 = Vect_get_node_line(Map, node, i);
68 Line = Map->plus.Line[abs(line2)];
69 if (!Line)
70 continue;
71 G_debug(4, " type = %d", Line->type);
72 if (!(Line->type & (otype & GV_LINES)))
73 continue;
74
76 if (angle2 == -9.0)
77 continue; /* Degenerated line */
78
79 G_debug(4, " line1 = %d angle1 = %e line2 = %d angle2 = %e",
81
82 if (angle2 == angle1) {
83 int j;
84 double length1, length2;
85 int short_line; /* line with shorter end segment */
86 int long_line; /* line with longer end segment */
87 int new_short_line =
88 0; /* line number of short line after rewrite */
90 double x, y, z, nx, ny, nz;
91
92 G_debug(4, " identical angles -> clean");
93
94 /* Length of end segments for both lines */
95 Vect_read_line(Map, Points, NULL, abs(line1));
96 if (line1 > 0) {
98 Points->x[0], Points->y[0], 0.0, Points->x[1],
99 Points->y[1], 0.0, 0);
100 }
101 else {
102 int np;
103
104 np = Points->n_points;
106 Points->x[np - 1], Points->y[np - 1], 0.0,
107 Points->x[np - 2], Points->y[np - 2], 0.0, 0);
108 }
109
110 Vect_read_line(Map, Points, NULL, abs(line2));
111 if (line2 > 0) {
113 Points->x[0], Points->y[0], 0.0, Points->x[1],
114 Points->y[1], 0.0, 0);
115 }
116 else {
117 int np;
118
119 np = Points->n_points;
121 Points->x[np - 1], Points->y[np - 1], 0.0,
122 Points->x[np - 2], Points->y[np - 2], 0.0, 0);
123 }
124
125 G_debug(4, " length1 = %f length2 = %f", length1, length2);
126
127 if (length1 < length2) {
130 }
131 else {
134 }
135
136 /* Remove end segment from short_line */
137 short_type =
139
140 if (short_line > 0) {
141 x = Points->x[1];
142 y = Points->y[1];
143 z = Points->z[1];
144 Vect_line_delete_point(Points, 0); /* first */
145 }
146 else {
147 x = Points->x[Points->n_points - 2];
148 y = Points->y[Points->n_points - 2];
149 z = Points->z[Points->n_points - 2];
151 Points->n_points - 1); /* last */
152 }
153
154 /* It may happen that it is one line: node could be deleted,
155 * in that case we have to read the node coords first */
156 Vect_get_node_coor(Map, node, &nx, &ny, &nz);
157
158 if (Points->n_points > 1) {
160 Map, abs(short_line), short_type, Points, SCats);
161 }
162 else {
164 }
165
166 /* It may happen that it is one line, in that case we have
167 * to take the new short line as long line, orientation is
168 * not changed */
169 if (abs(line1) == abs(line2)) {
170 if (long_line > 0)
172 else
174 }
175
176 /* Add new line (must be before rewrite of long_line
177 * otherwise node could be deleted) */
178 long_type =
180
182 for (j = 0; j < SCats->n_cats; j++) {
183 Vect_cat_set(OCats, SCats->field[j], SCats->cat[j]);
184 }
185 for (j = 0; j < LCats->n_cats; j++) {
186 Vect_cat_set(OCats, LCats->field[j], LCats->cat[j]);
187 }
188
191 }
192 else {
193 type = GV_LINE;
194 }
195
196 Vect_reset_line(Points);
197 Vect_append_point(Points, nx, ny, nz);
198 Vect_append_point(Points, x, y, z);
199 Vect_write_line(Map, type, Points, OCats);
200
201 if (Err) {
202 Vect_write_line(Err, type, Points, OCats);
203 }
204
205 /* Snap long_line to the new short_line end */
206 long_type =
208 if (long_line > 0) {
209 Points->x[0] = x;
210 Points->y[0] = y;
211 Points->z[0] = z;
212 }
213 else {
214 Points->x[Points->n_points - 1] = x;
215 Points->y[Points->n_points - 1] = y;
216 Points->z[Points->n_points - 1] = z;
217 }
218 Vect_line_prune(Points);
219 if (Points->n_points > 1) {
221 Points, LCats);
222 }
223 else {
225 }
226
227 nmodif += 3;
228 clean = 0;
229
230 break;
231 }
232
233 line1 = line2;
234 angle1 = angle2;
235 }
236
237 if (clean || !Vect_node_alive(Map, node))
238 break;
239 }
240 }
241 G_verbose_message(_("Modifications: %d"), nmodif);
246
247 return (nmodif);
248}
#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:31
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_node_coor(struct Map_info *, int, double *, double *, double *)
Get node coordinates.
Definition level_two.c:272
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:411
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:864
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:379
plus_t Vect_get_num_nodes(struct Map_info *)
Get number of nodes in vector map.
Definition level_two.c:32
int Vect_line_delete_point(struct line_pnts *, int)
Delete point at given index and move all points above down.
Definition line.c:208
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:127
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_append_point(struct line_pnts *, double, double, double)
Appends one point to the end of a line.
Definition line.c:146
#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