vertex.c 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354
  1. /**
  2. \file vector/vedit/vertex.c
  3. \brief Vedit library - vertex manipulation
  4. (C) 2006-2008 by the GRASS Development Team
  5. This program is free software under the GNU General Public License
  6. (>=v2). Read the file COPYING that comes with GRASS for details.
  7. \author Jachym Cepicky <jachym.cepicky gmail.com>
  8. \author Martin Landa <landa.martin gmail.com>
  9. \date 2006-2008
  10. */
  11. #include <grass/vedit.h>
  12. /**
  13. \brief Move all vertices in bounding box(es)
  14. \param Map vector map
  15. \param BgMap, nbgmaps list of background vector maps for snapping
  16. \param List list of selected lines
  17. \param coord points location
  18. \param thresh_coords threshold value for selecting lines
  19. \param thresh_snap threshold value used for snapping
  20. \param move_x,move_y,move_z direction (move_z is used when map is 3D)
  21. \param move_first move only first vertex found in the bounding box
  22. \param snap snapping mode (see vedit.h)
  23. \return number of moved verteces
  24. \return -1 on error
  25. */
  26. int Vedit_move_vertex(struct Map_info *Map, struct Map_info **BgMap,
  27. int nbgmaps, struct ilist *List,
  28. struct line_pnts *coord, double thresh_coords,
  29. double thresh_snap, double move_x, double move_y,
  30. double move_z, int move_first, int snap)
  31. {
  32. int nvertices_moved, nlines_modified, nvertices_snapped;
  33. int i, j, k;
  34. int line, type, rewrite;
  35. int npoints;
  36. double east, north, dist;
  37. double *x, *y, *z;
  38. char *moved;
  39. struct line_pnts *Points, *Points_snap;
  40. struct line_cats *Cats;
  41. nlines_modified = 0;
  42. nvertices_moved = nvertices_snapped = 0;
  43. moved = NULL;
  44. Points = Vect_new_line_struct();
  45. Points_snap = Vect_new_line_struct();
  46. Cats = Vect_new_cats_struct();
  47. for (i = 0; i < List->n_values; i++) {
  48. line = List->value[i];
  49. if (!Vect_line_alive(Map, line))
  50. continue;
  51. type = Vect_read_line(Map, Points, Cats, line);
  52. if (!(type & GV_LINES))
  53. continue;
  54. npoints = Points->n_points;
  55. x = Points->x;
  56. y = Points->y;
  57. z = Points->z;
  58. /* vertex moved
  59. 0 not moved
  60. 1 moved
  61. 2 moved and snapped
  62. */
  63. moved =
  64. (char *)G_realloc((void *)moved, Points->n_points * sizeof(char));
  65. G_zero((void *)moved, Points->n_points * sizeof(char));
  66. rewrite = 0;
  67. for (j = 0; j < coord->n_points; j++) {
  68. east = coord->x[j];
  69. north = coord->y[j];
  70. /* move all vertices in the bounding box */
  71. for (k = 0; k < Points->n_points; k++) {
  72. if (moved[k] == 0) {
  73. dist = Vect_points_distance(east, north, 0.0,
  74. x[k], y[k], z[k], WITHOUT_Z);
  75. if (dist <= thresh_coords) {
  76. G_debug(3,
  77. "Vedit_move_vertex(): line=%d; x=%f, y=%f -> x=%f, y=%f",
  78. line, x[k], y[k], x[k] + move_x,
  79. y[k] + move_y);
  80. x[k] += move_x;
  81. y[k] += move_y;
  82. if (Vect_is_3d(Map))
  83. z[k] += move_z;
  84. moved[k] = 1;
  85. G_debug(3, "Vedit_move_vertex(): line=%d, point=%d",
  86. line, k);
  87. if (snap != NO_SNAP) {
  88. if (Vedit_snap_point
  89. (Map, line, &x[k], &y[k], &z[k], thresh_snap,
  90. (snap == SNAPVERTEX) ? 1 : 0) == 0) {
  91. /* check also background maps */
  92. int bgi;
  93. for (bgi = 0; bgi < nbgmaps; bgi++) {
  94. if (Vedit_snap_point
  95. (BgMap[bgi], line, &x[k], &y[k],
  96. &z[k], thresh_snap,
  97. (snap == SNAPVERTEX) ? 1 : 0))
  98. moved[k] = 2;
  99. break; /* snapped, don't continue */
  100. }
  101. }
  102. else {
  103. moved[k] = 2;
  104. }
  105. }
  106. rewrite = 1;
  107. nvertices_moved++;
  108. if (move_first)
  109. break;
  110. }
  111. }
  112. } /* for each line vertex */
  113. /* close line or boundary */
  114. if ((type & GV_LINES) &&
  115. Vect_points_distance(x[0], y[0], z[0],
  116. x[npoints - 1], y[npoints - 1],
  117. z[npoints - 1],
  118. WITHOUT_Z) <= thresh_snap) {
  119. if (moved[0] == 1) { /* first node moved */
  120. x[0] = x[npoints - 1];
  121. y[0] = y[npoints - 1];
  122. if (Vect_is_3d(Map))
  123. z[0] = z[npoints - 1];
  124. }
  125. else if (moved[npoints - 1] == 1) { /* last node moved */
  126. x[npoints - 1] = x[0];
  127. y[npoints - 1] = y[0];
  128. if (Vect_is_3d(Map))
  129. z[npoints - 1] = z[0];
  130. }
  131. }
  132. } /* for each coord */
  133. if (rewrite) {
  134. if (Vect_rewrite_line(Map, line, type, Points, Cats) < 0) {
  135. return -1;
  136. }
  137. nlines_modified++;
  138. }
  139. } /* for each selected line */
  140. /* destroy structures */
  141. Vect_destroy_line_struct(Points);
  142. Vect_destroy_line_struct(Points_snap);
  143. Vect_destroy_cats_struct(Cats);
  144. /* G_free ((void *) moved); */
  145. return nvertices_moved;
  146. }
  147. /**
  148. \brief Add new vertex to line
  149. Shape of line is not changed.
  150. \todo 3D
  151. \param Map vector map
  152. \param List list of lines
  153. \param coord points location
  154. \param thresh find line in given threshold
  155. \return number of add verteces
  156. \return -1 on error
  157. */
  158. int Vedit_add_vertex(struct Map_info *Map, struct ilist *List,
  159. struct line_pnts *coord, double thresh)
  160. {
  161. int i, j;
  162. int type, line, seg;
  163. int nlines_modified, nvertices_added, rewrite;
  164. double east, north, dist;
  165. double *x, *y, *z;
  166. double px, py;
  167. struct line_pnts *Points;
  168. struct line_cats *Cats;
  169. nlines_modified = 0;
  170. nvertices_added = 0;
  171. Points = Vect_new_line_struct();
  172. Cats = Vect_new_cats_struct();
  173. for (i = 0; i < List->n_values; i++) {
  174. line = List->value[i];
  175. if (!Vect_line_alive(Map, line))
  176. continue;
  177. type = Vect_read_line(Map, Points, Cats, line);
  178. if (!(type & GV_LINES))
  179. continue;
  180. x = Points->x;
  181. y = Points->y;
  182. z = Points->z;
  183. rewrite = 0;
  184. for (j = 0; j < coord->n_points; j++) {
  185. east = coord->x[j];
  186. north = coord->y[j];
  187. seg = Vect_line_distance(Points, east, north, 0.0, /* standpoint */
  188. WITHOUT_Z, &px, &py, NULL, /* point on line */
  189. &dist, /* distance to line */
  190. NULL, NULL);
  191. if (dist <= thresh &&
  192. Vect_points_distance(px, py, 0.0, x[seg], y[seg], z[seg],
  193. WITHOUT_Z) > 0 &&
  194. Vect_points_distance(px, py, 0.0, x[seg - 1], y[seg - 1],
  195. z[seg - 1], WITHOUT_Z) > 0) {
  196. /* add new vertex */
  197. Vect_line_insert_point(Points, seg, px, py, 0.0);
  198. G_debug(3,
  199. "Vedit_add_vertex(): line=%d; x=%f, y=%f, index=%d",
  200. line, px, py, seg);
  201. rewrite = 1;
  202. nvertices_added++;
  203. }
  204. } /* for each point */
  205. /* rewrite the line */
  206. if (rewrite) {
  207. Vect_line_prune(Points);
  208. if (Vect_rewrite_line(Map, line, type, Points, Cats) < 0) {
  209. return -1;
  210. }
  211. nlines_modified++;
  212. }
  213. } /* for each line */
  214. /* destroy structures */
  215. Vect_destroy_line_struct(Points);
  216. Vect_destroy_cats_struct(Cats);
  217. return nvertices_added;
  218. }
  219. /**
  220. \brief Remove vertex from line
  221. \todo 3D
  222. \param Map vector map
  223. \param List list of selected lines
  224. \param coord points location
  225. \param thresh threshold value to find a line
  226. \return number of removed vertices
  227. \return -1 on error
  228. */
  229. int Vedit_remove_vertex(struct Map_info *Map, struct ilist *List,
  230. struct line_pnts *coord, double thresh)
  231. {
  232. int i, j, k;
  233. int type, line;
  234. int nvertices_removed, rewrite, nlines_modified;
  235. double east, north;
  236. double dist;
  237. double *x, *y, *z;
  238. struct line_pnts *Points;
  239. struct line_cats *Cats;
  240. nvertices_removed = nlines_modified = 0;
  241. Points = Vect_new_line_struct();
  242. Cats = Vect_new_cats_struct();
  243. for (i = 0; i < List->n_values; i++) {
  244. line = List->value[i];
  245. if (!Vect_line_alive(Map, line))
  246. continue;
  247. type = Vect_read_line(Map, Points, Cats, line);
  248. if (!(type & GV_LINES))
  249. continue;
  250. x = Points->x;
  251. y = Points->y;
  252. z = Points->z;
  253. rewrite = 0;
  254. for (j = 0; j < coord->n_points; j++) {
  255. east = coord->x[j];
  256. north = coord->y[j];
  257. for (k = 0; k < Points->n_points; k++) {
  258. dist = Vect_points_distance(east, north, 0.0,
  259. x[k], y[k], z[k], WITHOUT_Z);
  260. if (dist <= thresh) {
  261. /* remove vertex */
  262. Vect_line_delete_point(Points, k);
  263. G_debug(3,
  264. "Vedit_remove_vertex(): line=%d; x=%f, y=%f, index=%d",
  265. line, x[k], y[k], k);
  266. k--;
  267. nvertices_removed++;
  268. rewrite = 1;
  269. }
  270. } /* for each point */
  271. } /* for each bounding box */
  272. if (rewrite) {
  273. /* rewrite the line */
  274. if (Vect_rewrite_line(Map, line, type, Points, Cats) < 0) {
  275. return -1;
  276. }
  277. nlines_modified++;
  278. }
  279. } /* for each line */
  280. /* destroy structures */
  281. Vect_destroy_line_struct(Points);
  282. Vect_destroy_cats_struct(Cats);
  283. return nvertices_removed;
  284. }