plus_line.c 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358
  1. /**
  2. * \file plus_line.c
  3. *
  4. * \brief Vector library - update topo for lines (lower level functions)
  5. *
  6. * Lower level functions for reading/writing/manipulating vectors.
  7. *
  8. * This program is free software under the GNU General Public License
  9. * (>=v2). Read the file COPYING that comes with GRASS for details.
  10. *
  11. * \author CERL (probably Dave Gerdes), Radim Blazek
  12. *
  13. * \date 2001-2008
  14. */
  15. #include <stdlib.h>
  16. #include <grass/Vect.h>
  17. static int add_line(struct Plus_head *plus, int lineid, int type, struct line_pnts *Points,
  18. long offset)
  19. {
  20. int node, lp;
  21. P_LINE *line;
  22. BOUND_BOX box;
  23. plus->Line[lineid] = dig_alloc_line();
  24. line = plus->Line[lineid];
  25. /* Add nodes */
  26. G_debug(3, "Register node: type = %d, %f,%f", type, Points->x[0],
  27. Points->y[0]);
  28. node = dig_find_node(plus, Points->x[0], Points->y[0], Points->z[0]);
  29. G_debug(3, "node = %d", node);
  30. if (node == 0) {
  31. node = dig_add_node(plus, Points->x[0], Points->y[0], Points->z[0]);
  32. G_debug(3, "Add new node: %d", node);
  33. }
  34. else {
  35. G_debug(3, "Old node found: %d", node);
  36. }
  37. line->N1 = node;
  38. dig_node_add_line(plus, node, lineid, Points, type);
  39. if (plus->do_uplist)
  40. dig_node_add_updated(plus, node);
  41. if (type & GV_LINES) {
  42. lp = Points->n_points - 1;
  43. G_debug(3, "Register node %f,%f", Points->x[lp], Points->y[lp]);
  44. node =
  45. dig_find_node(plus, Points->x[lp], Points->y[lp], Points->z[lp]);
  46. G_debug(3, "node = %d", node);
  47. if (node == 0) {
  48. node =
  49. dig_add_node(plus, Points->x[lp], Points->y[lp],
  50. Points->z[lp]);
  51. G_debug(3, "Add new node: %d", node);
  52. }
  53. else {
  54. G_debug(3, "Old node found: %d", node);
  55. }
  56. line->N2 = node;
  57. dig_node_add_line(plus, node, -lineid, Points, type);
  58. if (plus->do_uplist)
  59. dig_node_add_updated(plus, node);
  60. }
  61. else {
  62. line->N2 = 0;
  63. }
  64. line->type = type;
  65. line->offset = offset;
  66. line->left = 0;
  67. line->right = 0;
  68. line->N = 0;
  69. line->S = 0;
  70. line->E = 0;
  71. line->W = 0;
  72. dig_line_box(Points, &box);
  73. dig_line_set_box(plus, lineid, &box);
  74. dig_spidx_add_line(plus, lineid, &box);
  75. if (plus->do_uplist)
  76. dig_line_add_updated(plus, lineid);
  77. return (lineid);
  78. }
  79. /*!
  80. * \brief Add new line to Plus_head structure.
  81. *
  82. * \param[in,out] plus pointer to Plus_head structure
  83. * \param[in] type feature type
  84. * \param[in] Points line geometry
  85. * \param[in] offset line offset
  86. *
  87. * \return -1 on error
  88. * \return line id
  89. */
  90. int
  91. dig_add_line(struct Plus_head *plus, int type, struct line_pnts *Points,
  92. long offset)
  93. {
  94. int ret;
  95. /* First look if we have space in array of pointers to lines
  96. * and reallocate if necessary */
  97. if (plus->n_lines >= plus->alloc_lines) { /* array is full */
  98. if (dig_alloc_lines(plus, 1000) == -1)
  99. return -1;
  100. }
  101. ret = add_line(plus, plus->n_lines + 1, type, Points, offset);
  102. if (ret == -1)
  103. return ret;
  104. plus->n_lines++;
  105. switch (type) {
  106. case GV_POINT:
  107. plus->n_plines++;
  108. break;
  109. case GV_LINE:
  110. plus->n_llines++;
  111. break;
  112. case GV_BOUNDARY:
  113. plus->n_blines++;
  114. break;
  115. case GV_CENTROID:
  116. plus->n_clines++;
  117. break;
  118. case GV_FACE:
  119. plus->n_flines++;
  120. break;
  121. case GV_KERNEL:
  122. plus->n_klines++;
  123. break;
  124. }
  125. return ret;
  126. }
  127. /*!
  128. * \brief Restore line in Plus_head structure.
  129. *
  130. * \param[in,out] plus pointer to Plus_head structure
  131. * \param[in] type feature type
  132. * \param[in] Points line geometry
  133. * \param[in] offset line offset
  134. *
  135. * \return -1 on error
  136. * \return line id
  137. */
  138. int
  139. dig_restore_line(struct Plus_head *plus, int lineid,
  140. int type, struct line_pnts *Points,
  141. long offset)
  142. {
  143. if (lineid < 1 || lineid > plus->n_lines) {
  144. return -1;
  145. }
  146. return add_line(plus, lineid, type, Points, offset);
  147. }
  148. /*!
  149. * \brief Delete line from Plus_head structure.
  150. *
  151. * Doesn't update area/isle references (dig_del_area() or dig_del_isle()) must be
  152. * run before the line is deleted if the line is part of such
  153. * structure). Update is info about line in nodes. If this line is
  154. * last in node then node is deleted.
  155. *
  156. * \param[in,out] plus pointer to Plus_head structure
  157. * \param[in] line line id
  158. *
  159. * \return -1 on error
  160. * \return 0 OK
  161. *
  162. */
  163. int dig_del_line(struct Plus_head *plus, int line)
  164. {
  165. int i, mv;
  166. P_LINE *Line;
  167. P_NODE *Node;
  168. /* TODO: free structures */
  169. G_debug(3, "dig_del_line() line = %d", line);
  170. Line = plus->Line[line];
  171. dig_spidx_del_line(plus, line);
  172. /* Delete from nodes (and nodes) */
  173. Node = plus->Node[Line->N1];
  174. mv = 0;
  175. for (i = 0; i < Node->n_lines; i++) {
  176. if (mv) {
  177. Node->lines[i - 1] = Node->lines[i];
  178. Node->angles[i - 1] = Node->angles[i];
  179. }
  180. else {
  181. if (abs(Node->lines[i]) == line)
  182. mv = 1;
  183. }
  184. }
  185. Node->n_lines--;
  186. if (Node->n_lines == 0) {
  187. G_debug(3, " node %d has 0 lines -> delete", Line->N1);
  188. dig_spidx_del_node(plus, Line->N1);
  189. plus->Node[Line->N1] = NULL;
  190. }
  191. else {
  192. if (plus->do_uplist)
  193. dig_node_add_updated(plus, Line->N1);
  194. }
  195. if (Line->type & GV_LINES) {
  196. Node = plus->Node[Line->N2];
  197. mv = 0;
  198. for (i = 0; i < Node->n_lines; i++) {
  199. if (mv) {
  200. Node->lines[i - 1] = Node->lines[i];
  201. Node->angles[i - 1] = Node->angles[i];
  202. }
  203. else {
  204. if (abs(Node->lines[i]) == line)
  205. mv = 1;
  206. }
  207. }
  208. Node->n_lines--;
  209. if (Node->n_lines == 0) {
  210. G_debug(3, " node %d has 0 lines -> delete", Line->N2);
  211. dig_spidx_del_node(plus, Line->N2);
  212. plus->Node[Line->N2] = NULL;
  213. }
  214. else {
  215. if (plus->do_uplist)
  216. dig_node_add_updated(plus, Line->N2);
  217. }
  218. }
  219. /* Delete line */
  220. plus->Line[line] = NULL;
  221. return 0;
  222. }
  223. /*!
  224. * \brief Get area number on line side.
  225. *
  226. * \param[in] plus pointer Plus_head structure
  227. * \param[in] line line id
  228. * \param[in] side side id (GV_LEFT || GV_RIGHT)
  229. *
  230. * \return area number
  231. * \return 0 no area
  232. * \return -1 on error
  233. */
  234. plus_t dig_line_get_area(struct Plus_head * plus, plus_t line, int side)
  235. {
  236. P_LINE *Line;
  237. Line = plus->Line[line];
  238. if (side == GV_LEFT) {
  239. G_debug(3,
  240. "dig_line_get_area(): line = %d, side = %d (left), area = %d",
  241. line, side, Line->left);
  242. return (Line->left);
  243. }
  244. if (side == GV_RIGHT) {
  245. G_debug(3,
  246. "dig_line_get_area(): line = %d, side = %d (right), area = %d",
  247. line, side, Line->right);
  248. return (Line->right);
  249. }
  250. return (-1);
  251. }
  252. /*!
  253. * \brief Set area number on line side
  254. *
  255. * \param[in] plus pointer Plus_head structure
  256. * \param[in] line line id
  257. * \param[in] side side id (GV_LEFT || GV_RIGHT)
  258. * \param[in] area area id
  259. *
  260. * \return 1
  261. */
  262. int
  263. dig_line_set_area(struct Plus_head *plus, plus_t line, int side, plus_t area)
  264. {
  265. P_LINE *Line;
  266. Line = plus->Line[line];
  267. if (side == GV_LEFT) {
  268. Line->left = area;
  269. }
  270. else if (side == GV_RIGHT) {
  271. Line->right = area;
  272. }
  273. return (1);
  274. }
  275. /*!
  276. * \brief Set line bounding box
  277. *
  278. * \param[in] plus pointer Plus_head structure
  279. * \param[in] line line id
  280. * \param[in] Box bounding box
  281. *
  282. * \return 1
  283. */
  284. int dig_line_set_box(struct Plus_head *plus, plus_t line, BOUND_BOX * Box)
  285. {
  286. P_LINE *Line;
  287. Line = plus->Line[line];
  288. Line->N = Box->N;
  289. Line->S = Box->S;
  290. Line->E = Box->E;
  291. Line->W = Box->W;
  292. Line->T = Box->T;
  293. Line->B = Box->B;
  294. return (1);
  295. }
  296. /*!
  297. * \brief Get line bounding box saved in topo
  298. *
  299. * \param[in] plus pointer Plus_head structure
  300. * \param[in] line line id
  301. * \param[in,out] Box bounding box
  302. *
  303. * \return 1
  304. */
  305. int dig_line_get_box(struct Plus_head *plus, plus_t line, BOUND_BOX * Box)
  306. {
  307. P_LINE *Line;
  308. Line = plus->Line[line];
  309. Box->N = Line->N;
  310. Box->S = Line->S;
  311. Box->E = Line->E;
  312. Box->W = Line->W;
  313. Box->T = Line->T;
  314. Box->B = Line->B;
  315. return (1);
  316. }