GRASS 8 Programmer's Manual 8.6.0dev(2026)-1d1e47ad9d
Loading...
Searching...
No Matches
merge.c
Go to the documentation of this file.
1/*!
2 \file lib/vector/vedit/merge.c
3
4 \brief Vedit library - merge lines
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 Merge two given lines a, b
19
20 a : Points1/Cats1
21 b : Points2/Cats2
22 merged line : Points/Cats
23
24 \param Points1,Cats1 first line
25 \param Points2,Cats2 second line
26 \param thresh threshold value
27 \param[out] Points result line
28
29 \return 1 on success
30 \return 0 on error
31 */
32static int merge_lines(struct line_pnts *Points1, struct line_cats *Cats1,
33 struct line_pnts *Points2, struct line_cats *Cats2,
34 double thresh, struct line_pnts **Points);
35
36/*!
37 \brief Merge lines/boundaries
38
39 At least two lines need to be given.
40
41 \param Map pointer to Map_info
42 \param List list of selected lines
43
44 \return number of merged lines
45 \return -1 on error
46 */
48{
49 struct ilist *List_in_box;
50
51 struct line_pnts *Points1, *Points2, *Points;
52 struct line_cats *Cats1, *Cats2;
53
54 int line_i, i, j;
55 int line, line1, type1, line2;
56 int do_merge;
57
58 /* number of lines (original, selected, merged) */
59 int nlines, nlines_merged;
60
61 nlines_merged = 0;
62
63 if (List->n_values < 2) {
64 return 0;
65 }
66
67 G_debug(1, "Vedit_merge_lines(): merging %d lines", List->n_values);
68
73 Points = Vect_new_line_struct();
74
76
77 nlines = Vect_get_num_lines(Map);
78
79 /* merge lines */
80 for (line_i = 0; line_i < List->n_values; line_i++) {
81 line1 = List->value[line_i];
82
84 continue;
85
87
88 if (!(type1 & GV_LINES))
89 continue;
90
91 /* remove duplicate points */
93
94 if (Points1->n_points < 2) {
95 G_debug(3, "Vedit_merge_lines(): skipping zero length line");
96 continue;
97 }
98
99 Vect_reset_line(Points);
100
101 for (i = 0; i < Points1->n_points; i += Points1->n_points - 1) {
103
104 /* define searching region */
106 /*
107 Vect_append_point (Points2, Points1 -> x[i] - thresh,
108 Points1 -> y[i] + thresh, Points1 -> z[i]);
109 Vect_append_point (Points2, Points1 -> x[i] + thresh,
110 Points1 -> y[i] + thresh, Points1 -> z[i]);
111 Vect_append_point (Points2, Points1 -> x[i] + thresh,
112 Points1 -> y[i] - thresh, Points1 -> z[i]);
113 Vect_append_point (Points2, Points1 -> x[i] - thresh,
114 Points1 -> y[i] - thresh, Points1 -> z[i]);
115 */
117 Points1->z[i]);
118
119 /*
120 * merge lines only if two lines found in the region
121 * i.e. the current line and an adjacent line
122 */
123 /* NOTE
124 * - this merges two lines also if more than two lines are
125 * found in the region, but only two of these lines are
126 * in the List
127 * - this not only merges lines connected by end points
128 * but also any adjacent line with a mid point identical
129 * to one of the end points of the current line
130 */
131 if (0 < Vect_find_line_list(Map, Points1->x[i], Points1->y[i],
132 Points1->z[i], GV_LINES, 0, 0, NULL,
133 List_in_box)) {
134 do_merge = 1;
135 line2 = -1;
136 for (j = 0; do_merge && j < List_in_box->n_values; j++) {
137 if (List_in_box->value[j] == line1 ||
138 !Vect_line_alive(Map, List_in_box->value[j]))
139 continue;
140
141 if (Vect_val_in_list(List, List_in_box->value[j])) {
142
144 List_in_box->value[j]);
146 if (Points2->n_points == 1) {
147 line2 = List_in_box->value[j];
148 do_merge = 1;
149 break;
150 }
151 if (line2 > 0) {
152 /* three lines found
153 * selected lines will be not merged
154 */
155 do_merge = 0;
156 }
157 else {
158 line2 = List_in_box->value[j];
159 }
160 }
161 }
162
163 if (!do_merge || line2 < 0)
164 continue;
165
167
168 merge_lines(Points1, Cats1, Points2, Cats2, -1.0,
169 &Points); /* do not use threshold value */
170
171 G_debug(3, "Vedit_merge_lines(): lines=%d,%d", line1, line2);
172
173 if (Points->n_points > 0) {
174 if (Vect_delete_line(Map, line2) == -1) {
175 return -1;
176 }
177
178 if (line2 <= nlines)
180 }
181 }
182 } /* for each node */
183
184 if (Points->n_points > 0) {
185 line = Vect_rewrite_line(Map, line1, type1, Points, Cats1);
186 if (line < 0) {
187 nlines_merged = -1;
188 goto free_exit;
189 }
190
191 if (line1 <= nlines)
193
194 /* update number of lines */
195 G_ilist_add(List, line);
196 }
197 } /* for each line */
198
200 /* destroy structures */
204
207
209
210 return nlines_merged;
211}
212
213static int merge_lines(struct line_pnts *Points1, struct line_cats *Cats1,
214 struct line_pnts *Points2, struct line_cats *Cats2,
215 double thresh, struct line_pnts **Points)
216{
217 struct line_pnts *ps = *Points;
218 struct line_cats *cs = Cats1;
219
220 int i, mindistidx;
221 double mindist;
222
223 /* find minimal distance and its index */
224 mindist = Vedit_get_min_distance(Points1, Points2, 0, /* TODO 3D */
225 &mindistidx);
226
227 G_debug(3, " merge line ? index: %d, mindist: %g, thresh: %g", mindistidx,
228 mindist, thresh);
229
230 if (thresh > 0 && mindist > thresh) {
231 return 0;
232 }
233
234 /* set index and other things */
235 switch (mindistidx) {
236 /* for each mindistidx create new line */
237 case 0:
239 if (ps->n_points == Points2->n_points)
241 break;
242 case 1:
244 if (ps->n_points == Points2->n_points)
246 break;
247 case 2:
248 if (ps->n_points == 0)
251 break;
252 case 3:
253 if (ps->n_points == 0)
256 break;
257 default:
258 break;
259 }
260
261 /* remove duplicate points */
263
264 /* copy categories if needed */
265 for (i = 0; i < Cats2->n_cats; i++) {
266 Vect_cat_set(cs, Cats2->field[i], Cats2->cat[i]);
267 }
268
269 return 1;
270}
#define NULL
Definition ccmath.h:32
void G_ilist_add(struct ilist *, int)
Add item to ilist.
Definition ilist.c:78
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)
plus_t Vect_get_num_lines(struct Map_info *)
Fetch number of features (points, lines, boundaries, centroids) in vector map.
Definition level_two.c:75
int Vect_cat_set(struct line_cats *, int, int)
Add new field/cat to category structure if doesn't exist yet.
int Vect_find_line_list(struct Map_info *, double, double, double, int, double, int, const struct ilist *, struct ilist *)
Find the nearest line(s).
void Vect_destroy_list(struct ilist *)
Frees all memory associated with a struct ilist, including the struct itself.
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_alive(struct Map_info *, int)
Check if feature is alive or dead (topological level required)
int Vect_delete_line(struct Map_info *, off_t)
Delete existing feature (topological level required)
struct line_cats * Vect_new_cats_struct(void)
Creates and initializes line_cats structure.
struct ilist * Vect_new_list(void)
Creates and initializes a struct ilist.
int Vect_val_in_list(const struct ilist *, int)
Find a given item in the list.
void Vect_reset_line(struct line_pnts *)
Reset line.
Definition line.c:129
int Vect_line_prune(struct line_pnts *)
Remove duplicate points, i.e. zero length segments.
Definition line.c:279
struct line_pnts * Vect_new_line_struct(void)
Creates and initializes a line_pnts structure.
Definition line.c:45
int Vect_reset_list(struct ilist *)
Reset ilist structure.
int Vect_append_point(struct line_pnts *, double, double, double)
Appends one point to the end of a line.
Definition line.c:148
int Vect_append_points(struct line_pnts *, const struct line_pnts *, int)
Appends points to the end of a line.
Definition line.c:335
double Vedit_get_min_distance(struct line_pnts *, struct line_pnts *, int, int *)
Calculate distances between two lines.
#define GV_LINES
#define GV_FORWARD
Line direction indicator forward/backward.
#define GV_BACKWARD
struct line_cats * Cats2
int Vedit_merge_lines(struct Map_info *Map, struct ilist *List)
Merge lines/boundaries.
Definition merge.c:47
struct ps_state ps
Vector map info.
List of integers.
Definition gis.h:715
Feature category info.
Feature geometry info - coordinates.
int n_points
Number of points.