index.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385
  1. /*!
  2. \file lib/vector/rtree/index.c
  3. \brief R-Tree library - Multidimensional index
  4. Higher level functions for managing R*-Trees.
  5. (C) 2010-2012 by the GRASS Development Team
  6. This program is free software under the
  7. GNU General Public License (>=v2).
  8. Read the file COPYING that comes with GRASS
  9. for details.
  10. \author Antonin Guttman - original code
  11. \author Daniel Green (green@superliminal.com) - major clean-up
  12. and implementation of bounding spheres
  13. \author Markus Metz - file-based and memory-based R*-tree
  14. */
  15. /* Read these articles first before attempting to modify the code
  16. *
  17. * R-Tree reference:
  18. * Guttman, A. (1984). "R-Trees: A Dynamic Index Structure for Spatial
  19. * Searching". Proceedings of the 1984 ACM SIGMOD international
  20. * conference on Management of data - SIGMOD '84. pp. 47.
  21. * DOI:10.1145/602259.602266
  22. * ISBN 0897911288
  23. *
  24. * R*-Tree reference:
  25. * Beckmann, N.; Kriegel, H. P.; Schneider, R.; Seeger, B. (1990).
  26. * "The R*-tree: an efficient and robust access method for points and
  27. * rectangles". Proceedings of the 1990 ACM SIGMOD international
  28. * conference on Management of data - SIGMOD '90. pp. 322.
  29. * DOI:10.1145/93597.98741
  30. * ISBN 0897913655
  31. */
  32. #include <stdlib.h>
  33. #include <sys/types.h>
  34. #include <unistd.h>
  35. #include <assert.h>
  36. #include <grass/gis.h>
  37. #include "index.h"
  38. /*!
  39. \brief Create new empty R*-Tree
  40. This method creates a new RTree, either in memory (fd < 0) or in file.
  41. If the file descriptor is positive, the corresponding file must have
  42. been opened for reading and writing.
  43. This method must also be called if an existing tree previously saved
  44. to file is going to be accessed.
  45. \param fd file descriptor to hold data, negative toggles memory mode
  46. \param rootpos offset in file to root node (past any header info)
  47. \param ndims number of dimensions for the new tree: min 2, max 20
  48. \return pointer to new RTree structure
  49. */
  50. struct RTree *RTreeCreateTree(int fd, off_t rootpos, int ndims)
  51. {
  52. struct RTree *new_rtree;
  53. struct RTree_Node *n;
  54. int i, j;
  55. new_rtree = (struct RTree *)malloc(sizeof(struct RTree));
  56. new_rtree->fd = fd;
  57. new_rtree->rootpos = rootpos;
  58. new_rtree->ndims = ndims;
  59. new_rtree->nsides = 2 * ndims;
  60. /* hack to keep compatibility */
  61. if (ndims < 3)
  62. new_rtree->ndims_alloc = 3;
  63. else
  64. new_rtree->ndims_alloc = ndims;
  65. new_rtree->nsides_alloc = 2 * new_rtree->ndims_alloc;
  66. /* init free nodes */
  67. new_rtree->free_nodes.avail = 0;
  68. new_rtree->free_nodes.alloc = 0;
  69. new_rtree->free_nodes.pos = NULL;
  70. new_rtree->rectsize = new_rtree->nsides_alloc * sizeof(RectReal);
  71. new_rtree->nodesize = sizeof(struct RTree_Node) -
  72. MAXCARD * sizeof(RectReal *) +
  73. MAXCARD * new_rtree->rectsize;
  74. new_rtree->branchsize = sizeof(struct RTree_Branch) -
  75. sizeof(RectReal *) + new_rtree->rectsize;
  76. /* create empty root node */
  77. n = RTreeAllocNode(new_rtree, 0);
  78. new_rtree->rootlevel = n->level = 0; /* leaf */
  79. new_rtree->root = NULL;
  80. /* use overflow by default */
  81. new_rtree->overflow = 1;
  82. if (fd > -1) { /* file based */
  83. /* nodecard and leafcard can be adjusted, must NOT be larger than MAXCARD */
  84. new_rtree->nodecard = MAXCARD;
  85. new_rtree->leafcard = MAXCARD;
  86. /* initialize node buffer */
  87. for (i = 0; i < MAXLEVEL; i++) {
  88. new_rtree->nb[i][0].dirty = 0;
  89. new_rtree->nb[i][1].dirty = 0;
  90. new_rtree->nb[i][2].dirty = 0;
  91. new_rtree->nb[i][0].pos = -1;
  92. new_rtree->nb[i][1].pos = -1;
  93. new_rtree->nb[i][2].pos = -1;
  94. /* usage order */
  95. new_rtree->used[i][0] = 2;
  96. new_rtree->used[i][1] = 1;
  97. new_rtree->used[i][2] = 0;
  98. /* alloc memory for rectangles */
  99. for (j = 0; j < MAXCARD; j++) {
  100. RTreeAllocBoundary(&(new_rtree->nb[i][0].n.branch[j].rect), new_rtree);
  101. RTreeAllocBoundary(&(new_rtree->nb[i][1].n.branch[j].rect), new_rtree);
  102. RTreeAllocBoundary(&(new_rtree->nb[i][2].n.branch[j].rect), new_rtree);
  103. RTreeAllocBoundary(&(new_rtree->fs[i].sn.branch[j].rect), new_rtree);
  104. }
  105. }
  106. /* write empty root node */
  107. lseek(new_rtree->fd, rootpos, SEEK_SET);
  108. RTreeWriteNode(n, new_rtree);
  109. RTreeFreeNode(n);
  110. new_rtree->insert_rect = RTreeInsertRectF;
  111. new_rtree->delete_rect = RTreeDeleteRectF;
  112. new_rtree->search_rect = RTreeSearchF;
  113. new_rtree->valid_child = RTreeValidChildF;
  114. }
  115. else { /* memory based */
  116. new_rtree->nodecard = MAXCARD;
  117. new_rtree->leafcard = MAXCARD;
  118. new_rtree->insert_rect = RTreeInsertRectM;
  119. new_rtree->delete_rect = RTreeDeleteRectM;
  120. new_rtree->search_rect = RTreeSearchM;
  121. new_rtree->valid_child = RTreeValidChildM;
  122. new_rtree->root = n;
  123. }
  124. /* minimum number of remaining children for RTreeDeleteRect */
  125. /* NOTE: min fill can be changed if needed, must be < nodecard and leafcard. */
  126. new_rtree->min_node_fill = (new_rtree->nodecard - 2) / 2;
  127. new_rtree->min_leaf_fill = (new_rtree->leafcard - 2) / 2;
  128. /* balance criteria for node splitting */
  129. new_rtree->minfill_node_split = (new_rtree->nodecard - 1) / 2;
  130. new_rtree->minfill_leaf_split = (new_rtree->leafcard - 1) / 2;
  131. new_rtree->n_nodes = 1;
  132. new_rtree->n_leafs = 0;
  133. /* initialize temp variables */
  134. RTreeAllocBoundary(&(new_rtree->p.cover[0]), new_rtree);
  135. RTreeAllocBoundary(&(new_rtree->p.cover[1]), new_rtree);
  136. RTreeAllocBoundary(&(new_rtree->tmpb1.rect), new_rtree);
  137. RTreeAllocBoundary(&(new_rtree->tmpb2.rect), new_rtree);
  138. RTreeAllocBoundary(&(new_rtree->c.rect), new_rtree);
  139. for (i = 0; i <= MAXCARD; i++) {
  140. RTreeAllocBoundary(&(new_rtree->BranchBuf[i].rect), new_rtree);
  141. }
  142. RTreeAllocBoundary(&(new_rtree->rect_0), new_rtree);
  143. RTreeAllocBoundary(&(new_rtree->rect_1), new_rtree);
  144. RTreeAllocBoundary(&(new_rtree->upperrect), new_rtree);
  145. RTreeAllocBoundary(&(new_rtree->orect), new_rtree);
  146. new_rtree->center_n = (RectReal *)malloc(new_rtree->ndims_alloc * sizeof(RectReal));
  147. return new_rtree;
  148. }
  149. /*!
  150. \brief Enable/disable R*-tree forced reinsertion (overflow)
  151. For dynamic R*-trees with runtime insertion and deletion,
  152. forced reinsertion results in a more compact tree, searches are a bit
  153. faster. For static R*-trees (no insertion/deletion after creation)
  154. forced reinsertion can be disabled at the cost of slower searches.
  155. \param t pointer to RTree structure
  156. \param overflow binary flag
  157. \return nothing
  158. */
  159. void RTreeSetOverflow(struct RTree *t, char overflow)
  160. {
  161. t->overflow = overflow != 0;
  162. }
  163. /*!
  164. \brief Destroy an R*-Tree
  165. This method releases all memory allocated to a RTree. It deletes all
  166. rectangles and all memory allocated for internal support data.
  167. Note that for a file-based RTree, the file is not deleted and not
  168. closed. The file can thus be used to permanently store an RTree.
  169. \param t pointer to RTree structure
  170. \return nothing
  171. */
  172. void RTreeDestroyTree(struct RTree *t)
  173. {
  174. int i, j;
  175. assert(t);
  176. if (t->fd > -1) {
  177. if (t->free_nodes.alloc)
  178. free(t->free_nodes.pos);
  179. }
  180. else if (t->root)
  181. RTreeDestroyNode(t->root, t->root->level ? t->nodecard : t->leafcard);
  182. if (t->fd > -1) { /* file based */
  183. /* free node buffer */
  184. for (i = 0; i < MAXLEVEL; i++) {
  185. /* free memory for rectangles */
  186. for (j = 0; j < MAXCARD; j++) {
  187. RTreeFreeBoundary(&(t->nb[i][0].n.branch[j].rect));
  188. RTreeFreeBoundary(&(t->nb[i][1].n.branch[j].rect));
  189. RTreeFreeBoundary(&(t->nb[i][2].n.branch[j].rect));
  190. RTreeFreeBoundary(&(t->fs[i].sn.branch[j].rect));
  191. }
  192. }
  193. }
  194. /* free temp variables */
  195. RTreeFreeBoundary(&(t->p.cover[0]));
  196. RTreeFreeBoundary(&(t->p.cover[1]));
  197. RTreeFreeBoundary(&(t->tmpb1.rect));
  198. RTreeFreeBoundary(&(t->tmpb2.rect));
  199. RTreeFreeBoundary(&(t->c.rect));
  200. for (i = 0; i <= MAXCARD; i++) {
  201. RTreeFreeBoundary(&(t->BranchBuf[i].rect));
  202. }
  203. RTreeFreeBoundary(&(t->rect_0));
  204. RTreeFreeBoundary(&(t->rect_1));
  205. RTreeFreeBoundary(&(t->upperrect));
  206. RTreeFreeBoundary(&(t->orect));
  207. free(t->center_n);
  208. free(t);
  209. return;
  210. }
  211. /*!
  212. \brief Search an R*-Tree
  213. Search in an RTree for all data retangles that overlap or touch the
  214. argument rectangle.
  215. Return the number of qualifying data rectangles.
  216. The search stops if the SearchHitCallBack function returns 0 (zero)
  217. or if there are no more qualifying data rectangles.
  218. \param t pointer to RTree structure
  219. \param r pointer to rectangle to use for searching
  220. \param shcb Search Hit CallBack function
  221. \param cbarg custom pointer used as argument for the shcb fn
  222. \return number of qualifying data rectangles
  223. */
  224. /*
  225. *
  226. * add option to select operator to select rectangles ?
  227. * current: overlap
  228. * possible alternatives:
  229. * - select all rectangles that are fully contained in r
  230. * - select all rectangles that fully contain r
  231. */
  232. int RTreeSearch(struct RTree *t, struct RTree_Rect *r,
  233. SearchHitCallback *shcb, void *cbarg)
  234. {
  235. assert(r && t);
  236. return t->search_rect(t, r, shcb, cbarg);
  237. }
  238. /*!
  239. \brief Insert an item into a R*-Tree
  240. \param r pointer to rectangle to use for searching
  241. \param tid data id stored with rectangle, must be > 0
  242. \param t pointer to RTree structure
  243. \return number of qualifying data rectangles
  244. */
  245. int RTreeInsertRect(struct RTree_Rect *r, int tid, struct RTree *t)
  246. {
  247. union RTree_Child newchild;
  248. assert(r && t && tid > 0);
  249. t->n_leafs++;
  250. newchild.id = tid;
  251. return t->insert_rect(r, newchild, 0, t);
  252. }
  253. /*!
  254. \brief Delete an item from a R*-Tree
  255. This method deletes an item from the RTree. The rectangle passed to
  256. this method does not need to be the exact rectangle, the only
  257. requirement is that this rectangle overlaps with the rectangle to
  258. be deleted. The rectangle to be deleted is identified by its id.
  259. \param r pointer to rectangle to use for searching
  260. \param tid id of the data to be deleted, must be > 0
  261. \param t pointer to RTree structure
  262. \return 0 on success
  263. \return 1 if data item not found
  264. */
  265. int RTreeDeleteRect(struct RTree_Rect *r, int tid, struct RTree *t)
  266. {
  267. union RTree_Child child;
  268. assert(r && t && tid > 0);
  269. child.id = tid;
  270. return t->delete_rect(r, child, t);
  271. }
  272. /***********************************
  273. * internally used functions *
  274. ***********************************/
  275. /*
  276. * Allocate space for a node in the list used in DeleteRect to
  277. * store Nodes that are too empty.
  278. */
  279. struct RTree_ListNode *RTreeNewListNode(void)
  280. {
  281. return (struct RTree_ListNode *)malloc(sizeof(struct RTree_ListNode));
  282. }
  283. void RTreeFreeListNode(struct RTree_ListNode *p)
  284. {
  285. free(p);
  286. }
  287. /*
  288. * Add a node to the reinsertion list. All its branches will later
  289. * be reinserted into the index structure.
  290. */
  291. void RTreeReInsertNode(struct RTree_Node *n, struct RTree_ListNode **ee)
  292. {
  293. struct RTree_ListNode *l = RTreeNewListNode();
  294. l->node = n;
  295. l->next = *ee;
  296. *ee = l;
  297. }
  298. /*
  299. * Free ListBranch, used by R*-type forced reinsertion
  300. */
  301. void RTreeFreeListBranch(struct RTree_ListBranch *p)
  302. {
  303. RTreeFreeBoundary(&(p->b.rect));
  304. free(p);
  305. }