GRASS Programmer's Manual  6.5.svn(2014)-r66266
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
merge.c
Go to the documentation of this file.
1 
15 #include <grass/vedit.h>
16 
32 static 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 
47 int Vedit_merge_lines(struct Map_info *Map, struct ilist *List)
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, type2;
56  int do_merge;
57 
58  /* number of lines (original, selected, merged) */
59  int nlines, nlines_selected, nlines_merged;
60 
61  nlines_merged = 0;
62 
63  if (List->n_values < 2) {
64  return 0;
65  }
66 
67  Points1 = Vect_new_line_struct();
68  Cats1 = Vect_new_cats_struct();
69  Points2 = Vect_new_line_struct();
70  Cats2 = Vect_new_cats_struct();
71  Points = Vect_new_line_struct();
72 
73  List_in_box = Vect_new_list();
74 
75  nlines = Vect_get_num_lines(Map);
76  nlines_selected = List->n_values;
77 
78  /* merge lines */
79  for (line_i = 0; line_i < List->n_values; line_i++) {
80  line1 = List->value[line_i];
81 
82  if (!Vect_line_alive(Map, line1))
83  continue;
84 
85  type1 = Vect_read_line(Map, Points1, Cats1, line1);
86 
87  if (!(type1 & GV_LINES))
88  continue;
89 
90  Vect_reset_line(Points);
91 
92  for (i = 0; i < Points1->n_points; i += Points1->n_points - 1) {
93  Vect_reset_list(List_in_box);
94 
95  /* define searching region */
96  Vect_reset_line(Points2);
97  /*
98  Vect_append_point (Points2, Points1 -> x[i] - thresh,
99  Points1 -> y[i] + thresh, Points1 -> z[i]);
100  Vect_append_point (Points2, Points1 -> x[i] + thresh,
101  Points1 -> y[i] + thresh, Points1 -> z[i]);
102  Vect_append_point (Points2, Points1 -> x[i] + thresh,
103  Points1 -> y[i] - thresh, Points1 -> z[i]);
104  Vect_append_point (Points2, Points1 -> x[i] - thresh,
105  Points1 -> y[i] - thresh, Points1 -> z[i]);
106  */
107  Vect_append_point(Points2, Points1->x[i],
108  Points1->y[i], Points1->z[i]);
109 
110  /*
111  * merge lines only if two lines found in the region
112  * i.e. the current line and an adjacent line
113  */
114  if (1 < Vect_select_lines_by_polygon(Map, Points2, 0, NULL,
115  GV_LINES, List_in_box)) {
116  do_merge = 1;
117  line2 = -1;
118  for (j = 0; do_merge && j < List->n_values; j++) {
119  if (List->value[j] == line1 ||
120  !Vect_line_alive(Map, List->value[j]))
121  continue;
122 
123  if (Vect_val_in_list(List_in_box, List->value[j])) {
124  if (line2 > 0) {
125  /* three lines found
126  * selected lines will be not merged
127  */
128  do_merge = 0;
129  }
130  else {
131  line2 = List->value[j];
132  }
133  }
134  }
135 
136  if (!do_merge || line2 < 0)
137  continue;
138 
139  type2 = Vect_read_line(Map, Points2, Cats2, line2);
140 
141  merge_lines(Points1, Cats1, Points2, Cats2, -1.0, &Points); /* do not use threshold value */
142 
143  G_debug(3, "Vedit_merge_lines(): lines=%d,%d", line1, line2);
144 
145  if (Points->n_points > 0) {
146  if (Vect_delete_line(Map, line2) == -1) {
147  return -1;
148  }
149 
150  if (line2 <= nlines)
151  nlines_merged++;
152  }
153  }
154  } /* for each node */
155 
156  if (Points->n_points > 0) {
157  line = Vect_rewrite_line(Map, line1, type1, Points, Cats1);
158  if (line < 0) {
159  return -1;
160  }
161 
162  if (line1 <= nlines)
163  nlines_merged++;
164 
165  /* update number of lines */
166  Vect_list_append(List, line);
167  }
168  } /* for each line */
169 
170  /* destroy stuctures */
171  Vect_destroy_line_struct(Points1);
172  Vect_destroy_line_struct(Points2);
173  Vect_destroy_line_struct(Points);
174 
177 
178  return nlines_merged;
179 }
180 
181 static int merge_lines(struct line_pnts *Points1, struct line_cats *Cats1,
182  struct line_pnts *Points2, struct line_cats *Cats2,
183  double thresh, struct line_pnts **Points)
184 {
185  struct line_pnts *ps = *Points;
186  struct line_cats *cs = Cats1;
187 
188  int i, mindistidx;
189  double mindist;
190 
191  /* find mininal distance and its index */
192  mindist = Vedit_get_min_distance(Points1, Points2, 0, /* TODO 3D */
193  &mindistidx);
194 
195  G_debug(3, " merge line ? index: %d, mindist: %g, thresh: %g",
196  mindistidx, mindist, thresh);
197 
198  if (thresh > 0 && mindist > thresh) {
199  return 0;
200  }
201 
202  /* set index and other things */
203  switch (mindistidx) {
204  /* for each mindistidx create new line */
205  case 0:
206  Vect_append_points(ps, Points2, GV_BACKWARD);
207  if (ps->n_points == Points2->n_points)
208  Vect_append_points(ps, Points1, GV_FORWARD);
209  break;
210  case 1:
211  Vect_append_points(ps, Points2, GV_FORWARD);
212  if (ps->n_points == Points2->n_points)
213  Vect_append_points(ps, Points1, GV_FORWARD);
214  break;
215  case 2:
216  if (ps->n_points == 0)
217  Vect_append_points(ps, Points1, GV_FORWARD);
218  Vect_append_points(ps, Points2, GV_FORWARD);
219  break;
220  case 3:
221  if (ps->n_points == 0)
222  Vect_append_points(ps, Points1, GV_FORWARD);
223  Vect_append_points(ps, Points2, GV_BACKWARD);
224  break;
225  default:
226  break;
227  }
228 
229  /* remove duplicate points */
230  Vect_line_prune(ps);
231 
232  /* copy categories if needed */
233  for (i = 0; i < Cats2->n_cats; i++) {
234  Vect_cat_set(cs, Cats2->field[i], Cats2->cat[i]);
235  }
236 
237  return 1;
238 }
struct line_pnts * Vect_new_line_struct()
Creates and initializes a struct line_pnts.
Definition: line.c:57
struct ilist * Vect_new_list(void)
Creates and initializes a struct ilist.
int Vect_append_points(struct line_pnts *Points, struct line_pnts *APoints, int direction)
Appends points to the end of a line.
Definition: line.c:312
int Vect_reset_line(struct line_pnts *Points)
Reset line.
Definition: line.c:148
int Vect_append_point(struct line_pnts *Points, double x, double y, double z)
Appends one point to the end of a line.
Definition: line.c:168
int Vect_cat_set(struct line_cats *Cats, int field, int cat)
Add new field/cat to category structure if doesn&#39;t exist yet.
int Vedit_merge_lines(struct Map_info *Map, struct ilist *List)
Merge lines/boundaries.
Definition: merge.c:47
int Vect_rewrite_line(struct Map_info *Map, int line, int type, struct line_pnts *points, struct line_cats *cats)
Rewrites feature info at the given offset.
int GV_LINES
Definition: vdigit/main.py:24
int Vect_reset_list(struct ilist *list)
Reset ilist structure.
int Vect_destroy_cats_struct(struct line_cats *p)
Frees all memory associated with line_cats structure, including the struct itself.
int Vect_list_append(struct ilist *list, int val)
Append new item to the end of list if not yet present.
int Vect_select_lines_by_polygon(struct Map_info *Map, struct line_pnts *Polygon, int nisles, struct line_pnts **Isles, int type, struct ilist *List)
Select lines by Polygon with optional isles.
int Vect_line_alive(struct Map_info *Map, int line)
Check if feature is alive or dead.
struct line_cats * Vect_new_cats_struct()
Creates and initializes line_cats structure.
return NULL
Definition: dbfopen.c:1394
int Vect_line_prune(struct line_pnts *Points)
Remove duplicate points, i.e. zero length segments.
Definition: line.c:255
int Vect_get_num_lines(struct Map_info *map)
Fetch number of features (points, lines, boundaries, centroids) in vector map.
Definition: level_two.c:69
double Vedit_get_min_distance(struct line_pnts *Points1, struct line_pnts *Points2, int with_z, int *mindistidx)
Calculate distances between two lines.
tuple Map
Definition: render.py:1310
int G_debug(int level, const char *msg,...)
Print debugging message.
Definition: gis/debug.c:51
int Vect_delete_line(struct Map_info *Map, int line)
Delete feature.
int Vect_val_in_list(struct ilist *list, int val)
Find a given item in the list.
int Vect_destroy_line_struct(struct line_pnts *p)
Frees all memory associated with a struct line_pnts, including the struct itself. ...
Definition: line.c:90
struct line_cats * Cats2
int Vect_read_line(struct Map_info *Map, struct line_pnts *line_p, struct line_cats *line_c, int line)
Read vector feature.