spindex.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530
  1. /*!
  2. \file diglib/spindex.c
  3. \brief Vector library - spatial index (lower level functions)
  4. Lower level functions for reading/writing/manipulating vectors.
  5. (C) 2001-2009 by the GRASS Development Team
  6. This program is free software under the GNU General Public License
  7. (>=v2). Read the file COPYING that comes with GRASS for details.
  8. \author Original author CERL, probably Dave Gerdes
  9. \author Update to GRASS 5.7 Radim Blazek
  10. */
  11. #include <grass/config.h>
  12. #include <stdlib.h>
  13. #include <string.h>
  14. #include <grass/gis.h>
  15. #include <grass/Vect.h>
  16. #include <grass/glocale.h>
  17. /*!
  18. \brief Initit spatial index (nodes, lines, areas, isles)
  19. \param Plus pointer to Plus_head structure
  20. \return 1 OK
  21. \return 0 on error
  22. */
  23. int dig_spidx_init(struct Plus_head *Plus)
  24. {
  25. G_debug(1, "dig_spidx_init()");
  26. Plus->Node_spidx = RTreeNewIndex();
  27. Plus->Line_spidx = RTreeNewIndex();
  28. Plus->Area_spidx = RTreeNewIndex();
  29. Plus->Isle_spidx = RTreeNewIndex();
  30. Plus->Node_spidx_offset = 0L;
  31. Plus->Edge_spidx_offset = 0L;
  32. Plus->Line_spidx_offset = 0L;
  33. Plus->Area_spidx_offset = 0L;
  34. Plus->Isle_spidx_offset = 0L;
  35. Plus->Volume_spidx_offset = 0L;
  36. Plus->Hole_spidx_offset = 0L;
  37. return 1;
  38. }
  39. /*!
  40. \brief Free spatial index for nodes
  41. \param Plus pointer to Plus_head structure
  42. */
  43. void dig_spidx_free_nodes(struct Plus_head *Plus)
  44. {
  45. RTreeDestroyNode(Plus->Node_spidx);
  46. Plus->Node_spidx = RTreeNewIndex();
  47. }
  48. /*!
  49. \brief Free spatial index for lines
  50. \param Plus pointer to Plus_head structure
  51. */
  52. void dig_spidx_free_lines(struct Plus_head *Plus)
  53. {
  54. RTreeDestroyNode(Plus->Line_spidx);
  55. Plus->Line_spidx = RTreeNewIndex();
  56. }
  57. /*!
  58. \brief Free spatial index for areas
  59. \param Plus pointer to Plus_head structure
  60. */
  61. void dig_spidx_free_areas(struct Plus_head *Plus)
  62. {
  63. RTreeDestroyNode(Plus->Area_spidx);
  64. Plus->Area_spidx = RTreeNewIndex();
  65. }
  66. /*!
  67. \brief Free spatial index for isles
  68. \param Plus pointer to Plus_head structure
  69. */
  70. void dig_spidx_free_isles(struct Plus_head *Plus)
  71. {
  72. RTreeDestroyNode(Plus->Isle_spidx);
  73. Plus->Isle_spidx = RTreeNewIndex();
  74. }
  75. /*!
  76. \brief Free spatial index (nodes, lines, areas, isles)
  77. \param Plus pointer to Plus_head structure
  78. */
  79. void dig_spidx_free(struct Plus_head *Plus)
  80. {
  81. dig_spidx_free_nodes(Plus);
  82. dig_spidx_free_lines(Plus);
  83. dig_spidx_free_areas(Plus);
  84. dig_spidx_free_isles(Plus);
  85. }
  86. /*!
  87. \brief Add new node to spatial index
  88. \param Plus pointer to Plus_head structure
  89. \param node node id
  90. \param x,y,z node coordinates
  91. \return 1 OK
  92. \return 0 on error
  93. */
  94. int
  95. dig_spidx_add_node(struct Plus_head *Plus, int node,
  96. double x, double y, double z)
  97. {
  98. struct Rect rect;
  99. G_debug(3, "dig_spidx_add_node(): node = %d, x,y,z = %f, %f, %f", node, x,
  100. y, z);
  101. rect.boundary[0] = x;
  102. rect.boundary[1] = y;
  103. rect.boundary[2] = z;
  104. rect.boundary[3] = x;
  105. rect.boundary[4] = y;
  106. rect.boundary[5] = z;
  107. RTreeInsertRect(&rect, node, &(Plus->Node_spidx), 0);
  108. return 1;
  109. }
  110. /*!
  111. \brief Add new line to spatial index
  112. \param Plus pointer to Plus_head structure
  113. \param line line id
  114. \param box bounding box
  115. \return 0
  116. */
  117. int dig_spidx_add_line(struct Plus_head *Plus, int line, BOUND_BOX * box)
  118. {
  119. struct Rect rect;
  120. G_debug(3, "dig_spidx_add_line(): line = %d", line);
  121. rect.boundary[0] = box->W;
  122. rect.boundary[1] = box->S;
  123. rect.boundary[2] = box->B;
  124. rect.boundary[3] = box->E;
  125. rect.boundary[4] = box->N;
  126. rect.boundary[5] = box->T;
  127. RTreeInsertRect(&rect, line, &(Plus->Line_spidx), 0);
  128. return 0;
  129. }
  130. /*!
  131. \brief Add new area to spatial index
  132. \param Plus pointer to Plus_head structure
  133. \param area area id
  134. \param box bounding box
  135. \return 0
  136. */
  137. int dig_spidx_add_area(struct Plus_head *Plus, int area, BOUND_BOX * box)
  138. {
  139. struct Rect rect;
  140. G_debug(3, "dig_spidx_add_area(): area = %d", area);
  141. rect.boundary[0] = box->W;
  142. rect.boundary[1] = box->S;
  143. rect.boundary[2] = box->B;
  144. rect.boundary[3] = box->E;
  145. rect.boundary[4] = box->N;
  146. rect.boundary[5] = box->T;
  147. RTreeInsertRect(&rect, area, &(Plus->Area_spidx), 0);
  148. return 0;
  149. }
  150. /*!
  151. \brief Add new island to spatial index
  152. \param Plus pointer to Plus_head structure
  153. \param isle isle id
  154. \param box bounding box
  155. \return 0
  156. */
  157. int dig_spidx_add_isle(struct Plus_head *Plus, int isle, BOUND_BOX * box)
  158. {
  159. struct Rect rect;
  160. G_debug(3, "dig_spidx_add_isle(): isle = %d", isle);
  161. rect.boundary[0] = box->W;
  162. rect.boundary[1] = box->S;
  163. rect.boundary[2] = box->B;
  164. rect.boundary[3] = box->E;
  165. rect.boundary[4] = box->N;
  166. rect.boundary[5] = box->T;
  167. RTreeInsertRect(&rect, isle, &(Plus->Isle_spidx), 0);
  168. return 0;
  169. }
  170. /*!
  171. \brief Delete node from spatial index
  172. G_fatal_error() called on error.
  173. \param Plus pointer to Plus_head structure
  174. \param node node id
  175. \return 0
  176. */
  177. int dig_spidx_del_node(struct Plus_head *Plus, int node)
  178. {
  179. int ret;
  180. P_NODE *Node;
  181. struct Rect rect;
  182. G_debug(3, "dig_spidx_del_node(): node = %d", node);
  183. Node = Plus->Node[node];
  184. rect.boundary[0] = Node->x;
  185. rect.boundary[1] = Node->y;
  186. rect.boundary[2] = Node->z;
  187. rect.boundary[3] = Node->x;
  188. rect.boundary[4] = Node->y;
  189. rect.boundary[5] = Node->z;
  190. ret = RTreeDeleteRect(&rect, node, &(Plus->Node_spidx));
  191. if (ret)
  192. G_fatal_error(_("Unable to delete node %d from spatial index"), node);
  193. return 0;
  194. }
  195. /*!
  196. \brief Delete line from spatial index
  197. G_fatal_error() called on error.
  198. \param Plus pointer to Plus_head structure
  199. \param line line id
  200. \return 0
  201. */
  202. int dig_spidx_del_line(struct Plus_head *Plus, int line)
  203. {
  204. P_LINE *Line;
  205. struct Rect rect;
  206. int ret;
  207. G_debug(3, "dig_spidx_del_line(): line = %d", line);
  208. Line = Plus->Line[line];
  209. G_debug(3, " box(x1,y1,z1,x2,y2,z2): %f %f %f %f %f %f", Line->W,
  210. Line->S, Line->B, Line->E, Line->N, Line->T);
  211. rect.boundary[0] = Line->W;
  212. rect.boundary[1] = Line->S;
  213. rect.boundary[2] = Line->B;
  214. rect.boundary[3] = Line->E;
  215. rect.boundary[4] = Line->N;
  216. rect.boundary[5] = Line->T;
  217. ret = RTreeDeleteRect(&rect, line, &(Plus->Line_spidx));
  218. G_debug(3, " ret = %d", ret);
  219. if (ret)
  220. G_fatal_error(_("Unable to delete line %d from spatial index"), line);
  221. return 0;
  222. }
  223. /*!
  224. \brief Delete area from spatial index
  225. G_fatal_error() called on error.
  226. \param Plus pointer to Plus_head structure
  227. \param area area id
  228. \return 0
  229. */
  230. int dig_spidx_del_area(struct Plus_head *Plus, int area)
  231. {
  232. int ret;
  233. P_AREA *Area;
  234. struct Rect rect;
  235. G_debug(3, "dig_spidx_del_area(): area = %d", area);
  236. Area = Plus->Area[area];
  237. if (Area == NULL) {
  238. G_fatal_error(_("Attempt to delete sidx for dead area"));
  239. }
  240. rect.boundary[0] = Area->W;
  241. rect.boundary[1] = Area->S;
  242. rect.boundary[2] = Area->B;
  243. rect.boundary[3] = Area->E;
  244. rect.boundary[4] = Area->N;
  245. rect.boundary[5] = Area->T;
  246. ret = RTreeDeleteRect(&rect, area, &(Plus->Area_spidx));
  247. if (ret)
  248. G_fatal_error(_("Unable to delete area %d from spatial index"), area);
  249. return 0;
  250. }
  251. /*!
  252. \brief Delete isle from spatial index
  253. G_fatal_error() called on error.
  254. \param Plus pointer to Plus_head structure
  255. \param isle isle id
  256. \return 0
  257. */
  258. int dig_spidx_del_isle(struct Plus_head *Plus, int isle)
  259. {
  260. int ret;
  261. P_ISLE *Isle;
  262. struct Rect rect;
  263. G_debug(3, "dig_spidx_del_isle(): isle = %d", isle);
  264. Isle = Plus->Isle[isle];
  265. rect.boundary[0] = Isle->W;
  266. rect.boundary[1] = Isle->S;
  267. rect.boundary[2] = Isle->B;
  268. rect.boundary[3] = Isle->E;
  269. rect.boundary[4] = Isle->N;
  270. rect.boundary[5] = Isle->T;
  271. ret = RTreeDeleteRect(&rect, isle, &(Plus->Isle_spidx));
  272. if (ret)
  273. G_fatal_error(_("Unable to delete isle %d from spatial index"), isle);
  274. return 0;
  275. }
  276. /* This function is called by RTreeSearch() to add selected node/line/area/isle to thelist */
  277. static int _add_item(int id, struct ilist *list)
  278. {
  279. dig_list_add(list, id);
  280. return 1;
  281. }
  282. /*!
  283. \brief Select nodes by bbox
  284. \param Plus pointer to Plus_head structure
  285. \param box bounding box
  286. \param list list of selected lines
  287. \return number of selected nodes
  288. \return -1 on error
  289. */
  290. int
  291. dig_select_nodes(struct Plus_head *Plus, const BOUND_BOX * box, struct ilist *list)
  292. {
  293. struct Rect rect;
  294. G_debug(3, "dig_select_nodes()");
  295. list->n_values = 0;
  296. rect.boundary[0] = box->W;
  297. rect.boundary[1] = box->S;
  298. rect.boundary[2] = box->B;
  299. rect.boundary[3] = box->E;
  300. rect.boundary[4] = box->N;
  301. rect.boundary[5] = box->T;
  302. RTreeSearch(Plus->Node_spidx, &rect, (void *)_add_item, list);
  303. return (list->n_values);
  304. }
  305. /* This function is called by RTreeSearch() for nodes to add selected node to list */
  306. static int _add_node(int id, int *node)
  307. {
  308. *node = id;
  309. return 0;
  310. }
  311. /*!
  312. \brief Find one node by coordinates
  313. \param Plus pointer to Plus_head structure
  314. \param x,y,z coordinates
  315. \return number of node
  316. \return 0 not found
  317. */
  318. int dig_find_node(struct Plus_head *Plus, double x, double y, double z)
  319. {
  320. struct Rect rect;
  321. struct ilist list;
  322. int node;
  323. G_debug(3, "dig_find_node()");
  324. dig_init_list(&list);
  325. rect.boundary[0] = x;
  326. rect.boundary[1] = y;
  327. rect.boundary[2] = z;
  328. rect.boundary[3] = x;
  329. rect.boundary[4] = y;
  330. rect.boundary[5] = z;
  331. node = 0;
  332. RTreeSearch(Plus->Node_spidx, &rect, (void *)_add_node, &node);
  333. return node;
  334. }
  335. /*!
  336. \brief Select lines by box
  337. \param Plus pointer to Plus_head structure
  338. \param box bounding box
  339. \param list list of selected lines
  340. \return number of selected lines
  341. */
  342. int
  343. dig_select_lines(struct Plus_head *Plus, const BOUND_BOX * box, struct ilist *list)
  344. {
  345. struct Rect rect;
  346. G_debug(3, "dig_select_lines()");
  347. list->n_values = 0;
  348. rect.boundary[0] = box->W;
  349. rect.boundary[1] = box->S;
  350. rect.boundary[2] = box->B;
  351. rect.boundary[3] = box->E;
  352. rect.boundary[4] = box->N;
  353. rect.boundary[5] = box->T;
  354. RTreeSearch(Plus->Line_spidx, &rect, (void *)_add_item, list);
  355. return (list->n_values);
  356. }
  357. /*!
  358. \brief Select areas by box
  359. \param Plus pointer to Plus_head structure
  360. \param box bounding box
  361. \param list list of selected lines
  362. \return number of selected areas
  363. */
  364. int
  365. dig_select_areas(struct Plus_head *Plus, const BOUND_BOX * box, struct ilist *list)
  366. {
  367. struct Rect rect;
  368. G_debug(3, "dig_select_areas()");
  369. list->n_values = 0;
  370. rect.boundary[0] = box->W;
  371. rect.boundary[1] = box->S;
  372. rect.boundary[2] = box->B;
  373. rect.boundary[3] = box->E;
  374. rect.boundary[4] = box->N;
  375. rect.boundary[5] = box->T;
  376. RTreeSearch(Plus->Area_spidx, &rect, (void *)_add_item, list);
  377. return (list->n_values);
  378. }
  379. /*!
  380. \brief Select isles by box
  381. \param Plus pointer to Plus_head structure
  382. \param box bounding box
  383. \param list list of selected lines
  384. \return number of selected isles
  385. */
  386. int
  387. dig_select_isles(struct Plus_head *Plus, const BOUND_BOX * box, struct ilist *list)
  388. {
  389. struct Rect rect;
  390. G_debug(3, "dig_select_isles()");
  391. list->n_values = 0;
  392. rect.boundary[0] = box->W;
  393. rect.boundary[1] = box->S;
  394. rect.boundary[2] = box->B;
  395. rect.boundary[3] = box->E;
  396. rect.boundary[4] = box->N;
  397. rect.boundary[5] = box->T;
  398. RTreeSearch(Plus->Isle_spidx, &rect, (void *)_add_item, list);
  399. return (list->n_values);
  400. }