GRASS Programmer's Manual 6.4.1(2011)
dangles.c
Go to the documentation of this file.
00001 
00020 #include <stdlib.h>
00021 #include <grass/gis.h>
00022 #include <grass/Vect.h>
00023 #include <grass/glocale.h>
00024 
00025 #define REMOVE_DANGLE 0
00026 #define CHTYPE_DANGLE 1
00027 #define SELECT_DANGLE 2
00028 
00029 static void dangles(struct Map_info *, int, int, double,
00030                     struct Map_info *, struct ilist *);
00031 
00053 void
00054 Vect_remove_dangles(struct Map_info *Map, int type, double maxlength,
00055                     struct Map_info *Err)
00056 {
00057     dangles(Map, type, REMOVE_DANGLE, maxlength, Err, NULL);
00058 }
00059 
00079 void
00080 Vect_chtype_dangles(struct Map_info *Map, double maxlength,
00081                     struct Map_info *Err)
00082 {
00083     dangles(Map, 0, CHTYPE_DANGLE, maxlength, Err, NULL);
00084 }
00085 
00103 void
00104 Vect_select_dangles(struct Map_info *Map, int type, double maxlength,
00105                     struct ilist *List)
00106 {
00107     dangles(Map, type, SELECT_DANGLE, maxlength, NULL, List);
00108 }
00109 
00110 /*
00111    Line is considered to be a dangle if on at least one end node is no
00112    other line of given type(s). If a dangle is formed by more lines,
00113    such string of lines is taken as one dangle and either deleted are
00114    all parts or nothing.  Optionally, if chtype is set to 1, only
00115    GV_BOUNDARY are checked for dangles, and if dangle is found lines
00116    are not deleted but rewritten with type GVLINE.  Optionally deleted
00117    dangles are written to error map.  Input map must be opened on level
00118    2 for update at least on GV_BUILD_BASE.
00119 
00120    Parameters:
00121    Map input map where have to be deleted
00122    type type of dangles 
00123    option dangle option (REMOVE_DANGLE, CHTYPE_DANGLE, SELECT_DANGLE)
00124    maxlength maxlength of dangles or -1 for all dangles
00125    Err vector map where deleted dangles are written or NULL
00126    List_dangle list of feature (selected dangles) ids 
00127  */
00128 static void dangles(struct Map_info *Map, int type, int option,
00129                     double maxlength, struct Map_info *Err,
00130                     struct ilist *List_dangle)
00131 {
00132     struct line_pnts *Points;
00133     struct line_cats *Cats;
00134     int i, line, ltype, next_line = 0, nnodelines;
00135     int nnodes, node, node1, node2, next_node;
00136     int lcount, tmp_next_line = 0;
00137     double length;
00138     int dangles_removed;        /* number of removed dangles */
00139     int lines_removed;          /* number of lines removed */
00140     struct ilist *List;         /* List of lines in chain */
00141     char *lmsg;
00142 
00143     next_line = tmp_next_line = 0;
00144     dangles_removed = 0;
00145     lines_removed = 0;
00146 
00147     type &= GV_LINES;           /* to work only with lines and boundaries */
00148 
00149     if (option == CHTYPE_DANGLE) {
00150         type = GV_BOUNDARY;     /* process boundaries only */
00151         lmsg = "changed lines";
00152     }
00153     else if (option == REMOVE_DANGLE) {
00154         lmsg = "removed lines";
00155     }
00156     else {
00157         lmsg = "selected lines";
00158     }
00159 
00160     if (List_dangle)
00161         Vect_reset_list(List_dangle);
00162 
00163     Points = Vect_new_line_struct();
00164     Cats = Vect_new_cats_struct();
00165     List = Vect_new_list();
00166 
00167     nnodes = Vect_get_num_nodes(Map);
00168     G_debug(2, "nnodes =  %d", nnodes);
00169 
00170     for (node = 1; node <= nnodes; node++) {
00171         G_percent(node, nnodes, 1);
00172         G_debug(3, "node =  %d", node);
00173         if (!Vect_node_alive(Map, node))
00174             continue;
00175 
00176         nnodelines = Vect_get_node_n_lines(Map, node);
00177 
00178         lcount = 0;             /* number of lines of given type */
00179         for (i = 0; i < nnodelines; i++) {
00180             line = Vect_get_node_line(Map, node, i);
00181             G_debug(3, "    node line %d = %d", i, line);
00182 
00183             ltype = Vect_read_line(Map, NULL, NULL, abs(line));
00184 
00185             if (ltype & type) {
00186                 lcount++;
00187                 next_line = line;
00188             }
00189         }
00190 
00191         Vect_reset_list(List);
00192         if (lcount == 1) {
00193             G_debug(3, "    node %d is dangle -> follow the line %d", node,
00194                     next_line);
00195 
00196             while (next_line != 0) {
00197                 Vect_list_append(List, abs(next_line));
00198 
00199                 /* Look at the next end of the line if just one another line of the type is connected */
00200                 Vect_get_line_nodes(Map, abs(next_line), &node1, &node2);
00201                 next_node = next_line > 0 ? node2 : node1;
00202 
00203                 G_debug(3, "    next_node = %d", next_node);
00204 
00205                 nnodelines = Vect_get_node_n_lines(Map, next_node);
00206 
00207                 lcount = 0;     /* number of lines of given type (except current next_line) */
00208                 for (i = 0; i < nnodelines; i++) {
00209                     line = Vect_get_node_line(Map, next_node, i);
00210                     G_debug(3, "      node line %d = %d", i, line);
00211 
00212                     ltype = Vect_read_line(Map, NULL, NULL, abs(line));
00213 
00214                     if (ltype & type && abs(line) != abs(next_line)) {
00215                         lcount++;
00216                         tmp_next_line = line;
00217                     }
00218                 }
00219                 if (lcount == 1)
00220                     next_line = tmp_next_line;
00221                 else
00222                     next_line = 0;
00223 
00224             }
00225 
00226             /* Length of the chain */
00227             length = 0;
00228             for (i = 0; i < List->n_values; i++) {
00229                 G_debug(3, "  chain line %d = %d", i, List->value[i]);
00230                 ltype = Vect_read_line(Map, Points, NULL, List->value[i]);
00231                 length += Vect_line_length(Points);
00232             }
00233 
00234             if (maxlength < 0 || length < maxlength) {  /* delete the chain */
00235                 G_debug(3, "  delete the chain (length=%g)", length);
00236 
00237                 for (i = 0; i < List->n_values; i++) {
00238                     ltype = Vect_read_line(Map, Points, Cats, List->value[i]);
00239 
00240                     /* Write to Err deleted dangle */
00241                     if (Err) {
00242                         Vect_write_line(Err, ltype, Points, Cats);
00243                     }
00244 
00245                     if (option == REMOVE_DANGLE) {
00246                         Vect_delete_line(Map, List->value[i]);
00247                     }
00248                     else if (option == CHTYPE_DANGLE) {
00249                         G_debug(3, "  rewrite line %d", List->value[i]);
00250                         Vect_rewrite_line(Map, List->value[i], GV_LINE,
00251                                           Points, Cats);
00252                     }
00253                     else {
00254                         if (List_dangle) {
00255                             Vect_list_append(List_dangle, List->value[i]);
00256                         }
00257                     }
00258                     lines_removed++;
00259                 }
00260             }                   /* delete the chain */
00261 
00262             dangles_removed++;
00263         }                       /* lcount == 1 */
00264     }                           /* node <= nnodes */
00265 }
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines