plus_line.c 7.8 KB

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