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