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