plus_line.c 9.1 KB

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