GRASS Programmer's Manual
6.4.2(2012)
|
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 }