GRASS Programmer's Manual
6.4.2(2012)
|
00001 00015 #include <grass/vedit.h> 00016 00032 static int merge_lines(struct line_pnts *Points1, struct line_cats *Cats1, 00033 struct line_pnts *Points2, struct line_cats *Cats2, 00034 double thresh, struct line_pnts **Points); 00035 00047 int Vedit_merge_lines(struct Map_info *Map, struct ilist *List) 00048 { 00049 struct ilist *List_in_box; 00050 00051 struct line_pnts *Points1, *Points2, *Points; 00052 struct line_cats *Cats1, *Cats2; 00053 00054 int line_i, i, j; 00055 int line, line1, type1, line2, type2; 00056 int do_merge; 00057 00058 /* number of lines (original, selected, merged) */ 00059 int nlines, nlines_selected, nlines_merged; 00060 00061 nlines_merged = 0; 00062 00063 if (List->n_values < 2) { 00064 return 0; 00065 } 00066 00067 Points1 = Vect_new_line_struct(); 00068 Cats1 = Vect_new_cats_struct(); 00069 Points2 = Vect_new_line_struct(); 00070 Cats2 = Vect_new_cats_struct(); 00071 Points = Vect_new_line_struct(); 00072 00073 List_in_box = Vect_new_list(); 00074 00075 nlines = Vect_get_num_lines(Map); 00076 nlines_selected = List->n_values; 00077 00078 /* merge lines */ 00079 for (line_i = 0; line_i < List->n_values; line_i++) { 00080 line1 = List->value[line_i]; 00081 00082 if (!Vect_line_alive(Map, line1)) 00083 continue; 00084 00085 type1 = Vect_read_line(Map, Points1, Cats1, line1); 00086 00087 if (!(type1 & GV_LINES)) 00088 continue; 00089 00090 Vect_reset_line(Points); 00091 00092 for (i = 0; i < Points1->n_points; i += Points1->n_points - 1) { 00093 Vect_reset_list(List_in_box); 00094 00095 /* define searching region */ 00096 Vect_reset_line(Points2); 00097 /* 00098 Vect_append_point (Points2, Points1 -> x[i] - thresh, 00099 Points1 -> y[i] + thresh, Points1 -> z[i]); 00100 Vect_append_point (Points2, Points1 -> x[i] + thresh, 00101 Points1 -> y[i] + thresh, Points1 -> z[i]); 00102 Vect_append_point (Points2, Points1 -> x[i] + thresh, 00103 Points1 -> y[i] - thresh, Points1 -> z[i]); 00104 Vect_append_point (Points2, Points1 -> x[i] - thresh, 00105 Points1 -> y[i] - thresh, Points1 -> z[i]); 00106 */ 00107 Vect_append_point(Points2, Points1->x[i], 00108 Points1->y[i], Points1->z[i]); 00109 00110 /* 00111 * merge lines only if two lines found in the region 00112 * i.e. the current line and an adjacent line 00113 */ 00114 if (1 < Vect_select_lines_by_polygon(Map, Points2, 0, NULL, 00115 GV_LINES, List_in_box)) { 00116 do_merge = 1; 00117 line2 = -1; 00118 for (j = 0; do_merge && j < List->n_values; j++) { 00119 if (List->value[j] == line1 || 00120 !Vect_line_alive(Map, List->value[j])) 00121 continue; 00122 00123 if (Vect_val_in_list(List_in_box, List->value[j])) { 00124 if (line2 > 0) { 00125 /* three lines found 00126 * selected lines will be not merged 00127 */ 00128 do_merge = 0; 00129 } 00130 else { 00131 line2 = List->value[j]; 00132 } 00133 } 00134 } 00135 00136 if (!do_merge || line2 < 0) 00137 continue; 00138 00139 type2 = Vect_read_line(Map, Points2, Cats2, line2); 00140 00141 merge_lines(Points1, Cats1, Points2, Cats2, -1.0, &Points); /* do not use threshold value */ 00142 00143 G_debug(3, "Vedit_merge_lines(): lines=%d,%d", line1, line2); 00144 00145 if (Points->n_points > 0) { 00146 if (Vect_delete_line(Map, line2) == -1) { 00147 return -1; 00148 } 00149 00150 if (line2 <= nlines) 00151 nlines_merged++; 00152 } 00153 } 00154 } /* for each node */ 00155 00156 if (Points->n_points > 0) { 00157 line = Vect_rewrite_line(Map, line1, type1, Points, Cats1); 00158 if (line < 0) { 00159 return -1; 00160 } 00161 00162 if (line1 <= nlines) 00163 nlines_merged++; 00164 00165 /* update number of lines */ 00166 Vect_list_append(List, line); 00167 } 00168 } /* for each line */ 00169 00170 /* destroy stuctures */ 00171 Vect_destroy_line_struct(Points1); 00172 Vect_destroy_line_struct(Points2); 00173 Vect_destroy_line_struct(Points); 00174 00175 Vect_destroy_cats_struct(Cats1); 00176 Vect_destroy_cats_struct(Cats2); 00177 00178 return nlines_merged; 00179 } 00180 00181 static int merge_lines(struct line_pnts *Points1, struct line_cats *Cats1, 00182 struct line_pnts *Points2, struct line_cats *Cats2, 00183 double thresh, struct line_pnts **Points) 00184 { 00185 struct line_pnts *ps = *Points; 00186 struct line_cats *cs = Cats1; 00187 00188 int i, mindistidx; 00189 double mindist; 00190 00191 /* find mininal distance and its index */ 00192 mindist = Vedit_get_min_distance(Points1, Points2, 0, /* TODO 3D */ 00193 &mindistidx); 00194 00195 G_debug(3, " merge line ? index: %d, mindist: %g, thresh: %g", 00196 mindistidx, mindist, thresh); 00197 00198 if (thresh > 0 && mindist > thresh) { 00199 return 0; 00200 } 00201 00202 /* set index and other things */ 00203 switch (mindistidx) { 00204 /* for each mindistidx create new line */ 00205 case 0: 00206 Vect_append_points(ps, Points2, GV_BACKWARD); 00207 if (ps->n_points == Points2->n_points) 00208 Vect_append_points(ps, Points1, GV_FORWARD); 00209 break; 00210 case 1: 00211 Vect_append_points(ps, Points2, GV_FORWARD); 00212 if (ps->n_points == Points2->n_points) 00213 Vect_append_points(ps, Points1, GV_FORWARD); 00214 break; 00215 case 2: 00216 if (ps->n_points == 0) 00217 Vect_append_points(ps, Points1, GV_FORWARD); 00218 Vect_append_points(ps, Points2, GV_FORWARD); 00219 break; 00220 case 3: 00221 if (ps->n_points == 0) 00222 Vect_append_points(ps, Points1, GV_FORWARD); 00223 Vect_append_points(ps, Points2, GV_BACKWARD); 00224 break; 00225 default: 00226 break; 00227 } 00228 00229 /* remove duplicate points */ 00230 Vect_line_prune(ps); 00231 00232 /* copy categories if needed */ 00233 for (i = 0; i < Cats2->n_cats; i++) { 00234 Vect_cat_set(cs, Cats2->field[i], Cats2->cat[i]); 00235 } 00236 00237 return 1; 00238 }