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
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
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;
00139 int lines_removed;
00140 struct ilist *List;
00141 char *lmsg;
00142
00143 next_line = tmp_next_line = 0;
00144 dangles_removed = 0;
00145 lines_removed = 0;
00146
00147 type &= GV_LINES;
00148
00149 if (option == CHTYPE_DANGLE) {
00150 type = GV_BOUNDARY;
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;
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
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;
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
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) {
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
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 }
00260
00261 dangles_removed++;
00262 }
00263 }
00264 }