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_debug(3, "node =  %d", node);
00172         if (!Vect_node_alive(Map, node))
00173             continue;
00174 
00175         nnodelines = Vect_get_node_n_lines(Map, node);
00176 
00177         lcount = 0;             /* number of lines of given type */
00178         for (i = 0; i < nnodelines; i++) {
00179             line = Vect_get_node_line(Map, node, i);
00180             G_debug(3, "    node line %d = %d", i, line);
00181 
00182             ltype = Vect_read_line(Map, NULL, NULL, abs(line));
00183 
00184             if (ltype & type) {
00185                 lcount++;
00186                 next_line = line;
00187             }
00188         }
00189 
00190         Vect_reset_list(List);
00191         if (lcount == 1) {
00192             G_debug(3, "    node %d is dangle -> follow the line %d", node,
00193                     next_line);
00194 
00195             while (next_line != 0) {
00196                 Vect_list_append(List, abs(next_line));
00197 
00198                 /* Look at the next end of the line if just one another line of the type is connected */
00199                 Vect_get_line_nodes(Map, abs(next_line), &node1, &node2);
00200                 next_node = next_line > 0 ? node2 : node1;
00201 
00202                 G_debug(3, "    next_node = %d", next_node);
00203 
00204                 nnodelines = Vect_get_node_n_lines(Map, next_node);
00205 
00206                 lcount = 0;     /* number of lines of given type (except current next_line) */
00207                 for (i = 0; i < nnodelines; i++) {
00208                     line = Vect_get_node_line(Map, next_node, i);
00209                     G_debug(3, "      node line %d = %d", i, line);
00210 
00211                     ltype = Vect_read_line(Map, NULL, NULL, abs(line));
00212 
00213                     if (ltype & type && abs(line) != abs(next_line)) {
00214                         lcount++;
00215                         tmp_next_line = line;
00216                     }
00217                 }
00218                 if (lcount == 1)
00219                     next_line = tmp_next_line;
00220                 else
00221                     next_line = 0;
00222 
00223             }
00224 
00225             /* Length of the chain */
00226             length = 0;
00227             for (i = 0; i < List->n_values; i++) {
00228                 G_debug(3, "  chain line %d = %d", i, List->value[i]);
00229                 ltype = Vect_read_line(Map, Points, NULL, List->value[i]);
00230                 length += Vect_line_length(Points);
00231             }
00232 
00233             if (maxlength < 0 || length < maxlength) {  /* delete the chain */
00234                 G_debug(3, "  delete the chain (length=%g)", length);
00235 
00236                 for (i = 0; i < List->n_values; i++) {
00237                     ltype = Vect_read_line(Map, Points, Cats, List->value[i]);
00238 
00239                     /* Write to Err deleted dangle */
00240                     if (Err) {
00241                         Vect_write_line(Err, ltype, Points, Cats);
00242                     }
00243 
00244                     if (option == REMOVE_DANGLE) {
00245                         Vect_delete_line(Map, List->value[i]);
00246                     }
00247                     else if (option == CHTYPE_DANGLE) {
00248                         G_debug(3, "  rewrite line %d", List->value[i]);
00249                         Vect_rewrite_line(Map, List->value[i], GV_LINE,
00250                                           Points, Cats);
00251                     }
00252                     else {
00253                         if (List_dangle) {
00254                             Vect_list_append(List_dangle, List->value[i]);
00255                         }
00256                     }
00257                     lines_removed++;
00258                 }
00259             }                   /* delete the chain */
00260 
00261             dangles_removed++;
00262         }                       /* lcount == 1 */
00263     }                           /* node <= nnodes */
00264 }

Generated on Sat Oct 24 03:25:19 2009 for GRASS Programmer's Manual by  doxygen 1.6.1