GRASS GIS 7 Programmer's Manual  7.9.dev(2021)-e5379bbd7
vedit/snap.c
Go to the documentation of this file.
1 /*!
2  \file lib/vector/vedit/snap.c
3 
4  \brief Vedit library - snapping
5 
6  (C) 2007-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 Martin Landa <landa.martin gmail.com>
12 */
13 
14 #include <grass/vedit.h>
15 
16 /*!
17  \brief Snap given point to the nearest primitive
18 
19  \param Map pointer to Map_info
20  \param line line to be excluded (point on line)
21  \param x,y,z point on line to be snapped
22  \param thresh snapping threshold (>0)
23  \param vertex snap also to vertex (non-zero)
24 
25  \return 1 snapped
26  \return 0 not snapped
27 */
28 int Vedit_snap_point(struct Map_info *Map,
29  int line, double *x, double *y, double *z, double thresh,
30  int vertex)
31 {
32  struct line_pnts *Points;
33 
34  int i, snapped;
35  int line2snap, mindist_idx;
36  double dist, mindist;
37 
38  snapped = 0;
39  mindist_idx = -1;
40  mindist = thresh;
41 
42  Points = Vect_new_line_struct();
43 
44  line2snap = Vect_find_line(Map, *x, *y, *z, -1, thresh, WITHOUT_Z, line);
45 
46  if (line2snap > 0) {
47  Vect_read_line(Map, Points, NULL, line2snap);
48 
49  if (!Vect_line_alive(Map, line2snap)) {
51  return snapped;
52  }
53 
54  for (i = 0; i < Points->n_points; i++) {
55  if (i > 0 && i < Points->n_points - 1)
56  if (!vertex)
57  continue;
58  dist = Vect_points_distance(*x, *y, *z,
59  Points->x[i], Points->y[i],
60  Points->z[i], WITHOUT_Z);
61 
62  if (mindist >= dist) {
63  mindist = dist;
64  mindist_idx = i;
65  }
66  }
67 
68  if (mindist_idx > -1) {
69  *x = Points->x[mindist_idx];
70  *y = Points->y[mindist_idx];
71  *z = Points->z[mindist_idx];
72  snapped = 1;
73  }
74  }
75 
76  G_debug(3, "Vedit_snap_point(): map=%s, line2snap=%d, snapped=%d",
77  Map->name, line2snap, snapped);
78 
80 
81  return snapped;
82 }
83 
84 /*!
85  \brief Snap selected primitive to its nearest primitive
86 
87  \param Map pointer to Map_info
88  \param BgMap,nbgmaps list of background maps used for snapping
89  \param line line id to be snapped (if already written, otherwise -1)
90  \param Points line geometry
91  \param layer layer number
92  \param thresh threshold value used for snapping (>0)
93  \param to_vertex allow snapping also to vertex
94 
95  \return 1 line snapped
96  \return 0 line not snapped
97  \return -1 line is dead (if 'line' is > 0)
98 */
99 int Vedit_snap_line(struct Map_info *Map, struct Map_info **BgMap,
100  int nbgmaps, int line, struct line_pnts *Points,
101  double thresh, int to_vertex)
102 {
103  int i, npoints, node, rewrite;
104  double *x, *y, *z;
105 
106  struct line_cats *Cats;
107 
108  Cats = Vect_new_cats_struct();
109 
110  G_debug(3, "Vedit_snap_line(): thresh=%g, to_vertex=%d", thresh,
111  to_vertex);
112 
113  if (line > 0 && !Vect_line_alive(Map, line))
114  return -1;
115 
116  npoints = Points->n_points;
117  x = Points->x;
118  y = Points->y;
119  z = Points->z;
120 
121  rewrite = 0;
122  for (node = 0; node < npoints; node++) {
123  if ((node > 0 && node < npoints - 1) && !to_vertex)
124  continue;
125 
126  if (Vedit_snap_point(Map, line, &x[node], &y[node], &z[node], thresh,
127  to_vertex)) {
128  rewrite = 1;
129  }
130  else {
131  /* check also background maps */
132  for (i = 0; i < nbgmaps; i++) {
133  if (Vedit_snap_point
134  (BgMap[i], -1, &x[node], &y[node], &z[node], thresh,
135  to_vertex)) {
136  rewrite = 1;
137  break; /* snapped, don't continue */
138  }
139  }
140  }
141  } /* for each line vertex */
142 
143  /* close boundaries or lines */
144  if (!rewrite &&
145  Vect_points_distance(x[0], y[0], z[0],
146  x[npoints - 1], y[npoints - 1], z[npoints - 1],
147  WITHOUT_Z) <= thresh) {
148  x[npoints - 1] = x[0];
149  y[npoints - 1] = y[0];
150  z[npoints - 1] = z[0];
151 
152  rewrite = 1;
153  }
154 
155  G_debug(3, "Vedit_snap_line(): line=%d, snapped=%d", line, rewrite);
156 
158 
159  return rewrite;
160 }
161 
162 /*!
163  \brief Snap lines/boundaries
164 
165  \param Map pointer to Map_info
166  \param BgMap,nbgmaps list of background maps used for snapping
167  \param List list of lines to be snapped
168  \param layer layer number
169  \param thresh threshold value used for snapping (>0)
170  \param to_vertex allow snapping also to vertex
171 
172  \return number of snapped lines
173  \return -1 on error
174 */
175 int Vedit_snap_lines(struct Map_info *Map, struct Map_info **BgMap,
176  int nbgmaps, struct ilist *List, double thresh,
177  int to_vertex)
178 {
179  int i, line, type;
180  int nlines_modified = 0;
181 
182  struct line_pnts *Points;
183  struct line_cats *Cats;
184 
185  Points = Vect_new_line_struct();
186  Cats = Vect_new_cats_struct();
187 
188  for (i = 0; i < List->n_values; i++) {
189  line = List->value[i];
190  type = Vect_read_line(Map, Points, Cats, line);
191 
192  if (!(type & (GV_POINT | GV_LINES))) {
193  continue;
194  }
195 
196  if (Vedit_snap_line(Map, BgMap, nbgmaps,
197  line, Points, thresh, to_vertex) == 1) {
198  if (Vect_rewrite_line(Map, line, type, Points, Cats) < 0) {
199  return -1;
200  }
201 
202  nlines_modified++;
203  }
204  }
205 
206  Vect_destroy_line_struct(Points);
208 
209  return nlines_modified;
210 }
char * name
Map name (for 4.0)
Definition: dig_structs.h:1332
Definition: path.h:11
int Vedit_snap_lines(struct Map_info *Map, struct Map_info **BgMap, int nbgmaps, struct ilist *List, double thresh, int to_vertex)
Snap lines/boundaries.
Definition: vedit/snap.c:175
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:698
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
#define GV_POINT
Feature types used in memory on run time (may change)
Definition: dig_defines.h:182
int Vect_find_line(struct Map_info *, double, double, double, int, double, int, int)
Find the nearest line.
Feature category info.
Definition: dig_structs.h:1702
double * x
Array of X coordinates.
Definition: dig_structs.h:1680
int Vedit_snap_line(struct Map_info *Map, struct Map_info **BgMap, int nbgmaps, int line, struct line_pnts *Points, double thresh, int to_vertex)
Snap selected primitive to its nearest primitive.
Definition: vedit/snap.c:99
Feature geometry info - coordinates.
Definition: dig_structs.h:1675
int Vedit_snap_point(struct Map_info *Map, int line, double *x, double *y, double *z, double thresh, int vertex)
Snap given point to the nearest primitive.
Definition: vedit/snap.c:28
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
struct line_cats * Vect_new_cats_struct(void)
Creates and initializes line_cats structure.
int Vect_line_alive(const struct Map_info *, int)
Check if feature is alive or dead (topological level required)
double * z
Array of Z coordinates.
Definition: dig_structs.h:1688
List of integers.
Definition: gis.h:689
int * value
Array of values.
Definition: gis.h:694
#define GV_LINES
Definition: dig_defines.h:192
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 G_debug(int, const char *,...) __attribute__((format(printf