index.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397
  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, k;
  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 node positions */
  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->branchsize = sizeof(struct RTree_Branch) -
  72. sizeof(struct RTree_Rect) +
  73. new_rtree->rectsize;
  74. new_rtree->nodesize = sizeof(struct RTree_Node) -
  75. sizeof(struct RTree_Branch *) +
  76. MAXCARD * new_rtree->branchsize;
  77. /* create empty root node */
  78. n = RTreeAllocNode(new_rtree, 0);
  79. new_rtree->rootlevel = n->level = 0; /* leaf */
  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. new_rtree->nb = calloc(MAXLEVEL, sizeof(struct NodeBuffer *));
  88. new_rtree->nb[0] = calloc(MAXLEVEL * NODE_BUFFER_SIZE, sizeof(struct NodeBuffer));
  89. for (i = 1; i < MAXLEVEL; i++) {
  90. new_rtree->nb[i] = new_rtree->nb[i - 1] + NODE_BUFFER_SIZE;
  91. }
  92. new_rtree->used = malloc(MAXLEVEL * sizeof(int *));
  93. new_rtree->used[0] = malloc(MAXLEVEL * NODE_BUFFER_SIZE * sizeof(int));
  94. for (i = 0; i < MAXLEVEL; i++) {
  95. if (i)
  96. new_rtree->used[i] = new_rtree->used[i - 1] + NODE_BUFFER_SIZE;
  97. for (j = 0; j < NODE_BUFFER_SIZE; j++) {
  98. new_rtree->nb[i][j].dirty = 0;
  99. new_rtree->nb[i][j].pos = -1;
  100. /* usage order */
  101. new_rtree->used[i][j] = j;
  102. new_rtree->nb[i][j].n.branch = malloc(MAXCARD * sizeof(struct RTree_Branch));
  103. /* alloc memory for rectangles */
  104. for (k = 0; k < MAXCARD; k++) {
  105. new_rtree->nb[i][j].n.branch[k].rect.boundary = RTreeAllocBoundary(new_rtree);
  106. }
  107. }
  108. }
  109. /* write empty root node */
  110. lseek(new_rtree->fd, rootpos, SEEK_SET);
  111. RTreeWriteNode(n, new_rtree);
  112. RTreeFreeNode(n);
  113. new_rtree->root = NULL;
  114. new_rtree->insert_rect = RTreeInsertRectF;
  115. new_rtree->delete_rect = RTreeDeleteRectF;
  116. new_rtree->search_rect = RTreeSearchF;
  117. new_rtree->valid_child = RTreeValidChildF;
  118. }
  119. else { /* memory based */
  120. new_rtree->nodecard = MAXCARD;
  121. new_rtree->leafcard = MAXCARD;
  122. new_rtree->insert_rect = RTreeInsertRectM;
  123. new_rtree->delete_rect = RTreeDeleteRectM;
  124. new_rtree->search_rect = RTreeSearchM;
  125. new_rtree->valid_child = RTreeValidChildM;
  126. new_rtree->root = n;
  127. }
  128. /* minimum number of remaining children for RTreeDeleteRect */
  129. /* NOTE: min fill can be changed if needed, must be < nodecard and leafcard. */
  130. new_rtree->min_node_fill = (new_rtree->nodecard - 2) / 2;
  131. new_rtree->min_leaf_fill = (new_rtree->leafcard - 2) / 2;
  132. /* balance criteria for node splitting */
  133. new_rtree->minfill_node_split = (new_rtree->nodecard - 1) / 2;
  134. new_rtree->minfill_leaf_split = (new_rtree->leafcard - 1) / 2;
  135. new_rtree->n_nodes = 1;
  136. new_rtree->n_leafs = 0;
  137. /* initialize temp variables */
  138. new_rtree->ns = malloc(MAXLEVEL * sizeof(struct nstack));
  139. new_rtree->p.cover[0].boundary = RTreeAllocBoundary(new_rtree);
  140. new_rtree->p.cover[1].boundary = RTreeAllocBoundary(new_rtree);
  141. new_rtree->tmpb1.rect.boundary = RTreeAllocBoundary(new_rtree);
  142. new_rtree->tmpb2.rect.boundary = RTreeAllocBoundary(new_rtree);
  143. new_rtree->c.rect.boundary = RTreeAllocBoundary(new_rtree);
  144. new_rtree->BranchBuf = malloc((MAXCARD + 1) * sizeof(struct RTree_Branch));
  145. for (i = 0; i <= MAXCARD; i++) {
  146. new_rtree->BranchBuf[i].rect.boundary = RTreeAllocBoundary(new_rtree);
  147. }
  148. new_rtree->rect_0.boundary = RTreeAllocBoundary(new_rtree);
  149. new_rtree->rect_1.boundary = RTreeAllocBoundary(new_rtree);
  150. new_rtree->upperrect.boundary = RTreeAllocBoundary(new_rtree);
  151. new_rtree->orect.boundary = RTreeAllocBoundary(new_rtree);
  152. new_rtree->center_n = (RectReal *)malloc(new_rtree->ndims_alloc * sizeof(RectReal));
  153. return new_rtree;
  154. }
  155. /*!
  156. \brief Enable/disable R*-tree forced reinsertion (overflow)
  157. For dynamic R*-trees with runtime insertion and deletion,
  158. forced reinsertion results in a more compact tree, searches are a bit
  159. faster. For static R*-trees (no insertion/deletion after creation)
  160. forced reinsertion can be disabled at the cost of slower searches.
  161. \param t pointer to RTree structure
  162. \param overflow binary flag
  163. \return nothing
  164. */
  165. void RTreeSetOverflow(struct RTree *t, char overflow)
  166. {
  167. t->overflow = overflow != 0;
  168. }
  169. /*!
  170. \brief Destroy an R*-Tree
  171. This method releases all memory allocated to a RTree. It deletes all
  172. rectangles and all memory allocated for internal support data.
  173. Note that for a file-based RTree, the file is not deleted and not
  174. closed. The file can thus be used to permanently store an RTree.
  175. \param t pointer to RTree structure
  176. \return nothing
  177. */
  178. void RTreeDestroyTree(struct RTree *t)
  179. {
  180. int i;
  181. assert(t);
  182. if (t->fd > -1) {
  183. int j, k;
  184. for (i = 0; i < MAXLEVEL; i++) {
  185. for (j = 0; j < NODE_BUFFER_SIZE; j++) {
  186. for (k = 0; k < MAXCARD; k++) {
  187. RTreeFreeBoundary(&t->nb[i][j].n.branch[k].rect);
  188. }
  189. free(t->nb[i][j].n.branch);
  190. }
  191. }
  192. if (t->free_nodes.alloc)
  193. free(t->free_nodes.pos);
  194. free(t->nb[0]);
  195. free(t->nb);
  196. free(t->used[0]);
  197. free(t->used);
  198. }
  199. else if (t->root)
  200. RTreeDestroyNode(t->root, t->root->level ? t->nodecard : t->leafcard);
  201. /* free temp variables */
  202. free(t->ns);
  203. RTreeFreeBoundary(&(t->p.cover[0]));
  204. RTreeFreeBoundary(&(t->p.cover[1]));
  205. RTreeFreeBoundary(&(t->tmpb1.rect));
  206. RTreeFreeBoundary(&(t->tmpb2.rect));
  207. RTreeFreeBoundary(&(t->c.rect));
  208. for (i = 0; i <= MAXCARD; i++) {
  209. RTreeFreeBoundary(&(t->BranchBuf[i].rect));
  210. }
  211. free(t->BranchBuf);
  212. RTreeFreeBoundary(&(t->rect_0));
  213. RTreeFreeBoundary(&(t->rect_1));
  214. RTreeFreeBoundary(&(t->upperrect));
  215. RTreeFreeBoundary(&(t->orect));
  216. free(t->center_n);
  217. free(t);
  218. return;
  219. }
  220. /*!
  221. \brief Search an R*-Tree
  222. Search in an RTree for all data retangles that overlap or touch the
  223. argument rectangle.
  224. Return the number of qualifying data rectangles.
  225. The search stops if the SearchHitCallBack function returns 0 (zero)
  226. or if there are no more qualifying data rectangles.
  227. \param t pointer to RTree structure
  228. \param r pointer to rectangle to use for searching
  229. \param shcb Search Hit CallBack function
  230. \param cbarg custom pointer used as argument for the shcb fn
  231. \return number of qualifying data rectangles
  232. */
  233. /*
  234. *
  235. * add option to select operator to select rectangles ?
  236. * current: overlap
  237. * possible alternatives:
  238. * - select all rectangles that are fully contained in r
  239. * - select all rectangles that fully contain r
  240. */
  241. int RTreeSearch(struct RTree *t, struct RTree_Rect *r,
  242. SearchHitCallback *shcb, void *cbarg)
  243. {
  244. assert(r && t);
  245. return t->search_rect(t, r, shcb, cbarg);
  246. }
  247. /*!
  248. \brief Insert an item into a R*-Tree
  249. \param r pointer to rectangle to use for searching
  250. \param tid data id stored with rectangle, must be > 0
  251. \param t pointer to RTree structure
  252. \return number of qualifying data rectangles
  253. */
  254. int RTreeInsertRect(struct RTree_Rect *r, int tid, struct RTree *t)
  255. {
  256. union RTree_Child newchild;
  257. assert(r && t && tid > 0);
  258. t->n_leafs++;
  259. newchild.id = tid;
  260. return t->insert_rect(r, newchild, 0, t);
  261. }
  262. /*!
  263. \brief Delete an item from a R*-Tree
  264. This method deletes an item from the RTree. The rectangle passed to
  265. this method does not need to be the exact rectangle, the only
  266. requirement is that this rectangle overlaps with the rectangle to
  267. be deleted. The rectangle to be deleted is identified by its id.
  268. \param r pointer to rectangle to use for searching
  269. \param tid id of the data to be deleted, must be > 0
  270. \param t pointer to RTree structure
  271. \return 0 on success
  272. \return 1 if data item not found
  273. */
  274. int RTreeDeleteRect(struct RTree_Rect *r, int tid, struct RTree *t)
  275. {
  276. union RTree_Child child;
  277. assert(r && t && tid > 0);
  278. child.id = tid;
  279. return t->delete_rect(r, child, t);
  280. }
  281. /***********************************
  282. * internally used functions *
  283. ***********************************/
  284. /*
  285. * Allocate space for a node in the list used in DeleteRect to
  286. * store Nodes that are too empty.
  287. */
  288. struct RTree_ListNode *RTreeNewListNode(void)
  289. {
  290. return (struct RTree_ListNode *)malloc(sizeof(struct RTree_ListNode));
  291. }
  292. void RTreeFreeListNode(struct RTree_ListNode *p)
  293. {
  294. free(p);
  295. }
  296. /*
  297. * Add a node to the reinsertion list. All its branches will later
  298. * be reinserted into the index structure.
  299. */
  300. void RTreeReInsertNode(struct RTree_Node *n, struct RTree_ListNode **ee)
  301. {
  302. struct RTree_ListNode *l = RTreeNewListNode();
  303. l->node = n;
  304. l->next = *ee;
  305. *ee = l;
  306. }
  307. /*
  308. * Free ListBranch, used by R*-type forced reinsertion
  309. */
  310. void RTreeFreeListBranch(struct RTree_ListBranch *p)
  311. {
  312. RTreeFreeBoundary(&(p->b.rect));
  313. free(p);
  314. }