sindex.c 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274
  1. /*!
  2. \file Vlib/sindex.c
  3. \brief Vector library - spatial index
  4. Higher 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 Radim Blazek
  9. \author Martin Landa <landa.martin gmail.com> (storing sidx to file)
  10. */
  11. #include <grass/config.h>
  12. #include <stdlib.h>
  13. #include <string.h>
  14. #include <grass/glocale.h>
  15. #include <grass/gis.h>
  16. #include <grass/vector.h>
  17. #include <grass/glocale.h>
  18. /*!
  19. \brief Initialize spatial index structure
  20. \param si pointer to spatial index structure
  21. \return void
  22. */
  23. void Vect_spatial_index_init(SPATIAL_INDEX *si)
  24. {
  25. G_debug(1, "Vect_spatial_index_init()");
  26. si->root = RTreeNewIndex();
  27. }
  28. /*!
  29. \brief Destroy existing spatial index
  30. Vect_spatial_index_init() must be call before new use.
  31. \param si pointer to spatial index structure
  32. \return void
  33. */
  34. void Vect_spatial_index_destroy(SPATIAL_INDEX *si)
  35. {
  36. G_debug(1, "Vect_spatial_index_destroy()");
  37. RTreeDestroyNode(si->root);
  38. }
  39. /*!
  40. \brief Add a new item to spatial index structure
  41. \param[in,out] si pointer to spatial index structure
  42. \param id item identifier
  43. \param box pointer to item bounding box
  44. \return void
  45. */
  46. void Vect_spatial_index_add_item(SPATIAL_INDEX *si, int id, const BOUND_BOX *box)
  47. {
  48. struct Rect rect;
  49. G_debug(3, "Vect_spatial_index_add_item(): id = %d", id);
  50. rect.boundary[0] = box->W;
  51. rect.boundary[1] = box->S;
  52. rect.boundary[2] = box->B;
  53. rect.boundary[3] = box->E;
  54. rect.boundary[4] = box->N;
  55. rect.boundary[5] = box->T;
  56. RTreeInsertRect(&rect, id, &(si->root), 0);
  57. }
  58. /*!
  59. \brief Delete item from spatial index structure
  60. \param[in,out] si pointer to spatial index structure
  61. \param id item identifier
  62. \return void
  63. */
  64. void Vect_spatial_index_del_item(SPATIAL_INDEX * si, int id)
  65. {
  66. int ret;
  67. struct Rect rect;
  68. G_debug(3, "Vect_spatial_index_del_item(): id = %d", id);
  69. /* TODO */
  70. G_fatal_error("Vect_spatial_index_del_item() %s", _("not implemented"));
  71. /* Bounding box of item would be needed, which is not stored in si. */
  72. /*
  73. rect.boundary[0] = ; rect.boundary[1] = ; rect.boundary[2] = ;
  74. rect.boundary[3] = ; rect.boundary[4] = ; rect.boundary[5] = ;
  75. */
  76. ret = RTreeDeleteRect(&rect, id, &(si->root));
  77. if (ret)
  78. G_fatal_error(_("Unable to delete item %d from spatial index"), id);
  79. }
  80. /*!
  81. \brief Create spatial index if necessary.
  82. To be used in modules.
  83. Map must be opened on level 2.
  84. \param[in,out] Map pointer to vector map
  85. \return 0 OK
  86. \return 1 error
  87. */
  88. int Vect_build_spatial_index(struct Map_info *Map)
  89. {
  90. if (Map->level < 2) {
  91. G_fatal_error(_("Unable to build spatial index from topology, "
  92. "vector map is not opened at topology level 2"));
  93. }
  94. if (!(Map->plus.Spidx_built)) {
  95. return (Vect_build_sidx_from_topo(Map));
  96. }
  97. return 0;
  98. }
  99. /*!
  100. \brief Create spatial index from topology if necessary
  101. \param Map pointer to vector map
  102. \return 0 OK
  103. \return 1 error
  104. */
  105. int Vect_build_sidx_from_topo(struct Map_info *Map)
  106. {
  107. int i, total, done;
  108. struct Plus_head *plus;
  109. BOUND_BOX box;
  110. P_LINE *Line;
  111. P_NODE *Node;
  112. P_AREA *Area;
  113. P_ISLE *Isle;
  114. G_debug(3, "Vect_build_sidx_from_topo()");
  115. plus = &(Map->plus);
  116. dig_spidx_init(plus);
  117. total = plus->n_nodes + plus->n_lines + plus->n_areas + plus->n_isles;
  118. /* Nodes */
  119. for (i = 1; i <= plus->n_nodes; i++) {
  120. G_percent(i, total, 3);
  121. Node = plus->Node[i];
  122. if (!Node)
  123. G_fatal_error(_("BUG (Vect_build_sidx_from_topo): node does not exist"));
  124. dig_spidx_add_node(plus, i, Node->x, Node->y, Node->z);
  125. }
  126. /* Lines */
  127. done = plus->n_nodes;
  128. for (i = 1; i <= plus->n_lines; i++) {
  129. G_percent(done + i, total, 3);
  130. Line = plus->Line[i];
  131. if (!Line)
  132. G_fatal_error(_("BUG (Vect_build_sidx_from_topo): line does not exist"));
  133. box.N = Line->N;
  134. box.S = Line->S;
  135. box.E = Line->E;
  136. box.W = Line->W;
  137. box.T = Line->T;
  138. box.B = Line->B;
  139. dig_spidx_add_line(plus, i, &box);
  140. }
  141. /* Areas */
  142. done += plus->n_lines;
  143. for (i = 1; i <= plus->n_areas; i++) {
  144. G_percent(done + i, total, 3);
  145. Area = plus->Area[i];
  146. if (!Area)
  147. G_fatal_error(_("BUG (Vect_build_sidx_from_topo): area does not exist"));
  148. box.N = Area->N;
  149. box.S = Area->S;
  150. box.E = Area->E;
  151. box.W = Area->W;
  152. box.T = Area->T;
  153. box.B = Area->B;
  154. dig_spidx_add_area(plus, i, &box);
  155. }
  156. /* Isles */
  157. done += plus->n_areas;
  158. for (i = 1; i <= plus->n_isles; i++) {
  159. G_percent(done + i, total, 3);
  160. Isle = plus->Isle[i];
  161. if (!Isle)
  162. G_fatal_error(_("BUG (Vect_build_sidx_from_topo): isle does not exist"));
  163. box.N = Isle->N;
  164. box.S = Isle->S;
  165. box.E = Isle->E;
  166. box.W = Isle->W;
  167. box.T = Isle->T;
  168. box.B = Isle->B;
  169. dig_spidx_add_isle(plus, i, &box);
  170. }
  171. Map->plus.Spidx_built = 1;
  172. G_debug(3, "Spatial index was built");
  173. return 0;
  174. }
  175. /************************* SELECT BY BOX *********************************/
  176. /* This function is called by RTreeSearch() to add selected item to the list */
  177. static int _add_item(int id, struct ilist *list)
  178. {
  179. dig_list_add(list, id);
  180. return 1;
  181. }
  182. /*!
  183. \brief Select items by bounding box to list
  184. \param si pointer to spatial index structure
  185. \param box bounding box
  186. \param[out] list pointer to list where selected items are stored
  187. \return number of selected items
  188. */
  189. int
  190. Vect_spatial_index_select(const SPATIAL_INDEX * si, const BOUND_BOX * box,
  191. struct ilist *list)
  192. {
  193. struct Rect rect;
  194. G_debug(3, "Vect_spatial_index_select()");
  195. Vect_reset_list(list);
  196. rect.boundary[0] = box->W;
  197. rect.boundary[1] = box->S;
  198. rect.boundary[2] = box->B;
  199. rect.boundary[3] = box->E;
  200. rect.boundary[4] = box->N;
  201. rect.boundary[5] = box->T;
  202. RTreeSearch(si->root, &rect, (void *)_add_item, list);
  203. G_debug(3, " %d items selected", list->n_values);
  204. return (list->n_values);
  205. }