GRASS 8 Programmer's Manual 8.6.0dev(2026)-4bb960b182
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 SPDX-FileCopyrightText: 2006-2008 GRASS Development Team
7 SPDX-License-Identifier: GPL-2.0-or-later
8
9 \author Jachym Cepicky <jachym.cepicky gmail.com>
10 \author Martin Landa <landa.martin gmail.com>
11 */
12
13#include <grass/vedit.h>
14
15/*!
16 \brief Merge two given lines a, b
17
18 a : Points1/Cats1
19 b : Points2/Cats2
20 merged line : Points/Cats
21
22 \param Points1,Cats1 first line
23 \param Points2,Cats2 second line
24 \param thresh threshold value
25 \param[out] Points result line
26
27 \return 1 on success
28 \return 0 on error
29 */
30static int merge_lines(struct line_pnts *Points1, struct line_cats *Cats1,
31 struct line_pnts *Points2, struct line_cats *Cats2,
32 double thresh, struct line_pnts **Points);
33
34/*!
35 \brief Merge lines/boundaries
36
37 At least two lines need to be given.
38
39 \param Map pointer to Map_info
40 \param List list of selected lines
41
42 \return number of merged lines
43 \return -1 on error
44 */
46{
47 struct ilist *List_in_box;
48
49 struct line_pnts *Points1, *Points2, *Points;
50 struct line_cats *Cats1, *Cats2;
51
52 int line_i, i, j;
53 int line, line1, type1, line2;
54 int do_merge;
55
56 /* number of lines (original, selected, merged) */
57 int nlines, nlines_merged;
58
59 nlines_merged = 0;
60
61 if (List->n_values < 2) {
62 return 0;
63 }
64
65 G_debug(1, "Vedit_merge_lines(): merging %d lines", List->n_values);
66
71 Points = Vect_new_line_struct();
72
74
75 nlines = Vect_get_num_lines(Map);
76
77 /* merge lines */
78 for (line_i = 0; line_i < List->n_values; line_i++) {
79 line1 = List->value[line_i];
80
82 continue;
83
85
86 if (!(type1 & GV_LINES))
87 continue;
88
89 /* remove duplicate points */
91
92 if (Points1->n_points < 2) {
93 G_debug(3, "Vedit_merge_lines(): skipping zero length line");
94 continue;
95 }
96
97 Vect_reset_line(Points);
98
99 for (i = 0; i < Points1->n_points; i += Points1->n_points - 1) {
101
102 /* define searching region */
104 /*
105 Vect_append_point (Points2, Points1 -> x[i] - thresh,
106 Points1 -> y[i] + thresh, Points1 -> z[i]);
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 */
115 Points1->z[i]);
116
117 /*
118 * merge lines only if two lines found in the region
119 * i.e. the current line and an adjacent line
120 */
121 /* NOTE
122 * - this merges two lines also if more than two lines are
123 * found in the region, but only two of these lines are
124 * in the List
125 * - this not only merges lines connected by end points
126 * but also any adjacent line with a mid point identical
127 * to one of the end points of the current line
128 */
129 if (0 < Vect_find_line_list(Map, Points1->x[i], Points1->y[i],
130 Points1->z[i], GV_LINES, 0, 0, NULL,
131 List_in_box)) {
132 do_merge = 1;
133 line2 = -1;
134 for (j = 0; do_merge && j < List_in_box->n_values; j++) {
135 if (List_in_box->value[j] == line1 ||
136 !Vect_line_alive(Map, List_in_box->value[j]))
137 continue;
138
139 if (Vect_val_in_list(List, List_in_box->value[j])) {
140
142 List_in_box->value[j]);
144 if (Points2->n_points == 1) {
145 line2 = List_in_box->value[j];
146 do_merge = 1;
147 break;
148 }
149 if (line2 > 0) {
150 /* three lines found
151 * selected lines will be not merged
152 */
153 do_merge = 0;
154 }
155 else {
156 line2 = List_in_box->value[j];
157 }
158 }
159 }
160
161 if (!do_merge || line2 < 0)
162 continue;
163
165
166 merge_lines(Points1, Cats1, Points2, Cats2, -1.0,
167 &Points); /* do not use threshold value */
168
169 G_debug(3, "Vedit_merge_lines(): lines=%d,%d", line1, line2);
170
171 if (Points->n_points > 0) {
172 if (Vect_delete_line(Map, line2) == -1) {
173 return -1;
174 }
175
176 if (line2 <= nlines)
178 }
179 }
180 } /* for each node */
181
182 if (Points->n_points > 0) {
183 line = Vect_rewrite_line(Map, line1, type1, Points, Cats1);
184 if (line < 0) {
185 nlines_merged = -1;
186 goto free_exit;
187 }
188
189 if (line1 <= nlines)
191
192 /* update number of lines */
193 G_ilist_add(List, line);
194 }
195 } /* for each line */
196
198 /* destroy structures */
202
205
207
208 return nlines_merged;
209}
210
211static int merge_lines(struct line_pnts *Points1, struct line_cats *Cats1,
212 struct line_pnts *Points2, struct line_cats *Cats2,
213 double thresh, struct line_pnts **Points)
214{
215 struct line_pnts *ps = *Points;
216 struct line_cats *cs = Cats1;
217
218 int i, mindistidx;
219 double mindist;
220
221 /* find minimal distance and its index */
222 mindist = Vedit_get_min_distance(Points1, Points2, 0, /* TODO 3D */
223 &mindistidx);
224
225 G_debug(3, " merge line ? index: %d, mindist: %g, thresh: %g", mindistidx,
226 mindist, thresh);
227
228 if (thresh > 0 && mindist > thresh) {
229 return 0;
230 }
231
232 /* set index and other things */
233 switch (mindistidx) {
234 /* for each mindistidx create new line */
235 case 0:
237 if (ps->n_points == Points2->n_points)
239 break;
240 case 1:
242 if (ps->n_points == Points2->n_points)
244 break;
245 case 2:
246 if (ps->n_points == 0)
249 break;
250 case 3:
251 if (ps->n_points == 0)
254 break;
255 default:
256 break;
257 }
258
259 /* remove duplicate points */
261
262 /* copy categories if needed */
263 for (i = 0; i < Cats2->n_cats; i++) {
264 Vect_cat_set(cs, Cats2->field[i], Cats2->cat[i]);
265 }
266
267 return 1;
268}
#define NULL
Definition ccmath.h:32
void G_ilist_add(struct ilist *, int)
Add item to ilist.
Definition ilist.c:75
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:75
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:73
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:127
int Vect_line_prune(struct line_pnts *)
Remove duplicate points, i.e. zero length segments.
Definition line.c:277
struct line_pnts * Vect_new_line_struct(void)
Creates and initializes a line_pnts structure.
Definition line.c:43
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:146
int Vect_append_points(struct line_pnts *, const struct line_pnts *, int)
Appends points to the end of a line.
Definition line.c:333
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:45
struct ps_state ps
Vector map info.
List of integers.
Definition gis.h:712
Feature category info.
Feature geometry info - coordinates.
int n_points
Number of points.