qtree.c 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. /*!
  2. * \file qtree.c
  3. *
  4. * \author
  5. * H. Mitasova, I. Kosinovsky, D. Gerdes, Fall 1993,
  6. * University of Illinois and
  7. * US Army Construction Engineering Research Lab
  8. *
  9. * \author H. Mitasova (University of Illinois),
  10. * \author I. Kosinovsky, (USA-CERL)
  11. * \author D.Gerdes (USA-CERL)
  12. *
  13. * \author updated/checked by Mitasova Nov. 96 (no changes necessary)
  14. *
  15. * \copyright
  16. * (C) 1993-1996 by Helena Mitasova and the GRASS Development Team
  17. *
  18. * \copyright
  19. * This program is free software under the
  20. * GNU General Public License (>=v2).
  21. * Read the file COPYING that comes with GRASS for details.
  22. */
  23. #include <stdio.h>
  24. #include <stdlib.h>
  25. #include <math.h>
  26. #include <grass/dataquad.h>
  27. #include <grass/qtree.h>
  28. /*! Initializes multfunc structure with given arguments */
  29. struct multfunc
  30. *MT_functions_new(int (*compare) (struct triple *, struct quaddata *),
  31. struct quaddata **(*divide_data) (struct quaddata *,
  32. int, double),
  33. int (*add_data) (struct triple *, struct quaddata *,
  34. double),
  35. int (*intersect) (struct quaddata *, struct quaddata *),
  36. int (*division_check) (struct quaddata *, int),
  37. int (*get_points) (struct quaddata *, struct quaddata *,
  38. int))
  39. {
  40. struct multfunc *functions;
  41. if (!(functions = (struct multfunc *)malloc(sizeof(struct multfunc)))) {
  42. return NULL;
  43. }
  44. functions->compare = compare;
  45. functions->divide_data = divide_data;
  46. functions->add_data = add_data;
  47. functions->intersect = intersect;
  48. functions->division_check = division_check;
  49. functions->get_points = get_points;
  50. return functions;
  51. }
  52. /*! Initializes tree_info using given arguments */
  53. struct tree_info *MT_tree_info_new(struct multtree *root,
  54. struct multfunc *functions, double dmin,
  55. int kmax)
  56. {
  57. struct tree_info *info;
  58. if (!(info = (struct tree_info *)malloc(sizeof(struct tree_info)))) {
  59. return NULL;
  60. }
  61. info->root = root;
  62. info->functions = functions;
  63. info->dmin = dmin;
  64. info->kmax = kmax;
  65. return info;
  66. }
  67. /** Initializes multtree using given arguments */
  68. struct multtree *MT_tree_new(struct quaddata *data,
  69. struct multtree **leafs, struct multtree *parent,
  70. int multant)
  71. {
  72. struct multtree *tree;
  73. if (!(tree = (struct multtree *)malloc(sizeof(struct multtree)))) {
  74. return NULL;
  75. }
  76. tree->data = data;
  77. tree->leafs = leafs;
  78. tree->parent = parent;
  79. tree->multant = multant;
  80. return tree;
  81. }
  82. /*!
  83. * First checks for dividing cond. (if n_points>=KMAX) and tree
  84. * is a leaf by calling one of tree's functions (`division_check()`).
  85. * If tree is not a leaf (is a node) uses function compare to determine
  86. * into which "son" we need to insert the point and calls MT_insert()
  87. * with this son as a n argument.
  88. *
  89. * If TREE is a leaf but we don't need to divide it (n_points<KMAX) then
  90. * calls function `add_data(point, ...)` to add point to the data of tree
  91. * and returns the result of `add_data()` (which returns 1 if the point is
  92. * inserted and 0 if its ignored (when its too dense)).
  93. *
  94. * If `division_check()` returns true, calls MT_divide() and then calls
  95. * MT_insert() to insert the point into divided tree and returns the
  96. * result of MT_divide().
  97. */
  98. int MT_insert(struct triple *point,
  99. struct tree_info *info, struct multtree *tree, int n_leafs)
  100. {
  101. int j = 0, i, k, comp;
  102. if (tree == NULL) {
  103. fprintf(stderr, "insert: tree is NULL\n");
  104. return -5;
  105. }
  106. if (tree->data == NULL) {
  107. fprintf(stderr, "insert: tree->data is NULL\n");
  108. return -5;
  109. }
  110. i = info->functions->division_check(tree->data, info->kmax);
  111. if (i <= 0) {
  112. if (i == -1) {
  113. comp = info->functions->compare(point, tree->data);
  114. if ((comp < 1) || (comp > n_leafs))
  115. return -3;
  116. j = MT_insert(point, info, tree->leafs[comp - 1], n_leafs);
  117. }
  118. else {
  119. if (i == 0) {
  120. j = info->functions->add_data(point, tree->data, info->dmin);
  121. }
  122. }
  123. }
  124. else {
  125. k = MT_divide(info, tree, n_leafs);
  126. if (k == 1)
  127. j = MT_insert(point, info, tree, n_leafs);
  128. if (k == -3) {
  129. static int once = 0;
  130. if (!once) {
  131. fprintf(stderr, "Point out of range!\n");
  132. once = 1;
  133. }
  134. }
  135. if (k < 0)
  136. return k;
  137. }
  138. return j;
  139. }
  140. /*!
  141. * Divide a tree
  142. *
  143. * Divides the tree by calling one of tree's functions (divide_data())
  144. * and returns the result of divide_data()
  145. */
  146. int MT_divide(struct tree_info *info, struct multtree *tree, int n_leafs)
  147. {
  148. int i;
  149. struct quaddata **datas;
  150. struct multtree *par;
  151. struct multtree **leafs;
  152. datas = info->functions->divide_data(tree->data, info->kmax, info->dmin);
  153. if (datas == NULL) {
  154. fprintf(stderr, "datas is NULL\n");
  155. return -7;
  156. }
  157. par = tree;
  158. leafs = (struct multtree **)malloc(sizeof(struct multtree *) * n_leafs);
  159. for (i = 1; i <= n_leafs; i++) {
  160. leafs[i - 1] = MT_tree_new(datas[i], NULL, par, i);
  161. }
  162. tree->leafs = leafs;
  163. return 1;
  164. }
  165. /*!
  166. * Get points inside a region from a tree
  167. *
  168. * Gets points inside the region defined by DATA from TREE and
  169. * adds them to DATA. If the number of eligible
  170. * point is more than MAX returns MAX+1 otherwise returns number of points added
  171. * to DATA.
  172. *
  173. * Uses tree's functions intersect() to find leafs that intersect given region
  174. * and get_points() to get points from such leafs.
  175. */
  176. int MT_region_data(struct tree_info *info, struct multtree *tree,
  177. struct quaddata *data,
  178. int MAX, /*!< max number of points we can add (KMAX2) */
  179. int n_leafs
  180. )
  181. {
  182. int n = 0, j;
  183. if (tree == NULL) {
  184. fprintf(stderr, "MT_region_data: tree is NULL\n");
  185. return n;
  186. }
  187. if (tree->data == NULL) {
  188. fprintf(stderr, "MT_region_data: data is NULL\n");
  189. return n;
  190. }
  191. if (info->functions->intersect(data, tree->data)) {
  192. if (tree->leafs != NULL) {
  193. for (j = 0; j < n_leafs; j++) {
  194. if ((n =
  195. n + MT_region_data(info, tree->leafs[j], data, MAX - n,
  196. n_leafs)) > MAX)
  197. return n;
  198. }
  199. }
  200. else {
  201. n = info->functions->get_points(data, tree->data, MAX);
  202. }
  203. return n;
  204. }
  205. return 0;
  206. }