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
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
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
00099 Vect_reset_line(Points2);
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110 Vect_append_point(Points2, Points1->x[i],
00111 Points1->y[i], Points1->z[i]);
00112
00113
00114
00115
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
00129
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);
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 }
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
00169 Vect_list_append(List, line);
00170 }
00171 }
00172
00173
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
00195 mindist = Vedit_get_min_distance(Points1, Points2, 0,
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
00206 switch (mindistidx) {
00207
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
00233 Vect_line_prune(ps);
00234
00235
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 }