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