GRASS Programmer's Manual  6.4.2(2012)
merge.c
Go to the documentation of this file.
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 }
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines