GRASS Programmer's Manual  6.5.svn(2014)-r66266
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
clean_nodes.c
Go to the documentation of this file.
1 
20 #include <stdlib.h>
21 #include <grass/gis.h>
22 #include <grass/Vect.h>
23 #include <grass/glocale.h>
24 
38 int
39 Vect_clean_small_angles_at_nodes(struct Map_info *Map, int otype,
40  struct Map_info *Err)
41 {
42  int node, nnodes;
43  int nmodif = 0;
44  struct line_pnts *Points;
45  struct line_cats *SCats, *LCats, *OCats;
46 
47  Points = Vect_new_line_struct();
48  SCats = Vect_new_cats_struct();
49  LCats = Vect_new_cats_struct();
50  OCats = Vect_new_cats_struct();
51 
52  nnodes = Vect_get_num_nodes(Map);
53  for (node = 1; node <= nnodes; node++) {
54  int i, nlines;
55 
56  G_percent(node, nnodes, 1);
57  G_debug(3, "node = %d", node);
58  if (!Vect_node_alive(Map, node))
59  continue;
60 
61  while (1) {
62  float angle1 = -100;
63  int line1 = -999; /* value not important, just for debug */
64  int clean = 1;
65 
66  nlines = Vect_get_node_n_lines(Map, node);
67  G_debug(3, "nlines = %d", nlines);
68 
69  for (i = 0; i < nlines; i++) {
70  P_LINE *Line;
71  int line2;
72  float angle2;
73 
74  line2 = Vect_get_node_line(Map, node, i);
75  Line = Map->plus.Line[abs(line2)];
76  if (!Line)
77  continue;
78  G_debug(4, " type = %d", Line->type);
79  if (!(Line->type & (otype & GV_LINES)))
80  continue;
81 
82  angle2 = Vect_get_node_line_angle(Map, node, i);
83  if (angle2 == -9.0)
84  continue; /* Degenerated line */
85 
86  G_debug(4, " line1 = %d angle1 = %e line2 = %d angle2 = %e",
87  line1, angle1, line2, angle2);
88 
89  if (angle2 == angle1) {
90  int j;
91  double length1, length2;
92  int short_line; /* line with shorter end segment */
93  int long_line; /* line with longer end segment */
94  int new_short_line = 0; /* line number of short line after rewrite */
95  int short_type, long_type, type;
96  double x, y, z, nx, ny, nz;
97 
98  G_debug(4, " identical angles -> clean");
99 
100  /* Length of end segments for both lines */
101  Vect_read_line(Map, Points, NULL, abs(line1));
102  if (line1 > 0) {
103  length1 =
104  Vect_points_distance(Points->x[0], Points->y[0],
105  0.0, Points->x[1],
106  Points->y[1], 0.0, 0);
107  }
108  else {
109  int np;
110 
111  np = Points->n_points;
112  length1 =
113  Vect_points_distance(Points->x[np - 1],
114  Points->y[np - 1], 0.0,
115  Points->x[np - 2],
116  Points->y[np - 2], 0.0, 0);
117  }
118 
119  Vect_read_line(Map, Points, NULL, abs(line2));
120  if (line2 > 0) {
121  length2 =
122  Vect_points_distance(Points->x[0], Points->y[0],
123  0.0, Points->x[1],
124  Points->y[1], 0.0, 0);
125  }
126  else {
127  int np;
128 
129  np = Points->n_points;
130  length2 =
131  Vect_points_distance(Points->x[np - 1],
132  Points->y[np - 1], 0.0,
133  Points->x[np - 2],
134  Points->y[np - 2], 0.0, 0);
135  }
136 
137  G_debug(4, " length1 = %f length2 = %f", length1,
138  length2);
139 
140  if (length1 < length2) {
141  short_line = line1;
142  long_line = line2;
143  }
144  else {
145  short_line = line2;
146  long_line = line1;
147  }
148 
149  /* Remove end segment from short_line */
150  short_type =
151  Vect_read_line(Map, Points, SCats, abs(short_line));
152 
153  if (short_line > 0) {
154  x = Points->x[1];
155  y = Points->y[1];
156  z = Points->z[1];
157  Vect_line_delete_point(Points, 0); /* first */
158  }
159  else {
160  x = Points->x[Points->n_points - 2];
161  y = Points->y[Points->n_points - 2];
162  z = Points->z[Points->n_points - 2];
163  Vect_line_delete_point(Points, Points->n_points - 1); /* last */
164  }
165 
166  /* It may happen that it is one line: node could be deleted,
167  * in that case we have to read the node coords first */
168  Vect_get_node_coor(Map, node, &nx, &ny, &nz);
169 
170  if (Points->n_points > 1) {
171  new_short_line =
172  Vect_rewrite_line(Map, abs(short_line),
173  short_type, Points, SCats);
174  }
175  else {
176  Vect_delete_line(Map, abs(short_line));
177  }
178 
179  /* It may happen that it is one line, in that case we have to take the new
180  * short line as long line, orientation is not changed */
181  if (abs(line1) == abs(line2)) {
182  if (long_line > 0)
183  long_line = new_short_line;
184  else
185  long_line = -new_short_line;
186  }
187 
188  /* Add new line (must be before rewrite of long_line otherwise node could be deleted) */
189  long_type =
190  Vect_read_line(Map, NULL, LCats, abs(long_line));
191 
192  Vect_reset_cats(OCats);
193  for (j = 0; j < SCats->n_cats; j++) {
194  Vect_cat_set(OCats, SCats->field[j], SCats->cat[j]);
195  }
196  for (j = 0; j < LCats->n_cats; j++) {
197  Vect_cat_set(OCats, LCats->field[j], LCats->cat[j]);
198  }
199 
200  if (long_type == GV_BOUNDARY || short_type == GV_BOUNDARY) {
201  type = GV_BOUNDARY;
202  }
203  else {
204  type = GV_LINE;
205  }
206 
207  Vect_reset_line(Points);
208  Vect_append_point(Points, nx, ny, nz);
209  Vect_append_point(Points, x, y, z);
210  Vect_write_line(Map, type, Points, OCats);
211 
212  if (Err) {
213  Vect_write_line(Err, type, Points, OCats);
214  }
215 
216  /* Snap long_line to the new short_line end */
217  long_type =
218  Vect_read_line(Map, Points, LCats, abs(long_line));
219  if (long_line > 0) {
220  Points->x[0] = x;
221  Points->y[0] = y;
222  Points->z[0] = z;
223  }
224  else {
225  Points->x[Points->n_points - 1] = x;
226  Points->y[Points->n_points - 1] = y;
227  Points->z[Points->n_points - 1] = z;
228  }
229  Vect_line_prune(Points);
230  if (Points->n_points > 1) {
231  Vect_rewrite_line(Map, abs(long_line), long_type,
232  Points, LCats);
233  }
234  else {
235  Vect_delete_line(Map, abs(long_line));
236  }
237 
238  nmodif += 3;
239  clean = 0;
240 
241  break;
242  }
243 
244  line1 = line2;
245  angle1 = angle2;
246  }
247 
248  if (clean || !Vect_node_alive(Map, node))
249  break;
250  }
251  nnodes = Vect_get_num_nodes(Map);
252  }
253 
254  return (nmodif);
255 }
int Vect_get_node_line(struct Map_info *Map, int node, int line)
Get line id for node line index.
Definition: level_two.c:316
struct line_pnts * Vect_new_line_struct()
Creates and initializes a struct line_pnts.
Definition: line.c:57
int Vect_node_alive(struct Map_info *Map, int node)
Check if node is alive or dead.
int Vect_clean_small_angles_at_nodes(struct Map_info *Map, int otype, struct Map_info *Err)
Clean small angles at nodes.
Definition: clean_nodes.c:39
int Vect_reset_line(struct line_pnts *Points)
Reset line.
Definition: line.c:148
int Vect_reset_cats(struct line_cats *Cats)
Reset category structure to make sure cats structure is clean to be re-used.
int y
Definition: plot.c:34
int Vect_append_point(struct line_pnts *Points, double x, double y, double z)
Appends one point to the end of a line.
Definition: line.c:168
int Vect_cat_set(struct line_cats *Cats, int field, int cat)
Add new field/cat to category structure if doesn&#39;t exist yet.
int G_percent(long n, long d, int s)
Print percent complete messages.
Definition: percent.c:63
int Vect_rewrite_line(struct Map_info *Map, int line, int type, struct line_pnts *points, struct line_cats *cats)
Rewrites feature info at the given offset.
int GV_LINES
Definition: vdigit/main.py:24
struct line_cats * Vect_new_cats_struct()
Creates and initializes line_cats structure.
return NULL
Definition: dbfopen.c:1394
int Vect_line_prune(struct line_pnts *Points)
Remove duplicate points, i.e. zero length segments.
Definition: line.c:255
tuple Map
Definition: render.py:1310
int G_debug(int level, const char *msg,...)
Print debugging message.
Definition: gis/debug.c:51
int Vect_delete_line(struct Map_info *Map, int line)
Delete feature.
float Vect_get_node_line_angle(struct Map_info *Map, int node, int line)
Angle of segment of the line connected to the node.
Definition: level_two.c:334
double Vect_points_distance(double x1, double y1, double z1, double x2, double y2, double z2, int with_z)
Calculate distance of 2 points.
Definition: line.c:745
int Vect_line_delete_point(struct line_pnts *Points, int index)
Delete point at given index and move all points above down.
Definition: line.c:227
long Vect_write_line(struct Map_info *Map, int type, struct line_pnts *points, struct line_cats *cats)
Writes new feature to the end of file (table)
int Vect_get_node_coor(struct Map_info *map, int num, double *x, double *y, double *z)
Get node coordinates.
Definition: level_two.c:223
int Vect_get_num_nodes(struct Map_info *map)
Get number of nodes in vector map.
Definition: level_two.c:29
int Vect_read_line(struct Map_info *Map, struct line_pnts *line_p, struct line_cats *line_c, int line)
Read vector feature.
int Vect_get_node_n_lines(struct Map_info *Map, int node)
Get number of lines for node.
Definition: level_two.c:296