GRASS Programmer's Manual 6.4.1(2011)
|
00001 00018 #include <grass/config.h> 00019 #include <stdlib.h> 00020 #include <math.h> 00021 #include <grass/gis.h> 00022 #include <grass/Vect.h> 00023 #include <grass/glocale.h> 00024 00044 int Vect_merge_lines(struct Map_info *Map, int type, int *new_lines, 00045 struct Map_info *Err) 00046 { 00047 int line, nlines, i, c, first, last, next_line, curr_line; 00048 int merged = 0, newl = 0; 00049 int next_node, direction, node_n_lines, same_type; 00050 struct Plus_head *Plus; 00051 struct ilist *List; 00052 struct line_pnts *MPoints, *Points; 00053 struct line_cats *MCats, *Cats; 00054 struct P_line *Line; 00055 00056 if ((type & GV_BOUNDARY) && (type & GV_LINE)) { 00057 G_warning 00058 ("Merging is done only with either lines or boundaries, not both types at the same time"); 00059 return 0; 00060 } 00061 if (!(type & GV_BOUNDARY) && !(type & GV_LINE)) { 00062 G_warning 00063 ("Merging is done with lines or boundaries only, not with other types"); 00064 return 0; 00065 } 00066 00067 Plus = &(Map->plus); 00068 nlines = Vect_get_num_lines(Map); 00069 00070 Points = Vect_new_line_struct(); 00071 Cats = Vect_new_cats_struct(); 00072 MPoints = Vect_new_line_struct(); 00073 MCats = Vect_new_cats_struct(); 00074 List = Vect_new_list(); 00075 00076 for (line = 1; line <= nlines; line++) { 00077 G_percent(line, nlines, 2); 00078 00079 if (!Vect_line_alive(Map, line)) 00080 continue; 00081 00082 Line = Plus->Line[line]; 00083 00084 if (!(Line->type & type)) 00085 continue; 00086 00087 /* special cases: 00088 * - loop back to start boundary via several other boundaries 00089 * - one boundary forming closed loop 00090 * - node with 3 entries but only 2 boundaries, one of them connecting twice, 00091 * the other one must then be topologically incorrect in case of boundary */ 00092 00093 /* go backward as long as there is only one other line/boundary at the current node */ 00094 G_debug(3, "go backward"); 00095 next_node = Line->N1; 00096 first = -line; 00097 while (1) { 00098 node_n_lines = Vect_get_node_n_lines(Map, next_node); 00099 same_type = 0; 00100 next_line = first; 00101 for (i = 0; i < node_n_lines; i++) { 00102 curr_line = Vect_get_node_line(Map, next_node, i); 00103 if ((Plus->Line[abs(curr_line)]->type & type)) { 00104 same_type++; 00105 if (abs(curr_line) != abs(first)) 00106 next_line = curr_line; 00107 } 00108 } 00109 if (same_type == 2 && abs(next_line) != abs(first) && 00110 abs(next_line) != line) { 00111 first = next_line; 00112 00113 if (first < 0) 00114 next_node = Plus->Line[-first]->N1; 00115 else 00116 next_node = Plus->Line[first]->N2; 00117 } 00118 else 00119 break; 00120 } 00121 00122 /* go forward as long as there is only one other line/boundary at the current node */ 00123 G_debug(3, "go forward"); 00124 00125 /* reverse direction */ 00126 last = -first; 00127 00128 if (last < 0) 00129 next_node = Plus->Line[-last]->N1; 00130 else 00131 next_node = Plus->Line[last]->N2; 00132 00133 Vect_reset_list(List); 00134 while (1) { 00135 Vect_list_append(List, last); 00136 node_n_lines = Vect_get_node_n_lines(Map, next_node); 00137 same_type = 0; 00138 next_line = last; 00139 for (i = 0; i < node_n_lines; i++) { 00140 curr_line = Vect_get_node_line(Map, next_node, i); 00141 if ((Plus->Line[abs(curr_line)]->type & type)) { 00142 same_type++; 00143 if (abs(curr_line) != abs(last)) 00144 next_line = curr_line; 00145 } 00146 } 00147 00148 if (same_type == 2 && abs(next_line) != abs(last) && 00149 abs(next_line) != abs(first)) { 00150 last = next_line; 00151 00152 if (last < 0) 00153 next_node = Plus->Line[-last]->N1; 00154 else 00155 next_node = Plus->Line[last]->N2; 00156 } 00157 else 00158 break; 00159 } 00160 00161 /* merge lines */ 00162 if (List->n_values > 1) { 00163 G_debug(3, "merge %d lines", List->n_values); 00164 Vect_reset_line(MPoints); 00165 Vect_reset_cats(MCats); 00166 00167 for (i = 0; i < List->n_values; i++) { 00168 Vect_reset_line(Points); 00169 Vect_reset_cats(Cats); 00170 Vect_read_line(Map, Points, Cats, abs(List->value[i])); 00171 direction = (List->value[i] < 0 ? GV_BACKWARD : GV_FORWARD); 00172 Vect_append_points(MPoints, Points, direction); 00173 MPoints->n_points--; 00174 for (c = 0; c < Cats->n_cats; c++) { 00175 Vect_cat_set(MCats, Cats->field[c], Cats->cat[c]); 00176 } 00177 if (Err) { 00178 /* write out lines/boundaries to be merged */ 00179 Vect_write_line(Err, type, Points, Cats); 00180 } 00181 Vect_delete_line(Map, abs(List->value[i])); 00182 } 00183 MPoints->n_points++; 00184 Vect_write_line(Map, type, MPoints, MCats); 00185 merged += List->n_values; 00186 newl++; 00187 } 00188 00189 nlines = Vect_get_num_lines(Map); 00190 } 00191 00192 G_verbose_message(_("%d boundaries merged"), merged); 00193 G_verbose_message(_("%d new boundaries"), newl); 00194 00195 if (new_lines) 00196 *new_lines = newl; 00197 00198 return merged; 00199 }