GRASS 8 Programmer's Manual 8.6.0dev(2026)-1878fdfec5
Loading...
Searching...
No Matches
vertex.c
Go to the documentation of this file.
1/*!
2 \file lib/vector/vedit/vertex.c
3
4 \brief Vedit library - vertex manipulation
5
6 SPDX-FileCopyrightText: 2006-2008 GRASS Development Team
7 SPDX-License-Identifier: GPL-2.0-or-later
8
9 \author Jachym Cepicky <jachym.cepicky gmail.com>
10 \author Martin Landa <landa.martin gmail.com>
11 */
12
13#include <grass/vedit.h>
14
15/*!
16 \brief Move all vertices in bounding box(es)
17
18 \param Map pointer to Map_info
19 \param BgMap, nbgmaps list of background vector maps for snapping
20 \param List list of selected lines
21 \param coord points location
22 \param thresh_coords threshold value for selecting lines
23 \param thresh_snap threshold value used for snapping
24 \param move_x,move_y,move_z direction (move_z is used when map is 3D)
25 \param move_first move only first vertex found in the bounding box
26 \param snap snapping mode (see vedit.h)
27
28 \return number of moved vertices
29 \return -1 on error
30 */
32 int nbgmaps, struct ilist *List, struct line_pnts *coord,
33 double thresh_coords, double thresh_snap, double move_x,
34 double move_y, double move_z, int move_first, int snap)
35{
37
38 int i, j, k;
39 int line, type, rewrite;
40 int npoints;
41 double east, north, dist;
42 double *x, *y, *z;
43 char *moved;
44
45 struct line_pnts *Points;
46 struct line_cats *Cats;
47
49 moved = NULL;
50
51 Points = Vect_new_line_struct();
53
54 for (i = 0; i < List->n_values; i++) {
55 line = List->value[i];
56
57 if (!Vect_line_alive(Map, line))
58 continue;
59
60 type = Vect_read_line(Map, Points, Cats, line);
61
62 if (!(type & GV_LINES))
63 continue;
64
65 npoints = Points->n_points;
66 x = Points->x;
67 y = Points->y;
68 z = Points->z;
69
70 /* vertex moved
71 0 not moved
72 1 moved
73 2 moved and snapped
74 */
75 moved =
76 (char *)G_realloc((void *)moved, Points->n_points * sizeof(char));
77 G_zero((void *)moved, Points->n_points * sizeof(char));
78
79 rewrite = 0;
80 for (j = 0; j < coord->n_points; j++) {
81 east = coord->x[j];
82 north = coord->y[j];
83
84 /* move all vertices in the bounding box */
85 for (k = 0; k < Points->n_points; k++) {
86 if (moved[k] == 0) {
87 dist = Vect_points_distance(east, north, 0.0, x[k], y[k],
88 z[k], WITHOUT_Z);
89 if (dist <= thresh_coords) {
90 G_debug(3,
91 "Vedit_move_vertex(): line=%d; x=%f, y=%f -> "
92 "x=%f, y=%f",
93 line, x[k], y[k], x[k] + move_x, y[k] + move_y);
94 x[k] += move_x;
95 y[k] += move_y;
96 if (Vect_is_3d(Map))
97 z[k] += move_z;
98
99 moved[k] = 1;
100
101 G_debug(3, "Vedit_move_vertex(): line=%d, point=%d",
102 line, k);
103
104 if (snap != NO_SNAP) {
106 Map, line, &x[k], &y[k], &z[k], thresh_snap,
107 (snap == SNAPVERTEX) ? 1 : 0) == 0) {
108 /* check also background maps */
109 int bgi;
110
111 for (bgi = 0; bgi < nbgmaps; bgi++) {
113 BgMap[bgi], -1, &x[k], &y[k], &z[k],
115 (snap == SNAPVERTEX) ? 1 : 0))
116 moved[k] = 2;
117 break; /* snapped, don't continue */
118 }
119 }
120 else {
121 moved[k] = 2;
122 }
123 }
124
125 rewrite = 1;
127
128 if (move_first)
129 break;
130 }
131 }
132 } /* for each line vertex */
133
134 /* close line or boundary */
135 if ((type & GV_LINES) &&
136 Vect_points_distance(x[0], y[0], z[0], x[npoints - 1],
137 y[npoints - 1], z[npoints - 1],
139
140 if (moved[0] == 1) { /* first node moved */
141 x[0] = x[npoints - 1];
142 y[0] = y[npoints - 1];
143 if (Vect_is_3d(Map))
144 z[0] = z[npoints - 1];
145 }
146 else if (moved[npoints - 1] == 1) { /* last node moved */
147 x[npoints - 1] = x[0];
148 y[npoints - 1] = y[0];
149 if (Vect_is_3d(Map))
150 z[npoints - 1] = z[0];
151 }
152 }
153 } /* for each coord */
154
155 if (rewrite) {
156 if (Vect_rewrite_line(Map, line, type, Points, Cats) < 0) {
157 nvertices_moved = -1;
158 goto free_exit;
159 }
160 }
161 } /* for each selected line */
162
164 /* destroy structures */
167 G_free(moved);
168
169 return nvertices_moved;
170}
171
172/*!
173 \brief Add new vertex to line
174
175 Shape of line is not changed.
176
177 \todo 3D
178
179 \param Map pointer to Map_info
180 \param List list of lines
181 \param coord points location
182 \param thresh find line in given threshold
183
184 \return number of add vertices
185 \return -1 on error
186 */
188 struct line_pnts *coord, double thresh)
189{
190 int i, j;
191 int type, line, seg;
193 double east, north, dist;
194 double *x, *y, *z;
195 double px, py;
196
197 struct line_pnts *Points;
198 struct line_cats *Cats;
199
200 nvertices_added = 0;
201 Points = Vect_new_line_struct();
203
204 for (i = 0; i < List->n_values; i++) {
205 line = List->value[i];
206
207 if (!Vect_line_alive(Map, line))
208 continue;
209
210 type = Vect_read_line(Map, Points, Cats, line);
211
212 if (!(type & GV_LINES))
213 continue;
214
215 G_debug(3, "Vedit_add_vertex(): line = %d, thresh = %f", line, thresh);
216
217 x = Points->x;
218 y = Points->y;
219 z = Points->z;
220 rewrite = FALSE;
221 for (j = 0; j < coord->n_points; j++) {
222 east = coord->x[j];
223 north = coord->y[j];
224
225 seg = Vect_line_distance(Points, east, north, 0.0, /* standpoint */
226 WITHOUT_Z, &px, &py,
227 NULL, /* point on line */
228 &dist, /* distance to line */
229 NULL, NULL);
230
231 if (dist <= thresh &&
232 Vect_points_distance(px, py, 0.0, x[seg], y[seg], z[seg],
233 WITHOUT_Z) > 0 &&
234 Vect_points_distance(px, py, 0.0, x[seg - 1], y[seg - 1],
235 z[seg - 1], WITHOUT_Z) > 0) {
236 /* add new vertex */
237 Vect_line_insert_point(Points, seg, px, py, 0.0);
238 G_debug(3, "Vedit_add_vertex(): line=%d; x=%f, y=%f, index=%d",
239 line, px, py, seg);
240 rewrite = TRUE;
242 }
243 } /* for each point */
244
245 /* rewrite the line */
246 if (rewrite) {
247 Vect_line_prune(Points);
248 if (Vect_rewrite_line(Map, line, type, Points, Cats) < 0) {
249 return -1;
250 }
251 }
252 } /* for each line */
253
254 /* destroy structures */
257
258 return nvertices_added;
259}
260
261/*!
262 \brief Remove vertex from line
263
264 \todo 3D
265
266 \param Map pointer to Map_info
267 \param List list of selected lines
268 \param coord points location
269 \param thresh threshold value to find a line
270
271 \return number of removed vertices
272 \return -1 on error
273 */
275 struct line_pnts *coord, double thresh)
276{
277 int i, j, k;
278 int type, line;
280 double east, north;
281 double dist;
282 double *x, *y, *z;
283
284 struct line_pnts *Points;
285 struct line_cats *Cats;
286
288
289 Points = Vect_new_line_struct();
291
292 for (i = 0; i < List->n_values; i++) {
293 line = List->value[i];
294
295 if (!Vect_line_alive(Map, line))
296 continue;
297
298 type = Vect_read_line(Map, Points, Cats, line);
299
300 if (!(type & GV_LINES))
301 continue;
302
303 x = Points->x;
304 y = Points->y;
305 z = Points->z;
306 rewrite = 0;
307 for (j = 0; j < coord->n_points; j++) {
308 east = coord->x[j];
309 north = coord->y[j];
310
311 for (k = 0; k < Points->n_points; k++) {
312 dist = Vect_points_distance(east, north, 0.0, x[k], y[k], z[k],
313 WITHOUT_Z);
314 if (dist <= thresh) {
315 /* remove vertex */
316 Vect_line_delete_point(Points, k);
317 G_debug(
318 3,
319 "Vedit_remove_vertex(): line=%d; x=%f, y=%f, index=%d",
320 line, x[k], y[k], k);
321 k--;
323 rewrite = 1;
324 }
325 } /* for each point */
326 } /* for each bounding box */
327
328 if (rewrite) {
329 /* rewrite the line */
330 if (Vect_rewrite_line(Map, line, type, Points, Cats) < 0) {
331 return -1;
332 }
333
335 }
336 } /* for each line */
337
338 /* destroy structures */
341
342 return nvertices_removed;
343}
#define NULL
Definition ccmath.h:32
void G_zero(void *, int)
Zero out a buffer, buf, of length i.
Definition gis/zero.c:21
void G_free(void *)
Free allocated memory.
Definition gis/alloc.c:145
#define G_realloc(p, n)
Definition defs/gis.h:138
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)
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_distance(const struct line_pnts *, double, double, double, int, double *, double *, double *, double *, double *, double *)
Calculate distance of point to line.
Definition line.c:646
double Vect_points_distance(double, double, double, double, double, double, int)
Calculate distance of 2 points.
Definition line.c:864
int Vect_line_alive(struct Map_info *, int)
Check if feature is alive or dead (topological level required)
struct line_cats * Vect_new_cats_struct(void)
Creates and initializes line_cats structure.
int Vect_line_insert_point(struct line_pnts *, int, double, double, double)
Insert new point at index position and move all old points at that position and above up.
Definition line.c:174
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_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_is_3d(struct Map_info *)
Check if vector map is 3D.
int Vedit_snap_point(struct Map_info *, int, double *, double *, double *, double, int)
Snap given point to the nearest primitive.
Definition vedit/snap.c:26
#define GV_LINES
#define WITHOUT_Z
2D/3D vector data
#define TRUE
Definition gis.h:75
#define FALSE
Definition gis.h:79
Vector map info.
List of integers.
Definition gis.h:712
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 NO_SNAP
Definition vedit.h:7
#define SNAPVERTEX
Definition vedit.h:9
int Vedit_move_vertex(struct Map_info *Map, struct Map_info **BgMap, int nbgmaps, struct ilist *List, struct line_pnts *coord, double thresh_coords, double thresh_snap, double move_x, double move_y, double move_z, int move_first, int snap)
Move all vertices in bounding box(es)
Definition vertex.c:31
int Vedit_add_vertex(struct Map_info *Map, struct ilist *List, struct line_pnts *coord, double thresh)
Add new vertex to line.
Definition vertex.c:187
int Vedit_remove_vertex(struct Map_info *Map, struct ilist *List, struct line_pnts *coord, double thresh)
Remove vertex from line.
Definition vertex.c:274
#define x