GRASS GIS 8 Programmer's Manual  8.5.0dev(2024)-602118adcc
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, int line, double *x, double *y,
29  double *z, double thresh, int vertex)
30 {
31  struct line_pnts *Points;
32 
33  int i, snapped;
34  int line2snap, mindist_idx;
35  double dist, mindist;
36 
37  snapped = 0;
38  mindist_idx = -1;
39  mindist = thresh;
40 
41  Points = Vect_new_line_struct();
42 
43  line2snap = Vect_find_line(Map, *x, *y, *z, -1, thresh, WITHOUT_Z, line);
44 
45  if (line2snap > 0) {
46  Vect_read_line(Map, Points, NULL, line2snap);
47 
48  if (!Vect_line_alive(Map, line2snap)) {
50  return snapped;
51  }
52 
53  for (i = 0; i < Points->n_points; i++) {
54  if (i > 0 && i < Points->n_points - 1)
55  if (!vertex)
56  continue;
57  dist = Vect_points_distance(*x, *y, *z, Points->x[i], Points->y[i],
58  Points->z[i], WITHOUT_Z);
59 
60  if (mindist >= dist) {
61  mindist = dist;
62  mindist_idx = i;
63  }
64  }
65 
66  if (mindist_idx > -1) {
67  *x = Points->x[mindist_idx];
68  *y = Points->y[mindist_idx];
69  *z = Points->z[mindist_idx];
70  snapped = 1;
71  }
72  }
73 
74  G_debug(3, "Vedit_snap_point(): map=%s, line2snap=%d, snapped=%d",
75  Map->name, line2snap, snapped);
76 
78 
79  return snapped;
80 }
81 
82 /*!
83  \brief Snap selected primitive to its nearest primitive
84 
85  \param Map pointer to Map_info
86  \param BgMap,nbgmaps list of background maps used for snapping
87  \param line line id to be snapped (if already written, otherwise -1)
88  \param Points line geometry
89  \param layer layer number
90  \param thresh threshold value used for snapping (>0)
91  \param to_vertex allow snapping also to vertex
92 
93  \return 1 line snapped
94  \return 0 line not snapped
95  \return -1 line is dead (if 'line' is > 0)
96  */
97 int Vedit_snap_line(struct Map_info *Map, struct Map_info **BgMap, int nbgmaps,
98  int line, struct line_pnts *Points, double thresh,
99  int to_vertex)
100 {
101  int i, npoints, node, rewrite;
102  double *x, *y, *z;
103 
104  struct line_cats *Cats;
105 
106  G_debug(3, "Vedit_snap_line(): thresh=%g, to_vertex=%d", thresh, to_vertex);
107 
108  if (line > 0 && !Vect_line_alive(Map, line))
109  return -1;
110 
111  Cats = Vect_new_cats_struct();
112 
113  npoints = Points->n_points;
114  x = Points->x;
115  y = Points->y;
116  z = Points->z;
117 
118  rewrite = 0;
119  for (node = 0; node < npoints; node++) {
120  if ((node > 0 && node < npoints - 1) && !to_vertex)
121  continue;
122 
123  if (Vedit_snap_point(Map, line, &x[node], &y[node], &z[node], thresh,
124  to_vertex)) {
125  rewrite = 1;
126  }
127  else {
128  /* check also background maps */
129  for (i = 0; i < nbgmaps; i++) {
130  if (Vedit_snap_point(BgMap[i], -1, &x[node], &y[node], &z[node],
131  thresh, to_vertex)) {
132  rewrite = 1;
133  break; /* snapped, don't continue */
134  }
135  }
136  }
137  } /* for each line vertex */
138 
139  /* close boundaries or lines */
140  if (!rewrite &&
141  Vect_points_distance(x[0], y[0], z[0], x[npoints - 1], y[npoints - 1],
142  z[npoints - 1], WITHOUT_Z) <= thresh) {
143  x[npoints - 1] = x[0];
144  y[npoints - 1] = y[0];
145  z[npoints - 1] = z[0];
146 
147  rewrite = 1;
148  }
149 
150  G_debug(3, "Vedit_snap_line(): line=%d, snapped=%d", line, rewrite);
151 
153 
154  return rewrite;
155 }
156 
157 /*!
158  \brief Snap lines/boundaries
159 
160  \param Map pointer to Map_info
161  \param BgMap,nbgmaps list of background maps used for snapping
162  \param List list of lines to be snapped
163  \param layer layer number
164  \param thresh threshold value used for snapping (>0)
165  \param to_vertex allow snapping also to vertex
166 
167  \return number of snapped lines
168  \return -1 on error
169  */
170 int Vedit_snap_lines(struct Map_info *Map, struct Map_info **BgMap, int nbgmaps,
171  struct ilist *List, double thresh, int to_vertex)
172 {
173  int i, line, type;
174  int nlines_modified = 0;
175 
176  struct line_pnts *Points;
177  struct line_cats *Cats;
178 
179  Points = Vect_new_line_struct();
180  Cats = Vect_new_cats_struct();
181 
182  for (i = 0; i < List->n_values; i++) {
183  line = List->value[i];
184  type = Vect_read_line(Map, Points, Cats, line);
185 
186  if (!(type & (GV_POINT | GV_LINES))) {
187  continue;
188  }
189 
190  if (Vedit_snap_line(Map, BgMap, nbgmaps, line, Points, thresh,
191  to_vertex) == 1) {
192  if (Vect_rewrite_line(Map, line, type, Points, Cats) < 0) {
193  nlines_modified = -1;
194  goto free_exit;
195  }
196 
197  nlines_modified++;
198  }
199  }
200 
201 free_exit:
202  Vect_destroy_line_struct(Points);
204 
205  return nlines_modified;
206 }
#define NULL
Definition: ccmath.h:32
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_find_line(struct Map_info *, double, double, double, int, double, int, int)
Find the nearest line.
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)
struct line_pnts * Vect_new_line_struct(void)
Creates and initializes a line_pnts structure.
Definition: line.c:45
struct line_cats * Vect_new_cats_struct(void)
Creates and initializes line_cats structure.
#define GV_POINT
Feature types used in memory on run time (may change)
Definition: dig_defines.h:183
#define GV_LINES
Definition: dig_defines.h:193
#define WITHOUT_Z
2D/3D vector data
Definition: dig_defines.h:171
Vector map info.
Definition: dig_structs.h:1243
char * name
Map name (for 4.0)
Definition: dig_structs.h:1316
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
Definition: path.h:10
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
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:170
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:97
#define x