plus_line.c 9.4 KB

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