clean_nodes.c 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. /*!
  2. \file clean_nodes.c
  3. \brief Vector library - Clean boundaries at nodes
  4. Higher level functions for reading/writing/manipulating vectors.
  5. (C) 2001-2008 by the GRASS Development Team
  6. This program is free software under the
  7. GNU General Public License (>=v2).
  8. Read the file COPYING that comes with GRASS
  9. for details.
  10. \author Radim Blazek
  11. \date 2001-2008
  12. */
  13. #include <stdlib.h>
  14. #include <grass/gis.h>
  15. #include <grass/Vect.h>
  16. #include <grass/glocale.h>
  17. /*!
  18. \brief Clean small angles at nodes.
  19. It may happen that even if the angle between 2 boundaries at node is
  20. very small, the calculated angle is 0 because of
  21. representation error. The map must be built at least on level
  22. GV_BUILD_BASE
  23. \param Map input map
  24. \param Err vector map where error line segments are written
  25. \return number of line modifications
  26. */
  27. int
  28. Vect_clean_small_angles_at_nodes(struct Map_info *Map, int otype,
  29. struct Map_info *Err)
  30. {
  31. int node;
  32. int nmodif = 0;
  33. struct line_pnts *Points;
  34. struct line_cats *SCats, *LCats, *OCats;
  35. Points = Vect_new_line_struct();
  36. SCats = Vect_new_cats_struct();
  37. LCats = Vect_new_cats_struct();
  38. OCats = Vect_new_cats_struct();
  39. for (node = 1; node <= Vect_get_num_nodes(Map); node++) {
  40. int i, nlines;
  41. G_debug(3, "node = %d", node);
  42. if (!Vect_node_alive(Map, node))
  43. continue;
  44. while (1) {
  45. float angle1 = -100;
  46. int line1 = -999; /* value not important, just for debug */
  47. int clean = 1;
  48. nlines = Vect_get_node_n_lines(Map, node);
  49. G_debug(3, "nlines = %d", nlines);
  50. for (i = 0; i < nlines; i++) {
  51. P_LINE *Line;
  52. int line2;
  53. float angle2;
  54. line2 = Vect_get_node_line(Map, node, i);
  55. Line = Map->plus.Line[abs(line2)];
  56. if (!Line)
  57. continue;
  58. G_debug(4, " type = %d", Line->type);
  59. if (!(Line->type & (otype & GV_LINES)))
  60. continue;
  61. angle2 = Vect_get_node_line_angle(Map, node, i);
  62. if (angle2 == -9.0)
  63. continue; /* Degenerated line */
  64. G_debug(4, " line1 = %d angle1 = %e line2 = %d angle2 = %e",
  65. line1, angle1, line2, angle2);
  66. if (angle2 == angle1) {
  67. int j;
  68. double length1, length2;
  69. int short_line; /* line with shorter end segment */
  70. int long_line; /* line with longer end segment */
  71. int new_short_line = 0; /* line number of short line after rewrite */
  72. int short_type, long_type, type;
  73. double x, y, z, nx, ny, nz;
  74. G_debug(4, " identical angles -> clean");
  75. /* Length of end segments for both lines */
  76. Vect_read_line(Map, Points, NULL, abs(line1));
  77. if (line1 > 0) {
  78. length1 =
  79. Vect_points_distance(Points->x[0], Points->y[0],
  80. 0.0, Points->x[1],
  81. Points->y[1], 0.0, 0);
  82. }
  83. else {
  84. int np;
  85. np = Points->n_points;
  86. length1 =
  87. Vect_points_distance(Points->x[np - 1],
  88. Points->y[np - 1], 0.0,
  89. Points->x[np - 2],
  90. Points->y[np - 2], 0.0, 0);
  91. }
  92. Vect_read_line(Map, Points, NULL, abs(line2));
  93. if (line2 > 0) {
  94. length2 =
  95. Vect_points_distance(Points->x[0], Points->y[0],
  96. 0.0, Points->x[1],
  97. Points->y[1], 0.0, 0);
  98. }
  99. else {
  100. int np;
  101. np = Points->n_points;
  102. length2 =
  103. Vect_points_distance(Points->x[np - 1],
  104. Points->y[np - 1], 0.0,
  105. Points->x[np - 2],
  106. Points->y[np - 2], 0.0, 0);
  107. }
  108. G_debug(4, " length1 = %f length2 = %f", length1,
  109. length2);
  110. if (length1 < length2) {
  111. short_line = line1;
  112. long_line = line2;
  113. }
  114. else {
  115. short_line = line2;
  116. long_line = line1;
  117. }
  118. /* Remove end segment from short_line */
  119. short_type =
  120. Vect_read_line(Map, Points, SCats, abs(short_line));
  121. if (short_line > 0) {
  122. x = Points->x[1];
  123. y = Points->y[1];
  124. z = Points->z[1];
  125. Vect_line_delete_point(Points, 0); /* first */
  126. }
  127. else {
  128. x = Points->x[Points->n_points - 2];
  129. y = Points->y[Points->n_points - 2];
  130. z = Points->z[Points->n_points - 2];
  131. Vect_line_delete_point(Points, Points->n_points - 1); /* last */
  132. }
  133. if (Points->n_points > 1) {
  134. new_short_line =
  135. Vect_rewrite_line(Map, abs(short_line),
  136. short_type, Points, SCats);
  137. }
  138. else {
  139. Vect_delete_line(Map, abs(short_line));
  140. }
  141. /* It may happen that it is one line, in that case we have to take the new
  142. * short line as long line, orientation is not changed */
  143. if (abs(line1) == abs(line2)) {
  144. if (long_line > 0)
  145. long_line = new_short_line;
  146. else
  147. long_line = -new_short_line;
  148. }
  149. /* Add new line (must be before rewrite of long_line otherwise node could be deleted) */
  150. long_type =
  151. Vect_read_line(Map, NULL, LCats, abs(long_line));
  152. Vect_reset_cats(OCats);
  153. for (j = 0; j < SCats->n_cats; j++) {
  154. Vect_cat_set(OCats, SCats->field[j], SCats->cat[j]);
  155. }
  156. for (j = 0; j < LCats->n_cats; j++) {
  157. Vect_cat_set(OCats, LCats->field[j], LCats->cat[j]);
  158. }
  159. if (long_type == GV_BOUNDARY || short_type == GV_BOUNDARY) {
  160. type = GV_BOUNDARY;
  161. }
  162. else {
  163. type = GV_LINE;
  164. }
  165. Vect_get_node_coor(Map, node, &nx, &ny, &nz);
  166. Vect_reset_line(Points);
  167. Vect_append_point(Points, nx, ny, nz);
  168. Vect_append_point(Points, x, y, z);
  169. Vect_write_line(Map, type, Points, OCats);
  170. if (Err) {
  171. Vect_write_line(Err, type, Points, OCats);
  172. }
  173. /* Snap long_line to the new short_line end */
  174. long_type =
  175. Vect_read_line(Map, Points, LCats, abs(long_line));
  176. if (long_line > 0) {
  177. Points->x[0] = x;
  178. Points->y[0] = y;
  179. Points->z[0] = z;
  180. }
  181. else {
  182. Points->x[Points->n_points - 1] = x;
  183. Points->y[Points->n_points - 1] = y;
  184. Points->z[Points->n_points - 1] = z;
  185. }
  186. Vect_line_prune(Points);
  187. if (Points->n_points > 1) {
  188. Vect_rewrite_line(Map, abs(long_line), long_type,
  189. Points, LCats);
  190. }
  191. else {
  192. Vect_delete_line(Map, abs(long_line));
  193. }
  194. nmodif += 3;
  195. clean = 0;
  196. break;
  197. }
  198. line1 = line2;
  199. angle1 = angle2;
  200. }
  201. if (clean)
  202. break;
  203. }
  204. }
  205. return (nmodif);
  206. }