plus_line.c 9.6 KB

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