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